Warning, /education/gcompris/src/core/Wordlist.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - Wordlist.qml 0002 * 0003 * SPDX-FileCopyrightText: 2014 Holger Kaelberer <holger.k@elberer.de> 0004 * 0005 * Authors: 0006 * Holger Kaelberer <holger.k@elberer.de> 0007 * 0008 * SPDX-License-Identifier: GPL-3.0-or-later 0009 */ 0010 import QtQuick 2.12 0011 import GCompris 1.0 0012 import "core.js" as Core 0013 0014 /** 0015 * A Wordlist component loads and maintains GCompris wordlists. 0016 * @ingroup components 0017 * 0018 * It loads wordlists from json-files, validates its content and exposes 0019 * wordlists and levels to activities. 0020 * 0021 * It expects and returns the following wordlist format (UTF8 encoded): 0022 * 0023 * @code 0024 * { 0025 * "name":"default-gd", 0026 * "description":"GĂ idhlig", 0027 * "locale":"gd", 0028 * "levels":[ { "level":1, 0029 * "speed":150, <-- optional 0030 * "fallspeed":7000, <-- optional 0031 * "sublevels":10, <-- optional 0032 * "words":["a","jim", "beam", ... ]}, <-- mandatory 0033 * { "level":2, ... } 0034 * ] 0035 * } 0036 * @endcode 0037 * 0038 * @inherit QtQuick.Item 0039 * @sa JsonParser 0040 */ 0041 Item { 0042 id: wordlist 0043 0044 /** 0045 * type:string 0046 * Default filename to be used if the language specific wordlist file could 0047 * not be loaded. 0048 * Default is emtpy. 0049 */ 0050 property string defaultFilename: "" 0051 0052 /** 0053 * type:bool 0054 * Whether to automatically fallback to the default filename if the 0055 * language specific wordlist file could not be loaded. 0056 * Default is true. 0057 */ 0058 property bool useDefault: true 0059 0060 /** 0061 * type:string 0062 * Name of the file to load the language specific wordlist from. 0063 * Default is empty. Can also be passed directly in loadFromFile(). 0064 * If set in the QML definition, the wordlist is autoloaded onCompleted. 0065 */ 0066 property string filename: "" 0067 0068 /** 0069 * type:object 0070 * Complete Wordlist content loaded. You probably want to use one of the 0071 * convenience accessors like getLevelWordList(). 0072 * Default is empty. 0073 */ 0074 property var wordList: ({}) 0075 0076 /// @cond INTERNAL_DOCS 0077 0078 property var randomWordList: [] 0079 property int maxLevel: 0 0080 0081 /// @endcond 0082 0083 /** 0084 * Emitted if an error occurs. 0085 * @param msg Error message. 0086 */ 0087 signal error(string msg); 0088 0089 /** 0090 * Load Wordlist from JSON Object. 0091 * 0092 * @param type:object levels to load wordlist from. 0093 */ 0094 function loadFromJSON(levels) { 0095 wordList = {levels: levels}; 0096 maxLevel = wordList.levels.length; 0097 return wordList; 0098 } 0099 0100 /** 0101 * Load Wordlist from file @p fname. 0102 * 0103 * @param type:string fname Filename to load wordlist from. 0104 */ 0105 function loadFromFile(fname) { 0106 filename = fname; 0107 var from; 0108 maxLevel = 0 0109 wordList = parser.parseFromUrl(filename, validateWordlist); 0110 if (wordList == null) { 0111 error("Wordlist: Invalid wordlist file " + fname); 0112 if (useDefault) { 0113 // fallback to default file: 0114 wordList = parser.parseFromUrl(defaultFilename, validateWordlist); 0115 if (wordList == null) { 0116 error("Wordlist: Invalid wordlist file " + defaultFilename); 0117 return; 0118 } 0119 from = "default-file " + defaultFilename; 0120 } 0121 else { 0122 error("Wordlist: do not use default list, no list loaded"); 0123 return; 0124 } 0125 } else { 0126 from = "file " + fname; 0127 } 0128 // at this point we have valid levels 0129 maxLevel = wordList.levels.length; 0130 console.log("Wordlist: loaded " + maxLevel + " levels from " + from); 0131 return wordList; 0132 } 0133 0134 /** 0135 * Get wordlist data for @p level 0136 * 0137 * @param type:int level Level. 0138 * @returns type:object wordlist data. 0139 */ 0140 function getLevelWordList(level) { 0141 if (level > maxLevel) 0142 return null; 0143 return wordList.levels[level - 1]; 0144 } 0145 0146 /** 0147 * Get number of sub-levels in @p level. 0148 * 0149 * @param type:int level Level. 0150 * @returns type:int Number of sublevels. 0151 */ 0152 function getMaxSubLevel(level) { 0153 if (level > maxLevel || level === 0) { 0154 console.log("ERROR: Wordlist.getMaxSubLevel out of range, requested level", level, 0155 "out of expected range", 1, "-", maxLevel) 0156 return null; 0157 } 0158 return wordList.levels[level - 1].sublevels !== undefined ? 0159 wordList.levels[level - 1].sublevels : 0; 0160 } 0161 0162 /** 0163 * Build a random word list for @p level. 0164 * 0165 * We don't want to propose several time the same word. First call 0166 * initRandomWord(level) to create the initial shuffled list of words. 0167 * Then call getRandomWord() to get the words one at a time. 0168 * If a word was not found by the child, add it again to the list 0169 * with appendRandomWord(word) 0170 * 0171 * @param type:int level Level. 0172 */ 0173 function initRandomWord(level) { 0174 randomWordList = Core.shuffle(wordList.levels[level - 1].words).slice(0) 0175 } 0176 0177 /** 0178 * Re-add a random word to a shuffled word list. 0179 * 0180 * @param type:string word Word to append. 0181 * @sa initRandomWord 0182 */ 0183 function appendRandomWord(word) { 0184 randomWordList.unshift(word) 0185 } 0186 0187 /** 0188 * Returns the next random word from a shuffled wordlist. 0189 * 0190 * @sa initRandomWord 0191 */ 0192 function getRandomWord() { 0193 return randomWordList.pop() 0194 } 0195 0196 /// @cond INTERNAL_DOCS 0197 0198 function validateWordlist(doc) 0199 { 0200 // minimal syntax check: 0201 var i; 0202 if (undefined === doc.levels) 0203 return false; 0204 for (i = 0; i < doc.levels.length; i++) { 0205 // check mandatory level properties only (speed, fallspeed and sublevels are optional) 0206 if (doc.levels[i].words.length < 1) 0207 return false; 0208 } 0209 if (i < 1) 0210 return false; 0211 return true; 0212 } 0213 0214 /// @endcond 0215 0216 JsonParser { 0217 id: parser 0218 0219 onError: wordlist.error(msg); 0220 } 0221 0222 Component.onCompleted: { 0223 if (filename != "") 0224 loadFromFile(filename); 0225 } 0226 }