Skip to content
Snippets Groups Projects
Verified Commit f4035629 authored by Ben Eltschig's avatar Ben Eltschig
Browse files

SkribblWords.js an neues JSON-Format angepasst

parent d41f065b
Branches custom-server
No related merge requests found
import SkribblWords from "../logic/SkribblWords.js";
import {SkribblTopic,SkribblWord} from "./CustomElements.js"; import {SkribblTopic,SkribblWord} from "./CustomElements.js";
(async()=>{ (async()=>{
/** /**
* @typedef {{word:string,description?:string,synonyms?:string[]}} Word * @typedef {import("../logic/SkribblWords.js").Module} Module
* @typedef {{word:string,description?:string,synonyms?:string[],relevance?:number}} WordRef * @typedef {import("../logic/SkribblWords.js").Topic} Topic
* @typedef {{from:string,words:(string|WordRef)[],relevance?:number}} WordRefs * @typedef {import("../logic/SkribblWords.js").WordRefs} WordRefs
* @typedef {{name:string,words?:Word[],subtopics?:Topic[]}} Topic * @typedef {import("../logic/SkribblWords.js").WordList} WordList
* @typedef {{name:string,words:(WordRef|WordRefs)[],defaultRelevance:number}} Module * @type {WordList}
* @type {{topics:Topic[],modules:Module[],macros?:{[key:string]:string;}}}
*/ */
const json = await (await fetch("../Skribbl.json")).json(); const json = await SkribblWords.fetchJson("../Skribbl.json");
const words = new SkribblWords(json);
console.log("json:",json); console.log("json:",json);
if (document.readyState=="loading"){ if (document.readyState=="loading"){
await new Promise(resolve=>{document.addEventListener("DOMContentLoaded",()=>resolve())}) await new Promise(resolve=>{document.addEventListener("DOMContentLoaded",()=>resolve())})
...@@ -22,13 +23,13 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js"; ...@@ -22,13 +23,13 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js";
* @param {HTMLElement} element * @param {HTMLElement} element
* @param {Module[]} modules * @param {Module[]} modules
*/ */
function appendModules(element,modules){ async function appendModules(element,modules){
if (modules){ if (modules){
modules.forEach(module=>{ modules.forEach(module=>{
let topicElement = new SkribblTopic(module.name); let topicElement = new SkribblTopic(module.name);
module.words.forEach(word=>{ module.words.forEach(async word=>{
if (!("word" in word)){ if (!("word" in word)){
let topic = getTopic(word.from); let topic = words.getTopic(word.from);
word.words.forEach(wordRef=>{ word.words.forEach(wordRef=>{
let word = topic.words.find(word=>word.word===(typeof wordRef=="string"?wordRef:wordRef.word)); let word = topic.words.find(word=>word.word===(typeof wordRef=="string"?wordRef:wordRef.word));
let wordElement = new SkribblWord(word.word,{description:word.description,synonyms:word.synonyms,macros:json.macros}); let wordElement = new SkribblWord(word.word,{description:word.description,synonyms:word.synonyms,macros:json.macros});
...@@ -62,21 +63,18 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js"; ...@@ -62,21 +63,18 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js";
}); });
} }
} }
/** @param {string} id */ /** @param {string} path */
function getTopic(id){ let getTopic = (path)=>words.getTopic(path);
let ids = id.split(">").map(s=>s.trim()); /** @param {string} path */
return ids.slice(1).reduce((topic,id)=>topic.subtopics.find(topic=>topic.name==id),json.topics.find(topic=>topic.name==ids[0])); let getWord = (path)=>words.getWord(path);
} /**
/** @param {Topic} topic */ * @param {Topic} topic
let getWordPaths = (topic,prefix="")=>{ * @param {string} [prefix]
let words = topic.words?topic.words.map(word=>prefix+topic.name+">"+word.word):[]; */
if (topic.subtopics){ let getWordPaths = (topic,prefix)=>words.getWordPaths(topic,prefix);
words.push(...topic.subtopics.map(subtopic=>getWordPaths(subtopic,prefix+topic.name+">")).flat()); let getRandomWord = ()=>words.getRandom();
}
return words;
};
let getUnusedWordIDs = ()=>{ let getUnusedWordIDs = ()=>{
let wordIDs = json.topics.map(topic=>getWordPaths(topic)).flat(); let wordIDs = json.topics.map(topic=>words.getWordPaths(topic)).flat();
return wordIDs.filter(wordID=>!json.modules.some(module=>module.words.some(wordRefs=>"from" in wordRefs&&wordRefs.words.some(word=>wordRefs.from+">"+(typeof word=="string"?word:word.word)==wordID)))); return wordIDs.filter(wordID=>!json.modules.some(module=>module.words.some(wordRefs=>"from" in wordRefs&&wordRefs.words.some(word=>wordRefs.from+">"+(typeof word=="string"?word:word.word)==wordID))));
}; };
/** @returns {WordRefs[]} */ /** @returns {WordRefs[]} */
...@@ -120,5 +118,5 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js"; ...@@ -120,5 +118,5 @@ import {SkribblTopic,SkribblWord} from "./CustomElements.js";
navigator.clipboard.writeText(JSON.stringify(json,null,"\t")); navigator.clipboard.writeText(JSON.stringify(json,null,"\t"));
}; };
// @ts-ignore // @ts-ignore
window.consoleTools = {getTopic,getWordPaths,getUnusedWordIDs,importUnusedWords,importWordsFromTopic,copyJson}; window.consoleTools = {getTopic,getWord,getWordPaths,getRandomWord,getUnusedWordIDs,importUnusedWords,importWordsFromTopic,copyJson};
})(); })();
\ No newline at end of file
...@@ -97,6 +97,7 @@ export default class SkribblServer { ...@@ -97,6 +97,7 @@ export default class SkribblServer {
* @type {string|string[]} * @type {string|string[]}
*/ */
this._word = null; this._word = null;
this._words = new SkribblWords(await SkribblWords.fetchJson());
this._id = await Signaler.host(dataChannel=>{ this._id = await Signaler.host(dataChannel=>{
this.connect(DataChannel.from(dataChannel,JSON.stringify,JSON.parse)); this.connect(DataChannel.from(dataChannel,JSON.stringify,JSON.parse));
}); });
...@@ -214,7 +215,7 @@ export default class SkribblServer { ...@@ -214,7 +215,7 @@ export default class SkribblServer {
(async()=>{ (async()=>{
for (this._round=1;this._round<=this._rounds;this._round++){ for (this._round=1;this._round<=this._rounds;this._round++){
for (this._drawingPlayer=0;this._drawingPlayer<this._clients.length;this._drawingPlayer++){ for (this._drawingPlayer=0;this._drawingPlayer<this._clients.length;this._drawingPlayer++){
let words = await Promise.all([SkribblWords.get(),SkribblWords.get(),SkribblWords.get()]); let words = await Promise.all([this._words.getRandom(),this._words.getRandom(),this._words.getRandom()]);
this._word = words.map(({word})=>word); this._word = words.map(({word})=>word);
this._state = "choosing"; this._state = "choosing";
this._sendStateUpdate(); this._sendStateUpdate();
...@@ -246,7 +247,7 @@ export default class SkribblServer { ...@@ -246,7 +247,7 @@ export default class SkribblServer {
let points = this._awardPoints(); let points = this._awardPoints();
this._state = "other"; this._state = "other";
this._sendStateUpdate(); this._sendStateUpdate();
this._sendToAll({action:"revealWord",word:this._word,description:words[wordIndex].description,macros:await SkribblWords.macros,points}); this._sendToAll({action:"revealWord",word:this._word,description:words[wordIndex].description,macros:this._words.macros,points});
await Util.wait(8); await Util.wait(8);
} }
} }
...@@ -290,7 +291,7 @@ export default class SkribblServer { ...@@ -290,7 +291,7 @@ export default class SkribblServer {
if (this._hasGameStarted){ if (this._hasGameStarted){
if (player.guessedWord||playerIndex==this._drawingPlayer){ if (player.guessedWord||playerIndex==this._drawingPlayer){
// TODO let people who already know the word send ghost messages to others who already know it too // TODO let people who already know the word send ghost messages to others who already know it too
}else if (typeof this._word=="string"&&SkribblWords._isCorrect(word,this._word)){ }else if (typeof this._word=="string"&&SkribblWords.isCorrect(word,this._word)){
player.guessedWord = true; player.guessedWord = true;
player.guessedIndex = Math.max(...this._clients.map(client=>client.guessedIndex))+1; player.guessedIndex = Math.max(...this._clients.map(client=>client.guessedIndex))+1;
this._clients.forEach((client,index)=>{ this._clients.forEach((client,index)=>{
...@@ -303,7 +304,7 @@ export default class SkribblServer { ...@@ -303,7 +304,7 @@ export default class SkribblServer {
this._allGuessedPromise.checkCondition(); this._allGuessedPromise.checkCondition();
}else{ }else{
this._clients.forEach((client,index)=>{ this._clients.forEach((client,index)=>{
let close = typeof this._word=="string"?SkribblWords._isClose(word,this._word):false; let close = typeof this._word=="string"?SkribblWords.isClose(word,this._word):false;
if (index==playerIndex){ if (index==playerIndex){
client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:false,word,close}); client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:false,word,close});
}else{ }else{
......
/** /**
* @typedef {object} WordList * @typedef {{word:string,description?:string,synonyms?:string[]}} Word
* @property {{[key:string]:string}} [macros] * @typedef {{word:string,description?:string,synonyms?:string[],relevance?:number}} WordRef
* @property {(Topic|Word)[]} words * @typedef {{from:string,words:(string|WordRef)[],relevance?:number}} WordRefs
* @typedef {{name:string,words?:Word[],subtopics?:Topic[]}} Topic
* @typedef {{name:string,words:(WordRef|WordRefs)[],defaultRelevance:number}} Module
* @typedef {{topics:Topic[],modules:Module[],macros?:{[key:string]:string;}}} WordList
*/ */
/** /**
* @typedef {object} Topic * Wrapper for a word list, most commonly the one specified in `Skribbl.json`.
* @property {"topic"} type
* @property {string} name
* @property {Word[]} words
*/
/**
* @typedef {object} Word
* @property {"word"} [type]
* @property {string} word
* @property {string} [context]
* @property {string} [description]
* @property {string[]} [synonyms]
*/
/** @type {Promise<WordList>} */
let json = (async()=>{
let response = await fetch("./Skribbl.json");
return await response.json();
})();
let words = (async()=>{
let words = (await json).words.map(wordOrTopic=>wordOrTopic.type=="topic"?wordOrTopic.words:[wordOrTopic]).flat();
return words;
})();
/**
* Wrapper for the word list specified in `Skribbl.json`.
*/ */
export default class SkribblWords { export default class SkribblWords {
/**
* @param {WordList} json
*/
constructor(json){
this._json = json;
}
static async fetchJson(url="./Skribbl.json"){
return await (await fetch(url)).json();
}
/**
* Returns the paths of all words in a given topic recursively.
* @param {Topic} topic
*/
getWordPaths = (topic,prefix="")=>{
let words = topic.words?topic.words.map(word=>prefix+topic.name+">"+word.word):[];
if (topic.subtopics){
words.push(...topic.subtopics.map(subtopic=>this.getWordPaths(subtopic,prefix+topic.name+">")).flat());
}
return words;
};
/**
* Returns the topic with the given path.
* @param {string} path
*/
getTopic(path){
let ids = path.split(">").map(s=>s.trim());
return ids.slice(1).reduce((topic,id)=>topic.subtopics.find(topic=>topic.name==id),this._json.topics.find(topic=>topic.name==ids[0]));
}
/**
* Returns the word with the given path.
* @param {string} path
*/
getWord(path){
let parts = path.split(">");
let topic = this.getTopic(parts.slice(0,-1).join(">"));
return topic.words.find(word=>word.word==parts[parts.length-1]);
}
/** /**
* Returns a random word from the list. * Returns a random word from the list.
*/ */
static async get(){ getRandom(){
let array = await words; let array = this._json.topics.map(topic=>this.getWordPaths(topic)).flat();
return array[Math.floor(Math.random()*array.length)]; let chosenPath = array[Math.floor(Math.random()*array.length)];
return this.getWord(chosenPath);
} }
/** /**
* @type {Promise<{[key:string]:string}>} * @type {{[key:string]:string}}
* @readonly * @readonly
*/ */
static get macros(){ get macros(){
return (async ()=>{ return this._json.macros;
return (await json).macros;
})();
} }
/** /**
...@@ -54,7 +75,7 @@ export default class SkribblWords { ...@@ -54,7 +75,7 @@ export default class SkribblWords {
* @param {string} guess * @param {string} guess
* @param {string} word * @param {string} word
*/ */
static _isClose(guess,word) { static isClose(guess,word) {
guess = guess.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, ""); guess = guess.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, "");
word = word.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, ""); word = word.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, "");
...@@ -123,7 +144,7 @@ export default class SkribblWords { ...@@ -123,7 +144,7 @@ export default class SkribblWords {
* @param {string} guess * @param {string} guess
* @param {string} word * @param {string} word
*/ */
static _isCorrect(guess, word) { static isCorrect(guess, word) {
guess = guess.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, ""); guess = guess.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, "");
word = word.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, ""); word = word.toLowerCase().replace(/-/g," ").replace(/'/g,'').normalize("NFD").replace(/[\u0300-\u0307\u0309-\u036f]/g, "");
return guess==word; return guess==word;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment