Changed event model

+ MoveEvent
This commit is contained in:
Kai S. K. Engelbart 2019-08-07 18:54:00 +02:00
parent 9d7d84302e
commit 50111729ad
Signed by: kske
GPG Key ID: 8BEB13EC5DF7EF13
8 changed files with 87 additions and 94 deletions

View File

@ -0,0 +1,15 @@
package dev.kske.chess.event;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>Event.java</strong><br>
* Created: <strong>7 Aug 2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public interface Event<T> {
/**
* @return The data associated with the event
*/
T getData();
}

View File

@ -1,22 +1,17 @@
package dev.kske.chess.event;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>EventBus.java</strong><br>
* Created: <strong>02.08.2019</strong><br>
* Created: <strong>7 Aug 2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public final class EventBus {
public class EventBus {
private Map<Class<?>, List<Invocation>> invocations;
private List<Subscribable> subscribers;
private static EventBus instance;
@ -26,40 +21,16 @@ public final class EventBus {
}
private EventBus() {
invocations = new ConcurrentHashMap<>();
subscribers = new ArrayList<>();
}
public void post(Object object) {
Class<?> type = object.getClass();
if (invocations.containsKey(type)) invocations.get(type).forEach(invocation -> invocation.invoke(object));
public void register(Subscribable subscribable) {
subscribers.add(subscribable);
}
public void register(Object object) {
Class<?> currentClass = object.getClass();
while (currentClass != null) {
for (Method method : findSubscriptionMethods(currentClass)) {
Class<?> type = method.getParameterTypes()[0];
if (invocations.containsKey(type)) invocations.get(type).add(new Invocation(method, object));
else {
List<Invocation> temp = new Vector<>();
temp.add(new Invocation(method, object));
invocations.put(type, temp);
}
}
currentClass = currentClass.getSuperclass();
}
public void dispatch(Event<?> event) {
subscribers.stream().filter(e -> e.supports().contains(event.getClass())).forEach(e -> e.handle(event));
}
private List<Method> findSubscriptionMethods(Class<?> type) {
List<Method> subscriberMethods = Arrays.stream(type.getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(Subscribe.class))
.collect(Collectors.toList());
checkSubscriberMethods(subscriberMethods);
return subscriberMethods;
}
private void checkSubscriberMethods(List<Method> subscriberMethods) {
if (subscriberMethods.stream().anyMatch(method -> method.getParameterCount() != 1))
throw new IllegalArgumentException("Method annotated with @Subscribe must have exactly one parameter");
}
public List<Subscribable> getSubscribers() { return subscribers; }
}

View File

@ -1,29 +0,0 @@
package dev.kske.chess.event;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>Invocation.java</strong><br>
* Created: <strong>02.08.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public final class Invocation {
private final Method method;
private final Object object;
public Invocation(Method method, Object object) {
this.method = method;
this.object = object;
}
public void invoke(Object arg) {
try {
method.invoke(object, arg);
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,21 @@
package dev.kske.chess.event;
import dev.kske.chess.board.Move;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>MoveEvent.java</strong><br>
* Created: <strong>7 Aug 2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public class MoveEvent implements Event<Move> {
private final Move move;
public MoveEvent(Move move) {
this.move = move;
}
@Override
public Move getData() { return move; }
}

View File

@ -0,0 +1,24 @@
package dev.kske.chess.event;
import java.util.Set;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>Subscribable.java</strong><br>
* Created: <strong>7 Aug 2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public interface Subscribable {
/**
* Consumes an event dispatched by an event bus.
*
* @param event The event dispatched by the event bus, only of supported type
*/
void handle(Event<?> event);
/**
* @return A set of classes this class is supposed to handle in events
*/
Set<Class<?>> supports();
}

View File

@ -1,19 +0,0 @@
package dev.kske.chess.event;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(METHOD)
/**
* Project: <strong>Chess</strong><br>
* File: <strong>Subscribe.java</strong><br>
* Created: <strong>02.08.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public @interface Subscribe {
}

View File

@ -10,6 +10,7 @@ import dev.kske.chess.board.GameState;
import dev.kske.chess.board.Move;
import dev.kske.chess.board.Piece.Color;
import dev.kske.chess.event.EventBus;
import dev.kske.chess.event.MoveEvent;
import dev.kske.chess.game.ai.AIPlayer;
import dev.kske.chess.ui.BoardComponent;
import dev.kske.chess.ui.BoardPane;
@ -66,7 +67,7 @@ public class Game {
System.out.printf("%s: %s%n", player.color, move);
System.out.println("FEN: " + board.toFEN());
EventBus.getInstance().post(move);
EventBus.getInstance().dispatch(new MoveEvent(move));
GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite());
switch (eventType) {
case CHECKMATE:

View File

@ -1,7 +1,10 @@
package dev.kske.chess.ui;
import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JPanel;
@ -12,9 +15,10 @@ import javax.swing.table.DefaultTableModel;
import dev.kske.chess.board.Log;
import dev.kske.chess.board.Log.LoggedMove;
import dev.kske.chess.board.Move;
import dev.kske.chess.event.Event;
import dev.kske.chess.event.EventBus;
import dev.kske.chess.event.Subscribe;
import dev.kske.chess.event.MoveEvent;
import dev.kske.chess.event.Subscribable;
/**
* Project: <strong>Chess</strong><br>
@ -22,7 +26,7 @@ import dev.kske.chess.event.Subscribe;
* Created: <strong>17.07.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public class LogFrame extends JFrame {
public class LogFrame extends JFrame implements Subscribable {
private static final long serialVersionUID = 1932671698254197119L;
@ -50,11 +54,16 @@ public class LogFrame extends JFrame {
mcontentPane.add(new JScrollPane(mtable), BorderLayout.CENTER);
EventBus.getInstance().register(this);
EventBus.getInstance().post(new Move(0, 0, 0, 0));
handle(null);
}
@Subscribe
public void updateData(Move move) {
@Override
public Set<Class<?>> supports() {
return new HashSet<>(Arrays.asList(MoveEvent.class));
}
@Override
public void handle(Event<?> event) {
final List<LoggedMove> moves = log.getLoggedMoves();
String[][] data = new String[moves.size() / 2 + moves.size() % 2][2];
for (int i = 0; i < data.length; i++) {