Skip to content

Commit

Permalink
Merge pull request #46 from fabaindaiz/dev
Browse files Browse the repository at this point in the history
Dev: some fixes
  • Loading branch information
fabaindaiz authored Oct 22, 2023
2 parents 9d3be4a + 159428f commit 7a744de
Show file tree
Hide file tree
Showing 26 changed files with 56 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Spellsolver is a software that helps to search for the best possible word in Spellcast discord activity. Spellsolver uses a trie to store the valid words, and then iteratively tries all the possible combinations of letters on the board, discarding the ones that don't make valid words and keeping the ones that do.

- Initialization of the trie structure to store valid words in single swap mode take 5 seconds, uses approximately 150 MB of ram memory and allows almost all spellsolver queries to be executed in less than two second.
- Double swap mode can be enabled in config.py, but it is not recommended as it significantly increases load times (25 seconds), ram usage (650 MB) and query time (up to 30 seconds)
- Double swap mode can be enabled in config.py, but it is not recommended as it significantly increases load times (25 seconds), ram usage (650 MB) and query time (up to 40 seconds)
- In case the wordlist.txt file does not exist, a new file will be automatically generated from the sources folder when starting spellsolver using any interface

A message like this will be printed on the screen while Spellsolver starts
Expand Down
1 change: 1 addition & 0 deletions consoleui.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from argparse import ArgumentParser, Namespace

from src.interfaces.baseui import BaseUI


Expand Down
2 changes: 1 addition & 1 deletion graphicalui.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import tkinter as tk
from typing import Tuple

from src.interfaces.tkinter.tkinterboard import TkinterBoard
from src.interfaces.graphicalui.tkinterboard import TkinterBoard
from src.interfaces.baseui import BaseUI


Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from typing import List, Tuple, Dict

from src.config import SWAP
from src.interfaces.baseui import BaseUI
from src.interfaces.tkinter.boardbutton import BoardButton
from src.interfaces.tkinter.boardlabel import BoardLabel
from src.interfaces.tkinter.boardtile import BoardTile
from src.interfaces.graphicalui.boardbutton import BoardButton
from src.interfaces.graphicalui.boardlabel import BoardLabel
from src.interfaces.graphicalui.boardtile import BoardTile
from src.modules.gameboard.resultlist import ResultWord
from src.utils.utils import aux_to_indices
from src.config import SWAP


class Board:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from tkinter import ttk

from typing import Callable


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import tkinter as tk

from src.interfaces.tkinter.boardentry import BoardEntry
from src.interfaces.tkinter.boardmenu import BoardMenu
from src.interfaces.graphicalui.boardentry import BoardEntry
from src.interfaces.graphicalui.boardmenu import BoardMenu


class BoardTile:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.interfaces.tkinter.board import Board
from src.interfaces.graphicalui.board import Board


class MultHandler:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from src.interfaces.baseui import BaseUI
from src.interfaces.tkinter.multhandler import MultHandler
from src.interfaces.tkinter.board import Board
from src.interfaces.graphicalui.multhandler import MultHandler
from src.interfaces.graphicalui.board import Board


class TkinterBoard(Board):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any, Dict, Optional
from pydantic import BaseModel
from src.interfaces.fastapi.baseapi import BaseRouter

from src.interfaces.webapi.baseapi import BaseRouter
from src.interfaces.baseui import BaseUI


Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/modules/gameboard/gameboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Generator, Dict, List, Tuple

