parent
86c976584f
commit
998b9ee6aa
33 changed files with 605 additions and 34 deletions
@ -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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package com.kob.backend.controller.service.pk; |
||||||
|
|
||||||
|
public interface ReceiveBotMoveService { |
||||||
|
String receiveBotMove(Integer userId,Integer direction); |
||||||
|
} |
@ -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); // 下一步要走的方向是什么
|
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
server.port=3002 |
@ -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); |
||||||
} |
} |
||||||
|
@ -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> |
Loading…
Reference in new issue