Merge pull request #136 from ThomasRubini/graphicalRefactor

Graphical refactor + other fix
This commit is contained in:
Djalim Simaila 2023-04-01 17:01:28 +02:00 committed by GitHub
commit 4c4aeb3edb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 419 additions and 84 deletions

View File

@ -52,6 +52,16 @@ def get_npc_random_answer(npc_id:int, qa_type:int) -> Answer :
answers = db.session.query(Answer).filter_by(QUESTION_TYPE_ID=qa_type,NPC_ID=npc_id.NPC_ID).all()
return random.choice(answers)
def get_npc_from_npc_id(npc_id: int) -> Npc:
"""
Gets a Npc object from a npc_id
:param npc_id: the id of the trait to search for
:return: a Npc object
"""
npc = db.session.query(Npc).filter_by(NPC_ID=npc_id).one()
return npc
def get_random_question(qa_type: int) -> QuestionType :
"""
Returns a random inspector question from a question type
@ -93,6 +103,18 @@ def get_reaction_description(lang, trait_id) -> str:
desc_lid = db.session.query(Trait).filter_by(TRAIT_ID=trait_id).one().DESC_LID
return get_text_from_lid(lang, desc_lid)
def get_reaction_from_npc_and_trait(npc_id: int,trait_id:int )-> Reaction:
"""_summary_
Args:
npc_id (int): _description_
trait_id (int): _description_
Returns:
Reaction: _description_
"""
return db.session.query(Reaction).filter_by(NPC_ID=npc_id,TRAIT_ID=trait_id).one()
def get_traits(lang: str) -> list:
"""
Returns the list of all possible reactions trait in the given language
@ -103,4 +125,15 @@ def get_traits(lang: str) -> list:
traits = []
for trait in db.session.query(Trait).all():
traits.append(get_text_from_lid(lang,trait.NAME_LID))
return traits
return traits
def get_reaction_from_uuid(input_uuid: str) -> Reaction :
"""_summary_ TODO
Args:
input_uuid (str): _description_
Returns:
Reaction: _description_
"""
return db.session.query(Reaction).filter_by(REACTION_UUID=input_uuid).one()

View File

@ -198,9 +198,9 @@ class Reaction(Base):
NPC_ID = Column(Integer, ForeignKey("T_NPC.NPC_ID"), primary_key=True, comment="Name of the NPC that will have this reaction")
TRAIT_ID = Column(Integer, ForeignKey("T_TRAIT.TRAIT_ID"), primary_key=True, comment="ID of the trait of this reaction")
IMG = Column(LargeBinary(length=2**24), comment="Binary data of the image associated to this npc and trait")
REACTION_UUID = Column(VARCHAR(255), unique=True, comment="ID of this reaction")
NPC = relationship("Npc")
TRAIT = relationship("Trait")
REACTION_UUID = Column(VARCHAR(255), unique=True, comment="ID of this reaction")
def __init__(self, REACTION_ID, NPC_ID, TRAIT_ID):
self.REACTION_ID = REACTION_ID

View File

