7. 实现微服务:Bot代码的执行

master
barney 2 years ago
parent 86c976584f
commit 998b9ee6aa
  1. 1
      backendCloud/backend/src/main/java/com/kob/backend/config/SecurityConfig.java
  2. 26
      backendCloud/backend/src/main/java/com/kob/backend/consumer/WebSocketServer.java
  3. 62
      backendCloud/backend/src/main/java/com/kob/backend/consumer/utils/Game.java
  4. 7
      backendCloud/backend/src/main/java/com/kob/backend/consumer/utils/Player.java
  5. 25
      backendCloud/backend/src/main/java/com/kob/backend/controller/pk/ReceiveBotController.java
  6. 4
      backendCloud/backend/src/main/java/com/kob/backend/controller/pk/StartGameController.java
  7. 25
      backendCloud/backend/src/main/java/com/kob/backend/controller/service/impl/pk/ReceiveBotMoveServiceImpl.java
  8. 6
      backendCloud/backend/src/main/java/com/kob/backend/controller/service/impl/pk/StartGameServiceImpl.java
  9. 5
      backendCloud/backend/src/main/java/com/kob/backend/controller/service/pk/ReceiveBotMoveService.java
  10. 2
      backendCloud/backend/src/main/java/com/kob/backend/controller/service/pk/StartGameService.java
  11. 42
      backendCloud/botRunningSystem/pom.xml
  12. 14
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/BotRunningSystemApplication.java
  13. 24
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Controller/BotRunningController.java
  14. 7
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Service/BotRunningService.java
  15. 16
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Service/impl/BotRunningServiceImpl.java
  16. 14
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Service/impl/utils/Bot.java
  17. 48
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Service/impl/utils/BotPool.java
  18. 64
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/Service/impl/utils/Consumer.java
  19. 13
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/config/RestTemplateConfig.java
  20. 30
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/config/SecurityConfig.java
  21. 80
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/utils/Bot.java
  22. 5
      backendCloud/botRunningSystem/src/main/java/com/kob/botRunningSystem/utils/BotInterface.java
  23. 1
      backendCloud/botRunningSystem/src/main/resources/application.properties
  24. 3
      backendCloud/matchingsystem/src/main/java/com/kob/matchingsystem/controller/MatchingController.java
  25. 2
      backendCloud/matchingsystem/src/main/java/com/kob/matchingsystem/service/MatchingService.java
  26. 6
      backendCloud/matchingsystem/src/main/java/com/kob/matchingsystem/service/impl/MatchingServiceImpl.java
  27. 6
      backendCloud/matchingsystem/src/main/java/com/kob/matchingsystem/service/impl/utils/MatchingPool.java
  28. 2
      backendCloud/matchingsystem/src/main/java/com/kob/matchingsystem/service/impl/utils/Player.java
  29. 1
      backendCloud/pom.xml
  30. 50
      web/src/components/MatchGround.vue
  31. 4
      web/src/components/ResultBoard.vue
  32. 22
      web/src/components/UserInfo.vue
  33. 14
      web/src/views/pk/PkIndexView.vue

@ -45,6 +45,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.authorizeRequests() .authorizeRequests()
.antMatchers("/user/account/token/", "/user/account/register/").permitAll() .antMatchers("/user/account/token/", "/user/account/register/").permitAll()
.antMatchers("/pk/start/game/").hasIpAddress("127.0.0.1") .antMatchers("/pk/start/game/").hasIpAddress("127.0.0.1")
.antMatchers("/pk/receive/bot/move/").hasIpAddress("127.0.0.1")
.antMatchers(HttpMethod.OPTIONS).permitAll() .antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated(); .anyRequest().authenticated();

