Mercurial > irccd
changeset 456:c81b38ec7bd2 release-2.1
Fix #644: fix word list and selection
Reuse the same list across successive hangman invocations.
Task: #644
Errata: 20170727
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 27 Jul 2017 21:54:30 +0200 |
parents | 8b615d37d303 |
children | c3f46ad1ece6 |
files | plugins/hangman/hangman.js tests/plugin-hangman/CMakeLists.txt tests/plugin-hangman/main.cpp tests/plugin-hangman/wordlist_fix_644.conf |
diffstat | 4 files changed, 75 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/plugins/hangman/hangman.js Tue Jul 25 17:08:19 2017 +0200 +++ b/plugins/hangman/hangman.js Thu Jul 27 21:54:30 2017 +0200 @@ -62,9 +62,12 @@ Hangman.map = {}; /** - * List of words + * List of words. */ -Hangman.words = []; +Hangman.words = { + all: [], //!< All words, + registry: {} //!< Words list per server/channel. +}; /** * Search for an existing game. @@ -139,15 +142,15 @@ while ((line = file.readline()) !== undefined) if (Hangman.isWord(line)) - Hangman.words.push(line); + Hangman.words.all.push(line); } catch (e) { throw new Error("could not open '" + path + "'"); } - if (Hangman.words.length === 0) + if (Hangman.words.all.length === 0) throw new Error("empty word database"); - Logger.info("number of words in database: " + Hangman.words.length); + Logger.info("number of words in database: " + Hangman.words.all.length); } /** @@ -182,14 +185,18 @@ */ Hangman.prototype.select = function () { + var id = this.server.toString() + "@" + this.channel; + // Reload the words if empty. - if (!this.words || this.words.length === 0) - this.words = Hangman.words.slice(0); + if (!Hangman.words.registry[id] || Hangman.words.registry[id].length === 0) + Hangman.words.registry[id] = Hangman.words.all.slice(0); - var i = Math.floor(Math.random() * this.words.length); + var i = Math.floor(Math.random() * Hangman.words.registry[id].length); - this.word = this.words[i]; - this.words.splice(i, 1); + this.word = Hangman.words.registry[id][i]; + + // Erase words from the registry. + Hangman.words.registry[id].splice(i, 1); // Fill table. this.table = {};
--- a/tests/plugin-hangman/CMakeLists.txt Tue Jul 25 17:08:19 2017 +0200 +++ b/tests/plugin-hangman/CMakeLists.txt Thu Jul 27 21:54:30 2017 +0200 @@ -18,7 +18,7 @@ irccd_define_test( NAME plugin-hangman - SOURCES main.cpp + SOURCES main.cpp words.conf wordlist_fix_644.conf LIBRARIES libirccd FLAGS PLUGINDIR=\"${IRCCD_FAKEROOTDIR}/${WITH_PLUGINDIR}\" )
--- a/tests/plugin-hangman/main.cpp Tue Jul 25 17:08:19 2017 +0200 +++ b/tests/plugin-hangman/main.cpp Thu Jul 27 21:54:30 2017 +0200 @@ -16,6 +16,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <unordered_map> +#include <unordered_set> + #include <gtest/gtest.h> #include <irccd/irccd.hpp> @@ -226,6 +229,57 @@ ASSERT_EQ("jean:win=hangman:!hangman:test:jean:jean!jean@localhost:jean:sky", m_server->last()); } +TEST_F(HangmanTest, wordlist_fix_644) +{ + /* + * To be sure that the selection use the same list, we create a list of + * three words that has different size to determine which one was selected. + * + * Then we run 3 games and verify that the old selection is not the same + * as the current. + * + * This is not very accurate but it's better than nothing. + */ + load({{ "file", SOURCEDIR "/wordlist_fix_644.conf" }}); + + std::unordered_map<unsigned, std::string> words{ + { 14, "abc" }, + { 16, "abcd" }, + { 18, "abcde" } + }; + std::unordered_set<unsigned> found; + + m_plugin->setFormats({ + { "start", "#{word}" } + }); + + unsigned last, current; + + // 1. Initial game + finish. + m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""}); + last = m_server->last().length(); + found.insert(last); + m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", words[last]}); + + // 2. Current must not be the last one. + m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""}); + current = m_server->last().length(); + + ASSERT_NE(last, current); + ASSERT_EQ(0U, found.count(current)); + + found.insert(current); + last = current; + m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", words[current]}); + + // 3. Last word must be the one that is kept into the map. + m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""}); + current = m_server->last().length(); + + ASSERT_NE(last, current); + ASSERT_EQ(0U, found.count(current)); +} + int main(int argc, char **argv) { path::setApplicationPath(argv[0]);