mirror of
https://github.com/kmitresse/Cards-Rush.git
synced 2026-05-13 17:11:49 +00:00
feat(DevWeb): Create WebsocketToolkit.js
This commit is contained in:
@@ -91,7 +91,7 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
<version>3.3.2</version>
|
<version>3.3.2</version>
|
||||||
</plugin>
|
</plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>16</source><target>16</target></configuration></plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package uppa.project.json.websocket;
|
package uppa.project.json.websocket;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
public class Message {
|
public class Message {
|
||||||
|
private final static Gson gson = new Gson();
|
||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
private final String data;
|
private final String data;
|
||||||
|
|
||||||
@@ -17,6 +21,10 @@ public class Message {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toJson() {
|
||||||
|
return gson.toJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Message{" + "type=" + type + ", data=" + data + '}';
|
return "Message{" + "type=" + type + ", data=" + data + '}';
|
||||||
|
|||||||
@@ -5,45 +5,50 @@ import jakarta.websocket.OnClose;
|
|||||||
import jakarta.websocket.OnError;
|
import jakarta.websocket.OnError;
|
||||||
import jakarta.websocket.OnMessage;
|
import jakarta.websocket.OnMessage;
|
||||||
import jakarta.websocket.OnOpen;
|
import jakarta.websocket.OnOpen;
|
||||||
import jakarta.websocket.RemoteEndpoint;
|
|
||||||
import jakarta.websocket.Session;
|
import jakarta.websocket.Session;
|
||||||
|
import jakarta.websocket.server.PathParam;
|
||||||
import jakarta.websocket.server.ServerEndpoint;
|
import jakarta.websocket.server.ServerEndpoint;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import uppa.project.database.dao.DAO;
|
||||||
|
import uppa.project.database.dao.DAOException;
|
||||||
|
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
||||||
import uppa.project.database.pojo.User;
|
import uppa.project.database.pojo.User;
|
||||||
import uppa.project.json.websocket.Message;
|
import uppa.project.json.websocket.Message;
|
||||||
|
|
||||||
@ServerEndpoint(value = "/ws/connected-users")
|
@ServerEndpoint(value = "/ws/users/{user_id}")
|
||||||
public class ConnectedUsersWS {
|
public class ConnectedUsersWS {
|
||||||
|
|
||||||
public static final HashMap<Session, User> connections = new HashMap<>();
|
public static final HashMap<Session, User> users = new HashMap<>();
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void onOpen(Session session) {}
|
public void onOpen(Session session, @PathParam("user_id") String userId) throws DAOException {
|
||||||
|
Message message;
|
||||||
|
final DAO<User> userDAO = new Game_JPA_DAO_Factory().getDAOUser();
|
||||||
|
|
||||||
private void broadcastConnectedUsers() {
|
int id = Integer.parseInt(userId);
|
||||||
Gson gson = new Gson();
|
User user = userDAO.findById(id);
|
||||||
User[] connectedUsers = connections.values().toArray(new User[0]);
|
|
||||||
|
|
||||||
Message websocketObject = new Message("userList", gson.toJson(connectedUsers));
|
// Send the new user to all connected users
|
||||||
String message = gson.toJson(websocketObject);
|
message = new Message("addUser", gson.toJson(new SimpleUser(user)));
|
||||||
|
broadcast(message.toJson());
|
||||||
|
|
||||||
for (Session session : connections.keySet()) {
|
// Send all connected users to the new user
|
||||||
RemoteEndpoint.Basic remote = session.getBasicRemote();
|
users.put(session, user);
|
||||||
try {
|
ArrayList<SimpleUser> connectedUsers = new ArrayList<>();
|
||||||
remote.sendText(message);
|
for (User u : users.values()) connectedUsers.add(new SimpleUser(u));
|
||||||
} catch (IOException e) {
|
message = new Message("init", gson.toJson(connectedUsers));
|
||||||
e.printStackTrace();
|
session.getAsyncRemote().sendText(message.toJson());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClose
|
@OnClose
|
||||||
public void onClose(Session session) {
|
public void onClose(Session session) {
|
||||||
connections.remove(session);
|
users.remove(session);
|
||||||
|
|
||||||
// Update connected users list
|
Message message = new Message("removeUser", gson.toJson(new SimpleUser(users.get(session))));
|
||||||
broadcastConnectedUsers();
|
broadcast(message.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnError
|
@OnError
|
||||||
@@ -53,13 +58,26 @@ public class ConnectedUsersWS {
|
|||||||
|
|
||||||
@OnMessage
|
@OnMessage
|
||||||
public void onMessage(String message, Session session) {
|
public void onMessage(String message, Session session) {
|
||||||
Gson gson = new Gson();
|
// Do nothing
|
||||||
Message websocketMessage = gson.fromJson(message, Message.class);
|
}
|
||||||
|
|
||||||
if (websocketMessage.getType().equals("linkUserSession")) {
|
private static void broadcast(String message) {
|
||||||
User user = gson.fromJson(websocketMessage.getData(), User.class);
|
for (Session session : users.keySet()) {
|
||||||
connections.put(session, user);
|
try {
|
||||||
broadcastConnectedUsers();
|
session.getBasicRemote().sendText(message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SimpleUser {
|
||||||
|
public int id;
|
||||||
|
public String username;
|
||||||
|
|
||||||
|
public SimpleUser(User user) {
|
||||||
|
this.id = user.getId().intValue();
|
||||||
|
this.username = user.getUsername();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +1,63 @@
|
|||||||
|
<jsp:useBean id="user" scope="session" type="uppa.project.database.pojo.User"/>
|
||||||
<%@tag description="component/connected-user-list" pageEncoding="UTF-8" %>
|
<%@tag description="component/connected-user-list" pageEncoding="UTF-8" %>
|
||||||
|
|
||||||
<%@tag import="com.google.gson.Gson" %>
|
<%@tag import="com.google.gson.Gson" %>
|
||||||
<%@tag import="uppa.project.database.pojo.User" %>
|
|
||||||
|
|
||||||
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
|
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
|
||||||
|
|
||||||
|
<%@attribute name="anonymous"%>
|
||||||
|
|
||||||
<table id="connected-user-list" class="table is-fullwidth">
|
<table id="connected-user-list" class="table is-fullwidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Utilisateur</th>
|
<th>Utilisateur</th>
|
||||||
<%-- <th>Nombre de parties</th>--%>
|
|
||||||
<%-- <th>Victoires (%)</th>--%>
|
|
||||||
<%-- <th>Clics corrects (%)</th>--%>
|
|
||||||
<%-- <th>Clics rapides (%)</th>--%>
|
|
||||||
<%-- <th>Action</th>--%>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<script defer type="module">
|
<script defer type="module">
|
||||||
const tbodyElement = document.querySelector('#connected-user-list tbody');
|
import WebsocketToolkit from "${pageContext.request.contextPath}/static/js/WebsocketToolkit.js";
|
||||||
|
|
||||||
// effacer ce qu'il y a apres /project_war_exploded
|
let users = [];
|
||||||
const url = new URL(window.location.href);
|
function updateUsers() {
|
||||||
url.pathname = "${pageContext.request.contextPath}/ws/connected-users";
|
const table = document.querySelector('#connected-user-list tbody');
|
||||||
url.protocol = "ws:"
|
|
||||||
|
|
||||||
const websocket = new WebSocket(url);
|
// Clear the table
|
||||||
|
table.innerHTML = '';
|
||||||
|
|
||||||
<%
|
// Add the users to the table
|
||||||
Gson gson = new Gson();
|
|
||||||
User user = (User) request.getSession().getAttribute("user");
|
|
||||||
%>
|
|
||||||
websocket.onopen = () => {
|
|
||||||
const linkUserSession = {
|
|
||||||
type: 'linkUserSession',
|
|
||||||
data: JSON.stringify(<%= gson.toJson(user) %>)
|
|
||||||
}
|
|
||||||
websocket.send(JSON.stringify(linkUserSession));
|
|
||||||
}
|
|
||||||
|
|
||||||
websocket.onmessage = (event) => {
|
|
||||||
const data = JSON.parse(event.data);
|
|
||||||
|
|
||||||
if (data.type === 'userList') {
|
|
||||||
const users = JSON.parse(data.data);
|
|
||||||
updateUserList(users);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
websocket.onclose = () => {}
|
|
||||||
websocket.onerror = (error) => console.error(error);
|
|
||||||
|
|
||||||
function updateUserList(users) {
|
|
||||||
tbodyElement.innerHTML = '';
|
|
||||||
users.forEach(user => {
|
users.forEach(user => {
|
||||||
const trElement = document.createElement('tr');
|
const tr = document.createElement('tr');
|
||||||
const tdElement = [
|
const td = document.createElement('td');
|
||||||
document.createElement('td'),
|
|
||||||
// document.createElement('td'),
|
|
||||||
// document.createElement('td'),
|
|
||||||
// document.createElement('td'),
|
|
||||||
// document.createElement('td'),
|
|
||||||
// document.createElement('td')
|
|
||||||
];
|
|
||||||
// const buttonElement = document.createElement('button');
|
|
||||||
|
|
||||||
tdElement[0].textContent = user.username;
|
td.dataset.id = user.id;
|
||||||
// tdElement[1].textContent = user.nbPlayedGames;
|
td.textContent = user.username;
|
||||||
// tdElement[2].textContent = user.WinRate + '%';
|
|
||||||
// tdElement[3].textContent = user.rightClickPercentRate + '%';
|
|
||||||
// tdElement[4].textContent = user.rapidClickPercentRate + '%';
|
|
||||||
|
|
||||||
// If it's not the current user, we can display the button
|
tr.appendChild(td);
|
||||||
<%--if (user.id !== <%= user.getId() %>) {--%>
|
table.appendChild(tr);
|
||||||
<%-- buttonElement.classList.add('button', 'is-light');--%>
|
|
||||||
<%-- buttonElement.textContent = 'Inviter';--%>
|
|
||||||
|
|
||||||
<%-- // TODO Ajouter l'événement click--%>
|
|
||||||
<%--}--%>
|
|
||||||
|
|
||||||
// tdElement[5].appendChild(buttonElement);
|
|
||||||
trElement.appendChild(tdElement[0]);
|
|
||||||
// trElement.appendChild(tdElement[1]);
|
|
||||||
// trElement.appendChild(tdElement[2]);
|
|
||||||
// trElement.appendChild(tdElement[3]);
|
|
||||||
// trElement.appendChild(tdElement[4]);
|
|
||||||
// trElement.appendChild(tdElement[5]);
|
|
||||||
|
|
||||||
tbodyElement.appendChild(trElement);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new WebSocket
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.pathname = "${pageContext.request.contextPath}/ws/users/${user.id}";
|
||||||
|
url.protocol = "ws:"
|
||||||
|
|
||||||
|
const ws = new WebsocketToolkit(url);
|
||||||
|
ws.onOpen(() => console.log("Connected to the server"));
|
||||||
|
ws.onMessage("init", (data) => {
|
||||||
|
users = data;
|
||||||
|
updateUsers();
|
||||||
|
});
|
||||||
|
ws.onMessage("addUser", (data) => {
|
||||||
|
users.push(data);
|
||||||
|
updateUsers();
|
||||||
|
});
|
||||||
|
ws.onMessage("removeUser", (data) => {
|
||||||
|
users = users.filter(user => user.id !== data.id);
|
||||||
|
updateUsers();
|
||||||
|
});
|
||||||
|
ws.onError((error) => console.error(error));
|
||||||
|
ws.onClose(() => console.log("Disconnected from the server"));
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
<% if (session.getAttribute("user") != null) { %>
|
<% if (session.getAttribute("user") != null) { %>
|
||||||
|
|
||||||
<a class="navbar-item" href="${pageContext.request.contextPath}/lobby">
|
<a class="navbar-item" href="${pageContext.request.contextPath}/lobby">
|
||||||
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260">
|
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260" alt="Logo">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
|
|
||||||
<a class="navbar-item" href="${pageContext.request.contextPath}/">
|
<a class="navbar-item" href="${pageContext.request.contextPath}/">
|
||||||
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260">
|
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260" alt="Logo">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
export default class Message {
|
||||||
|
constructor(rawMessage) {
|
||||||
|
// Parse the message
|
||||||
|
const message = JSON.parse(rawMessage);
|
||||||
|
message.data = JSON.parse(message.data);
|
||||||
|
|
||||||
|
console.log(message);
|
||||||
|
|
||||||
|
// Set the message properties
|
||||||
|
this.type = message.type;
|
||||||
|
this.data = message.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import Message from "./Message.js";
|
||||||
|
|
||||||
|
export default class WebsocketToolkit {
|
||||||
|
|
||||||
|
action = {}
|
||||||
|
|
||||||
|
constructor(url) {
|
||||||
|
this.url = url;
|
||||||
|
this.ws = new WebSocket(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen(callback) {
|
||||||
|
this.ws.onopen = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(type, callback) {
|
||||||
|
this.action[type] = callback;
|
||||||
|
this.ws.onmessage = (event) => {
|
||||||
|
const message = new Message(event.data);
|
||||||
|
this.action[message.type](message.data)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose(callback) {
|
||||||
|
this.ws.onclose = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(callback) {
|
||||||
|
this.ws.onerror = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const nbColorsElement = document.getElementById("nbColors");
|
|
||||||
const nbValuesElement = document.getElementById("nbValues");
|
|
||||||
const nbRoundsElement = document.getElementById("nbRounds")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mise à jour du nombre de rounds max en fonction du nombre de couleurs et de valeurs séléctionnés
|
|
||||||
*/
|
|
||||||
function updateOnChange() {
|
|
||||||
nbRoundsElement.max = nbColorsElement.value * nbValuesElement.value;
|
|
||||||
|
|
||||||
nbRoundsElement.value =
|
|
||||||
(nbRoundsElement.value > nbRoundsElement.max)
|
|
||||||
? nbRoundsElement.max
|
|
||||||
: nbRoundsElement.value
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
nbColorsElement.addEventListener("change", updateOnChange);
|
|
||||||
nbValuesElement.addEventListener("change", updateOnChange);
|
|
||||||
Reference in New Issue
Block a user