|
|
@@ -1,20 +1,217 @@
|
|
|
package com.izouma.nineth.service;
|
|
|
|
|
|
+import com.izouma.nineth.config.MetaConstants;
|
|
|
import com.izouma.nineth.domain.MetaObjectMove;
|
|
|
+import com.izouma.nineth.domain.MetaObjectMoveCoordinate;
|
|
|
+import com.izouma.nineth.dto.MetaObjectMoveCoordinateDTO;
|
|
|
import com.izouma.nineth.dto.PageQuery;
|
|
|
+import com.izouma.nineth.exception.BusinessException;
|
|
|
+import com.izouma.nineth.repo.MetaObjectMoveCoordinateRepo;
|
|
|
import com.izouma.nineth.repo.MetaObjectMoveRepo;
|
|
|
import com.izouma.nineth.utils.JpaUtils;
|
|
|
import lombok.AllArgsConstructor;
|
|
|
+import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.springframework.data.domain.Page;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import javax.transaction.Transactional;
|
|
|
+import java.time.ZoneOffset;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
@Service
|
|
|
@AllArgsConstructor
|
|
|
public class MetaObjectMoveService {
|
|
|
|
|
|
- private MetaObjectMoveRepo metaObjectMoveRepo;
|
|
|
+ private MetaObjectMoveRepo metaObjectMoveRepo;
|
|
|
+ private MetaObjectMoveCoordinateRepo metaObjectMoveCoordinateRepo;
|
|
|
+ private RedisTemplate<String, Object> redisTemplate;
|
|
|
|
|
|
public Page<MetaObjectMove> all(PageQuery pageQuery) {
|
|
|
return metaObjectMoveRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaObjectMove.class), JpaUtils.toPageRequest(pageQuery));
|
|
|
}
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public MetaObjectMove save(MetaObjectMove record) {
|
|
|
+ if (Objects.isNull(record)) {
|
|
|
+ throw new BusinessException("params can not be null");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(record.getObjectId())) {
|
|
|
+ throw new BusinessException("objectId can not be null");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(record.getStartTime())) {
|
|
|
+ throw new BusinessException("startTime can not be null");
|
|
|
+ }
|
|
|
+ MetaObjectMove metaObjectMove = metaObjectMoveRepo.findByObjectIdAndDel(record.getObjectId(), false);
|
|
|
+ if (Objects.nonNull(metaObjectMove)) {
|
|
|
+ throw new BusinessException("objectId already exists");
|
|
|
+ }
|
|
|
+ List<MetaObjectMoveCoordinateDTO> metaObjectMoveCoordinateDTOS = record.getMetaObjectMoveCoordinateDTOS();
|
|
|
+ if (CollectionUtils.isEmpty(metaObjectMoveCoordinateDTOS)) {
|
|
|
+ throw new BusinessException("object movement coordinates can not be null");
|
|
|
+ }
|
|
|
+ if (metaObjectMoveCoordinateDTOS.size() < 2) {
|
|
|
+ throw new BusinessException("object moves with at least two coordinates");
|
|
|
+ }
|
|
|
+ for (int i = 0; i < metaObjectMoveCoordinateDTOS.size(); i++) {
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getAxisX())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,axisX can not be null");
|
|
|
+ }
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getAxisY())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,axisY can not be null");
|
|
|
+ }
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getAxisZ())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,axisZ can not be null");
|
|
|
+ }
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getEulerX())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,eulerX can not be null");
|
|
|
+ }
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getEulerY())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,eulerY can not be null");
|
|
|
+ }
|
|
|
+ if (Float.isNaN(metaObjectMoveCoordinateDTOS.get(i).getEulerZ())) {
|
|
|
+ throw new BusinessException("coordinates are illegal,eulerZ can not be null");
|
|
|
+ }
|
|
|
+ if (i > 0 && metaObjectMoveCoordinateDTOS.get(i).getTime() <= metaObjectMoveCoordinateDTOS.get(i - 1).getTime()) {
|
|
|
+ throw new BusinessException("coordinates are illegal,time must be incremented");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ record.setTotalTime(metaObjectMoveCoordinateDTOS.get(metaObjectMoveCoordinateDTOS.size() - 1).getTime());
|
|
|
+ MetaObjectMove save = metaObjectMoveRepo.save(record);
|
|
|
+ String objectMoveKey = MetaConstants.META_OBJECT_MOVE_REDIS_KEY.concat(String.valueOf(save.getObjectId()));
|
|
|
+ // 缓存-物体移动配置
|
|
|
+ if (Boolean.FALSE.equals(redisTemplate.hasKey(objectMoveKey))) {
|
|
|
+ redisTemplate.opsForValue().set(objectMoveKey, save);
|
|
|
+ handleCoordinate(save.getId());
|
|
|
+ return save;
|
|
|
+ }
|
|
|
+ redisTemplate.delete(objectMoveKey);
|
|
|
+ redisTemplate.opsForValue().set(objectMoveKey, save);
|
|
|
+ handleCoordinate(save.getId());
|
|
|
+ return save;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public void handleCoordinate(Long id) {
|
|
|
+ MetaObjectMove metaObjectMove = metaObjectMoveRepo.findByIdAndDel(id, false);
|
|
|
+ if (Objects.isNull(metaObjectMove)) {
|
|
|
+ throw new BusinessException("物体移动配置为空");
|
|
|
+ }
|
|
|
+ List<MetaObjectMoveCoordinateDTO> metaObjectMoveCoordinateDTOS = metaObjectMove.getMetaObjectMoveCoordinateDTOS();
|
|
|
+ if (CollectionUtils.isEmpty(metaObjectMoveCoordinateDTOS)) {
|
|
|
+ throw new BusinessException("物体移动坐标配置为空");
|
|
|
+ }
|
|
|
+ int size = metaObjectMoveCoordinateDTOS.size();
|
|
|
+ if (size < 2) {
|
|
|
+ throw new BusinessException("物体移动最低配置两个坐标");
|
|
|
+ }
|
|
|
+ List<MetaObjectMoveCoordinate> list = new ArrayList<>();
|
|
|
+ for (int i = 0; i < size - 1; i++) {
|
|
|
+ MetaObjectMoveCoordinateDTO start = metaObjectMoveCoordinateDTOS.get(i);
|
|
|
+ // 开始时间(getTime取出来的值单位为秒)
|
|
|
+ int startTime = (int) start.getTime() * 24;
|
|
|
+ MetaObjectMoveCoordinateDTO end = metaObjectMoveCoordinateDTOS.get(i + 1);
|
|
|
+ // 到达时间(getTime取出来的值单位为秒)
|
|
|
+ int endTime = (int) end.getTime() * 24;
|
|
|
+ // 两个坐标间总共移动时间
|
|
|
+ int time = endTime - startTime;
|
|
|
+ if (time <= 0) {
|
|
|
+ throw new BusinessException("两个坐标间移动时间必须大于0");
|
|
|
+ }
|
|
|
+ float startAxisX = start.getAxisX();
|
|
|
+ float endAxisX = end.getAxisX();
|
|
|
+ float axisX = (endAxisX - startAxisX) / time;
|
|
|
+
|
|
|
+ float startAxisY = start.getAxisY();
|
|
|
+ float endAxisY = end.getAxisY();
|
|
|
+ float axisY = (endAxisY - startAxisY) / time;
|
|
|
+
|
|
|
+ float startAxisZ = start.getAxisZ();
|
|
|
+ float endAxisZ = end.getAxisZ();
|
|
|
+ float axisZ = (endAxisZ - startAxisZ) / time;
|
|
|
+
|
|
|
+ float startEulerX = start.getEulerX();
|
|
|
+ float endEulerX = end.getEulerX();
|
|
|
+ float eulerX = (endEulerX - startEulerX) / time;
|
|
|
+
|
|
|
+ float startEulerY = start.getEulerY();
|
|
|
+ float endEulerY = end.getEulerY();
|
|
|
+ float eulerY = (endEulerY - startEulerY) / time;
|
|
|
+
|
|
|
+ float startEulerZ = start.getEulerZ();
|
|
|
+ float endEulerZ = end.getEulerZ();
|
|
|
+ float eulerZ = (endEulerZ - startEulerZ) / time;
|
|
|
+
|
|
|
+ for (int a = startTime; a <= endTime; a++) {
|
|
|
+ MetaObjectMoveCoordinate dbExist = metaObjectMoveCoordinateRepo.findByObjectIdAndCoordinateIndexAndDel(metaObjectMove.getObjectId(), a, false);
|
|
|
+ if (Objects.isNull(dbExist)) {
|
|
|
+ dbExist = new MetaObjectMoveCoordinate();
|
|
|
+ dbExist.setObjectId(metaObjectMove.getObjectId());
|
|
|
+ dbExist.setCoordinateIndex(a);
|
|
|
+ dbExist.setAxisX(startAxisX + (a - startTime) * axisX);
|
|
|
+ dbExist.setAxisY(startAxisY + (a - startTime) * axisY);
|
|
|
+ dbExist.setAxisZ(startAxisZ + (a - startTime) * axisZ);
|
|
|
+ dbExist.setEulerX(startEulerX + (a - startTime) * eulerX);
|
|
|
+ dbExist.setEulerY(startEulerY + (a - startTime) * eulerY);
|
|
|
+ dbExist.setEulerZ(startEulerZ + (a - startTime) * eulerZ);
|
|
|
+ list.add(dbExist);
|
|
|
+ // 查询缓存坐标信息
|
|
|
+ String coordinateKey = MetaConstants.META_OBJECT_INDEX_REDIS_KEY.concat(String.valueOf(dbExist.getObjectId())).concat("_").concat(String.valueOf(dbExist.getCoordinateIndex()));
|
|
|
+ if (Boolean.FALSE.equals(redisTemplate.hasKey(coordinateKey))) {
|
|
|
+ redisTemplate.opsForValue().set(coordinateKey, dbExist);
|
|
|
+ } else {
|
|
|
+ redisTemplate.delete(coordinateKey);
|
|
|
+ redisTemplate.opsForValue().set(coordinateKey, dbExist);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 多索引去重
|
|
|
+ List<MetaObjectMoveCoordinate> distinctList = list.stream()
|
|
|
+ .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
|
|
|
+ new TreeSet<>(Comparator.comparing(MetaObjectMoveCoordinate::getCoordinateIndex))),
|
|
|
+ ArrayList::new));
|
|
|
+ metaObjectMoveCoordinateRepo.saveAll(distinctList);
|
|
|
+ }
|
|
|
+
|
|
|
+ public MetaObjectMoveCoordinate queryCoordinate(Long objectId) {
|
|
|
+ // 查询缓存-物体移动配置
|
|
|
+ String objectMoveKey = MetaConstants.META_OBJECT_MOVE_REDIS_KEY.concat(String.valueOf(objectId));
|
|
|
+ MetaObjectMove metaObjectMove = (MetaObjectMove) redisTemplate.opsForValue().get(objectMoveKey);
|
|
|
+ // 缓存不存在 查询数据库
|
|
|
+ if (Objects.isNull(metaObjectMove)) {
|
|
|
+ metaObjectMove = metaObjectMoveRepo.findByObjectIdAndDel(objectId, false);
|
|
|
+ if (Objects.isNull(metaObjectMove)) {
|
|
|
+ throw new BusinessException("物体配置不存在!");
|
|
|
+ }
|
|
|
+ // 重新缓存-物体移动配置
|
|
|
+ redisTemplate.delete(objectMoveKey);
|
|
|
+ redisTemplate.opsForValue().set(objectMoveKey, metaObjectMove);
|
|
|
+ }
|
|
|
+ // 开始时间戳(单位为秒)
|
|
|
+ long startTime = metaObjectMove.getStartTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
|
|
|
+ // 当前时间戳(单位为秒)
|
|
|
+ long currentTime = System.currentTimeMillis() / 1000;
|
|
|
+ // 计算坐标索引
|
|
|
+ long index = (currentTime - startTime) % (metaObjectMove.getTotalTime() * 2L);
|
|
|
+ if (index > (metaObjectMove.getTotalTime())) {
|
|
|
+ index = metaObjectMove.getTotalTime() * 2L - index;
|
|
|
+ }
|
|
|
+ index = index * 24;
|
|
|
+ // 查询缓存坐标信息
|
|
|
+ String coordinateKey = MetaConstants.META_OBJECT_INDEX_REDIS_KEY.concat(String.valueOf(objectId)).concat("_").concat(String.valueOf(index));
|
|
|
+ MetaObjectMoveCoordinate metaObjectMoveCoordinate = (MetaObjectMoveCoordinate) redisTemplate.opsForValue().get(coordinateKey);
|
|
|
+ if (Objects.isNull(metaObjectMoveCoordinate)) {
|
|
|
+ // 查询数据库坐标信息
|
|
|
+ metaObjectMoveCoordinate = metaObjectMoveCoordinateRepo.findByObjectIdAndCoordinateIndexAndDel(objectId, (int) index, false);
|
|
|
+ if (Objects.isNull(metaObjectMoveCoordinate)) {
|
|
|
+ throw new BusinessException("坐标信息为空");
|
|
|
+ }
|
|
|
+ // 重新缓存坐标信息
|
|
|
+ redisTemplate.delete(coordinateKey);
|
|
|
+ redisTemplate.opsForValue().set(coordinateKey, metaObjectMoveCoordinate);
|
|
|
+ }
|
|
|
+ return metaObjectMoveCoordinate;
|
|
|
+ }
|
|
|
}
|