@ -3,8 +3,6 @@ import time
import random
from typing import Union
from sqlalchemy import select, and_
from truthinquiry.ext.database.models import *
from truthinquiry.ext.database.fsa import db
from truthinquiry.ext.database import dbutils
@ -90,6 +88,7 @@ class Game:
trait_id = self.reaction_table[npc_id]
trait = dbutils.get_trait_from_trait_id(trait_id)
npcs[npc_id]["reaction"] = dbutils.get_text_from_lid("FR", trait.NAME_LID)
npcs[npc_id]["uuid"] = dbutils.get_reaction_from_npc_and_trait(npc_id,self.reaction_table[npc_id]).REACTION_UUID
npcs[npc_id]["description"] = dbutils.get_reaction_description("FR", trait.TRAIT_ID)
player_results = data["player"] = {}
for member in self.members:
@ -140,11 +139,7 @@ class Game:
if npc_id not in self.reaction_table:
return None
trait_id = self.reaction_table[npc_id]
reaction = db.session.execute(
select(Reaction)
.where(and_(Reaction.NPC_ID == int(npc_id), Reaction.TRAIT_ID == int(trait_id)))
).one()[0]
reaction = dbutils.get_reaction_from_npc_and_trait(npc_id,trait_id)
return reaction.IMG
def get_player_results(self, responses: dict) -> Union[dict, None]:
@ -347,5 +342,15 @@ def get_npc_image(npc_id: int):
:param npc_id: npc to get the neutral image from
:return: the byte representation of the image, none if its not found or not readable
"""
npc = db.session.execute(select(Npc).where(Npc.NPC_ID==npc_id)).one()[0]
npc = dbutils.get_npc_from_npc_id(npc_id)
return npc.DEFAULT_IMG
def get_reactions_image_from_uuid(uuid: str):
"""
Returns the byte representation of the neutral image for an npc
:param npc_id: npc to get the neutral image from
:return: the byte representation of the image, none if its not found or not readable
"""
reaction = dbutils.get_reaction_from_uuid(uuid)
return reaction.IMG

View File

@ -85,12 +85,16 @@ def join_game():
if not game.add_member(username):
return {"error": 1, "msg": f"Username '{username}' already used in game {game.game_id}"}
if game.has_started:
return {"error": 1, "msg": f"Game {game.game_id} has already started"}
flask.session["game_id"] = game.game_id
flask.session["is_owner"] = False
flask.session["username"] = username
socket_io.emit("playersjoin", [flask.session["username"]], room="game."+game.game_id)
socket_io.emit("playersjoin", flask.session["username"], room="game."+game.game_id)
return {"error": 0}
@ -199,14 +203,11 @@ def get_npc_reaction():
@routes_api.route("/getReaction", methods=["GET", "POST"])
def get_reaction():
input_uuid = flask.request.values.get("uuid")
results = db.session.execute(select(Reaction).where(Reaction.REACTION_UUID==input_uuid))
row = results.first()
if row == None:
image = game_logic.get_reactions_image_from_uuid(input_uuid)
if image is None:
return {"error": 1, "msg": "No such reaction"}
reaction_obj = row[0]
return flask.send_file(io.BytesIO(reaction_obj.IMG), mimetype='image/png')
return flask.send_file(io.BytesIO(image), mimetype='image/png')
@ -230,6 +231,24 @@ def game_progress():
return {"error": 0}
@routes_api.route("/chatMessage", methods=["GET", "POST"])
def chat_message():
if not flask.session:
return {"error": 1, "msg": "No session"}
game_id = flask.session["game_id"]
if not game_logic.check_game_id(game_id):
return {"error": 1, "msg": "invalid game_id"}
game = game_logic.get_game(game_id)
if game is None:
return {"error": 1, "msg": "this game doesn't exist"}
username = flask.session["username"]
message_received = flask.request.values.get("msg")
message_sent = f"{username} : {message_received}"
socket_io.emit("chatMessage", message_sent, room="game."+game.game_id)
return {"error": 0}
@routes_api.route("/submitAnswers", methods=["GET", "POST"])
def check_anwser():

View File

@ -17,6 +17,23 @@
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-display: swap;
font-family: "Park Lane";
font-style: normal;
font-weight: 400;
src: url("../fonts/park_lane/parklane.regular.otf") format('otf'), url("../fonts/park_lane/parklane.regular.ttf") format('truetype');
}
@font-face {
font-display: swap;
font-family: "Ironick";
font-style: normal;
font-weight: 400;
src: url("../fonts/ironick_nf/IronickNF.otf") format('otf'), url("../fonts/ironick_nf/IronickNF.ttf") format('truetype');
}
@font-face {
font-display: swap;
font-family: "Roboto Mono";
@ -31,12 +48,14 @@
/* Colors */
color-scheme: dark;
--alert-dialog-background-color: #000000DF;
--dark-theme-background-color: #213C40;
--dark-theme-background-color: #0c0b0c;
--game-black: #000000;
--game-blue: #7DDCFF;
--game-green: #008000;
--game-grey: #5A5656;
--game-red: #BD1E1E;
--game-gold: rgb(214,168,81);
--game-dark-gold: #B9935A;
--game-white: #FFFFFF;
--light-theme-background-color: #B1EDE8;
/* Sizes */
@ -58,7 +77,7 @@ noscript .alert_dialog_background, noscript .alert_dialog_msg, noscript .alert_d
}
.action_button {
background-color: var(--game-red);
background-color: var(--game-dark-gold);
border-color: var(--game-black);
border-radius: var(--button-and-dialog-border-radius);
border-style: solid;
@ -89,8 +108,14 @@ noscript .alert_dialog_background, noscript .alert_dialog_msg, noscript .alert_d
/* Utility classes */
.hidden {
display: none !important;
transition: all 0.5s ease;
}
.gray {
filter: grayscale(1);
}
/* Links */
.link {
text-decoration: none;

View File

@ -12,8 +12,8 @@ html {
font-family: "Titan One", sans-serif;
}
.anwser_title, .emotion_and_culprit_choices_title, .introduction_text, .introduction_title, .interrogation_title, .results_title, .reveal_culprit_title, .score_title, .summary_title {
font-family: "Spicy Rice", serif;
.anwser_title, .emotion_and_culprit_choices_title, .introduction_text, .introduction_title, .interrogation_title, .results_title,.introduction_right ,.reveal_culprit_title, .score_title, .summary_title {
font-family: "Ironick", serif;
}
.culprit_btn, .interrogation, .player_score, .question_answer, .questions_and_image, .reveal_culprit, .reveal_score, .scores, .summary, .summary_suspect, .suspect_picture[alt], .suspect, .suspects, .suspects_list {
@ -50,7 +50,7 @@ html {
}
.emotion_and_culprit_choices_title, .interrogation_title, .introduction_title, .results_title, .reveal_culprit_title, .reveal_score, .score_title, .summary_title {
color: var(--game-red);
color: var(--game-gold);
}
.emotion_and_culprit_choices_title, .results_title, .reveal_culprit_title, .score_title, .summary, .summary_title, .suspect_picture[alt] {
@ -110,8 +110,33 @@ html {
}
.suspect_picture {
border: var(--game-dark-gold) solid 5px;
border-radius: 1em;
height: 15em;
width: 15em;
transition: all 0.5s ease;
}
.npc_answer{
flex-direction: column;
width: 40em;
}
.image_interrogation{
height: 25em;
width: 25em;
}
.question_answer{
border: var(--game-dark-gold) solid;
border-radius: 1em;
height: 6em;
background-color: #000000d0;
}
.suspect > .suspect_picture:hover {
filter: grayscale(0);
transition: all 0.5s ease;
background-color: #000000d0;
}
.suspect_picture[alt] {
@ -124,7 +149,7 @@ html {
}
.home_button, .next_btn {
fill: var(--game-red);
fill: var(--game-dark-gold);
height: 5em;
width: 5em;
}
@ -151,12 +176,21 @@ html {
/* Introduction */
.introduction {
padding: 1em;
display: flex;
flex-direction: row;
}
.introduction_left{
padding: 1em;
max-width: 50vw;
}
.introduction_text {
.introduction_right{
font-size: 2em;
padding: 1em;
max-width: 50vw;
}
.introduction_text {
font-size: 3em;
margin-bottom: 1em;
margin-top: 1em;
}
@ -166,13 +200,25 @@ html {
text-align: left;
}
.inspector_picture{
border: var(--game-dark-gold) solid 5px;
border-radius: 1em;
max-width: 45vw;
background-color: #000000d0;
}
.username{
font-size: 3em;
margin-bottom: 1em;
margin-top: 1em;
}
/* Interrogation */
.ask_button {
background-color: var(--game-white);
background-color: var(--game-dark-gold);
color: var(--game-black);
text-transform: none;
}
.anwser_title {
font-size: 2.5em;
margin: 0.25em;
@ -194,6 +240,16 @@ html {
#interrogation_suspect_previous_btn {
margin-right: 1em;
}
.suspect_name{
font-family: "Park Lane";
font-size: 2em;
color: var(--game-dark-gold);
border-radius: 0.25em;
margin: 0;
border: var(--game-dark-gold) solid 1px;
padding: 0.25em;
background-color: #000000dd;
}
/* Emotion and culprit choices */
.culprit_icon {
@ -203,6 +259,7 @@ html {
width: 1em;
}
.culprit_btn_checked {
background-color: var(--game-green);
}
@ -235,6 +292,13 @@ html {
}
/* Results and scores */
.explain {
border: var(--game-dark-gold) solid;
border-radius: 1em;
background-color: #000000d0;
}
.explain_suspect_emotion_description {
font-size: 1.25em;
font-weight: normal;
@ -283,3 +347,87 @@ html {
#return_lobby_button {
border: transparent;
}
* {box-sizing: border-box;}
/* chat */
/* Button used to open the chat form - fixed at the bottom of the page */
.open-button {
background-color: #000000dd;
color: var(--game-dark-gold);
padding: 16px 20px;
border: var(--game-dark-gold) solid;
border-radius: 1em;
cursor: pointer;
opacity: 0.8;
position: fixed;
bottom: 23px;
right: 28px;
width: 280px;
}
/* The popup chat - hidden by default */
.chat-popup {
display: none;
position: fixed;
bottom: 0;
color: var(--game-dark-gold);
right: 15px;
z-index: 9;
border: solid black 1px;
border-radius: 1em;
}
/* Add styles to the form container */
.form-container {
max-width: 300px;
padding: 10px;
border: solid var(--game-dark-gold);
border-radius: 1em;
background-color: black;
}
/* Full-width textarea */
.form-container textarea {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
background: #f1f1f1;
resize: none;
min-height: 5em;
}
/* When the textarea gets focus, do something */
#chat_message_box{
background-color: #505050;
outline: none;
margin: 10px;
}
.message{
list-style-type: none
}
/* Set a style for the submit/send button */
.form-container .btn {
background-color: black;
color: #04AA6D;
padding: 16px 20px;
border: #04AA6D solid;
border-radius: 1em;
cursor: pointer;
width: 100%;
margin-bottom:10px;
opacity: 0.8;
}
/* Add a red background color to the cancel button */
.form-container .cancel {
background-color: black;
color: red;
border-color: red;
}
/* Add some hover effects to buttons */
.form-container .btn:hover, .open-button:hover {
opacity: 1;
}

View File

@ -3,6 +3,18 @@ html {
background-color: var(--game-black);
color: var(--game-white);
}
.current_background {
background-position: center;
background-size: cover;
filter: blur(4px);
position: fixed;
height: 100%;
left: 0;
top: 0;
width: 100%;
/* Place the background behind everything */
z-index: -9999;
}
.action_button, .multi_player_mode_choice_title, .multi_player_mode_waiting_for_host, .player_name, .players_title, .rounds_count_title, .room_code_text_title, .room_title, #game_username, #rounds_count {
font-family: "Titan One", sans-serif;
@ -13,7 +25,7 @@ html {
}
.game_start_failed, .multi_player_challenge_mode_invalid_input, .room_code, .room_title {
color: var(--game-red);
color: var(--game-dark-gold);
}
.join_room_view, .multi_player_mode_choice, .multi_player_mode_choice_number, .players_title, .room_code_text, .room_view_container {
@ -133,6 +145,9 @@ html {
.multi_player_mode_choices {
padding: 1em;
border: var(--game-dark-gold) solid;
border-radius: 1em;
background-color: #000000d0;
}
/* Rounds count */
@ -163,7 +178,6 @@ html {
border-radius: 0.75em;
font-size: 1.25em;
max-height: 12em;
min-width: 25em;
overflow-y: scroll;
padding: 0.25em;
}

View File

@ -50,14 +50,15 @@ input::placeholder {
}
.back_btn {
fill: var(--game-red);
fill: var(--game-dark-gold);
}
.game_begin {
background-image: url("../images/start_background.png");
background-image: url("../images/start_background.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: var(--game-gold) solid 1px;
border-radius: 1.5em;
flex-wrap: wrap;
/*
@ -66,15 +67,14 @@ input::placeholder {
*/
height: calc(100vh - var(--body-margin) * 2
- var(--game-begin-margin) * 2
- var(--header-actions-side)
- var(--footer-links-height));
justify-content: center;
margin: var(--game-begin-margin);
}
.game_title {
color: var(--game-red);
font-family: "Spicy Rice", serif;
color: var(--game-gold);
font-family: "Ironick", serif;
font-size: 5em;
font-weight: bold;
margin: 0.25em;
@ -109,7 +109,7 @@ input::placeholder {
}
.game_mode_selection {
background-image: url("../images/start_background.png");
background-image: url("../images/start_background.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
@ -133,10 +133,6 @@ input::placeholder {
}
.game_mode_choice_selector {
background-color: var(--game-black);
border-color: var(--game-white);
border-style: solid;
border-radius: 1.5em;
padding: 1em;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 4.2 MiB

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

Before

Width:  |  Height:  |  Size: 5.7 MiB

After

Width:  |  Height:  |  Size: 5.7 MiB

View File

Before

Width:  |  Height:  |  Size: 5.8 MiB

After

Width:  |  Height:  |  Size: 5.8 MiB

View File

Before

Width:  |  Height:  |  Size: 602 KiB

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -1,8 +1,9 @@
const INTRO_IMAGE_PATH = "/static/images/entrée-manoir.png";
const INTERROGATION_IMAGE_PATH = "/static/images/salle-interrogation.png";
const RESULTS_IMAGE_PATH = "/static/images/salle-resultats.png";
const INTRO_IMAGE_PATH = "/static/images/entrée-manoir.jpg";
const INTERROGATION_IMAGE_PATH = "/static/images/salle-interrogation.jpg";
const RESULTS_IMAGE_PATH = "/static/images/salle-resultats.jpg";
const NPC_REACTION_PATH = "/api/v1/getNpcReaction?npcid=";
const NPC_IMAGE_PATH = "/api/v1/getNpcImage?npcid=";
const NPC_FINAL_REACTION_PATH = "/api/v1/getReaction?uuid="
let npcsIds = [];
let gameData = {};
@ -48,6 +49,32 @@ function unsetQuestionButtonsListeners() {
.removeEventListener("click", askTypeOneQuestion);
}
function setChatBoxButtonsListeners() {
document.getElementById("close_chat_button")
.addEventListener("click", closeForm);
document.getElementById("open_chat_button")
.addEventListener("click", openForm);
document.getElementById("chat_button_send")
.addEventListener("click", sendChatMessage);
}
/**
* Shows the chat box
*/
function openForm() {
document.getElementById("chatbox").style.display = "block";
}
/**
* Hides the chat box
*/
function closeForm() {
document.getElementById("chatbox").style.display = "none";
}
/**
* Go back to interrogation view, by hiding the interrogation suspect view.
*/
@ -179,7 +206,7 @@ async function askQuestion(buildAnswer) {
document.querySelector(".suspect_answer").textContent = buildAnswer(
getNpcLocationAndPartner(currentNpc));
showFirstClassElement("question_answer");
showFirstClassElement("suspect_answer");
document.getElementById("currentNpcPicure").src = NPC_REACTION_PATH + currentNpc;
@ -188,7 +215,7 @@ async function askQuestion(buildAnswer) {
await new Promise(r => setTimeout(r, 4000));
document.getElementById("currentNpcPicure").src = NPC_IMAGE_PATH + currentNpc;
hideFirstClassElement("question_answer");
hideFirstClassElement("suspect_answer");
document.querySelector(".suspect_answer").textContent = "";
@ -291,19 +318,35 @@ function createCulpritSvgElement(buttonCssClass, pathAttributeValue, isHidden) {
* Show the screen in which the player asks questions to the npcs.
*/
function renderInterrogation() {
if (gameData["solo"] === true) document.getElementById("open_chat_button").classList.add("hidden");
document.getElementById("QA_0").textContent = gameData["questions"]["QA_0"];
document.getElementById("QA_1").textContent = gameData["questions"]["QA_1"];
const interrogationSuspects = document.getElementById("interrogation_suspects");
npcsIds.forEach(element => {
npcsIds.forEach(npc_id => {
const suspect = document.createElement("li");
suspect.classList.add("suspect");
const name = document.createElement('p')
name.textContent = gameData['npcs'][npc_id]["name"]
name.classList.add("suspect_name");
suspect.appendChild(name);
const img = document.createElement('img');
img.id = "suspect_picture_of_" + npc_id
img.classList.add("suspect_picture");
img.setAttribute("alt", "Image d'un suspect");
img.src = NPC_IMAGE_PATH + element;
img.src = NPC_IMAGE_PATH + npc_id;
img.addEventListener("click", () => {
// TODO remove this listener when we know the questions has already been asked;
currentNpc = npc_id;
document.getElementById("suspect_picture_of_" + npc_id).classList.add("gray");
document.getElementById("currentNpcPicure").src = NPC_IMAGE_PATH + npc_id;
hideFirstClassElement("interrogation");
showFirstClassElement("interrogation_suspect");
});
suspect.appendChild(img);
const button = document.createElement("button");
@ -311,17 +354,29 @@ function renderInterrogation() {
button.textContent = "Interroger";
button.addEventListener("click", () => {
// TODO remove this listener when we know the questions has already been asked;
currentNpc = element;
document.getElementById("currentNpcPicure").src = NPC_IMAGE_PATH + element;
currentNpc = npc_id;
document.getElementById("suspect_picture_of_" + npc_id).classList.add("gray");
document.getElementById("currentNpcPicure").src = NPC_IMAGE_PATH + npc_id;
hideFirstClassElement("interrogation");
showFirstClassElement("interrogation_suspect");
});
suspect.appendChild(button);
interrogationSuspects.appendChild(suspect);
});
}
function sendChatMessage(){
const message = document.getElementById("chat_message_box").value;
const data = {};
data["msg"] = message;
makeAPIRequest("chatMessage",data);
document.getElementById("chat_message_box").value = '';
}
function renderIntroduction(){
document.getElementById("username").textContent += username;
}
/**
* Initialize the websocket for this page, its primary use is to show the final page once it
* receives the event that all players have finished.
@ -346,8 +401,16 @@ function initSock() {
socket.on("gameprogress", username => {
console.log(username);
});
socket.on("chatMessage", message => {
const message_received = document.createElement("li");
message_received.classList.add("message");
message_received.textContent = message;
document.getElementById("message_list").appendChild(message_received);
});
socket.on("gamefinished", finalResults => {
console.log(finalResults);
hideFirstClassElement("emotion_and_culprit_choices");
const revealScoreElement = document.createElement("h2");
revealScoreElement.classList.add("reveal_score");
@ -398,22 +461,25 @@ function initSock() {
const img = document.createElement("img");
img.setAttribute("alt", "Image d'un suspect");
img.src = NPC_IMAGE_PATH + npcid;
img.src = NPC_FINAL_REACTION_PATH + finalResults["npcs"][npcid]["uuid"];
suspect.appendChild(img);
const explain = document.createElement("div")
explain.classList.add("explain")
const emotionTitle = document.createElement("h2");
emotionTitle.classList.add("explain_suspect_emotion_title");
emotionTitle.textContent = "Ce suspect était "
+ finalResults["npcs"][npcid]["reaction"] + ".";
suspect.appendChild(emotionTitle);
explain.appendChild(emotionTitle);
const emotionDesc = document.createElement("p");
emotionDesc.classList.add("explain_suspect_emotion_description");
emotionDesc.textContent = "Cette émotion se caractérise par "
+ finalResults["npcs"][npcid]["description"];
suspect.appendChild(emotionDesc);
explain.appendChild(emotionDesc);
suspect.appendChild(explain)
suspectListElement.appendChild(suspect);
});
});
@ -439,10 +505,12 @@ async function setGameData() {
async function initGame() {
await setGameData();
initSock();
renderIntroduction();
renderAnswerSelectionPanel();
renderInterrogation();
setQuestionButtonsListeners()
setIntroductionAndInterrogationListeners();
setChatBoxButtonsListeners();
showFirstClassElement("introduction");
setGameBackground(INTRO_IMAGE_PATH);
}

View File

@ -1,5 +1,13 @@
const LOBBY_IMAGE_PATH = "/static/images/cuisine.jpg"
// Display functions
/*
* Set the current game background to the first element with the current_background CSS class.
*/
function setGameBackground(backgroundPath) {
document.querySelector(".current_background").style.backgroundImage = 'url("' + backgroundPath + '")';
}
/**
* Display the invalid rounds count message element, by removing the hidden CSS class.
*
@ -129,7 +137,6 @@ function joinRoom() {
response.then(() => {
displayRoomView();
displayPlayerList();
initSock();
hideFirstClassElement("join_room_view");
})
}
@ -348,13 +355,15 @@ function initSock() {
console.log("Connected to the server!");
})
socket.on("gamestart", () => {
window.location.href = "/multi";
socket.on("gamestart", async () => {
if (await hasJoinedRoom()) window.location.href = "/multi";
})
socket.on("playersjoin", username => {
document.querySelector(".player_names")
.appendChild(document.createTextNode(username + "\n"));
console.log(username);
Array.from(document.getElementsByClassName("player_names")).forEach(playerList =>{
playerList.textContent += username + "\n";
})
});
}
@ -375,9 +384,10 @@ function initSock() {
* </p>
*/
async function initLobby() {
setGameBackground(LOBBY_IMAGE_PATH)
getMembers()
initSock();
if (await hasJoinedRoom()) {
initSock();
displayRoomView();
if (await isRoomOwner()) {

View File

@ -281,4 +281,4 @@ document.getElementById("join_room_button").addEventListener("click", joinMultiP
// Execution of functions
setCurrentTheme();
//setCurrentTheme();

View File

@ -18,13 +18,19 @@
<body class="game_app">
<div class="current_background"></div>
<section class="introduction hidden">
<h1 class="introduction_title">Truth Inquiry</h1>
<p class="introduction_text">Bienvenue dans Truth Inquiry, vous allez intégrer la peau dun enquêteur.<br><br>Vous avez été donné responsable de résoudre une enquête et devez trouver le coupable dun vol.<br><br>Cliquez sur la flèche pour découvrir les suspects et les interroger.</p>
<button id="introduction_next_btn" class="next_btn" aria-label="Commencer" title="Cliquez ici pour commencer à jouer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path d="m23.15 36.95-17.3-11.1Q4.7 25.25 4.7 24t1.15-1.9L23.15 11q1.15-.7 2.35-.075 1.2.625 1.2 2.025v8.75h15.8q.95 0 1.625.675T44.8 24q0 .95-.675 1.6-.675.65-1.625.65H26.7V35q0 1.45-1.2 2.075-1.2.625-2.35-.125Z" />
</svg>
</button>
<div class="introduction_left">
<h1 class="introduction_title">Truth Inquiry</h1>
<p class="introduction_text">Bienvenue dans Truth Inquiry, vous allez intégrer la peau dun enquêteur.<br><br>Vous avez été donné responsable de résoudre une enquête et devez trouver le coupable dun vol.<br><br>Cliquez sur la flèche pour découvrir les suspects et les interroger.</p>
<button id="introduction_next_btn" class="next_btn" aria-label="Commencer" title="Cliquez ici pour commencer à jouer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path d="m23.15 36.95-17.3-11.1Q4.7 25.25 4.7 24t1.15-1.9L23.15 11q1.15-.7 2.35-.075 1.2.625 1.2 2.025v8.75h15.8q.95 0 1.625.675T44.8 24q0 .95-.675 1.6-.675.65-1.625.65H26.7V35q0 1.45-1.2 2.075-1.2.625-2.35-.125Z" />
</svg>
</button>
</div>
<div class="introduction_right">
<p id="username">Le celebre inspecteur : </p>
<img class="inspector_picture" src="/static/images/inspector.png" alt="Image de l'inspecteur">
</div>
</section>
<section class="interrogation hidden">
<h1 class="interrogation_title">Suspects</h1>
@ -34,6 +40,23 @@
</svg>
</button>
<ul class="suspects" id="interrogation_suspects"></ul>
<Section>
<button id="open_chat_button" class="open-button">Chat</button>
<div class="chat-popup" id="chatbox">
<div class="form-container">
<h1>Chat</h1>
<div class="messages_received_container">
<ul id="message_list" class="messages">
</ul>
</div>
<label for="msg"><b>Message</b></label>
<input type="text" id="chat_message_box" placeholder="Type message.." name="msg" required></textarea>
<button id="chat_button_send" class="btn">Send</button>
<button id="close_chat_button" type="button" class="btn cancel">Close</button>
</div>
</div>
</Section>
</section>
<section class="emotion_and_culprit_choices hidden">
<h1 class="emotion_and_culprit_choices_title">Choix du coupable et émotion des suspects</h1>
@ -53,14 +76,16 @@
</svg>
</button>
<img class="image_interrogation suspect_picture" id="currentNpcPicure" alt="Image du suspect en cours d'interrogation" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
<div class="questions_list">
<button class="action_button question_button" id="QA_0">Où étiez vous hier soir&nbsp;?</button>
<button class="action_button question_button" id="QA_1">Avec qui étiez vous&nbsp;?</button>
<div class ="npc_answer">
<h1 class="anwser_title">Réponse du suspect à la question</h1>
<div class="question_answer">
<p class="suspect_answer"></p>
</div>
</div>
</div>
<div class="question_answer hidden">
<h1 class="anwser_title">Réponse du suspect à la question</h1>
<p class="suspect_answer"></p>
<div class="questions_list">
<button class="action_button question_button" id="QA_0">Où étiez vous hier soir&nbsp;?</button>
<button class="action_button question_button" id="QA_1">Avec qui étiez vous&nbsp;?</button>
</div>
</section>
<section class="results_game hidden">

View File

@ -17,15 +17,6 @@
</head>
<body class="game_app">
<section class="game_start">
<menu class="header_actions">
<li class="header_action">
<button class="theme_switcher" aria-label="Changer de thème">
<svg class="theme_switcher_btn" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path d="M24 34q-4.15 0-7.075-2.925T14 24q0-4.15 2.925-7.075T24 14q4.15 0 7.075 2.925T34 24q0 4.15-2.925 7.075T24 34ZM2 25.5v-3h8v3Zm36 0v-3h8v3ZM22.5 10V2h3v8Zm0 36v-8h3v8Zm-9.45-30.85L8.1 10.2l2.1-2.1 4.95 4.95ZM37.8 39.9l-4.95-4.95 2.1-2.1 4.95 4.95Zm-2.85-24.75-2.1-2.1L37.8 8.1l2.1 2.1ZM10.2 39.9l-2.1-2.1 4.95-4.95 2.1 2.1Z"/>
</svg>
</button>
</li>
</menu>
<div class="game_begin">
<h1 class="game_title">Truth Inquiry</h1>
<button class="action_button" id="play_button">Jouer</button>

View File

@ -16,6 +16,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body class="game_app">
<div class="current_background"></div>
<input type="hidden" id="game_id" name="game_id" value={{gameid}}>
<section class="join_room_view hidden">
<h1 class="room_title">Salon</h1>