每次要多传一个bot_id
判网关的时候判127.0.0.1所以最好改localhost
创建SpringCloud的子项目 BotRunningSystem
在BotRunningSystem项目中添加依赖:
joor-java-8
可动态编译Java代码
2. 修改前端,传入对Bot的选择操作
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();
}
}
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;
@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();
}
}
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);
}
}
package com.kob.botrunningsystem.service.impl.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Bot {
Integer userId;
String botCode;
String input;
}
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 final static String receiveBotMoveUrl = "http://127.0.0.1:8080/pk/receive/bot/move/";
@Autowired
public void setRestTemplate(RestTemplate restTemplate) {
Consumer.restTemplate = restTemplate;
}
public void startTimeout(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);
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);
}
}
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 final static 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";
}
}
package com.kob.botrunningsystem.service;
public interface BotRunningService {
String addBot(Integer userId, String botCode, String input);
}
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 step) { // 检验当前回合,蛇的长度是否增加
if (step <= 10) return true;
return step % 3 == 1;
}
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));
if (!check_tail_increasing( ++ step)) {
res.remove(0);
}
}
return res;
}
@Override
public Integer nextMove(String input) {
String[] strs = input.split("#");
int[][] g = new int[15][16];
for (int i = 0, k = 0; i < 15; i ++ ) {
for (int j = 0; j < 16; 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]);
List<Cell> aCells = getCells(aSx, aSy, strs[3]);
List<Cell> bCells = getCells(bSx, bSy, strs[6]);
for (Cell c: aCells) g[c.x][c.y] = 1;
for (Cell c: bCells) g[c.x][c.y] = 1;
int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
for (int i = 0; i < 4; i ++ ) {
int x = aCells.get(aCells.size() - 1).x + dx[i];
int y = aCells.get(aCells.size() - 1).y + dy[i];
if (x >= 0 && x < 15 && y >= 0 && y < 16 && g[x][y] == 0) {
return i;
}
}
return 0;
}
}
package com.kob.botrunningsystem.utils;
public interface BotInterface {
Integer nextMove(String input);
}
package com.kob.botrunningsystem;
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();
SpringApplication.run(BotRunningSystemApplication.class, args);
}
}