mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Apply source formatting to samples
This commit is contained in:
parent
efe102bd51
commit
1a9ce42da9
@ -48,6 +48,26 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<configuration>
|
||||
<useProjectReferences>false</useProjectReferences>
|
||||
<additionalConfig>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.ui.prefs</name>
|
||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.ui.prefs</location>
|
||||
</file>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.core.prefs</name>
|
||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.core.prefs</location>
|
||||
</file>
|
||||
</additionalConfig>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<version>0.5.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<java.version>1.7</java.version>
|
||||
<tomcat.version>8.0.0-RC3</tomcat.version>
|
||||
</properties>
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.client;
|
||||
|
||||
public interface GreetingService {
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.client;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -33,7 +34,8 @@ public class SimpleClientWebSocketHandler extends TextWebSocketHandlerAdapter {
|
||||
private CountDownLatch latch;
|
||||
|
||||
@Autowired
|
||||
public SimpleClientWebSocketHandler(GreetingService greetingService, CountDownLatch latch) {
|
||||
public SimpleClientWebSocketHandler(GreetingService greetingService,
|
||||
CountDownLatch latch) {
|
||||
this.greetingService = greetingService;
|
||||
this.latch = latch;
|
||||
}
|
||||
@ -45,10 +47,11 @@ public class SimpleClientWebSocketHandler extends TextWebSocketHandlerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||
logger.info("Received: " + message + " (" + latch.getCount() + ")");
|
||||
public void handleTextMessage(WebSocketSession session, TextMessage message)
|
||||
throws Exception {
|
||||
this.logger.info("Received: " + message + " (" + this.latch.getCount() + ")");
|
||||
session.close();
|
||||
latch.countDown();
|
||||
this.latch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.client;
|
||||
|
||||
public class SimpleGreetingService implements GreetingService {
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.echo;
|
||||
|
||||
public class DefaultEchoService implements EchoService {
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.echo;
|
||||
|
||||
public interface EchoService {
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.echo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -29,14 +45,16 @@ public class EchoWebSocketHandler extends TextWebSocketHandlerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||
public void handleTextMessage(WebSocketSession session, TextMessage message)
|
||||
throws Exception {
|
||||
String echoMessage = this.echoService.getMessage(message.getPayload());
|
||||
logger.debug(echoMessage);
|
||||
session.sendMessage(new TextMessage(echoMessage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception)
|
||||
throws Exception {
|
||||
session.close(CloseStatus.SERVER_ERROR);
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
public enum Direction {
|
||||
NONE, NORTH, SOUTH, EAST, WEST
|
||||
NONE, NORTH, SOUTH, EAST, WEST
|
||||
}
|
||||
|
@ -14,58 +14,60 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import org.springframework.boot.samples.websocket.snake.Direction;
|
||||
|
||||
|
||||
public class Location {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int x;
|
||||
public int y;
|
||||
public static final int GRID_SIZE = 10;
|
||||
public static final int PLAYFIELD_HEIGHT = 480;
|
||||
public static final int PLAYFIELD_WIDTH = 640;
|
||||
|
||||
public Location(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public Location(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public Location getAdjacentLocation(Direction direction) {
|
||||
switch (direction) {
|
||||
case NORTH:
|
||||
return new Location(x, y - Location.GRID_SIZE);
|
||||
case SOUTH:
|
||||
return new Location(x, y + Location.GRID_SIZE);
|
||||
case EAST:
|
||||
return new Location(x + Location.GRID_SIZE, y);
|
||||
case WEST:
|
||||
return new Location(x - Location.GRID_SIZE, y);
|
||||
case NONE:
|
||||
// fall through
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public Location getAdjacentLocation(Direction direction) {
|
||||
switch (direction) {
|
||||
case NORTH:
|
||||
return new Location(this.x, this.y - Location.GRID_SIZE);
|
||||
case SOUTH:
|
||||
return new Location(this.x, this.y + Location.GRID_SIZE);
|
||||
case EAST:
|
||||
return new Location(this.x + Location.GRID_SIZE, this.y);
|
||||
case WEST:
|
||||
return new Location(this.x - Location.GRID_SIZE, this.y);
|
||||
case NONE:
|
||||
// fall through
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Location location = (Location) o;
|
||||
Location location = (Location) o;
|
||||
|
||||
if (x != location.x) return false;
|
||||
if (y != location.y) return false;
|
||||
if (this.x != location.x)
|
||||
return false;
|
||||
if (this.y != location.y)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = x;
|
||||
result = 31 * result + y;
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.x;
|
||||
result = 31 * result + this.y;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
@ -23,117 +24,116 @@ import java.util.Deque;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
|
||||
public class Snake {
|
||||
|
||||
private static final int DEFAULT_LENGTH = 5;
|
||||
private static final int DEFAULT_LENGTH = 5;
|
||||
|
||||
private final int id;
|
||||
private final WebSocketSession session;
|
||||
private final int id;
|
||||
private final WebSocketSession session;
|
||||
|
||||
private Direction direction;
|
||||
private int length = DEFAULT_LENGTH;
|
||||
private Location head;
|
||||
private final Deque<Location> tail = new ArrayDeque<Location>();
|
||||
private final String hexColor;
|
||||
private Direction direction;
|
||||
private int length = DEFAULT_LENGTH;
|
||||
private Location head;
|
||||
private final Deque<Location> tail = new ArrayDeque<Location>();
|
||||
private final String hexColor;
|
||||
|
||||
public Snake(int id, WebSocketSession session) {
|
||||
this.id = id;
|
||||
this.session = session;
|
||||
this.hexColor = SnakeUtils.getRandomHexColor();
|
||||
resetState();
|
||||
}
|
||||
public Snake(int id, WebSocketSession session) {
|
||||
this.id = id;
|
||||
this.session = session;
|
||||
this.hexColor = SnakeUtils.getRandomHexColor();
|
||||
resetState();
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
this.direction = Direction.NONE;
|
||||
this.head = SnakeUtils.getRandomLocation();
|
||||
this.tail.clear();
|
||||
this.length = DEFAULT_LENGTH;
|
||||
}
|
||||
private void resetState() {
|
||||
this.direction = Direction.NONE;
|
||||
this.head = SnakeUtils.getRandomLocation();
|
||||
this.tail.clear();
|
||||
this.length = DEFAULT_LENGTH;
|
||||
}
|
||||
|
||||
private synchronized void kill() throws Exception {
|
||||
resetState();
|
||||
sendMessage("{'type': 'dead'}");
|
||||
}
|
||||
private synchronized void kill() throws Exception {
|
||||
resetState();
|
||||
sendMessage("{'type': 'dead'}");
|
||||
}
|
||||
|
||||
private synchronized void reward() throws Exception {
|
||||
length++;
|
||||
sendMessage("{'type': 'kill'}");
|
||||
}
|
||||
private synchronized void reward() throws Exception {
|
||||
this.length++;
|
||||
sendMessage("{'type': 'kill'}");
|
||||
}
|
||||
|
||||
protected void sendMessage(String msg) throws Exception {
|
||||
this.session.sendMessage(new TextMessage(msg));
|
||||
}
|
||||
|
||||
protected void sendMessage(String msg) throws Exception {
|
||||
session.sendMessage(new TextMessage(msg));
|
||||
}
|
||||
public synchronized void update(Collection<Snake> snakes) throws Exception {
|
||||
Location nextLocation = this.head.getAdjacentLocation(this.direction);
|
||||
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) {
|
||||
nextLocation.x = 0;
|
||||
}
|
||||
if (nextLocation.y >= SnakeUtils.PLAYFIELD_HEIGHT) {
|
||||
nextLocation.y = 0;
|
||||
}
|
||||
if (nextLocation.x < 0) {
|
||||
nextLocation.x = SnakeUtils.PLAYFIELD_WIDTH;
|
||||
}
|
||||
if (nextLocation.y < 0) {
|
||||
nextLocation.y = SnakeUtils.PLAYFIELD_HEIGHT;
|
||||
}
|
||||
if (this.direction != Direction.NONE) {
|
||||
this.tail.addFirst(this.head);
|
||||
if (this.tail.size() > this.length) {
|
||||
this.tail.removeLast();
|
||||
}
|
||||
this.head = nextLocation;
|
||||
}
|
||||
|
||||
public synchronized void update(Collection<Snake> snakes) throws Exception {
|
||||
Location nextLocation = head.getAdjacentLocation(direction);
|
||||
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) {
|
||||
nextLocation.x = 0;
|
||||
}
|
||||
if (nextLocation.y >= SnakeUtils.PLAYFIELD_HEIGHT) {
|
||||
nextLocation.y = 0;
|
||||
}
|
||||
if (nextLocation.x < 0) {
|
||||
nextLocation.x = SnakeUtils.PLAYFIELD_WIDTH;
|
||||
}
|
||||
if (nextLocation.y < 0) {
|
||||
nextLocation.y = SnakeUtils.PLAYFIELD_HEIGHT;
|
||||
}
|
||||
if (direction != Direction.NONE) {
|
||||
tail.addFirst(head);
|
||||
if (tail.size() > length) {
|
||||
tail.removeLast();
|
||||
}
|
||||
head = nextLocation;
|
||||
}
|
||||
handleCollisions(snakes);
|
||||
}
|
||||
|
||||
handleCollisions(snakes);
|
||||
}
|
||||
private void handleCollisions(Collection<Snake> snakes) throws Exception {
|
||||
for (Snake snake : snakes) {
|
||||
boolean headCollision = this.id != snake.id
|
||||
&& snake.getHead().equals(this.head);
|
||||
boolean tailCollision = snake.getTail().contains(this.head);
|
||||
if (headCollision || tailCollision) {
|
||||
kill();
|
||||
if (this.id != snake.id) {
|
||||
snake.reward();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCollisions(Collection<Snake> snakes) throws Exception {
|
||||
for (Snake snake : snakes) {
|
||||
boolean headCollision = id != snake.id && snake.getHead().equals(head);
|
||||
boolean tailCollision = snake.getTail().contains(head);
|
||||
if (headCollision || tailCollision) {
|
||||
kill();
|
||||
if (id != snake.id) {
|
||||
snake.reward();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public synchronized Location getHead() {
|
||||
return this.head;
|
||||
}
|
||||
|
||||
public synchronized Location getHead() {
|
||||
return head;
|
||||
}
|
||||
public synchronized Collection<Location> getTail() {
|
||||
return this.tail;
|
||||
}
|
||||
|
||||
public synchronized Collection<Location> getTail() {
|
||||
return tail;
|
||||
}
|
||||
public synchronized void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public synchronized void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
public synchronized String getLocationsJson() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x),
|
||||
Integer.valueOf(this.head.y)));
|
||||
for (Location location : this.tail) {
|
||||
sb.append(',');
|
||||
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(location.x),
|
||||
Integer.valueOf(location.y)));
|
||||
}
|
||||
return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id),
|
||||
sb.toString());
|
||||
}
|
||||
|
||||
public synchronized String getLocationsJson() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("{x: %d, y: %d}",
|
||||
Integer.valueOf(head.x), Integer.valueOf(head.y)));
|
||||
for (Location location : tail) {
|
||||
sb.append(',');
|
||||
sb.append(String.format("{x: %d, y: %d}",
|
||||
Integer.valueOf(location.x), Integer.valueOf(location.y)));
|
||||
}
|
||||
return String.format("{'id':%d,'body':[%s]}",
|
||||
Integer.valueOf(id), sb.toString());
|
||||
}
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getHexColor() {
|
||||
return hexColor;
|
||||
}
|
||||
public String getHexColor() {
|
||||
return this.hexColor;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -32,84 +33,77 @@ import org.apache.juli.logging.LogFactory;
|
||||
*/
|
||||
public class SnakeTimer {
|
||||
|
||||
private static final Log log =
|
||||
LogFactory.getLog(SnakeTimer.class);
|
||||
private static final Log log = LogFactory.getLog(SnakeTimer.class);
|
||||
|
||||
private static Timer gameTimer = null;
|
||||
private static Timer gameTimer = null;
|
||||
|
||||
private static final long TICK_DELAY = 100;
|
||||
private static final long TICK_DELAY = 100;
|
||||
|
||||
private static final ConcurrentHashMap<Integer, Snake> snakes =
|
||||
new ConcurrentHashMap<Integer, Snake>();
|
||||
private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>();
|
||||
|
||||
public static synchronized void addSnake(Snake snake) {
|
||||
if (snakes.size() == 0) {
|
||||
startTimer();
|
||||
}
|
||||
snakes.put(Integer.valueOf(snake.getId()), snake);
|
||||
}
|
||||
public static synchronized void addSnake(Snake snake) {
|
||||
if (snakes.size() == 0) {
|
||||
startTimer();
|
||||
}
|
||||
snakes.put(Integer.valueOf(snake.getId()), snake);
|
||||
}
|
||||
|
||||
public static Collection<Snake> getSnakes() {
|
||||
return Collections.unmodifiableCollection(snakes.values());
|
||||
}
|
||||
|
||||
public static Collection<Snake> getSnakes() {
|
||||
return Collections.unmodifiableCollection(snakes.values());
|
||||
}
|
||||
public static synchronized void removeSnake(Snake snake) {
|
||||
snakes.remove(Integer.valueOf(snake.getId()));
|
||||
if (snakes.size() == 0) {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick() throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator(); iterator
|
||||
.hasNext();) {
|
||||
Snake snake = iterator.next();
|
||||
snake.update(SnakeTimer.getSnakes());
|
||||
sb.append(snake.getLocationsJson());
|
||||
if (iterator.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
broadcast(String.format("{'type': 'update', 'data' : [%s]}", sb.toString()));
|
||||
}
|
||||
|
||||
public static synchronized void removeSnake(Snake snake) {
|
||||
snakes.remove(Integer.valueOf(snake.getId()));
|
||||
if (snakes.size() == 0) {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
public static void broadcast(String message) throws Exception {
|
||||
Collection<Snake> snakes = new CopyOnWriteArrayList<>(SnakeTimer.getSnakes());
|
||||
for (Snake snake : snakes) {
|
||||
try {
|
||||
snake.sendMessage(message);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// if Snake#sendMessage fails the client is removed
|
||||
removeSnake(snake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startTimer() {
|
||||
gameTimer = new Timer(SnakeTimer.class.getSimpleName() + " Timer");
|
||||
gameTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
tick();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
log.error("Caught to prevent timer from shutting down", e);
|
||||
}
|
||||
}
|
||||
}, TICK_DELAY, TICK_DELAY);
|
||||
}
|
||||
|
||||
public static void tick() throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator();
|
||||
iterator.hasNext();) {
|
||||
Snake snake = iterator.next();
|
||||
snake.update(SnakeTimer.getSnakes());
|
||||
sb.append(snake.getLocationsJson());
|
||||
if (iterator.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
broadcast(String.format("{'type': 'update', 'data' : [%s]}",
|
||||
sb.toString()));
|
||||
}
|
||||
|
||||
public static void broadcast(String message) throws Exception {
|
||||
Collection<Snake> snakes = new CopyOnWriteArrayList<>(SnakeTimer.getSnakes());
|
||||
for (Snake snake : snakes) {
|
||||
try {
|
||||
snake.sendMessage(message);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// if Snake#sendMessage fails the client is removed
|
||||
removeSnake(snake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void startTimer() {
|
||||
gameTimer = new Timer(SnakeTimer.class.getSimpleName() + " Timer");
|
||||
gameTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
tick();
|
||||
} catch (Throwable e) {
|
||||
log.error("Caught to prevent timer from shutting down", e);
|
||||
}
|
||||
}
|
||||
}, TICK_DELAY, TICK_DELAY);
|
||||
}
|
||||
|
||||
|
||||
public static void stopTimer() {
|
||||
if (gameTimer != null) {
|
||||
gameTimer.cancel();
|
||||
}
|
||||
}
|
||||
public static void stopTimer() {
|
||||
if (gameTimer != null) {
|
||||
gameTimer.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import java.awt.Color;
|
||||
@ -21,36 +22,33 @@ import java.util.Random;
|
||||
|
||||
public class SnakeUtils {
|
||||
|
||||
public static final int PLAYFIELD_WIDTH = 640;
|
||||
public static final int PLAYFIELD_HEIGHT = 480;
|
||||
public static final int GRID_SIZE = 10;
|
||||
public static final int PLAYFIELD_WIDTH = 640;
|
||||
public static final int PLAYFIELD_HEIGHT = 480;
|
||||
public static final int GRID_SIZE = 10;
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final Random random = new Random();
|
||||
|
||||
public static String getRandomHexColor() {
|
||||
float hue = random.nextFloat();
|
||||
// sat between 0.1 and 0.3
|
||||
float saturation = (random.nextInt(2000) + 1000) / 10000f;
|
||||
float luminance = 0.9f;
|
||||
Color color = Color.getHSBColor(hue, saturation, luminance);
|
||||
return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
public static String getRandomHexColor() {
|
||||
float hue = random.nextFloat();
|
||||
// sat between 0.1 and 0.3
|
||||
float saturation = (random.nextInt(2000) + 1000) / 10000f;
|
||||
float luminance = 0.9f;
|
||||
Color color = Color.getHSBColor(hue, saturation, luminance);
|
||||
return '#' + Integer.toHexString(
|
||||
(color.getRGB() & 0xffffff) | 0x1000000).substring(1);
|
||||
}
|
||||
public static Location getRandomLocation() {
|
||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH));
|
||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT));
|
||||
return new Location(x, y);
|
||||
}
|
||||
|
||||
|
||||
public static Location getRandomLocation() {
|
||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH));
|
||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT));
|
||||
return new Location(x, y);
|
||||
}
|
||||
|
||||
|
||||
private static int roundByGridSize(int value) {
|
||||
value = value + (GRID_SIZE / 2);
|
||||
value = value / GRID_SIZE;
|
||||
value = value * GRID_SIZE;
|
||||
return value;
|
||||
}
|
||||
private static int roundByGridSize(int value) {
|
||||
value = value + (GRID_SIZE / 2);
|
||||
value = value / GRID_SIZE;
|
||||
value = value * GRID_SIZE;
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import java.awt.Color;
|
||||
@ -28,85 +29,84 @@ import org.springframework.web.socket.adapter.TextWebSocketHandlerAdapter;
|
||||
|
||||
public class SnakeWebSocketHandler extends TextWebSocketHandlerAdapter {
|
||||
|
||||
public static final int PLAYFIELD_WIDTH = 640;
|
||||
public static final int PLAYFIELD_HEIGHT = 480;
|
||||
public static final int GRID_SIZE = 10;
|
||||
public static final int PLAYFIELD_WIDTH = 640;
|
||||
public static final int PLAYFIELD_HEIGHT = 480;
|
||||
public static final int GRID_SIZE = 10;
|
||||
|
||||
private static final AtomicInteger snakeIds = new AtomicInteger(0);
|
||||
private static final Random random = new Random();
|
||||
private static final AtomicInteger snakeIds = new AtomicInteger(0);
|
||||
private static final Random random = new Random();
|
||||
|
||||
private final int id;
|
||||
private Snake snake;
|
||||
|
||||
private final int id;
|
||||
private Snake snake;
|
||||
public static String getRandomHexColor() {
|
||||
float hue = random.nextFloat();
|
||||
// sat between 0.1 and 0.3
|
||||
float saturation = (random.nextInt(2000) + 1000) / 10000f;
|
||||
float luminance = 0.9f;
|
||||
Color color = Color.getHSBColor(hue, saturation, luminance);
|
||||
return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
public static String getRandomHexColor() {
|
||||
float hue = random.nextFloat();
|
||||
// sat between 0.1 and 0.3
|
||||
float saturation = (random.nextInt(2000) + 1000) / 10000f;
|
||||
float luminance = 0.9f;
|
||||
Color color = Color.getHSBColor(hue, saturation, luminance);
|
||||
return '#' + Integer.toHexString(
|
||||
(color.getRGB() & 0xffffff) | 0x1000000).substring(1);
|
||||
}
|
||||
public static Location getRandomLocation() {
|
||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH));
|
||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT));
|
||||
return new Location(x, y);
|
||||
}
|
||||
|
||||
private static int roundByGridSize(int value) {
|
||||
value = value + (GRID_SIZE / 2);
|
||||
value = value / GRID_SIZE;
|
||||
value = value * GRID_SIZE;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Location getRandomLocation() {
|
||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH));
|
||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT));
|
||||
return new Location(x, y);
|
||||
}
|
||||
public SnakeWebSocketHandler() {
|
||||
this.id = snakeIds.getAndIncrement();
|
||||
}
|
||||
|
||||
|
||||
private static int roundByGridSize(int value) {
|
||||
value = value + (GRID_SIZE / 2);
|
||||
value = value / GRID_SIZE;
|
||||
value = value * GRID_SIZE;
|
||||
return value;
|
||||
}
|
||||
|
||||
public SnakeWebSocketHandler() {
|
||||
this.id = snakeIds.getAndIncrement();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||
this.snake = new Snake(id, session);
|
||||
SnakeTimer.addSnake(snake);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator();
|
||||
iterator.hasNext();) {
|
||||
Snake snake = iterator.next();
|
||||
sb.append(String.format("{id: %d, color: '%s'}",
|
||||
Integer.valueOf(snake.getId()), snake.getHexColor()));
|
||||
if (iterator.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
SnakeTimer.broadcast(String.format("{'type': 'join','data':[%s]}",
|
||||
sb.toString()));
|
||||
}
|
||||
this.snake = new Snake(this.id, session);
|
||||
SnakeTimer.addSnake(this.snake);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator(); iterator
|
||||
.hasNext();) {
|
||||
Snake snake = iterator.next();
|
||||
sb.append(String.format("{id: %d, color: '%s'}",
|
||||
Integer.valueOf(snake.getId()), snake.getHexColor()));
|
||||
if (iterator.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
SnakeTimer
|
||||
.broadcast(String.format("{'type': 'join','data':[%s]}", sb.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message)
|
||||
throws Exception {
|
||||
String payload = message.getPayload();
|
||||
if ("west".equals(payload)) {
|
||||
this.snake.setDirection(Direction.WEST);
|
||||
}
|
||||
else if ("north".equals(payload)) {
|
||||
this.snake.setDirection(Direction.NORTH);
|
||||
}
|
||||
else if ("east".equals(payload)) {
|
||||
this.snake.setDirection(Direction.EAST);
|
||||
}
|
||||
else if ("south".equals(payload)) {
|
||||
this.snake.setDirection(Direction.SOUTH);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||
String payload = message.getPayload();
|
||||
if ("west".equals(payload)) {
|
||||
snake.setDirection(Direction.WEST);
|
||||
} else if ("north".equals(payload)) {
|
||||
snake.setDirection(Direction.NORTH);
|
||||
} else if ("east".equals(payload)) {
|
||||
snake.setDirection(Direction.EAST);
|
||||
} else if ("south".equals(payload)) {
|
||||
snake.setDirection(Direction.SOUTH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
|
||||
SnakeTimer.removeSnake(snake);
|
||||
SnakeTimer.broadcast(String.format("{'type': 'leave', 'id': %d}",
|
||||
Integer.valueOf(id)));
|
||||
}
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status)
|
||||
throws Exception {
|
||||
SnakeTimer.removeSnake(this.snake);
|
||||
SnakeTimer.broadcast(String.format("{'type': 'leave', 'id': %d}",
|
||||
Integer.valueOf(this.id)));
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.boot.samples.websocket.echo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
package org.springframework.boot.samples.websocket.echo;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -40,6 +39,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
|
||||
import org.springframework.web.socket.client.endpoint.StandardWebSocketClient;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class SampleWebSocketsApplicationTests {
|
||||
|
||||
private static Log logger = LogFactory.getLog(SampleWebSocketsApplicationTests.class);
|
||||
@ -55,7 +56,7 @@ public class SampleWebSocketsApplicationTests {
|
||||
new Callable<ConfigurableApplicationContext>() {
|
||||
@Override
|
||||
public ConfigurableApplicationContext call() throws Exception {
|
||||
return (ConfigurableApplicationContext) SpringApplication
|
||||
return SpringApplication
|
||||
.run(SampleWebSocketsApplication.class);
|
||||
}
|
||||
});
|
||||
@ -71,7 +72,8 @@ public class SampleWebSocketsApplicationTests {
|
||||
|
||||
@Test
|
||||
public void runAndWait() throws Exception {
|
||||
ConfigurableApplicationContext context = (ConfigurableApplicationContext) SpringApplication.run(ClientConfiguration.class, "--spring.main.web_environment=false");
|
||||
ConfigurableApplicationContext context = SpringApplication.run(
|
||||
ClientConfiguration.class, "--spring.main.web_environment=false");
|
||||
long count = context.getBean(ClientConfiguration.class).latch.getCount();
|
||||
context.close();
|
||||
assertEquals(0, count);
|
||||
@ -84,15 +86,16 @@ public class SampleWebSocketsApplicationTests {
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
logger.info("Waiting for response: latch=" + latch.getCount());
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
logger.info("Got response: latch=" + latch.getCount());
|
||||
logger.info("Waiting for response: latch=" + this.latch.getCount());
|
||||
this.latch.await(10, TimeUnit.SECONDS);
|
||||
logger.info("Got response: latch=" + this.latch.getCount());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketConnectionManager wsConnectionManager() {
|
||||
|
||||
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), handler(), WS_URI);
|
||||
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(),
|
||||
handler(), WS_URI);
|
||||
manager.setAutoStartup(true);
|
||||
|
||||
return manager;
|
||||
@ -105,7 +108,7 @@ public class SampleWebSocketsApplicationTests {
|
||||
|
||||
@Bean
|
||||
public SimpleClientWebSocketHandler handler() {
|
||||
return new SimpleClientWebSocketHandler(greetingService(), latch);
|
||||
return new SimpleClientWebSocketHandler(greetingService(), this.latch);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -1,9 +1,25 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.samples.websocket.snake;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
@ -12,13 +28,13 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
public class SnakeTimerTests {
|
||||
|
||||
@Test
|
||||
public void removeDysfunctionalSnakes() throws Exception {
|
||||
Snake snake = mock(Snake.class);
|
||||
doThrow(new IOException()).when(snake).sendMessage(anyString());
|
||||
SnakeTimer.addSnake(snake);
|
||||
@Test
|
||||
public void removeDysfunctionalSnakes() throws Exception {
|
||||
Snake snake = mock(Snake.class);
|
||||
doThrow(new IOException()).when(snake).sendMessage(anyString());
|
||||
SnakeTimer.addSnake(snake);
|
||||
|
||||
SnakeTimer.broadcast("");
|
||||
assertThat(SnakeTimer.getSnakes().size(), is(0));
|
||||
}
|
||||
SnakeTimer.broadcast("");
|
||||
assertThat(SnakeTimer.getSnakes().size(), is(0));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user