@ -3,7 +3,9 @@ package com.kob.backend.consumer;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.kob.backend.consumer.utils.Game; import com.kob.backend.consumer.utils.Game;
import com.kob.backend.consumer.utils.JwtAuthentication; import com.kob.backend.consumer.utils.JwtAuthentication;
import com.kob.backend.controller.pojo.Bot;
import com.kob.backend.controller.pojo.User; import com.kob.backend.controller.pojo.User;
import com.kob.backend.mapper.BotMapper;
import com.kob.backend.mapper.RecordMapper; import com.kob.backend.mapper.RecordMapper;
import com.kob.backend.mapper.UserMapper; import com.kob.backend.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -34,15 +36,17 @@ public class WebSocketServer {
// 发起请求链接对应的用户 // 发起请求链接对应的用户
private User user; private User user;
private Session session = null; private Session session = null;
private Game game = null; public Game game = null;
// 注入userMapper(和之前的有点不一样) // 注入userMapper(和之前的有点不一样)
private static UserMapper userMapper; private static UserMapper userMapper;
// 注入RecordMapper // 注入RecordMapper
public static RecordMapper recordMapper; public static RecordMapper recordMapper;
// 注入BotMapper
private static BotMapper botMapper;
// 注入RestTemplate // 注入RestTemplate
private static RestTemplate restTemplate; // 可以作用于两个springboot进程间的通信 public static RestTemplate restTemplate; // 可以作用于两个springboot进程间的通信
private static final String addPlayerUrl = "http://127.0.0.1:3001/player/add/"; private static final String addPlayerUrl = "http://127.0.0.1:3001/player/add/";
private static final String removePlayerUrl = "http://127.0.0.1:3001/player/remove/"; private static final String removePlayerUrl = "http://127.0.0.1:3001/player/remove/";
@ -63,6 +67,10 @@ public class WebSocketServer {
WebSocketServer.restTemplate = restTemplate; WebSocketServer.restTemplate = restTemplate;
} }
@Autowired
private void setBotMapper(BotMapper botMapper) {
WebSocketServer.botMapper = botMapper;
}
@OnOpen @OnOpen
public void onOpen(Session session, @PathParam("token") String token) throws IOException { public void onOpen(Session session, @PathParam("token") String token) throws IOException {
// 建立连接 // 建立连接
@ -91,10 +99,11 @@ public class WebSocketServer {
users.remove(this.user.getId()); users.remove(this.user.getId());
} }
} }
public static void startGame(Integer aId, Integer bId) { public static void startGame(Integer aId, Integer a_bot_id,Integer bId,Integer b_bot_id) {
User a = userMapper.selectById(aId),b = userMapper.selectById(bId); User a = userMapper.selectById(aId),b = userMapper.selectById(bId);
Bot bot_a = botMapper.selectById(a_bot_id),bot_b = botMapper.selectById(b_bot_id);
Game game = new Game(13,14,20,a.getId(),b.getId()); Game game = new Game(13,14,20,a.getId(),b.getId(),bot_a,bot_b);
game.createMap(); game.createMap();
if (users.get(a.getId()) != null) if (users.get(a.getId()) != null)
users.get(a.getId()).game = game; users.get(a.getId()).game = game;
@ -134,13 +143,14 @@ public class WebSocketServer {
} }
private void startMatching() { private void startMatching(Integer botId) {
System.out.println("start-----matching----"); System.out.println("start-----matching----");
MultiValueMap<String,String> data = new LinkedMultiValueMap<>(); MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
// 请求参数 // 请求参数
data.add("user_id",this.user.getId().toString()); data.add("user_id",this.user.getId().toString());
data.add("rating",this.user.getRating().toString()); data.add("rating",this.user.getRating().toString());
data.add("bot_id",botId.toString());
// 向后端发送请求,添加一个用户 // 向后端发送请求,添加一个用户
restTemplate.postForObject(addPlayerUrl,data,String.class); restTemplate.postForObject(addPlayerUrl,data,String.class);
@ -157,11 +167,15 @@ public class WebSocketServer {
private void move(int direction) { private void move(int direction) {
if (game.getPlayerA().getId().equals(user.getId())) { if (game.getPlayerA().getId().equals(user.getId())) {
if (game.getPlayerA().getBotId().equals(-1)) { // 如果是用户出战
game.setNextStepA(direction); game.setNextStepA(direction);
}
}else if (game.getPlayerB().getId().equals(user.getId())) { }else if (game.getPlayerB().getId().equals(user.getId())) {
if (game.getPlayerB().getBotId().equals(-1)) { // 如果是用户出战
game.setNextStepB(direction); game.setNextStepB(direction);
} }
} }
}
@OnMessage @OnMessage
public void onMessage(String message, Session session) { public void onMessage(String message, Session session) {
@ -171,7 +185,7 @@ public class WebSocketServer {
String event = data.getString("event"); String event = data.getString("event");
if ("start-matching".equals(event)) { if ("start-matching".equals(event)) {
startMatching(); startMatching(data.getInteger("bot_id"));
} }
else if ("stop-matching".equals(event)){ else if ("stop-matching".equals(event)){
stopMatching(); stopMatching();

@ -2,7 +2,10 @@ package com.kob.backend.consumer.utils;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.kob.backend.consumer.WebSocketServer; import com.kob.backend.consumer.WebSocketServer;
import com.kob.backend.controller.pojo.Bot;
import com.kob.backend.controller.pojo.Record; import com.kob.backend.controller.pojo.Record;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -20,7 +23,6 @@ public class Game extends Thread {
private final int[][] g; private final int[][] g;
private final Player playerA, playerB; private final Player playerA, playerB;
private final static int[] dx = {-1, 0, 1, 0}; private final static int[] dx = {-1, 0, 1, 0};
private final static int[] dy = {0, 1, 0, -1}; private final static int[] dy = {0, 1, 0, -1};
@ -31,13 +33,27 @@ public class Game extends Thread {
private String status = "playing"; // playing -> finished private String status = "playing"; // playing -> finished
private String loser = "";// "all": 平局 "A": A输 "B": B输 private String loser = "";// "all": 平局 "A": A输 "B": B输
public Game(Integer rows, Integer cols, Integer inner_walls_count, Integer idA, Integer idB) { private final static String addBotUrl = "http://127.0.0.1:3002/bot/add/";
public Game(Integer rows, Integer cols, Integer inner_walls_count, Integer idA, Integer idB, Bot bot_a,Bot bot_b) {
this.rows = rows; this.rows = rows;
this.cols = cols; this.cols = cols;
this.inner_walls_count = inner_walls_count; this.inner_walls_count = inner_walls_count;
this.g = new int[rows][cols]; this.g = new int[rows][cols];
this.playerA = new Player(idA, rows - 2, 1, new ArrayList<>()); Integer bot_a_id = -1,bot_b_id = -1;
this.playerB = new Player(idB, 1, cols - 2, new ArrayList<>()); String bot_a_code = "",bot_b_code = "";
if (bot_a != null) {
bot_a_id = bot_a.getId();
bot_a_code = bot_a.getContent();
}
if (bot_b != null) {
bot_b_id = bot_b.getId();
bot_b_code = bot_b.getContent();
}
this.playerA = new Player(idA, bot_a_id,bot_a_code,rows - 2, 1, new ArrayList<>());
this.playerB = new Player(idB,bot_b_id,bot_b_code, 1, cols - 2, new ArrayList<>());
} }
public int[][] getG() { public int[][] getG() {
@ -141,6 +157,39 @@ public class Game extends Thread {
} }
} }
private String getInput(Player player) {
Player me,you;
if (playerA.getId().equals(player.getId())) {
me = playerA;
you = playerB;
}else {
me = playerB;
you = playerA;
}
return getMapString() + "#" +
me.getSx() + "#" +
me.getSy() + "#(" +
me.getStepsString() + ")#" +
you.getSx() + "#" +
you.getSy() + "#(" +
you.getStepsString() + ")";
}
// 是否需要使用bot代码
private void sendBotCode(Player player) {
if (player.getBotId().equals(-1)) { // 用户出战直接返回
return;
}
MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.add("user_id",player.getId().toString());
data.add("bot_code",player.getBotCode());
data.add("input",getInput(player));
// 向BotRunningSystem发送信息
WebSocketServer.restTemplate.postForObject(addBotUrl,data,String.class);
}
public boolean nextStep() { public boolean nextStep() {
try { try {
// 保证前端不会遗漏操作,前端是每200ms移动一个格子 // 保证前端不会遗漏操作,前端是每200ms移动一个格子
@ -148,6 +197,11 @@ public class Game extends Thread {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
sendBotCode(playerA);
sendBotCode(playerB);
// 10s倒计时操作,10s内没有输入判输 // 10s倒计时操作,10s内没有输入判输
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
try { try {

@ -16,12 +16,19 @@ import java.util.List;
public class Player{ public class Player{
// 玩家id // 玩家id
private Integer id; private Integer id;
private Integer botId; // -1表示用户对局,其他表示bot对局
private String botCode; // bot执行的代码
// 玩家的起始坐标(x,y) // 玩家的起始坐标(x,y)
private Integer sx; private Integer sx;
private Integer sy; private Integer sy;
// 所有历史指令 // 所有历史指令
private List<Integer> steps; private List<Integer> steps;
private boolean check_tail_increasing(int steps) { private boolean check_tail_increasing(int steps) {
if (steps <= 10) { if (steps <= 10) {
return true; return true;

@ -0,0 +1,25 @@
package com.kob.backend.controller.pk;
import com.kob.backend.controller.service.pk.ReceiveBotMoveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Objects;
@RestController
public class ReceiveBotController {
@Autowired
private ReceiveBotMoveService receiveBotMoveService;
@PostMapping("/pk/receive/bot/move/")
public String receiveBotMove(@RequestParam MultiValueMap<String,String> data){
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
Integer direction = Integer.parseInt(Objects.requireNonNull(data.getFirst("direction")));
return receiveBotMoveService.receiveBotMove(userId,direction);
}
}

@ -18,8 +18,10 @@ public class StartGameController {
public String startGame(@RequestParam MultiValueMap<String,String> data) { public String startGame(@RequestParam MultiValueMap<String,String> data) {
Integer aId = Integer.parseInt(Objects.requireNonNull(data.getFirst("a_id"))); Integer aId = Integer.parseInt(Objects.requireNonNull(data.getFirst("a_id")));
Integer a_bot_id = Integer.parseInt(Objects.requireNonNull(data.getFirst("a_bot_id")));
Integer bId = Integer.parseInt(Objects.requireNonNull(data.getFirst("b_id"))); Integer bId = Integer.parseInt(Objects.requireNonNull(data.getFirst("b_id")));
return startGameService.startGame(aId,bId); Integer b_bot_id = Integer.parseInt(Objects.requireNonNull(data.getFirst("b_bot_id")));
return startGameService.startGame(aId,a_bot_id,bId,b_bot_id);
} }

@ -0,0 +1,25 @@
package com.kob.backend.controller.service.impl.pk;
import com.kob.backend.consumer.WebSocketServer;
import com.kob.backend.consumer.utils.Game;
import com.kob.backend.controller.service.pk.ReceiveBotMoveService;
import org.springframework.stereotype.Service;
@Service
public class ReceiveBotMoveServiceImpl implements ReceiveBotMoveService {
@Override
public String receiveBotMove(Integer userId, Integer direction) {
System.out.println("receive bot move: " + userId + " " + direction);
if (WebSocketServer.users.get(userId) != null) {
Game game = WebSocketServer.users.get(userId).game;
if (game != null) {
if (game.getPlayerA().getId().equals(userId)) {
game.setNextStepA(direction);
} else if (game.getPlayerB().getId().equals(userId)) {
game.setNextStepB(direction);
}
}
}
return "receive bot move success";
}
}

@ -7,9 +7,9 @@ import org.springframework.stereotype.Service;
@Service @Service
public class StartGameServiceImpl implements StartGameService { public class StartGameServiceImpl implements StartGameService {
@Override @Override
public String startGame(Integer aId, Integer bId) { public String startGame(Integer aId, Integer a_bot_id,Integer bId,Integer b_bot_id) {
System.out.println("PlayerA id: " + aId + ", PlayerB id:" + bId); System.out.println("[PlayerA, bot] id: " + aId + " " + a_bot_id + ", [PlayerB,bot] id:" + bId + " " + b_bot_id);
WebSocketServer.startGame(aId,bId); WebSocketServer.startGame(aId,a_bot_id,bId,b_bot_id);
return "start game success"; return "start game success";
} }
} }

@ -0,0 +1,5 @@
package com.kob.backend.controller.service.pk;
public interface ReceiveBotMoveService {
String receiveBotMove(Integer userId,Integer direction);
}

@ -4,5 +4,5 @@ import org.springframework.stereotype.Service;
public interface StartGameService { public interface StartGameService {
String startGame(Integer aId,Integer bId); String startGame(Integer aId,Integer a_bot_id,Integer bId,Integer b_bot_id);
} }

@ -18,4 +18,46 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor-java-8</artifactId>
<version>0.9.14</version>
</dependency>
</dependencies>
</project> </project>

@ -0,0 +1,14 @@
package com.kob.botRunningSystem;
import com.kob.botRunningSystem.Service.BotRunningService;
import com.kob.botRunningSystem.Service.impl.BotRunningServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BotRunningSystemApplication {
public static void main(String[] args) {
BotRunningServiceImpl.botpool.start(); // 启动bot代码执行线程
SpringApplication.run(BotRunningSystemApplication.class,args);
}
}

@ -0,0 +1,24 @@
package com.kob.botRunningSystem.Controller;
import com.kob.botRunningSystem.Service.BotRunningService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Objects;
@RestController
public class BotRunningController {
@Autowired
private BotRunningService botRunningService;
@PostMapping("/bot/add/")
public String addBot(@RequestParam MultiValueMap<String,String> data){
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
String botCode = data.getFirst("bot_code");
String input = data.getFirst("input");
return botRunningService.addBot(userId,botCode,input);
}
}

@ -0,0 +1,7 @@
package com.kob.botRunningSystem.Service;
public interface BotRunningService {
String addBot(Integer userId,String botCode,String input); // 用户id,bot执行代码,一些输入信息(地图,位置,操作等)
}

@ -0,0 +1,16 @@
package com.kob.botRunningSystem.Service.impl;
import com.kob.botRunningSystem.Service.BotRunningService;
import com.kob.botRunningSystem.Service.impl.utils.BotPool;
import org.springframework.stereotype.Service;
@Service
public class BotRunningServiceImpl implements BotRunningService {
public static final BotPool botpool = new BotPool();
@Override
public String addBot(Integer userId, String botCode, String input) {
System.out.println("add bot: " + userId + " " + botCode + " " + input);
botpool.addBot(userId,botCode,input);
return "add bot success";
}
}

@ -0,0 +1,14 @@
package com.kob.botRunningSystem.Service.impl.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Bot {
Integer userId;
String botCode;
String input;
}

@ -0,0 +1,48 @@
package com.kob.botRunningSystem.Service.impl.utils;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class BotPool extends Thread{
private final ReentrantLock lock = new ReentrantLock(); // 加锁
private final Condition condition = lock.newCondition(); // 条件变量
private final Queue<Bot> bots = new LinkedList<>(); // 所有bots
public void addBot(Integer userId,String botCode,String input) {
lock.lock();
try {
bots.add(new Bot(userId,botCode,input)); // 添加一个bot
condition.signalAll(); // 唤醒其他线程
}finally {
lock.unlock();
}
}
private void consume(Bot bot) {
Consumer consumer = new Consumer();
consumer.setTimeout(2000,bot);
}
@Override
public void run() {
while (true) {
lock.lock();
if (bots.isEmpty()) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
lock.unlock();
break;
}
} else {
Bot bot = bots.remove(); // 取出队头
lock.unlock(); // 先解锁
consume(bot); // 执行bot的代码(可能比较耗时)
}
}
}
}

@ -0,0 +1,64 @@
package com.kob.botRunningSystem.Service.impl.utils;
import com.kob.botRunningSystem.utils.BotInterface;
import org.joor.Reflect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.UUID;
@Component
public class Consumer extends Thread{
private Bot bot;
private static RestTemplate restTemplate;
private static final String receiveBotMoveUrl = "http://127.0.0.1:3000/pk/receive/bot/move/";
@Autowired
private void setRestTemplate(RestTemplate restTemplate) {
Consumer.restTemplate = restTemplate;
}
public void setTimeout(long timeout,Bot bot) {
this.bot = bot;
this.start();
try {
this.join(timeout); // 最多等待timeout秒
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.interrupt(); // 终止当前进程
}
}
private String addUid(String code,String uid) { // 在Code的bot类名后添加uid
int k = code.indexOf(" implements com.kob.botRunningSystem.utils.BotInterface");
return code.substring(0,k) + uid + code.substring(k);
}
@Override
public void run() {
UUID uuid = UUID.randomUUID();
String uid = uuid.toString().substring(0,8); // 获取8位随机字符串
BotInterface botInterface = Reflect.compile(
"com.kob.botRunningSystem.utils.Bot" + uid,
addUid(bot.getBotCode(),uid)).create().get();
Integer direction = botInterface.nextMove(bot.getInput());
System.out.println("move-direction: " + bot.getUserId() + " " + direction);
MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.add("user_id",bot.getUserId().toString());
data.add("direction",direction.toString());
restTemplate.postForObject(receiveBotMoveUrl,data,String.class);
}
}

@ -0,0 +1,13 @@
package com.kob.botRunningSystem.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

@ -0,0 +1,30 @@
package com.kob.botRunningSystem.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
/**
* @author zfp
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/bot/add/").hasIpAddress("127.0.0.1")
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
}
}

@ -0,0 +1,80 @@
package com.kob.botRunningSystem.utils;
import java.util.ArrayList;
import java.util.List;
public class Bot implements com.kob.botRunningSystem.utils.BotInterface{
static class Cell{
public int x,y;
public Cell(int x,int y) {
this.x = x;
this.y = y;
}
}
private boolean check_tail_increasing(int steps) {
if (steps <= 10) {
return true;
}
if (steps % 3 == 1) {
return true;
}
return false;
}
public List<Cell> getCells(int sx,int sy,String steps) {
steps = steps.substring(1,steps.length() - 1); // 去掉编码时加的'()'
List<Cell> res = new ArrayList<>();
int []dx = {-1,0,1,0}, dy = {0,1,0,-1};
int x = sx, y = sy;
int step = 0;
res.add(new Cell(x,y));
for (int i = 0; i < steps.length(); i++) {
int d = steps.charAt(i) - '0';
x += dx[d];
y += dy[d];
res.add(new Cell(x,y));
step++;
if (!check_tail_increasing(step)) {
res.remove(0);
}
}
return res;
}
@Override
public Integer nextMove(String input) {
String[] strs = input.split("#");
int [][] g = new int[13][14];
for (int i = 0,k = 0; i < 13; i++) {
for (int j = 0; j < 14; j++,k++) {
if (strs[0].charAt(k) == '1')
g[i][j] = 1;
}
}
int aSx = Integer.parseInt(strs[1]), aSy = Integer.parseInt(strs[2]);
int bSx = Integer.parseInt(strs[4]), bSy = Integer.parseInt(strs[5]);
// 蛇的身体标记为1
List<Cell> cellsA = getCells(aSx,aSy,strs[3]);
List<Cell> cellsB = getCells(bSx,bSy,strs[6]);
for (Cell c: cellsA) g[c.x][c.y] = 1;
for (Cell c: cellsB) g[c.x][c.y] = 1;
int[] dx = {-1,0,1,0};
int[] dy = {0,1,0,-1};
for (int i = 0; i < 4; i++) {
// 蛇尾坐标,cellsA表示自己的那条蛇
int x = cellsA.get(cellsA.size() - 1).x + dx[i];
int y = cellsA.get(cellsA.size() - 1).y + dy[i];
if (x >= 0 && x < 13 && y >= 0 && y < 14 && g[x][y] == 0) {
return i; // 可以走的位置
}
}
return 0; // 向上走
}
}

@ -0,0 +1,5 @@
package com.kob.botRunningSystem.utils;
public interface BotInterface {
Integer nextMove(String input); // 下一步要走的方向是什么
}

@ -18,7 +18,8 @@ public class MatchingController {
public String addPlayer(@RequestParam MultiValueMap<String,String> data) { public String addPlayer(@RequestParam MultiValueMap<String,String> data) {
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id"))); Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
Integer rating = Integer.parseInt(Objects.requireNonNull(data.getFirst("rating"))); Integer rating = Integer.parseInt(Objects.requireNonNull(data.getFirst("rating")));
return matchingService.addPlayer(userId,rating); Integer botId = Integer.parseInt(Objects.requireNonNull(data.getFirst("bot_id")));
return matchingService.addPlayer(userId,rating,botId);
} }
@PostMapping("/player/remove/") @PostMapping("/player/remove/")

@ -1,6 +1,6 @@
package com.kob.matchingsystem.service; package com.kob.matchingsystem.service;
public interface MatchingService { public interface MatchingService {
String addPlayer(Integer userId, Integer rating); String addPlayer(Integer userId, Integer rating,Integer botId);
String removePlayer(Integer userId); String removePlayer(Integer userId);
} }

@ -10,9 +10,9 @@ public class MatchingServiceImpl implements MatchingService {
public static final MatchingPool matchingPool = new MatchingPool(); public static final MatchingPool matchingPool = new MatchingPool();
@Override @Override
public String addPlayer(Integer userId, Integer rating) { public String addPlayer(Integer userId, Integer rating,Integer botId) {
System.out.println("<add user> user id: " + userId + ", rating: " + rating); System.out.println("<add user> user id: " + userId + ", rating: " + rating + " bot_id: " + botId);
matchingPool.addPlayer(userId,rating); matchingPool.addPlayer(userId,rating,botId);
return "add user success"; return "add user success";
} }

@ -25,10 +25,10 @@ public class MatchingPool extends Thread{
MatchingPool.restTemplate = restTemplate; MatchingPool.restTemplate = restTemplate;
} }
public void addPlayer(Integer userId,Integer rating) { public void addPlayer(Integer userId,Integer rating,Integer botId) {
lock.lock(); lock.lock();
try { try {
players.add(new Player(userId,rating,0)); players.add(new Player(userId,rating,botId,0));
}finally { }finally {
lock.unlock(); lock.unlock();
} }
@ -94,7 +94,9 @@ public class MatchingPool extends Thread{
System.out.println("send result " + a + " " + b); System.out.println("send result " + a + " " + b);
MultiValueMap<String,String> data = new LinkedMultiValueMap<>(); MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.add("a_id",a.getUserId().toString()); data.add("a_id",a.getUserId().toString());
data.add("a_bot_id",a.getBotId().toString());
data.add("b_id",b.getUserId().toString()); data.add("b_id",b.getUserId().toString());
data.add("b_bot_id",b.getBotId().toString());
// 向WebServer返回匹配结果 // 向WebServer返回匹配结果
restTemplate.postForObject(startGameUrl,data,String.class); restTemplate.postForObject(startGameUrl,data,String.class);

@ -10,5 +10,7 @@ import lombok.NoArgsConstructor;
public class Player { public class Player {
private Integer userId; private Integer userId;
private Integer rating; private Integer rating;
private Integer botId; // bot的id
private Integer waitingTime; // 匹配等待的时间 private Integer waitingTime; // 匹配等待的时间
} }

@ -6,6 +6,7 @@
<modules> <modules>
<module>matchingsystem</module> <module>matchingsystem</module>
<module>backend</module> <module>backend</module>
<module>botRunningSystem</module>
</modules> </modules>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

@ -1,7 +1,7 @@
<template> <template>
<div class="matchground"> <div class="matchground">
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-4">
<div class="user_photo"> <div class="user_photo">
<img :src="$store.state.user.photo" alt=""> <img :src="$store.state.user.photo" alt="">
</div> </div>
@ -9,7 +9,18 @@
{{ $store.state.user.username }} {{ $store.state.user.username }}
</div> </div>
</div> </div>
<div class="col-6"> <div class="col-4">
<div class="select-bot">
<select class="form-select" v-model="select_bot" aria-label="Default select example">
<option value="-1">用户出战</option>
<option v-for="bot in bots" :key="bot.id" :value="bot.id">{{bot.title}}</option>
</select>
</div>
</div>
<div class="col-4">
<div class="user_photo"> <div class="user_photo">
<img :src="$store.state.pk.opponent_photo" alt=""> <img :src="$store.state.pk.opponent_photo" alt="">
</div> </div>
@ -26,8 +37,9 @@
</template> </template>
<script> <script>
import { ref } from 'vue' import { ref } from 'vue';
import {useStore} from 'vuex' import {useStore} from 'vuex';
import $ from 'jquery';
export default { export default {
setup() { setup() {
@ -35,14 +47,18 @@ export default {
let match_btn_info = ref("开始匹配"); let match_btn_info = ref("开始匹配");
let is_matched = ref(true); let is_matched = ref(true);
let bots = ref([]);
let select_bot = ref("-1");
const click_match_btn = () => { const click_match_btn = () => {
if (match_btn_info.value === "开始匹配") { if (match_btn_info.value === "开始匹配") {
match_btn_info.value = "取消匹配"; match_btn_info.value = "取消匹配";
is_matched.value = false; is_matched.value = false;
console.log(select_bot.value);
// json // json
store.state.pk.socket.send(JSON.stringify({ store.state.pk.socket.send(JSON.stringify({
event: "start-matching", event: "start-matching",
bot_id: select_bot.value,
})); }));
}else { }else {
@ -54,10 +70,27 @@ export default {
})); }));
} }
} }
const refresh_bots = () => {
$.ajax({
url: "http://localhost:3000/user/bot/getlist/",
type: "GET",
headers:{
"Authorization": "Bearer " + store.state.user.token, //
},
success(resp){
// bot
bots.value = resp;
}
})
}
refresh_bots();
return { return {
match_btn_info, match_btn_info,
is_matched, is_matched,
click_match_btn, click_match_btn,
bots,
select_bot,
} }
}, },
} }
@ -91,4 +124,13 @@ img {
text-align: center; text-align: center;
} }
.select-bot {
padding-top: 15vh;
}
.select-bot > select {
widows: 60%;
margin: 0 auto;
}
</style> </style>

@ -5,11 +5,11 @@
</div> </div>
<div class="result-text" v-else-if="$store.state.pk.loser === 'A' && $store.state.pk.a_id === parseInt($store.state.user.id)"> <div class="result-text" v-else-if="$store.state.pk.loser === 'A' && $store.state.pk.a_id === parseInt($store.state.user.id)">
You Lose(A) Lose
</div> </div>
<div class="result-text" v-else-if="$store.state.pk.loser === 'B' && $store.state.pk.b_id == parseInt($store.state.user.id)"> <div class="result-text" v-else-if="$store.state.pk.loser === 'B' && $store.state.pk.b_id == parseInt($store.state.user.id)">
You Lose(B) Lose
</div> </div>
<div class="result-text" v-else> <div class="result-text" v-else>

@ -0,0 +1,22 @@
<template>
<div class="show">
<div class="snakeInfo" style="background-color: #4876ec;" v-if="$store.state.user.id == $store.state.pk.a_id">蓝方</div>
<div class="snakeInfo" style="background-color: #f94848;" v-if="$store.state.user.id == $store.state.pk.b_id">红方</div>
</div>
</template>
<script>
</script>
<style scoped>
.snakeInfo {
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
top: 30vh;
left: 8vw;
text-align: center;
line-height: 50px;
}
</style>

@ -3,13 +3,14 @@
<PlayGround v-if="$store.state.pk.status === 'playing'" /> <PlayGround v-if="$store.state.pk.status === 'playing'" />
<MatchGround v-if="$store.state.pk.status === 'matching'" /> <MatchGround v-if="$store.state.pk.status === 'matching'" />
<ResultBoard v-if="$store.state.pk.loser !== 'none'"/> <ResultBoard v-if="$store.state.pk.loser !== 'none'"/>
<UserInfo v-if="$store.state.pk.status === 'playing'"/>
</template> </template>
<script> <script>
import PlayGround from "../../components/PlayGround.vue"; import PlayGround from "../../components/PlayGround.vue";
import MatchGround from "../../components/MatchGround.vue"; import MatchGround from "../../components/MatchGround.vue";
import ResultBoard from '@/components/ResultBoard.vue'; import ResultBoard from '@/components/ResultBoard.vue';
import UserInfo from '@/components/UserInfo.vue';
import { onMounted, onUnmounted } from "vue"; // import { onMounted, onUnmounted } from "vue"; //
import { useStore } from "vuex"; import { useStore } from "vuex";
@ -19,10 +20,14 @@ export default {
PlayGround, PlayGround,
MatchGround, MatchGround,
ResultBoard, ResultBoard,
UserInfo,
}, },
setup() { setup() {
const store = useStore(); const store = useStore();
const socket_url = `ws://localhost:3000/websocket/${store.state.user.token}/`; const socket_url = `ws://localhost:3000/websocket/${store.state.user.token}/`;
store.commit("updateLoser","none");
let socket = null; let socket = null;
// (pk) // (pk)
// onMountedsetup // onMountedsetup
@ -39,18 +44,22 @@ export default {
store.commit("updateSocket", socket); store.commit("updateSocket", socket);
console.log("connnected!"); console.log("connnected!");
}; };
// //
socket.onmessage = (msg) => { socket.onmessage = (msg) => {
const data = JSON.parse(msg.data); const data = JSON.parse(msg.data);
// //
if (data.event === "start-matching") { if (data.event === "start-matching") {
store.commit("updateOpponent", { store.commit("updateOpponent", {
username: data.opponent_username, username: data.opponent_username,
photo: data.opponent_photo, photo: data.opponent_photo,
}); });
setTimeout(() => { setTimeout(() => {
store.commit("updateStatus", "playing"); store.commit("updateStatus", "playing");
}, 500); // 0.5 }, 200); // 0.2(穿bug)
// (id) // (id)
store.commit("updateGame", data.game); store.commit("updateGame", data.game);
} else if (data.event === "move") { } else if (data.event === "move") {
@ -58,6 +67,7 @@ export default {
const [snake0, snake1] = game.snakes; const [snake0, snake1] = game.snakes;
snake0.set_direction(data.a_direction); snake0.set_direction(data.a_direction);
snake1.set_direction(data.b_direction); snake1.set_direction(data.b_direction);
} else if (data.event === "result") { } else if (data.event === "result") {
const game = store.state.pk.gameObject; const game = store.state.pk.gameObject;
const [snake0, snake1] = game.snakes; const [snake0, snake1] = game.snakes;

Loading…
Cancel
Save