diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java index f666126..4fed50c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java @@ -92,6 +92,7 @@ @Value("${casic.obstacle:60}") private Integer obstacle; private volatile AtomicInteger atomicInteger = new AtomicInteger(); + public TaskInfoServiceImpl(@Lazy IRouteInfoService routeInfoService, IRobotStatusInfoService statusInfoService, AbstractDictService dictService, @Lazy IAlarmRecordService recordService, @Lazy ITaskHeatMapService taskHeatMapService, IAlgorithmService algorithmService, IRobotCacheService cacheService, @Lazy IBaseRobotService baseRobotService, ITaskInfoImgService imgService, ITaskGridInfoService taskGridInfoService) { this.routeInfoService = routeInfoService; this.statusInfoService = statusInfoService; @@ -130,6 +131,7 @@ log.error(e.getMessage()); } } + protected void sendTaskMsg(InstructStatusMsgEnums enums, String robotId, TaskEndMsg heatMap) { try { WsMsgBaseDTO wsMsgBaseDTO = new WsMsgBaseDTO(); @@ -142,6 +144,7 @@ log.error(e.getMessage()); } } + @Override public List selectTaskInfoPage(Page page, QueryWrapper query) { return this.baseMapper.selectTaskInfoPage(page, query); @@ -212,12 +215,12 @@ RobotInfo robotInfo = cacheService.getRobotInfo(Convert.toLong(robotId)); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_IS_TASK + robotId, isTask); //添加任务记录 - TaskInfo taskInfo = addTaskByStartTrack( robotInfo, request); + TaskInfo taskInfo = addTaskByStartTrack(robotInfo, request); //No.3 更新器人执行任务信息 // Long currRouteId = routeInfo.getId(); Long currTaskId = taskInfo.getId(); - statusInfoService.updateCurrTask(robotId, currTaskId); + statusInfoService.updateCurrTask(robotId, currTaskId); //算法初始化标志创建 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_ID + robotId, currTaskId); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_INIT + robotId, 0); @@ -241,7 +244,7 @@ robotCacheClean(robotId); //清楚规划任务锁 CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_PLANING_FLAG + robotId); - CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID+ robotId); + CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); //清空机器当前任务 statusInfoService.updateCurrTask(robotId, null); } @@ -315,7 +318,7 @@ //No.1 任务初始化 pathInit(longId, robotInfo, pointDTO, taskId, robotId, taskInfo.getStepLen()); //No.2 路线规划 - pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo,dto); + pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo, dto); } /** @@ -340,7 +343,7 @@ * @param taskId 任务ID * @param robotId 机器人ID */ - private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo,PoseMessageResponseDTO curPoint) { + private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo, PoseMessageResponseDTO curPoint) { if (taskId != null) { //规划节点 PointNextDTO pointNextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); @@ -350,11 +353,11 @@ if (!flag) { return; } - log.info("curr point:{}",curPoint); + log.info("curr point:{}", curPoint); log.debug("curr pointGrid:{}", pointDTO); log.debug("oldEstimateGrid:{}", oldEstimateGrid); try { - if (pointNextDTO == null || oldEstimateGrid==null || isEquals(pointDTO, oldEstimateGrid,robotInfo)) { + if (pointNextDTO == null || oldEstimateGrid == null || isEquals(pointDTO, oldEstimateGrid, robotInfo)) { atomicInteger = new AtomicInteger(0); log.info("当前栅格变更......", pointDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_POINT + robotId, pointDTO); @@ -372,7 +375,7 @@ AlgorithmResponse response = algorithmService.pathPlanning(pathPlanDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId, response.getPointNextDTO()); - new Thread(){ + new Thread() { @Override public void run() { //存储循迹任务信息 @@ -400,9 +403,12 @@ //是否触发停止状态 if (!response.isEnd()) { //机器人寻点指令下发 - sendTargetPoint(robotInfo, response,curPoint); + if (robotInfo.getIsOpen() == null || robotInfo.getIsOpen() == 0) { + sendTargetPoint(robotInfo, response, curPoint); + } else { + log.debug("task mode isOpen:{}", robotInfo.getIsOpen()); + } } else { - log.debug("task stop-- robotId:{},taskId:{}", robotId, taskId); //机器人停止指令下发 SoftwareStopRequest request = new SoftwareStopRequest(); request.setRobotId(robotInfo.getId()); @@ -417,8 +423,8 @@ endMsg.setMessage("寻源结束"); sendTaskMsg(InstructStatusMsgEnums.TASK_END, robotId, endMsg); } - }else{ - if(!isChange(pointDTO, oldEstimateGrid)){ + } else { + if (!isChange(pointDTO, oldEstimateGrid)) { atomicInteger.incrementAndGet(); } } @@ -461,20 +467,20 @@ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); Integer height = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId); - if(height==null){ - height=521; + if (height == null) { + throw new ServiceException(500, "未获取到栅格宽度信息"); } - Integer newX = robotInfo.getNewOriginX(); - Integer newY = height-robotInfo.getNewOriginY(); + Integer newX = robotInfo.getNewGridX(); + Integer newY = height - robotInfo.getNewGridY(); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if (i <= newY) { List newList = new ArrayList<>(); - List sourceList= costList.get(i); + List sourceList = costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if (j >= newX) { newList.add(sourceList.get(j)); } } @@ -488,7 +494,7 @@ FileUtil.writeLines(strs2, new File(path + "map2.txt"), "utf-8"); //行转列 为算法输入数据 - if(CollectionUtil.isNotEmpty(newCostList)){ + if (CollectionUtil.isNotEmpty(newCostList)) { CollectionUtil.reverse(newCostList); for (int i = 0; i < newCostList.get(0).size(); i++) { ArrayList ints = new ArrayList<>(); @@ -596,7 +602,7 @@ * @param robotInfo 机器人信息 * @param response 算法输出数据 */ - private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response,PoseMessageResponseDTO curPoint) { + private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response, PoseMessageResponseDTO curPoint) { //读取已设置巡点目标信息 PointNextDTO nextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TARGET_POINT_ID + robotInfo.getId()); //巡点 @@ -610,7 +616,7 @@ request.setZ(curPoint.getZ().toString()); request.setTheta(curPoint.getTheta().toString()); request.setRobotId(robotInfo.getId()); - log.info("下发寻源点位:{}",request); + log.info("下发寻源点位:{}", request); //执行巡点指令 baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); //重设寻点点位 @@ -678,7 +684,7 @@ //读取 Integer index = 1; LambdaQueryWrapper taskGridQuery = new LambdaQueryWrapper<>(); - taskGridQuery.eq(TaskGridInfo::getTaskId,info.getId()); + taskGridQuery.eq(TaskGridInfo::getTaskId, info.getId()); taskGridQuery.orderByAsc(TaskGridInfo::getCreateTime); List taskGridInfos = taskGridInfoService.list(taskGridQuery); if (CollectionUtil.isNotEmpty(taskGridInfos)) { @@ -783,23 +789,24 @@ /** * 栅格判定方法 - * @param pointDTO 当前栅格 + * + * @param pointDTO 当前栅格 * @param oldPointDTO 预期栅格 - * @param robotInfo 机器信息 + * @param robotInfo 机器信息 * @return */ - private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO,RobotInfo robotInfo) { - if(oldPointDTO==null||oldPointDTO.getX()==null){ + private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO, RobotInfo robotInfo) { + if (oldPointDTO == null || oldPointDTO.getX() == null) { return false; } - if(robotInfo.getResolution().compareTo(new BigDecimal(0.21))>0){ + if (robotInfo.getResolution().compareTo(new BigDecimal(0.21)) > 0) { //大于0.2则默认该点 if (pointDTO.getX().compareTo(oldPointDTO.getX()) == 0 && pointDTO.getY().compareTo(oldPointDTO.getY()) == 0) { return true; } - }else{ + } else { //小于0.2则可判定相邻栅格 - if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue()<=1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { + if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue() <= 1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { return true; } @@ -818,7 +825,7 @@ return pathInitDTO; } - private TaskInfo addTaskByStartTrack( RobotInfo robotInfo, StartTrackRequest request) { + private TaskInfo addTaskByStartTrack(RobotInfo robotInfo, StartTrackRequest request) { //No.2 新增任务信息 TaskInfo taskInfo = new TaskInfo(); String currDate = DateUtil.format(new Date(), "yyyyMMdd"); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java index f666126..4fed50c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java @@ -92,6 +92,7 @@ @Value("${casic.obstacle:60}") private Integer obstacle; private volatile AtomicInteger atomicInteger = new AtomicInteger(); + public TaskInfoServiceImpl(@Lazy IRouteInfoService routeInfoService, IRobotStatusInfoService statusInfoService, AbstractDictService dictService, @Lazy IAlarmRecordService recordService, @Lazy ITaskHeatMapService taskHeatMapService, IAlgorithmService algorithmService, IRobotCacheService cacheService, @Lazy IBaseRobotService baseRobotService, ITaskInfoImgService imgService, ITaskGridInfoService taskGridInfoService) { this.routeInfoService = routeInfoService; this.statusInfoService = statusInfoService; @@ -130,6 +131,7 @@ log.error(e.getMessage()); } } + protected void sendTaskMsg(InstructStatusMsgEnums enums, String robotId, TaskEndMsg heatMap) { try { WsMsgBaseDTO wsMsgBaseDTO = new WsMsgBaseDTO(); @@ -142,6 +144,7 @@ log.error(e.getMessage()); } } + @Override public List selectTaskInfoPage(Page page, QueryWrapper query) { return this.baseMapper.selectTaskInfoPage(page, query); @@ -212,12 +215,12 @@ RobotInfo robotInfo = cacheService.getRobotInfo(Convert.toLong(robotId)); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_IS_TASK + robotId, isTask); //添加任务记录 - TaskInfo taskInfo = addTaskByStartTrack( robotInfo, request); + TaskInfo taskInfo = addTaskByStartTrack(robotInfo, request); //No.3 更新器人执行任务信息 // Long currRouteId = routeInfo.getId(); Long currTaskId = taskInfo.getId(); - statusInfoService.updateCurrTask(robotId, currTaskId); + statusInfoService.updateCurrTask(robotId, currTaskId); //算法初始化标志创建 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_ID + robotId, currTaskId); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_INIT + robotId, 0); @@ -241,7 +244,7 @@ robotCacheClean(robotId); //清楚规划任务锁 CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_PLANING_FLAG + robotId); - CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID+ robotId); + CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); //清空机器当前任务 statusInfoService.updateCurrTask(robotId, null); } @@ -315,7 +318,7 @@ //No.1 任务初始化 pathInit(longId, robotInfo, pointDTO, taskId, robotId, taskInfo.getStepLen()); //No.2 路线规划 - pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo,dto); + pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo, dto); } /** @@ -340,7 +343,7 @@ * @param taskId 任务ID * @param robotId 机器人ID */ - private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo,PoseMessageResponseDTO curPoint) { + private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo, PoseMessageResponseDTO curPoint) { if (taskId != null) { //规划节点 PointNextDTO pointNextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); @@ -350,11 +353,11 @@ if (!flag) { return; } - log.info("curr point:{}",curPoint); + log.info("curr point:{}", curPoint); log.debug("curr pointGrid:{}", pointDTO); log.debug("oldEstimateGrid:{}", oldEstimateGrid); try { - if (pointNextDTO == null || oldEstimateGrid==null || isEquals(pointDTO, oldEstimateGrid,robotInfo)) { + if (pointNextDTO == null || oldEstimateGrid == null || isEquals(pointDTO, oldEstimateGrid, robotInfo)) { atomicInteger = new AtomicInteger(0); log.info("当前栅格变更......", pointDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_POINT + robotId, pointDTO); @@ -372,7 +375,7 @@ AlgorithmResponse response = algorithmService.pathPlanning(pathPlanDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId, response.getPointNextDTO()); - new Thread(){ + new Thread() { @Override public void run() { //存储循迹任务信息 @@ -400,9 +403,12 @@ //是否触发停止状态 if (!response.isEnd()) { //机器人寻点指令下发 - sendTargetPoint(robotInfo, response,curPoint); + if (robotInfo.getIsOpen() == null || robotInfo.getIsOpen() == 0) { + sendTargetPoint(robotInfo, response, curPoint); + } else { + log.debug("task mode isOpen:{}", robotInfo.getIsOpen()); + } } else { - log.debug("task stop-- robotId:{},taskId:{}", robotId, taskId); //机器人停止指令下发 SoftwareStopRequest request = new SoftwareStopRequest(); request.setRobotId(robotInfo.getId()); @@ -417,8 +423,8 @@ endMsg.setMessage("寻源结束"); sendTaskMsg(InstructStatusMsgEnums.TASK_END, robotId, endMsg); } - }else{ - if(!isChange(pointDTO, oldEstimateGrid)){ + } else { + if (!isChange(pointDTO, oldEstimateGrid)) { atomicInteger.incrementAndGet(); } } @@ -461,20 +467,20 @@ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); Integer height = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId); - if(height==null){ - height=521; + if (height == null) { + throw new ServiceException(500, "未获取到栅格宽度信息"); } - Integer newX = robotInfo.getNewOriginX(); - Integer newY = height-robotInfo.getNewOriginY(); + Integer newX = robotInfo.getNewGridX(); + Integer newY = height - robotInfo.getNewGridY(); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if (i <= newY) { List newList = new ArrayList<>(); - List sourceList= costList.get(i); + List sourceList = costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if (j >= newX) { newList.add(sourceList.get(j)); } } @@ -488,7 +494,7 @@ FileUtil.writeLines(strs2, new File(path + "map2.txt"), "utf-8"); //行转列 为算法输入数据 - if(CollectionUtil.isNotEmpty(newCostList)){ + if (CollectionUtil.isNotEmpty(newCostList)) { CollectionUtil.reverse(newCostList); for (int i = 0; i < newCostList.get(0).size(); i++) { ArrayList ints = new ArrayList<>(); @@ -596,7 +602,7 @@ * @param robotInfo 机器人信息 * @param response 算法输出数据 */ - private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response,PoseMessageResponseDTO curPoint) { + private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response, PoseMessageResponseDTO curPoint) { //读取已设置巡点目标信息 PointNextDTO nextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TARGET_POINT_ID + robotInfo.getId()); //巡点 @@ -610,7 +616,7 @@ request.setZ(curPoint.getZ().toString()); request.setTheta(curPoint.getTheta().toString()); request.setRobotId(robotInfo.getId()); - log.info("下发寻源点位:{}",request); + log.info("下发寻源点位:{}", request); //执行巡点指令 baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); //重设寻点点位 @@ -678,7 +684,7 @@ //读取 Integer index = 1; LambdaQueryWrapper taskGridQuery = new LambdaQueryWrapper<>(); - taskGridQuery.eq(TaskGridInfo::getTaskId,info.getId()); + taskGridQuery.eq(TaskGridInfo::getTaskId, info.getId()); taskGridQuery.orderByAsc(TaskGridInfo::getCreateTime); List taskGridInfos = taskGridInfoService.list(taskGridQuery); if (CollectionUtil.isNotEmpty(taskGridInfos)) { @@ -783,23 +789,24 @@ /** * 栅格判定方法 - * @param pointDTO 当前栅格 + * + * @param pointDTO 当前栅格 * @param oldPointDTO 预期栅格 - * @param robotInfo 机器信息 + * @param robotInfo 机器信息 * @return */ - private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO,RobotInfo robotInfo) { - if(oldPointDTO==null||oldPointDTO.getX()==null){ + private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO, RobotInfo robotInfo) { + if (oldPointDTO == null || oldPointDTO.getX() == null) { return false; } - if(robotInfo.getResolution().compareTo(new BigDecimal(0.21))>0){ + if (robotInfo.getResolution().compareTo(new BigDecimal(0.21)) > 0) { //大于0.2则默认该点 if (pointDTO.getX().compareTo(oldPointDTO.getX()) == 0 && pointDTO.getY().compareTo(oldPointDTO.getY()) == 0) { return true; } - }else{ + } else { //小于0.2则可判定相邻栅格 - if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue()<=1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { + if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue() <= 1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { return true; } @@ -818,7 +825,7 @@ return pathInitDTO; } - private TaskInfo addTaskByStartTrack( RobotInfo robotInfo, StartTrackRequest request) { + private TaskInfo addTaskByStartTrack(RobotInfo robotInfo, StartTrackRequest request) { //No.2 新增任务信息 TaskInfo taskInfo = new TaskInfo(); String currDate = DateUtil.format(new Date(), "yyyyMMdd"); diff --git a/casic-web/src/main/resources/config/application-test.yml b/casic-web/src/main/resources/config/application-test.yml index 534e2fb..67a0241 100644 --- a/casic-web/src/main/resources/config/application-test.yml +++ b/casic-web/src/main/resources/config/application-test.yml @@ -1,30 +1,48 @@ server: - port: 11307 + port: 8083 ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://localhost:3306/casic_template?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/casic_robot_inspection?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root - password: Casic203! - initial-size: 2 - min-idle: 1 - jms: - pub-sub-domain: true -# session: + password: 123456 + druid: + max-active: 50 + min-idle: 20 +jms: + pub-sub-domain: true +# session: # store-type: redis +# redis: +# host: 111.198.10.15 +# port: 11412 +# password: ew5T4K3#203lwh +# serializer: org.springframework.data.redis.serializer.StringRedisSerializer +# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: - # kaptcha-open: false #是否开启登录时验证码 (true/false) - nologin-urls: /user/login,/user/appLogin,/kaptcha/base64,/config/baseConfig,/route/mockToken,/workflow/** + #kaptcha-open: false #是否开启登录时验证码 (true/false) + no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/websocket/*,/webjars/**,/v2/api-docs,/v2/api-docs-ext,/doc.html,/v2/api-docs/swagger-ui.html,/swagger-resources #flowable数据源和多数据源配置 - flowable: - datasource: - url: jdbc:mysql://localhost:3306/template_flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull - username: root - password: Casic203! -flowable: - checkProcessDefinitions: false #不校验process文件 + db: + init: + enable: false + hikSdk: D:\robot\hiklib\HCNetSDK.dll + hikPlay: D:\robot\hiklib\PlayCtrl.dll + algorithm: + path: D:\robot\path\ + initPathName: init.exe + planPathName: search.exe + doc: + temp: D:\robot\path\report.docx + config: + export-path: D:\java\boot\guns-web-1.0.0-SNAPSHOT\export\ + config-path: E:\Develop\IdeaProject\smartcity\casic-smartcity-dcms\casic-web\src\main\resources\config\ logging: level.root: info level.com.casic: debug + level.com.casic.missiles.netty: error + level.com.casic.missiles.modular.neutron: error + level.org.springframework.web: info file: - path: logs/ \ No newline at end of file + path: D:\\robot\\logs \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java index f666126..4fed50c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java @@ -92,6 +92,7 @@ @Value("${casic.obstacle:60}") private Integer obstacle; private volatile AtomicInteger atomicInteger = new AtomicInteger(); + public TaskInfoServiceImpl(@Lazy IRouteInfoService routeInfoService, IRobotStatusInfoService statusInfoService, AbstractDictService dictService, @Lazy IAlarmRecordService recordService, @Lazy ITaskHeatMapService taskHeatMapService, IAlgorithmService algorithmService, IRobotCacheService cacheService, @Lazy IBaseRobotService baseRobotService, ITaskInfoImgService imgService, ITaskGridInfoService taskGridInfoService) { this.routeInfoService = routeInfoService; this.statusInfoService = statusInfoService; @@ -130,6 +131,7 @@ log.error(e.getMessage()); } } + protected void sendTaskMsg(InstructStatusMsgEnums enums, String robotId, TaskEndMsg heatMap) { try { WsMsgBaseDTO wsMsgBaseDTO = new WsMsgBaseDTO(); @@ -142,6 +144,7 @@ log.error(e.getMessage()); } } + @Override public List selectTaskInfoPage(Page page, QueryWrapper query) { return this.baseMapper.selectTaskInfoPage(page, query); @@ -212,12 +215,12 @@ RobotInfo robotInfo = cacheService.getRobotInfo(Convert.toLong(robotId)); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_IS_TASK + robotId, isTask); //添加任务记录 - TaskInfo taskInfo = addTaskByStartTrack( robotInfo, request); + TaskInfo taskInfo = addTaskByStartTrack(robotInfo, request); //No.3 更新器人执行任务信息 // Long currRouteId = routeInfo.getId(); Long currTaskId = taskInfo.getId(); - statusInfoService.updateCurrTask(robotId, currTaskId); + statusInfoService.updateCurrTask(robotId, currTaskId); //算法初始化标志创建 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_ID + robotId, currTaskId); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_INIT + robotId, 0); @@ -241,7 +244,7 @@ robotCacheClean(robotId); //清楚规划任务锁 CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_PLANING_FLAG + robotId); - CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID+ robotId); + CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); //清空机器当前任务 statusInfoService.updateCurrTask(robotId, null); } @@ -315,7 +318,7 @@ //No.1 任务初始化 pathInit(longId, robotInfo, pointDTO, taskId, robotId, taskInfo.getStepLen()); //No.2 路线规划 - pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo,dto); + pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo, dto); } /** @@ -340,7 +343,7 @@ * @param taskId 任务ID * @param robotId 机器人ID */ - private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo,PoseMessageResponseDTO curPoint) { + private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo, PoseMessageResponseDTO curPoint) { if (taskId != null) { //规划节点 PointNextDTO pointNextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); @@ -350,11 +353,11 @@ if (!flag) { return; } - log.info("curr point:{}",curPoint); + log.info("curr point:{}", curPoint); log.debug("curr pointGrid:{}", pointDTO); log.debug("oldEstimateGrid:{}", oldEstimateGrid); try { - if (pointNextDTO == null || oldEstimateGrid==null || isEquals(pointDTO, oldEstimateGrid,robotInfo)) { + if (pointNextDTO == null || oldEstimateGrid == null || isEquals(pointDTO, oldEstimateGrid, robotInfo)) { atomicInteger = new AtomicInteger(0); log.info("当前栅格变更......", pointDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_POINT + robotId, pointDTO); @@ -372,7 +375,7 @@ AlgorithmResponse response = algorithmService.pathPlanning(pathPlanDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId, response.getPointNextDTO()); - new Thread(){ + new Thread() { @Override public void run() { //存储循迹任务信息 @@ -400,9 +403,12 @@ //是否触发停止状态 if (!response.isEnd()) { //机器人寻点指令下发 - sendTargetPoint(robotInfo, response,curPoint); + if (robotInfo.getIsOpen() == null || robotInfo.getIsOpen() == 0) { + sendTargetPoint(robotInfo, response, curPoint); + } else { + log.debug("task mode isOpen:{}", robotInfo.getIsOpen()); + } } else { - log.debug("task stop-- robotId:{},taskId:{}", robotId, taskId); //机器人停止指令下发 SoftwareStopRequest request = new SoftwareStopRequest(); request.setRobotId(robotInfo.getId()); @@ -417,8 +423,8 @@ endMsg.setMessage("寻源结束"); sendTaskMsg(InstructStatusMsgEnums.TASK_END, robotId, endMsg); } - }else{ - if(!isChange(pointDTO, oldEstimateGrid)){ + } else { + if (!isChange(pointDTO, oldEstimateGrid)) { atomicInteger.incrementAndGet(); } } @@ -461,20 +467,20 @@ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); Integer height = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId); - if(height==null){ - height=521; + if (height == null) { + throw new ServiceException(500, "未获取到栅格宽度信息"); } - Integer newX = robotInfo.getNewOriginX(); - Integer newY = height-robotInfo.getNewOriginY(); + Integer newX = robotInfo.getNewGridX(); + Integer newY = height - robotInfo.getNewGridY(); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if (i <= newY) { List newList = new ArrayList<>(); - List sourceList= costList.get(i); + List sourceList = costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if (j >= newX) { newList.add(sourceList.get(j)); } } @@ -488,7 +494,7 @@ FileUtil.writeLines(strs2, new File(path + "map2.txt"), "utf-8"); //行转列 为算法输入数据 - if(CollectionUtil.isNotEmpty(newCostList)){ + if (CollectionUtil.isNotEmpty(newCostList)) { CollectionUtil.reverse(newCostList); for (int i = 0; i < newCostList.get(0).size(); i++) { ArrayList ints = new ArrayList<>(); @@ -596,7 +602,7 @@ * @param robotInfo 机器人信息 * @param response 算法输出数据 */ - private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response,PoseMessageResponseDTO curPoint) { + private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response, PoseMessageResponseDTO curPoint) { //读取已设置巡点目标信息 PointNextDTO nextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TARGET_POINT_ID + robotInfo.getId()); //巡点 @@ -610,7 +616,7 @@ request.setZ(curPoint.getZ().toString()); request.setTheta(curPoint.getTheta().toString()); request.setRobotId(robotInfo.getId()); - log.info("下发寻源点位:{}",request); + log.info("下发寻源点位:{}", request); //执行巡点指令 baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); //重设寻点点位 @@ -678,7 +684,7 @@ //读取 Integer index = 1; LambdaQueryWrapper taskGridQuery = new LambdaQueryWrapper<>(); - taskGridQuery.eq(TaskGridInfo::getTaskId,info.getId()); + taskGridQuery.eq(TaskGridInfo::getTaskId, info.getId()); taskGridQuery.orderByAsc(TaskGridInfo::getCreateTime); List taskGridInfos = taskGridInfoService.list(taskGridQuery); if (CollectionUtil.isNotEmpty(taskGridInfos)) { @@ -783,23 +789,24 @@ /** * 栅格判定方法 - * @param pointDTO 当前栅格 + * + * @param pointDTO 当前栅格 * @param oldPointDTO 预期栅格 - * @param robotInfo 机器信息 + * @param robotInfo 机器信息 * @return */ - private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO,RobotInfo robotInfo) { - if(oldPointDTO==null||oldPointDTO.getX()==null){ + private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO, RobotInfo robotInfo) { + if (oldPointDTO == null || oldPointDTO.getX() == null) { return false; } - if(robotInfo.getResolution().compareTo(new BigDecimal(0.21))>0){ + if (robotInfo.getResolution().compareTo(new BigDecimal(0.21)) > 0) { //大于0.2则默认该点 if (pointDTO.getX().compareTo(oldPointDTO.getX()) == 0 && pointDTO.getY().compareTo(oldPointDTO.getY()) == 0) { return true; } - }else{ + } else { //小于0.2则可判定相邻栅格 - if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue()<=1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { + if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue() <= 1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { return true; } @@ -818,7 +825,7 @@ return pathInitDTO; } - private TaskInfo addTaskByStartTrack( RobotInfo robotInfo, StartTrackRequest request) { + private TaskInfo addTaskByStartTrack(RobotInfo robotInfo, StartTrackRequest request) { //No.2 新增任务信息 TaskInfo taskInfo = new TaskInfo(); String currDate = DateUtil.format(new Date(), "yyyyMMdd"); diff --git a/casic-web/src/main/resources/config/application-test.yml b/casic-web/src/main/resources/config/application-test.yml index 534e2fb..67a0241 100644 --- a/casic-web/src/main/resources/config/application-test.yml +++ b/casic-web/src/main/resources/config/application-test.yml @@ -1,30 +1,48 @@ server: - port: 11307 + port: 8083 ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://localhost:3306/casic_template?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/casic_robot_inspection?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root - password: Casic203! - initial-size: 2 - min-idle: 1 - jms: - pub-sub-domain: true -# session: + password: 123456 + druid: + max-active: 50 + min-idle: 20 +jms: + pub-sub-domain: true +# session: # store-type: redis +# redis: +# host: 111.198.10.15 +# port: 11412 +# password: ew5T4K3#203lwh +# serializer: org.springframework.data.redis.serializer.StringRedisSerializer +# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: - # kaptcha-open: false #是否开启登录时验证码 (true/false) - nologin-urls: /user/login,/user/appLogin,/kaptcha/base64,/config/baseConfig,/route/mockToken,/workflow/** + #kaptcha-open: false #是否开启登录时验证码 (true/false) + no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/websocket/*,/webjars/**,/v2/api-docs,/v2/api-docs-ext,/doc.html,/v2/api-docs/swagger-ui.html,/swagger-resources #flowable数据源和多数据源配置 - flowable: - datasource: - url: jdbc:mysql://localhost:3306/template_flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull - username: root - password: Casic203! -flowable: - checkProcessDefinitions: false #不校验process文件 + db: + init: + enable: false + hikSdk: D:\robot\hiklib\HCNetSDK.dll + hikPlay: D:\robot\hiklib\PlayCtrl.dll + algorithm: + path: D:\robot\path\ + initPathName: init.exe + planPathName: search.exe + doc: + temp: D:\robot\path\report.docx + config: + export-path: D:\java\boot\guns-web-1.0.0-SNAPSHOT\export\ + config-path: E:\Develop\IdeaProject\smartcity\casic-smartcity-dcms\casic-web\src\main\resources\config\ logging: level.root: info level.com.casic: debug + level.com.casic.missiles.netty: error + level.com.casic.missiles.modular.neutron: error + level.org.springframework.web: info file: - path: logs/ \ No newline at end of file + path: D:\\robot\\logs \ No newline at end of file diff --git a/casic-web/src/main/resources/config/path/map.txt b/casic-web/src/main/resources/config/path/map.txt index 5953cbb..f44820b 100644 --- a/casic-web/src/main/resources/config/path/map.txt +++ b/casic-web/src/main/resources/config/path/map.txt @@ -1,110 +1,93 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java index f666126..4fed50c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java @@ -92,6 +92,7 @@ @Value("${casic.obstacle:60}") private Integer obstacle; private volatile AtomicInteger atomicInteger = new AtomicInteger(); + public TaskInfoServiceImpl(@Lazy IRouteInfoService routeInfoService, IRobotStatusInfoService statusInfoService, AbstractDictService dictService, @Lazy IAlarmRecordService recordService, @Lazy ITaskHeatMapService taskHeatMapService, IAlgorithmService algorithmService, IRobotCacheService cacheService, @Lazy IBaseRobotService baseRobotService, ITaskInfoImgService imgService, ITaskGridInfoService taskGridInfoService) { this.routeInfoService = routeInfoService; this.statusInfoService = statusInfoService; @@ -130,6 +131,7 @@ log.error(e.getMessage()); } } + protected void sendTaskMsg(InstructStatusMsgEnums enums, String robotId, TaskEndMsg heatMap) { try { WsMsgBaseDTO wsMsgBaseDTO = new WsMsgBaseDTO(); @@ -142,6 +144,7 @@ log.error(e.getMessage()); } } + @Override public List selectTaskInfoPage(Page page, QueryWrapper query) { return this.baseMapper.selectTaskInfoPage(page, query); @@ -212,12 +215,12 @@ RobotInfo robotInfo = cacheService.getRobotInfo(Convert.toLong(robotId)); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_IS_TASK + robotId, isTask); //添加任务记录 - TaskInfo taskInfo = addTaskByStartTrack( robotInfo, request); + TaskInfo taskInfo = addTaskByStartTrack(robotInfo, request); //No.3 更新器人执行任务信息 // Long currRouteId = routeInfo.getId(); Long currTaskId = taskInfo.getId(); - statusInfoService.updateCurrTask(robotId, currTaskId); + statusInfoService.updateCurrTask(robotId, currTaskId); //算法初始化标志创建 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_ID + robotId, currTaskId); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_INIT + robotId, 0); @@ -241,7 +244,7 @@ robotCacheClean(robotId); //清楚规划任务锁 CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_PLANING_FLAG + robotId); - CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID+ robotId); + CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); //清空机器当前任务 statusInfoService.updateCurrTask(robotId, null); } @@ -315,7 +318,7 @@ //No.1 任务初始化 pathInit(longId, robotInfo, pointDTO, taskId, robotId, taskInfo.getStepLen()); //No.2 路线规划 - pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo,dto); + pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo, dto); } /** @@ -340,7 +343,7 @@ * @param taskId 任务ID * @param robotId 机器人ID */ - private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo,PoseMessageResponseDTO curPoint) { + private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo, PoseMessageResponseDTO curPoint) { if (taskId != null) { //规划节点 PointNextDTO pointNextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); @@ -350,11 +353,11 @@ if (!flag) { return; } - log.info("curr point:{}",curPoint); + log.info("curr point:{}", curPoint); log.debug("curr pointGrid:{}", pointDTO); log.debug("oldEstimateGrid:{}", oldEstimateGrid); try { - if (pointNextDTO == null || oldEstimateGrid==null || isEquals(pointDTO, oldEstimateGrid,robotInfo)) { + if (pointNextDTO == null || oldEstimateGrid == null || isEquals(pointDTO, oldEstimateGrid, robotInfo)) { atomicInteger = new AtomicInteger(0); log.info("当前栅格变更......", pointDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_POINT + robotId, pointDTO); @@ -372,7 +375,7 @@ AlgorithmResponse response = algorithmService.pathPlanning(pathPlanDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId, response.getPointNextDTO()); - new Thread(){ + new Thread() { @Override public void run() { //存储循迹任务信息 @@ -400,9 +403,12 @@ //是否触发停止状态 if (!response.isEnd()) { //机器人寻点指令下发 - sendTargetPoint(robotInfo, response,curPoint); + if (robotInfo.getIsOpen() == null || robotInfo.getIsOpen() == 0) { + sendTargetPoint(robotInfo, response, curPoint); + } else { + log.debug("task mode isOpen:{}", robotInfo.getIsOpen()); + } } else { - log.debug("task stop-- robotId:{},taskId:{}", robotId, taskId); //机器人停止指令下发 SoftwareStopRequest request = new SoftwareStopRequest(); request.setRobotId(robotInfo.getId()); @@ -417,8 +423,8 @@ endMsg.setMessage("寻源结束"); sendTaskMsg(InstructStatusMsgEnums.TASK_END, robotId, endMsg); } - }else{ - if(!isChange(pointDTO, oldEstimateGrid)){ + } else { + if (!isChange(pointDTO, oldEstimateGrid)) { atomicInteger.incrementAndGet(); } } @@ -461,20 +467,20 @@ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); Integer height = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId); - if(height==null){ - height=521; + if (height == null) { + throw new ServiceException(500, "未获取到栅格宽度信息"); } - Integer newX = robotInfo.getNewOriginX(); - Integer newY = height-robotInfo.getNewOriginY(); + Integer newX = robotInfo.getNewGridX(); + Integer newY = height - robotInfo.getNewGridY(); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if (i <= newY) { List newList = new ArrayList<>(); - List sourceList= costList.get(i); + List sourceList = costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if (j >= newX) { newList.add(sourceList.get(j)); } } @@ -488,7 +494,7 @@ FileUtil.writeLines(strs2, new File(path + "map2.txt"), "utf-8"); //行转列 为算法输入数据 - if(CollectionUtil.isNotEmpty(newCostList)){ + if (CollectionUtil.isNotEmpty(newCostList)) { CollectionUtil.reverse(newCostList); for (int i = 0; i < newCostList.get(0).size(); i++) { ArrayList ints = new ArrayList<>(); @@ -596,7 +602,7 @@ * @param robotInfo 机器人信息 * @param response 算法输出数据 */ - private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response,PoseMessageResponseDTO curPoint) { + private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response, PoseMessageResponseDTO curPoint) { //读取已设置巡点目标信息 PointNextDTO nextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TARGET_POINT_ID + robotInfo.getId()); //巡点 @@ -610,7 +616,7 @@ request.setZ(curPoint.getZ().toString()); request.setTheta(curPoint.getTheta().toString()); request.setRobotId(robotInfo.getId()); - log.info("下发寻源点位:{}",request); + log.info("下发寻源点位:{}", request); //执行巡点指令 baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); //重设寻点点位 @@ -678,7 +684,7 @@ //读取 Integer index = 1; LambdaQueryWrapper taskGridQuery = new LambdaQueryWrapper<>(); - taskGridQuery.eq(TaskGridInfo::getTaskId,info.getId()); + taskGridQuery.eq(TaskGridInfo::getTaskId, info.getId()); taskGridQuery.orderByAsc(TaskGridInfo::getCreateTime); List taskGridInfos = taskGridInfoService.list(taskGridQuery); if (CollectionUtil.isNotEmpty(taskGridInfos)) { @@ -783,23 +789,24 @@ /** * 栅格判定方法 - * @param pointDTO 当前栅格 + * + * @param pointDTO 当前栅格 * @param oldPointDTO 预期栅格 - * @param robotInfo 机器信息 + * @param robotInfo 机器信息 * @return */ - private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO,RobotInfo robotInfo) { - if(oldPointDTO==null||oldPointDTO.getX()==null){ + private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO, RobotInfo robotInfo) { + if (oldPointDTO == null || oldPointDTO.getX() == null) { return false; } - if(robotInfo.getResolution().compareTo(new BigDecimal(0.21))>0){ + if (robotInfo.getResolution().compareTo(new BigDecimal(0.21)) > 0) { //大于0.2则默认该点 if (pointDTO.getX().compareTo(oldPointDTO.getX()) == 0 && pointDTO.getY().compareTo(oldPointDTO.getY()) == 0) { return true; } - }else{ + } else { //小于0.2则可判定相邻栅格 - if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue()<=1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { + if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue() <= 1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { return true; } @@ -818,7 +825,7 @@ return pathInitDTO; } - private TaskInfo addTaskByStartTrack( RobotInfo robotInfo, StartTrackRequest request) { + private TaskInfo addTaskByStartTrack(RobotInfo robotInfo, StartTrackRequest request) { //No.2 新增任务信息 TaskInfo taskInfo = new TaskInfo(); String currDate = DateUtil.format(new Date(), "yyyyMMdd"); diff --git a/casic-web/src/main/resources/config/application-test.yml b/casic-web/src/main/resources/config/application-test.yml index 534e2fb..67a0241 100644 --- a/casic-web/src/main/resources/config/application-test.yml +++ b/casic-web/src/main/resources/config/application-test.yml @@ -1,30 +1,48 @@ server: - port: 11307 + port: 8083 ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://localhost:3306/casic_template?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/casic_robot_inspection?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root - password: Casic203! - initial-size: 2 - min-idle: 1 - jms: - pub-sub-domain: true -# session: + password: 123456 + druid: + max-active: 50 + min-idle: 20 +jms: + pub-sub-domain: true +# session: # store-type: redis +# redis: +# host: 111.198.10.15 +# port: 11412 +# password: ew5T4K3#203lwh +# serializer: org.springframework.data.redis.serializer.StringRedisSerializer +# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: - # kaptcha-open: false #是否开启登录时验证码 (true/false) - nologin-urls: /user/login,/user/appLogin,/kaptcha/base64,/config/baseConfig,/route/mockToken,/workflow/** + #kaptcha-open: false #是否开启登录时验证码 (true/false) + no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/websocket/*,/webjars/**,/v2/api-docs,/v2/api-docs-ext,/doc.html,/v2/api-docs/swagger-ui.html,/swagger-resources #flowable数据源和多数据源配置 - flowable: - datasource: - url: jdbc:mysql://localhost:3306/template_flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull - username: root - password: Casic203! -flowable: - checkProcessDefinitions: false #不校验process文件 + db: + init: + enable: false + hikSdk: D:\robot\hiklib\HCNetSDK.dll + hikPlay: D:\robot\hiklib\PlayCtrl.dll + algorithm: + path: D:\robot\path\ + initPathName: init.exe + planPathName: search.exe + doc: + temp: D:\robot\path\report.docx + config: + export-path: D:\java\boot\guns-web-1.0.0-SNAPSHOT\export\ + config-path: E:\Develop\IdeaProject\smartcity\casic-smartcity-dcms\casic-web\src\main\resources\config\ logging: level.root: info level.com.casic: debug + level.com.casic.missiles.netty: error + level.com.casic.missiles.modular.neutron: error + level.org.springframework.web: info file: - path: logs/ \ No newline at end of file + path: D:\\robot\\logs \ No newline at end of file diff --git a/casic-web/src/main/resources/config/path/map.txt b/casic-web/src/main/resources/config/path/map.txt index 5953cbb..f44820b 100644 --- a/casic-web/src/main/resources/config/path/map.txt +++ b/casic-web/src/main/resources/config/path/map.txt @@ -1,110 +1,93 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/casic-web/src/main/resources/config/path/map2.txt b/casic-web/src/main/resources/config/path/map2.txt index c87c7ea..13dc54c 100644 --- a/casic-web/src/main/resources/config/path/map2.txt +++ b/casic-web/src/main/resources/config/path/map2.txt @@ -1,82 +1,116 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java index 92c8c8e..6e94193 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/IBaseRobotService.java @@ -5,10 +5,7 @@ import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelRequest; -import com.casic.missiles.modular.robot.opt.instruct.dto.AppCmdVelResponse; -import com.casic.missiles.modular.robot.opt.instruct.dto.BaseRobotCmdDTO; -import com.casic.missiles.modular.robot.opt.instruct.dto.StartTrackRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.*; /** * 机器人操作类 @@ -76,4 +73,11 @@ void reloadPcd(RobotInfo info); void startTrack(StartTrackRequest request); + + /** + * 栅格寻点指令 + * @param request 请求 + * @return + */ + ResponseDataDTO targetGrid(TargetPointRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java index 6cc1c58..3faa8f3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/controller/RobotOptController.java @@ -26,7 +26,6 @@ import io.swagger.annotations.ApiParam; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Param; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -79,6 +78,7 @@ /** * /{robotId} + * * @param file * @param robotId * @return @@ -116,7 +116,12 @@ robotInfoService.updateSpeed(robotInfo); return ResponseDataDTO.success(); } - + @ApiOperation(value = "设置任务启动模式", notes = "返回 1成功 0失败") + @PostMapping(value = "/setTaskMode") + public ResponseDataDTO setTaskMode(@RequestBody TaskModeRequest request) { + robotInfoService.setTaskMode(request); + return ResponseDataDTO.success(); + } @ApiOperation(value = "机器人数据更新", notes = "1.pcd重载 2.路线及关键点数据重载") @PostMapping(value = "/reload") public ResponseDataDTO reload(@RequestBody BaseRobotCmdDTO request) { @@ -156,6 +161,8 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.TRACK_RECORD); } + + /** * 机器人请求id * @@ -168,6 +175,16 @@ return baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); } + @ApiOperation(value = "寻栅格指令", notes = "") + @PostMapping(value = "/targetGrid") + public ResponseDataDTO targetGrid(@RequestBody TargetGridRequest request) { + TargetPointRequest targetPointRequest = new TargetPointRequest(); + targetPointRequest.setRobotId(request.getRobotId()); + targetPointRequest.setX(request.getEstimateGridX()); + targetPointRequest.setY(request.getEstimateGridY()); + return baseRobotService.targetGrid(targetPointRequest); + } + /** * 机器人请求id * diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java new file mode 100644 index 0000000..709bcd3 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/GridDTO.java @@ -0,0 +1,23 @@ +package com.casic.missiles.modular.robot.dto; + +import lombok.Data; + +@Data +public class GridDTO { + /** + * 当前栅格x + */ + private Integer currGridX; + /** + * 当前栅格y + */ + private Integer currGridY; + /** + * 规划栅格x + */ + private Integer estimateGridX; + /** + * 规划栅格y + */ + private Integer estimateGridY; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java index acbeb93..b9ad7a3 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/dto/RobotInfoSetDTO.java @@ -23,4 +23,8 @@ private BigDecimal gridWidth; @ApiModelProperty(value = "栅格分辨率", dataType = "BigDecimal") private BigDecimal resolution; + @ApiModelProperty(value = "新设原点X", dataType = "BigDecimal") + private BigDecimal newX; + @ApiModelProperty(value = "新设原点Y", dataType = "BigDecimal") + private BigDecimal newY; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java index 2cd7683..d5ae18a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/model/RobotInfo.java @@ -155,16 +155,45 @@ @TableField("resolution") private BigDecimal resolution; /** - * 设定栅格X + * 新设定栅格原点X */ @TableField("new_origin_x") - private Integer newOriginX; + private BigDecimal newOriginX; /** - * 设定栅格Y + * 新设定栅格原点Y */ @TableField("new_origin_y") - private Integer newOriginY; + private BigDecimal newOriginY; + /** + * 新设定栅格X + */ + @TableField("new_grid_x") + private Integer newGridX; + /** + * 新设定栅格Y + */ + @TableField("new_grid_y") + private Integer newGridY; + + /** + * 裁剪右顶点X + */ + @TableField("right_grid_x") + private Integer rightGridX; + @TableField("is_open") + private Integer isOpen; + /** + * 裁剪右顶点Y + */ + @TableField("right_grid_y") + private Integer rightGridY; + public BigDecimal getNewX(){ + return newOriginX; + } + public BigDecimal getNewY(){ + return newOriginY; + } @Override public String toString() { return "RobotInfo{" diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java index 7940a24..40a60a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/impl/RobotOptServiceImpl.java @@ -1,9 +1,13 @@ package com.casic.missiles.modular.robot.opt.impl; import cn.hutool.core.util.StrUtil; +import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.core.util.SpringContextHolder; +import com.casic.missiles.model.exception.ServiceException; import com.casic.missiles.model.response.dto.ResponseDataDTO; +import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.IBaseRobotService; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; import com.casic.missiles.modular.robot.opt.IRobotRouteOptService; @@ -11,6 +15,7 @@ import com.casic.missiles.modular.robot.opt.handler.IBaseCmdHandler; import com.casic.missiles.modular.robot.opt.instruct.base.dto.MessageRequestDTO; import com.casic.missiles.modular.robot.opt.instruct.dto.*; +import com.casic.missiles.modular.robot.service.IAlgorithmService; import com.casic.missiles.modular.robot.service.IRobotInfoService; import com.casic.missiles.modular.robot.service.ITaskInfoService; import com.casic.missiles.mqtt.config.MqttClientConnection; @@ -32,11 +37,13 @@ private final IRobotRouteOptService robotRouteOptService; private final IRobotInfoService robotInfoService; private final ITaskInfoService taskInfoService; + private final IAlgorithmService algorithmService; - public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService) { + public RobotOptServiceImpl(IRobotRouteOptService robotRouteOptService, @Lazy IRobotInfoService robotInfoService, ITaskInfoService taskInfoService, @Lazy IAlgorithmService algorithmService) { this.robotRouteOptService = robotRouteOptService; this.robotInfoService = robotInfoService; this.taskInfoService = taskInfoService; + this.algorithmService = algorithmService; } /** @@ -117,7 +124,7 @@ //线路关键点读取 if (requestDTO.getData() != null) { for (RouteInfo routeInfo : requestDTO.getData()) { - if("11-1 79-1".equals(routeInfo.getRouteName())){ + if ("11-1 79-1".equals(routeInfo.getRouteName())) { continue; } TrackPointListRequest request = new TrackPointListRequest(); @@ -141,6 +148,7 @@ //机器人pcd读取 robotInfoService.loadPcd(info); } + @Transactional @Override public void startTrack(StartTrackRequest request) { @@ -149,6 +157,25 @@ // this.execCmdHandler(request, InstructCodeEnums.START_TRACK); } + @Override + public ResponseDataDTO targetGrid(TargetPointRequest request) { + PoseMessageResponseDTO responseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.ROBOT_POINT + request.getRobotId()); + if(responseDTO==null){ + throw new ServiceException(500,"请优先开启导航"); + } + RobotInfo robotInfo = robotInfoService.getById(request.getRobotId()); + GridPointDTO gridPointDTO = new GridPointDTO(); + //获取栅格中心点 + GridPointDTO pointDTO = algorithmService.convertGridCenterPoint(gridPointDTO,robotInfo.getResolution(),robotInfo); + request.setX(pointDTO.getX().toString()); + request.setY(pointDTO.getY().toString()); + request.setZ(responseDTO.getZ().toString()); + request.setTheta(responseDTO.getTheta().toString()); + //执行巡点指令 + ResponseDataDTO responseDataDTO = this.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); + return responseDataDTO; + } + public IRobotRouteOptService getRobotRouteOptService() { return robotRouteOptService; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java new file mode 100644 index 0000000..7d69964 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TargetGridRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 获取循迹路线下发指令 + */ +@Data +public class TargetGridRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "栅格x坐标", dataType = "String") + private String estimateGridX; + @ApiModelProperty(value = "栅格y坐标", dataType = "String") + private String estimateGridY; + @ApiModelProperty(value = "z坐标", dataType = "String") + private String z; + @ApiModelProperty(value = "theta", dataType = "String") + private String theta; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java new file mode 100644 index 0000000..763656b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/opt/instruct/dto/TaskModeRequest.java @@ -0,0 +1,13 @@ +package com.casic.missiles.modular.robot.opt.instruct.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 导航下发指令 + */ +@Data +public class TaskModeRequest extends BaseRobotCmdDTO { + @ApiModelProperty(value = "控制模式 1:手动 0:自动", dataType = "String") + private Integer isOpen; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java index 8c95459..89697b8 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/IRobotInfoService.java @@ -6,6 +6,7 @@ import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RouteInfo; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import java.util.List; @@ -52,4 +53,6 @@ * @param dto 栅格信息 */ void updateRobotGrid(String robotId, AppCostmapResponseDTO dto); + + void setTaskMode(TaskModeRequest request); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java index 911eb83..a6f5116 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/AlgorithmServiceImpl.java @@ -169,8 +169,8 @@ pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); //todo 原点栅格转换,减去相对原点值 - pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); return pointDTO; } @@ -183,21 +183,22 @@ */ public GridPointDTO convertGridCenterPoint(GridPointDTO pointDTO, BigDecimal resolution, RobotInfo robotInfo) { - pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewOriginX()))); - pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewOriginY()))); + pointDTO.setX(pointDTO.getX().add(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().add(new BigDecimal(robotInfo.getNewGridY()))); GridPointDTO centerPoint = new GridPointDTO(); BigDecimal scale = resolution; //点位转换 转换后栅格-1 从1开始计算 BigDecimal slamX = (pointDTO.getX().subtract(new BigDecimal(1))).multiply(scale); BigDecimal slamY = (pointDTO.getY().subtract(new BigDecimal(1))).multiply(scale); + //中心栅格点位中心添加 centerPoint.setX(slamX.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); centerPoint.setY(slamY.add(scale.divide(new BigDecimal(2), 10, BigDecimal.ROUND_HALF_UP))); + //加上栅格原点坐标 centerPoint.setX(centerPoint.getX().add(robotInfo.getOriginX())); centerPoint.setY(centerPoint.getY().add(robotInfo.getOriginY())); - return centerPoint; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java index 24fa9f5..cdbbe89 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotInfoServiceImpl.java @@ -12,11 +12,13 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.robot.IBaseRobotService; import com.casic.missiles.modular.robot.dao.RobotInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.dto.RobotInfoSetDTO; import com.casic.missiles.modular.robot.model.*; import com.casic.missiles.modular.robot.opt.enums.InstructCodeEnums; import com.casic.missiles.modular.robot.opt.instruct.dto.CostMapResolutionRequest; import com.casic.missiles.modular.robot.opt.instruct.dto.DataRecordRequest; +import com.casic.missiles.modular.robot.opt.instruct.dto.TaskModeRequest; import com.casic.missiles.modular.robot.opt.instruct.response.AppCostmapResponseDTO; import com.casic.missiles.modular.robot.service.*; import com.casic.missiles.modular.robot.utils.PcdDownUtil; @@ -51,16 +53,18 @@ private final IDeviceInfoService deviceInfoService; private final IRobotPointInfoService pointInfoService; private final IBaseRobotService baseRobotService; + private final IAlgorithmService algorithmService; @Value("${casic.file.uploadPath}") private String filePath; - public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService) { + public RobotInfoServiceImpl(@Lazy IRobotStatusInfoService robotStatusInfoService, AbstractDictService dictService, @Lazy IRouteInfoService routeInfoService, @Lazy IDeviceInfoService deviceInfoService, @Lazy IRobotPointInfoService pointInfoService, @Lazy IBaseRobotService baseRobotService, @Lazy IAlgorithmService algorithmService) { this.robotStatusInfoService = robotStatusInfoService; this.dictService = dictService; this.routeInfoService = routeInfoService; this.deviceInfoService = deviceInfoService; this.pointInfoService = pointInfoService; this.baseRobotService = baseRobotService; + this.algorithmService = algorithmService; } @Transactional @@ -99,13 +103,27 @@ update.set(RobotInfo::getMaxThreshold, robotInfo.getAlarmThreshold()); } if (robotInfo.getGridHeight() != null && robotInfo.getGridWidth() != null) { + RobotInfo oldRobotInfo = getById(robotInfo.getId()); update.set(RobotInfo::getGridHeight, robotInfo.getGridHeight()); update.set(RobotInfo::getGridWidth, robotInfo.getGridWidth()); update.set(RobotInfo::getResolution, robotInfo.getResolution()); + update.set(RobotInfo::getNewOriginX, robotInfo.getNewX()); + update.set(RobotInfo::getNewOriginY, robotInfo.getNewY()); + //计算左下原点 + oldRobotInfo.setNewGridX(0); + oldRobotInfo.setNewGridY(0); + GridPointDTO gridPointDTO = algorithmService.convertSlamToGrid(robotInfo.getNewX(), robotInfo.getNewY(), robotInfo.getResolution(), oldRobotInfo); + update.set(RobotInfo::getNewGridX, gridPointDTO.getX().intValue()); + update.set(RobotInfo::getNewGridY, gridPointDTO.getY().intValue()); + //计算右顶点 + Integer rightX = robotInfo.getGridWidth().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + Integer rightY = robotInfo.getGridHeight().divide(robotInfo.getResolution(), 0, BigDecimal.ROUND_HALF_UP).intValue(); + update.set(RobotInfo::getRightGridX, rightX); + update.set(RobotInfo::getRightGridY, rightY); + //下发障碍物栅格 sendCostMapResolution(robotInfo.getResolution(), robotInfo.getId()); - //重新生成栅格地图 - //sendChangePcd(robotInfo.getId()); + } update.eq(RobotInfo::getId, robotInfo.getId()); update(update); @@ -163,6 +181,16 @@ update(lambdaUpdateWrapper); } + @Override + public void setTaskMode(TaskModeRequest request) { + if (request.getRobotId() != null) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.set(RobotInfo::getIsOpen, request.getIsOpen()); + lambdaUpdateWrapper.eq(RobotInfo::getId, request.getRobotId()); + update(lambdaUpdateWrapper); + } + } + @Transactional @Override public List list(Wrapper queryWrapper) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java index 69ce932..f52940c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotStatusInfoServiceImpl.java @@ -14,6 +14,7 @@ import com.casic.missiles.core.cache.CacheUtil; import com.casic.missiles.modular.constants.RobotDictConstants; import com.casic.missiles.modular.robot.dao.RobotStatusInfoMapper; +import com.casic.missiles.modular.robot.dto.GridPointDTO; import com.casic.missiles.modular.robot.model.RobotInfo; import com.casic.missiles.modular.robot.model.RobotStatusInfo; import com.casic.missiles.modular.robot.opt.instruct.base.dto.RobotMsgDTO; @@ -80,6 +81,7 @@ } private void wrapInfo(RobotStatusInfo statusInfo) { + // todo 报错 StopStateResponseDTO stopStateResponseDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.STOP_STATE + statusInfo.getRobotId()); if (stopStateResponseDTO != null) { statusInfo.setSoft(stopStateResponseDTO.getSoft()); @@ -303,28 +305,6 @@ } } - private void toStringAry(RobotResponseDTO responseDTO) { - int index = 0; - List> lists = new ArrayList<>(); - List integers = new ArrayList<>(); - for (Integer datum : responseDTO.getMsg().getData()) { - index++; - if (index >= 34) { - System.out.println(integers); - index = 0; - integers = new ArrayList<>(); - } - if (datum >= 0) { - if (datum < obstacle) { - integers.add(1); - } else { - integers.add(0); - } - - } - } - } - private void writeCache(ArrayList integers, Integer width, Integer height, String robotId) { List> arrays = CollectionUtil.split(integers, width); ArrayList> arrayList = new ArrayList<>(); @@ -334,24 +314,58 @@ } CollectionUtil.reverse(arrayList); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP + robotId, arrayList); + //写入栅格宽度 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId, height); - writeCost(arrayList,width,height); + writeCost(arrayList,width,height,robotId); } - private void writeCost(ArrayList> costList,Integer width, Integer height){ + /** + * slam经纬度转换为栅格 + * + * @param x slam x + * @param y slam y + */ + public GridPointDTO convertSlamToGrid(BigDecimal x, BigDecimal y, BigDecimal resolution, RobotInfo robotInfo) { + GridPointDTO pointDTO = new GridPointDTO(); + BigDecimal scale = resolution; + //减去栅格原点坐标 + x = x.subtract(robotInfo.getOriginX()); + y = y.subtract(robotInfo.getOriginY()); + pointDTO.setX(new BigDecimal(x.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue()+1)); + pointDTO.setY(new BigDecimal(y.divide(scale, 3, BigDecimal.ROUND_HALF_UP).intValue() +1)); + + //todo 原点栅格转换,减去相对原点值 + pointDTO.setX(pointDTO.getX().subtract(new BigDecimal(robotInfo.getNewGridX()))); + pointDTO.setY(pointDTO.getY().subtract(new BigDecimal(robotInfo.getNewGridY()))); + return pointDTO; + } + + private void writeCost(ArrayList> costList,Integer width, Integer height,String robotId){ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); - Integer newX = 60; - Integer newY = height-440; + RobotInfo robotInfo = cacheService.getRobotInfo(Long.valueOf(robotId)); + if(robotInfo==null||robotInfo.getGridWidth()==null||robotInfo.getResolution() ==null){ + log.info("robot gridHeight is not found...."); + return; + } + + //计算左下角位置 + Integer newX = robotInfo.getNewGridX(); + Integer newY = height-robotInfo.getNewGridY(); +// log.info("left point:({},{})",robotInfo.getNewGridX(),robotInfo.getNewGridY()); + //计算右上角位置 + Integer rightX = robotInfo.getRightGridX(); + Integer rightY = height-robotInfo.getRightGridY(); +// log.info("right point:({},{})",rightX,rightY); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if(i<=newY&&i>=rightY){ List newList = new ArrayList<>(); List sourceList= costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if(j>=newX&&j<=rightX){ newList.add(sourceList.get(j)); } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java index f1262a2..cb7aa09 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/RobotTrajectoryInfoServiceImpl.java @@ -69,17 +69,6 @@ } catch (Exception e) { log.error("task error", e); } -// if (routeId != null) { -// RobotTrajectoryInfo info = new RobotTrajectoryInfo(); -// info.setRobotId(Long.valueOf(robotId)); -// info.setCreateTime(new Date()); -// info.setPostionX(dto.getX()); -// info.setPostionY(dto.getY()); -// info.setPostionZ(dto.getZ()); -// info.setTheta(dto.getTheta()); -// save(info); - -// } } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java index f666126..4fed50c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/robot/service/impl/TaskInfoServiceImpl.java @@ -92,6 +92,7 @@ @Value("${casic.obstacle:60}") private Integer obstacle; private volatile AtomicInteger atomicInteger = new AtomicInteger(); + public TaskInfoServiceImpl(@Lazy IRouteInfoService routeInfoService, IRobotStatusInfoService statusInfoService, AbstractDictService dictService, @Lazy IAlarmRecordService recordService, @Lazy ITaskHeatMapService taskHeatMapService, IAlgorithmService algorithmService, IRobotCacheService cacheService, @Lazy IBaseRobotService baseRobotService, ITaskInfoImgService imgService, ITaskGridInfoService taskGridInfoService) { this.routeInfoService = routeInfoService; this.statusInfoService = statusInfoService; @@ -130,6 +131,7 @@ log.error(e.getMessage()); } } + protected void sendTaskMsg(InstructStatusMsgEnums enums, String robotId, TaskEndMsg heatMap) { try { WsMsgBaseDTO wsMsgBaseDTO = new WsMsgBaseDTO(); @@ -142,6 +144,7 @@ log.error(e.getMessage()); } } + @Override public List selectTaskInfoPage(Page page, QueryWrapper query) { return this.baseMapper.selectTaskInfoPage(page, query); @@ -212,12 +215,12 @@ RobotInfo robotInfo = cacheService.getRobotInfo(Convert.toLong(robotId)); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_IS_TASK + robotId, isTask); //添加任务记录 - TaskInfo taskInfo = addTaskByStartTrack( robotInfo, request); + TaskInfo taskInfo = addTaskByStartTrack(robotInfo, request); //No.3 更新器人执行任务信息 // Long currRouteId = routeInfo.getId(); Long currTaskId = taskInfo.getId(); - statusInfoService.updateCurrTask(robotId, currTaskId); + statusInfoService.updateCurrTask(robotId, currTaskId); //算法初始化标志创建 CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_ID + robotId, currTaskId); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TASK_INIT + robotId, 0); @@ -241,7 +244,7 @@ robotCacheClean(robotId); //清楚规划任务锁 CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_PLANING_FLAG + robotId); - CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID+ robotId); + CacheUtil.remove(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); //清空机器当前任务 statusInfoService.updateCurrTask(robotId, null); } @@ -315,7 +318,7 @@ //No.1 任务初始化 pathInit(longId, robotInfo, pointDTO, taskId, robotId, taskInfo.getStepLen()); //No.2 路线规划 - pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo,dto); + pathPlaning(longId, robotInfo, pointDTO, taskId, robotId, taskInfo, dto); } /** @@ -340,7 +343,7 @@ * @param taskId 任务ID * @param robotId 机器人ID */ - private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo,PoseMessageResponseDTO curPoint) { + private void pathPlaning(Long longId, RobotInfo robotInfo, GridPointDTO pointDTO, Long taskId, String robotId, TaskInfo taskInfo, PoseMessageResponseDTO curPoint) { if (taskId != null) { //规划节点 PointNextDTO pointNextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId); @@ -350,11 +353,11 @@ if (!flag) { return; } - log.info("curr point:{}",curPoint); + log.info("curr point:{}", curPoint); log.debug("curr pointGrid:{}", pointDTO); log.debug("oldEstimateGrid:{}", oldEstimateGrid); try { - if (pointNextDTO == null || oldEstimateGrid==null || isEquals(pointDTO, oldEstimateGrid,robotInfo)) { + if (pointNextDTO == null || oldEstimateGrid == null || isEquals(pointDTO, oldEstimateGrid, robotInfo)) { atomicInteger = new AtomicInteger(0); log.info("当前栅格变更......", pointDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_POINT + robotId, pointDTO); @@ -372,7 +375,7 @@ AlgorithmResponse response = algorithmService.pathPlanning(pathPlanDTO); CacheUtil.put(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_ESTIMATE_GRID + robotId, response.getPointNextDTO()); - new Thread(){ + new Thread() { @Override public void run() { //存储循迹任务信息 @@ -400,9 +403,12 @@ //是否触发停止状态 if (!response.isEnd()) { //机器人寻点指令下发 - sendTargetPoint(robotInfo, response,curPoint); + if (robotInfo.getIsOpen() == null || robotInfo.getIsOpen() == 0) { + sendTargetPoint(robotInfo, response, curPoint); + } else { + log.debug("task mode isOpen:{}", robotInfo.getIsOpen()); + } } else { - log.debug("task stop-- robotId:{},taskId:{}", robotId, taskId); //机器人停止指令下发 SoftwareStopRequest request = new SoftwareStopRequest(); request.setRobotId(robotInfo.getId()); @@ -417,8 +423,8 @@ endMsg.setMessage("寻源结束"); sendTaskMsg(InstructStatusMsgEnums.TASK_END, robotId, endMsg); } - }else{ - if(!isChange(pointDTO, oldEstimateGrid)){ + } else { + if (!isChange(pointDTO, oldEstimateGrid)) { atomicInteger.incrementAndGet(); } } @@ -461,20 +467,20 @@ List strs = new ArrayList<>(); List strs2 = new ArrayList<>(); Integer height = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_COST_MAP_HEIGHT + robotId); - if(height==null){ - height=521; + if (height == null) { + throw new ServiceException(500, "未获取到栅格宽度信息"); } - Integer newX = robotInfo.getNewOriginX(); - Integer newY = height-robotInfo.getNewOriginY(); + Integer newX = robotInfo.getNewGridX(); + Integer newY = height - robotInfo.getNewGridY(); //裁剪栅格 List> newCostList = new ArrayList<>(); for (int i = 0; i < costList.size(); i++) { - if(i<=newY){ + if (i <= newY) { List newList = new ArrayList<>(); - List sourceList= costList.get(i); + List sourceList = costList.get(i); for (int j = 0; j < sourceList.size(); j++) { - if(j>=newX){ + if (j >= newX) { newList.add(sourceList.get(j)); } } @@ -488,7 +494,7 @@ FileUtil.writeLines(strs2, new File(path + "map2.txt"), "utf-8"); //行转列 为算法输入数据 - if(CollectionUtil.isNotEmpty(newCostList)){ + if (CollectionUtil.isNotEmpty(newCostList)) { CollectionUtil.reverse(newCostList); for (int i = 0; i < newCostList.get(0).size(); i++) { ArrayList ints = new ArrayList<>(); @@ -596,7 +602,7 @@ * @param robotInfo 机器人信息 * @param response 算法输出数据 */ - private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response,PoseMessageResponseDTO curPoint) { + private void sendTargetPoint(RobotInfo robotInfo, AlgorithmResponse response, PoseMessageResponseDTO curPoint) { //读取已设置巡点目标信息 PointNextDTO nextDTO = CacheUtil.get(RobotDictConstants.CACHE_SCHEMA, RobotDictConstants.KEY_CUR_TARGET_POINT_ID + robotInfo.getId()); //巡点 @@ -610,7 +616,7 @@ request.setZ(curPoint.getZ().toString()); request.setTheta(curPoint.getTheta().toString()); request.setRobotId(robotInfo.getId()); - log.info("下发寻源点位:{}",request); + log.info("下发寻源点位:{}", request); //执行巡点指令 baseRobotService.execCmdHandler(request, InstructCodeEnums.SET_TARGETPOINT); //重设寻点点位 @@ -678,7 +684,7 @@ //读取 Integer index = 1; LambdaQueryWrapper taskGridQuery = new LambdaQueryWrapper<>(); - taskGridQuery.eq(TaskGridInfo::getTaskId,info.getId()); + taskGridQuery.eq(TaskGridInfo::getTaskId, info.getId()); taskGridQuery.orderByAsc(TaskGridInfo::getCreateTime); List taskGridInfos = taskGridInfoService.list(taskGridQuery); if (CollectionUtil.isNotEmpty(taskGridInfos)) { @@ -783,23 +789,24 @@ /** * 栅格判定方法 - * @param pointDTO 当前栅格 + * + * @param pointDTO 当前栅格 * @param oldPointDTO 预期栅格 - * @param robotInfo 机器信息 + * @param robotInfo 机器信息 * @return */ - private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO,RobotInfo robotInfo) { - if(oldPointDTO==null||oldPointDTO.getX()==null){ + private boolean isEquals(GridPointDTO pointDTO, GridPointDTO oldPointDTO, RobotInfo robotInfo) { + if (oldPointDTO == null || oldPointDTO.getX() == null) { return false; } - if(robotInfo.getResolution().compareTo(new BigDecimal(0.21))>0){ + if (robotInfo.getResolution().compareTo(new BigDecimal(0.21)) > 0) { //大于0.2则默认该点 if (pointDTO.getX().compareTo(oldPointDTO.getX()) == 0 && pointDTO.getY().compareTo(oldPointDTO.getY()) == 0) { return true; } - }else{ + } else { //小于0.2则可判定相邻栅格 - if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue()<=1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { + if (pointDTO.getX().subtract(oldPointDTO.getX()).abs().intValue() <= 1 && pointDTO.getY().subtract(oldPointDTO.getY()).abs().intValue() <= 1) { return true; } @@ -818,7 +825,7 @@ return pathInitDTO; } - private TaskInfo addTaskByStartTrack( RobotInfo robotInfo, StartTrackRequest request) { + private TaskInfo addTaskByStartTrack(RobotInfo robotInfo, StartTrackRequest request) { //No.2 新增任务信息 TaskInfo taskInfo = new TaskInfo(); String currDate = DateUtil.format(new Date(), "yyyyMMdd"); diff --git a/casic-web/src/main/resources/config/application-test.yml b/casic-web/src/main/resources/config/application-test.yml index 534e2fb..67a0241 100644 --- a/casic-web/src/main/resources/config/application-test.yml +++ b/casic-web/src/main/resources/config/application-test.yml @@ -1,30 +1,48 @@ server: - port: 11307 + port: 8083 ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://localhost:3306/casic_template?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/casic_robot_inspection?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root - password: Casic203! - initial-size: 2 - min-idle: 1 - jms: - pub-sub-domain: true -# session: + password: 123456 + druid: + max-active: 50 + min-idle: 20 +jms: + pub-sub-domain: true +# session: # store-type: redis +# redis: +# host: 111.198.10.15 +# port: 11412 +# password: ew5T4K3#203lwh +# serializer: org.springframework.data.redis.serializer.StringRedisSerializer +# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: - # kaptcha-open: false #是否开启登录时验证码 (true/false) - nologin-urls: /user/login,/user/appLogin,/kaptcha/base64,/config/baseConfig,/route/mockToken,/workflow/** + #kaptcha-open: false #是否开启登录时验证码 (true/false) + no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/websocket/*,/webjars/**,/v2/api-docs,/v2/api-docs-ext,/doc.html,/v2/api-docs/swagger-ui.html,/swagger-resources #flowable数据源和多数据源配置 - flowable: - datasource: - url: jdbc:mysql://localhost:3306/template_flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull - username: root - password: Casic203! -flowable: - checkProcessDefinitions: false #不校验process文件 + db: + init: + enable: false + hikSdk: D:\robot\hiklib\HCNetSDK.dll + hikPlay: D:\robot\hiklib\PlayCtrl.dll + algorithm: + path: D:\robot\path\ + initPathName: init.exe + planPathName: search.exe + doc: + temp: D:\robot\path\report.docx + config: + export-path: D:\java\boot\guns-web-1.0.0-SNAPSHOT\export\ + config-path: E:\Develop\IdeaProject\smartcity\casic-smartcity-dcms\casic-web\src\main\resources\config\ logging: level.root: info level.com.casic: debug + level.com.casic.missiles.netty: error + level.com.casic.missiles.modular.neutron: error + level.org.springframework.web: info file: - path: logs/ \ No newline at end of file + path: D:\\robot\\logs \ No newline at end of file diff --git a/casic-web/src/main/resources/config/path/map.txt b/casic-web/src/main/resources/config/path/map.txt index 5953cbb..f44820b 100644 --- a/casic-web/src/main/resources/config/path/map.txt +++ b/casic-web/src/main/resources/config/path/map.txt @@ -1,110 +1,93 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/casic-web/src/main/resources/config/path/map2.txt b/casic-web/src/main/resources/config/path/map2.txt index c87c7ea..13dc54c 100644 --- a/casic-web/src/main/resources/config/path/map2.txt +++ b/casic-web/src/main/resources/config/path/map2.txt @@ -1,82 +1,116 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 diff --git a/casic-web/src/main/resources/config/path/map3.txt b/casic-web/src/main/resources/config/path/map3.txt index f2f3f61..424cf89 100644 --- a/casic-web/src/main/resources/config/path/map3.txt +++ b/casic-web/src/main/resources/config/path/map3.txt @@ -1,110 +1,46 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 -0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 +1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0