parent
108ae844f0
commit
1e2149a014
80 changed files with 500 additions and 162 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,52 +0,0 @@ |
||||
package com.kob.backend.controller.pk; |
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@RestController |
||||
@RequestMapping("/pk/") |
||||
public class BotInfoController { |
||||
|
||||
@RequestMapping("getInfo/") |
||||
public List<Map<String,String>> getInfo(){ |
||||
List<Map<String,String>> li = new LinkedList<>(); |
||||
Map<String,String> bot1 = new HashMap<>(3); |
||||
bot1.put("name","John"); |
||||
bot1.put("age","14"); |
||||
bot1.put("sex","male"); |
||||
|
||||
Map<String,String> bot2 = new HashMap<>(3); |
||||
bot2.put("name","smith"); |
||||
bot2.put("age","18"); |
||||
bot2.put("sex","female"); |
||||
li.add(bot1); |
||||
li.add(bot2); |
||||
return li; |
||||
} |
||||
|
||||
@RequestMapping("getInfo1/") |
||||
public List<String> getInfo1(){ |
||||
List<String> li = new LinkedList<>(); |
||||
li.add("apple"); |
||||
li.add("banana"); |
||||
li.add("cat"); |
||||
return li; |
||||
} |
||||
|
||||
@RequestMapping("getInfo2/") |
||||
public Map<String,String> getInfo2(){ |
||||
Map<String,String> map = new HashMap<>(); |
||||
map.put("name","acwing"); |
||||
map.put("rating","100"); |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -1,18 +0,0 @@ |
||||
package com.kob.backend.controller.pk; |
||||
|
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
|
||||
@Controller |
||||
public class IndexController { |
||||
@RequestMapping("/") |
||||
public String getIndex(){ |
||||
return "pk/index.html"; |
||||
} |
||||
|
||||
} |
@ -1,2 +1,2 @@ |
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip |
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip |
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar |
@ -0,0 +1,13 @@ |
||||
package com.kob.backend.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,28 @@ |
||||
package com.kob.backend.controller.pk; |
||||
|
||||
import com.kob.backend.controller.service.pk.StartGameService; |
||||
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 StartGameController { |
||||
@Autowired |
||||
private StartGameService startGameService; |
||||
|
||||
@PostMapping("/pk/start/game/") |
||||
|
||||
public String startGame(@RequestParam MultiValueMap<String,String> data) { |
||||
Integer aId = Integer.parseInt(Objects.requireNonNull(data.getFirst("a_id"))); |
||||
Integer bId = Integer.parseInt(Objects.requireNonNull(data.getFirst("b_id"))); |
||||
return startGameService.startGame(aId,bId); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,15 @@ |
||||
package com.kob.backend.controller.service.impl.pk; |
||||
|
||||
import com.kob.backend.consumer.WebSocketServer; |
||||
import com.kob.backend.controller.service.pk.StartGameService; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Service |
||||
public class StartGameServiceImpl implements StartGameService { |
||||
@Override |
||||
public String startGame(Integer aId, Integer bId) { |
||||
System.out.println("PlayerA id: " + aId + ", PlayerB id:" + bId); |
||||
WebSocketServer.startGame(aId,bId); |
||||
return "start game success"; |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
package com.kob.backend.controller.service.pk; |
||||
|
||||
import org.springframework.stereotype.Service; |
||||
|
||||
|
||||
public interface StartGameService { |
||||
String startGame(Integer aId,Integer bId); |
||||
} |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@ -0,0 +1,56 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>backendCloud</artifactId> |
||||
<groupId>com.kob</groupId> |
||||
<version>0.0.1-SNAPSHOT</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>com.kob.matchingsystem</groupId> |
||||
<artifactId>matchingsystem</artifactId> |
||||
|
||||
<properties> |
||||
<maven.compiler.source>8</maven.compiler.source> |
||||
<maven.compiler.target>8</maven.compiler.target> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
</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> |
||||
|
||||
</dependencies> |
||||
|
||||
</project> |
@ -0,0 +1,14 @@ |
||||
package com.kob.matchingsystem; |
||||
|
||||
import com.kob.matchingsystem.service.impl.MatchingServiceImpl; |
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
@SpringBootApplication |
||||
public class MatchingSystemApplication { |
||||
public static void main(String[] args) |
||||
{ |
||||
MatchingServiceImpl.matchingPool.start(); // 启动匹配线程
|
||||
SpringApplication.run(MatchingSystemApplication.class,args); |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.kob.matchingsystem.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.matchingsystem.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("/player/add/", "/player/remove/").hasIpAddress("127.0.0.1") |
||||
.antMatchers(HttpMethod.OPTIONS).permitAll() |
||||
.anyRequest().authenticated(); |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,30 @@ |
||||
package com.kob.matchingsystem.controller; |
||||
|
||||
import com.kob.matchingsystem.service.MatchingService; |
||||
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 MatchingController { |
||||
@Autowired |
||||
private MatchingService matchingService; |
||||
|
||||
@PostMapping("/player/add/") |
||||
public String addPlayer(@RequestParam MultiValueMap<String,String> data) { |
||||
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id"))); |
||||
Integer rating = Integer.parseInt(Objects.requireNonNull(data.getFirst("rating"))); |
||||
return matchingService.addPlayer(userId,rating); |
||||
} |
||||
|
||||
@PostMapping("/player/remove/") |
||||
public String removePlayer(@RequestParam MultiValueMap<String,String> data) { |
||||
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id"))); |
||||
return matchingService.removePlayer(userId); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,6 @@ |
||||
package com.kob.matchingsystem.service; |
||||
|
||||
public interface MatchingService { |
||||
String addPlayer(Integer userId, Integer rating); |
||||
String removePlayer(Integer userId); |
||||
} |
@ -0,0 +1,25 @@ |
||||
package com.kob.matchingsystem.service.impl; |
||||
|
||||
import com.kob.matchingsystem.service.MatchingService; |
||||
import com.kob.matchingsystem.service.impl.utils.MatchingPool; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Service |
||||
public class MatchingServiceImpl implements MatchingService { |
||||
|
||||
public static final MatchingPool matchingPool = new MatchingPool(); |
||||
|
||||
@Override |
||||
public String addPlayer(Integer userId, Integer rating) { |
||||
System.out.println("<add user> user id: " + userId + ", rating: " + rating); |
||||
matchingPool.addPlayer(userId,rating); |
||||
return "add user success"; |
||||
} |
||||
|
||||
@Override |
||||
public String removePlayer(Integer userId) { |
||||
System.out.println("<remove user> user id: " + userId); |
||||
matchingPool.removePlayer(userId); |
||||
return "remove user success"; |
||||
} |
||||
} |
@ -0,0 +1,121 @@ |
||||
package com.kob.matchingsystem.service.impl.utils; |
||||
|
||||
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.ArrayList; |
||||
import java.util.List; |
||||
import java.util.concurrent.locks.ReentrantLock; |
||||
@Component |
||||
public class MatchingPool extends Thread{ |
||||
|
||||
public static List<Player> players = new ArrayList<>(); |
||||
// 加锁
|
||||
public ReentrantLock lock = new ReentrantLock(); |
||||
|
||||
private static RestTemplate restTemplate; |
||||
|
||||
private static final String startGameUrl= "http://127.0.0.1:3000/pk/start/game/"; |
||||
|
||||
@Autowired |
||||
public void setRestTemplate(RestTemplate restTemplate) { |
||||
MatchingPool.restTemplate = restTemplate; |
||||
} |
||||
|
||||
public void addPlayer(Integer userId,Integer rating) { |
||||
lock.lock(); |
||||
try { |
||||
players.add(new Player(userId,rating,0)); |
||||
}finally { |
||||
lock.unlock(); |
||||
} |
||||
} |
||||
|
||||
public void removePlayer(Integer userId){ |
||||
lock.lock(); |
||||
try { |
||||
List<Player> newPlayers = new ArrayList<>(); |
||||
for (Player player: players) { |
||||
if (!player.getUserId().equals(userId)) { |
||||
newPlayers.add(player); |
||||
} |
||||
} |
||||
players = newPlayers; |
||||
}finally { |
||||
lock.unlock(); |
||||
} |
||||
} |
||||
|
||||
private void increaseWaitingTime() { |
||||
// 所有等待的用户等待时间加1
|
||||
for (Player p : players) { |
||||
p.setWaitingTime(p.getWaitingTime() + 1); |
||||
} |
||||
} |
||||
|
||||
// 判断两名玩家是否匹配
|
||||
private boolean checkMatched(Player a,Player b) { |
||||
int ratingDelta = Math.abs(a.getRating() - b.getRating()); // 分差
|
||||
int waitingTime = Math.min(a.getWaitingTime(),b.getWaitingTime()); // 同时满足两名用户的要求
|
||||
return ratingDelta < waitingTime * 10; |
||||
} |
||||
|
||||
// 尝试匹配玩家
|
||||
private void matchPlayer() { |
||||
System.out.println("match_players: " + players.toString()); |
||||
boolean[] used = new boolean[players.size()]; // 记录用户是否已经被匹配
|
||||
|
||||
for (int i = 0; i < players.size(); i++) { |
||||
if (used[i]) continue; |
||||
for (int j = i + 1; j < players.size(); j++) { |
||||
if (used[j]) continue; |
||||
Player a = players.get(i), b = players.get(j); |
||||
if (checkMatched(a,b)) { |
||||
used[i] = used[j] = true; |
||||
sendResult(a,b); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
// 删除已经匹配成功的用户
|
||||
List<Player> newPlayers = new ArrayList<>(); |
||||
for (int i = 0; i < players.size(); i++) { |
||||
if (!used[i]) newPlayers.add(players.get(i)); |
||||
} |
||||
|
||||
players = newPlayers; |
||||
} |
||||
|
||||
// 返回两名玩家的匹配结果
|
||||
private void sendResult(Player a,Player b) { |
||||
System.out.println("send result " + a + " " + b); |
||||
MultiValueMap<String,String> data = new LinkedMultiValueMap<>(); |
||||
data.add("a_id",a.getUserId().toString()); |
||||
data.add("b_id",b.getUserId().toString()); |
||||
// 向WebServer返回匹配结果
|
||||
restTemplate.postForObject(startGameUrl,data,String.class); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
while (true) { |
||||
try { |
||||
Thread.sleep(1000); |
||||
lock.lock(); |
||||
try{ |
||||
increaseWaitingTime(); |
||||
matchPlayer(); |
||||
}finally { |
||||
lock.unlock(); |
||||
} |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
package com.kob.matchingsystem.service.impl.utils; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public class Player { |
||||
private Integer userId; |
||||
private Integer rating; |
||||
private Integer waitingTime; // 匹配等待的时间
|
||||
} |
@ -0,0 +1 @@ |
||||
server.port=3001 |
@ -0,0 +1,34 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<packaging>pom</packaging> |
||||
<modules> |
||||
<module>matchingsystem</module> |
||||
<module>backend</module> |
||||
</modules> |
||||
<parent> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-parent</artifactId> |
||||
<version>2.7.3</version> |
||||
<relativePath/> <!-- lookup parent from repository --> |
||||
</parent> |
||||
<groupId>com.kob</groupId> |
||||
<artifactId>backendCloud</artifactId> |
||||
<version>0.0.1-SNAPSHOT</version> |
||||
<name>backendCloud</name> |
||||
<description>backendCloud</description> |
||||
<properties> |
||||
<java.version>1.8</java.version> |
||||
</properties> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
</project> |
Loading…
Reference in new issue