from src.utils.utils import (
aux_to_indices,
get_letter_point_value,
Expand Down
1 change: 1 addition & 0 deletions src/modules/gameboard/path.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import List, Tuple

from src.modules.gameboard.gameboard import GameTile


Expand Down
1 change: 1 addition & 0 deletions src/modules/gameboard/resultlist.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Any, Dict, Generator, List, Tuple

from src.modules.gameboard.gameboard import GameTile
from src.utils.timer import Timer

Expand Down
12 changes: 10 additions & 2 deletions src/modules/trie/base.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
from typing import Any, Generator, Tuple

from src.modules.wordlist.wordlist import WordList


class Trie:
"""Represents a Patricia Trie"""

def insert_trie(self, loader: WordList) -> None:
"""Insert the words from the loader into the trie"""
raise NotImplementedError()

def query_trie(self) -> "TrieQuery":
"""Obtains an object that allows queries to be made to the trie"""
raise NotImplementedError()


class TrieQuery:
"""Represents a Patricia Trie Query"""

def get_root(self) -> Any:
"""Obtains a representation of the base node of the trie"""
return NotImplementedError()

def get_key(self, node: Any, word: str) -> Tuple[Any, str]:
def get_key(self, node: Any, letter: str) -> Tuple[Any, str]:
"""Obtains the key associated with a letter from a node"""
raise NotImplementedError()

def get_leaf(self, node: Any, word: str) -> Generator[str, None, None]:
def get_leaf(self, node: Any) -> Generator[str, None, None]:
"""Gets the words associated with a node"""
raise NotImplementedError()
3 changes: 2 additions & 1 deletion src/modules/trie/loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List, Generator
from typing import Generator
from itertools import combinations

from src.config import SWAP


Expand Down
1 change: 1 addition & 0 deletions src/modules/trie/marisa.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from marisa_trie import RecordTrie
from typing import Any, Generator, List, Tuple

from src.modules.trie.base import Trie, TrieQuery
from src.modules.wordlist.wordlist import WordList
from src.modules.trie.loader import word_iter
Expand Down
10 changes: 9 additions & 1 deletion src/modules/trie/patricia.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Any, Dict, Generator, List, Tuple

from src.modules.trie.base import Trie, TrieQuery
from src.modules.wordlist.wordlist import WordList
from src.modules.trie.loader import word_iter


class PatriciaNode:
"""Represents a node of a Patricia trie"""
"""Represents a node of a Patricia Trie"""

def __init__(self) -> None:
self.childs: Dict[str, PatriciaNode] = {}
Expand Down Expand Up @@ -61,30 +62,37 @@ def merge_tries(self, trie: "PatriciaNode") -> None:


class PatriciaTrie(Trie):
"""Represents a Patricia Trie"""

def __init__(self) -> None:
self.node: PatriciaNode = PatriciaNode()

def insert_trie(self, loader: WordList) -> None:
"""Insert the words from the loader into the trie"""
for word in loader.get_words():
for iword in word_iter(word):
self.node.insert(iword, word)

def query_trie(self) -> "TrieQuery":
"""Obtains an object that allows queries to be made to the trie"""
return PatriciaTrieQuery(self)


class PatriciaTrieQuery(TrieQuery):
"""Represents a Patricia Trie Query"""

def __init__(self, trie: Trie) -> None:
self.trie: PatriciaTrie = trie

def get_root(self) -> PatriciaNode:
"""Obtains a representation of the base node of the trie"""
return self.trie.node

def get_key(self, node: PatriciaNode, letter: str) -> Tuple[Any, str]:
"""Obtains the key associated with a letter from a node"""
child_key = node.get_key(letter)
return node.childs[child_key] if child_key else None, child_key

def get_leaf(self, node: PatriciaNode) -> Generator[str, None, None]:
"""Gets the words associated with a node"""
yield from node.get_leaf()
10 changes: 9 additions & 1 deletion src/modules/trie/prefix.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Any, Dict, Generator, List, Tuple

from src.modules.trie.base import Trie, TrieQuery
from src.modules.wordlist.wordlist import WordList
from src.modules.trie.loader import word_iter


class PrefixNode:
"""Represents a node of a trie"""
"""Represents a node of a Patricia Trie"""

def __init__(self) -> None:
self.childs: Dict[str, PrefixNode] = {}
Expand Down Expand Up @@ -55,30 +56,37 @@ def merge_tries(self, trie: "PrefixNode") -> None:


class PrefixTrie(Trie):
"""Represents a Prefix Trie"""

def __init__(self) -> None:
self.node: PrefixNode = PrefixNode()

def insert_trie(self, loader: WordList) -> None:
"""Insert the words from the loader into the trie"""
for word in loader.get_words():
for iword in word_iter(word):
self.node.insert(iword, word)

def query_trie(self) -> "PrefixTrieQuery":
"""Obtains an object that allows queries to be made to the trie"""
return PrefixTrieQuery(self)


class PrefixTrieQuery(TrieQuery):
"""Represents a Patricia Trie Query"""

def __init__(self, trie: Trie) -> None:
self.trie: PrefixTrie = trie

def get_root(self) -> PrefixNode:
"""Obtains a representation of the base node of the trie"""
return self.trie.node

def get_key(self, node: PrefixNode, letter: str) -> Tuple[Any, str]:
"""Obtains the key associated with a letter from a node"""
child_key = node.get_key(letter)
return node.childs[child_key] if child_key else None, child_key

def get_leaf(self, node: PrefixNode) -> Generator[str, None, None]:
"""Gets the words associated with a node"""
yield from node.get_leaf()
1 change: 1 addition & 0 deletions src/modules/wordlist/generate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from typing import Callable, Generator

from src.utils.utils import is_valid_word


Expand Down
1 change: 1 addition & 0 deletions src/modules/wordlist/wordlist.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from typing import Generator, TextIO

from src.modules.wordlist.generate import generate_wordlist
from src.config import SOURCES, WORDLIST

Expand Down
2 changes: 1 addition & 1 deletion src/spellsolver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import multiprocessing
from typing import Any, Generator, List

from src.modules.wordlist.validate import WordValidate
from src.modules.gameboard.gameboard import GameBoard, GameTile
from src.modules.gameboard.resultlist import ResultList, ResultWord
Expand Down
2 changes: 1 addition & 1 deletion tests/test_validate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from src.modules.wordlist.validate import WordValidate
from src.modules.trie.marisa import MarisaTrie


class Validate(unittest.TestCase):
Expand Down
5 changes: 3 additions & 2 deletions webapi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import uvicorn
from fastapi import FastAPI
from src.interfaces.baseapi import BaseAPI, BaseRouter
from src.interfaces.apirouter import SolverRouter

from src.interfaces.webapi.baseapi import BaseAPI, BaseRouter
from src.interfaces.webapi.apirouter import SolverRouter
from src.interfaces.baseui import BaseUI
from src.config import VERSION, HOST, PORT

Expand Down

0 comments on commit 7a744de

Please sign in to comment.