add difficulty parameter

This commit is contained in:
Jonas Weinz 2021-07-03 20:21:04 +02:00
parent bc15c440a7
commit 77882f4981
4 changed files with 70 additions and 31 deletions

View File

@ -2,6 +2,7 @@ import enum
import json import json
import logging import logging
import numpy as np import numpy as np
from numpy.lib.function_base import diff
from . import crossword_generator from . import crossword_generator
@ -105,10 +106,11 @@ class LetterField(Field):
class Grid(object): class Grid(object):
def __init__(self, width: int, height: int, lang_code: str, density=0.55): def __init__(self, width: int, height: int, lang_code: str, density=0.55, difficulty: int = 0):
self._width = width self._width = width
self._height = height self._height = height
self._lang_code = lang_code self._lang_code = lang_code
self._difficulty = difficulty
self._density = density self._density = density
self._grid = [] self._grid = []
self._solution_locations = None self._solution_locations = None
@ -213,7 +215,8 @@ class Grid(object):
return status_update return status_update
def check_and_reveal_word(self, x: int, y: int): def check_and_reveal_word(self, x: int, y: int):
grid_update = self.check_and_reveal_horizontal(x, y) + self.check_and_reveal_vertical(x, y) grid_update = self.check_and_reveal_horizontal(
x, y) + self.check_and_reveal_vertical(x, y)
# check also the solution locations # check also the solution locations
@ -267,7 +270,7 @@ class Grid(object):
cell.user_input(letter.lower()) cell.user_input(letter.lower())
revealed_changes = self.check_and_reveal_word(x,y) revealed_changes = self.check_and_reveal_word(x, y)
if len(revealed_changes) == 0: if len(revealed_changes) == 0:
return [{ return [{
@ -282,8 +285,11 @@ class Grid(object):
return self._solution_locations return self._solution_locations
def _build_grid(self): def _build_grid(self):
raw_grid, word_infos, solution_locations = crossword_generator.create_word_grid( raw_grid, word_infos, solution_locations = crossword_generator.create_word_grid(self._width - 1,
self._width - 1, self._height - 1, lang_code=self._lang_code, target_density=self._density) self._height - 1,
lang_code=self._lang_code,
target_density=self._density,
difficulty=self._difficulty)
self._solution_locations = solution_locations self._solution_locations = solution_locations
# fix solution locations offsets # fix solution locations offsets
@ -334,10 +340,11 @@ class Grid(object):
class Crossword(object): class Crossword(object):
def __init__(self, width: int, height: int, lang_code: str = "en"): def __init__(self, width: int, height: int, lang_code: str = "en", difficulty: int = 0):
self._width = width self._width = width
self._height = height self._height = height
self._grid = Grid(width, height, lang_code) self._difficulty = difficulty
self._grid = Grid(width, height, lang_code, difficulty=difficulty)
def serialize(self): def serialize(self):
return { return {

View File

@ -31,7 +31,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
self._session = None self._session = None
async def send_crossword(self, sessionId: str, lang: str = "en"): async def send_crossword(self, sessionId: str, lang: str = "en", difficulty: int = 0):
if sessionId not in CrosswordConnection.sessions: if sessionId not in CrosswordConnection.sessions:
await self.send_error(msg="unknown session") await self.send_error(msg="unknown session")
return return
@ -45,7 +45,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
await self.send_error(msg="you are not registered to given session") await self.send_error(msg="you are not registered to given session")
return return
crossword = sess.get_crossword(lang=lang) crossword = sess.get_crossword(lang=lang, difficulty=difficulty)
await self.send({ await self.send({
'type': 'crossword', 'type': 'crossword',
'crossword': crossword.serialize() 'crossword': crossword.serialize()
@ -70,7 +70,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
'updates': update_message 'updates': update_message
}) })
async def register(self, sessionId: str = None, lang: str = "en"): async def register(self, sessionId: str = None, lang: str = "en", difficulty: int = 0):
if sessionId is None: if sessionId is None:
@ -85,7 +85,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
await self.send_error("unknown session id") await self.send_error("unknown session id")
# register with new id: # register with new id:
await self.register(lang=lang) await self.register(lang=lang, difficulty=difficulty)
return return
sess = CrosswordConnection.sessions[sessionId] sess = CrosswordConnection.sessions[sessionId]
@ -98,7 +98,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
'sessionId': sessionId 'sessionId': sessionId
}) })
await self.send_crossword(sessionId, lang=lang) await self.send_crossword(sessionId, lang=lang, difficulty=difficulty)
# clean up old session # clean up old session
CrosswordConnection.clean_sessions() CrosswordConnection.clean_sessions()
@ -119,11 +119,14 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection):
if message['type'] == 'register': if message['type'] == 'register':
sessionId = None sessionId = None
lang = "en" lang = "en"
difficulty = 0
if 'sessionId' in message: if 'sessionId' in message:
sessionId = message['sessionId'] sessionId = message['sessionId']
if "lang" in message: if "lang" in message:
lang = message['lang'] lang = message['lang']
await self.register(sessionId=sessionId, lang=lang) if "difficulty" in message:
difficulty = message["difficulty"]
await self.register(sessionId=sessionId, lang=lang, difficulty=difficulty)
return return
if self._session is None: if self._session is None:

View File

@ -6,6 +6,24 @@ import pathlib
import logging import logging
def get_difficulty_threshold(lang: str, difficulty: int):
return get_difficulty_threshold.thresholds[lang][difficulty]
get_difficulty_threshold.thresholds = {
'de': {
0: 12,
1: 6,
2: 0
},
'en': {
0: 200,
1: 100,
2: 10
}
}
def get_database(lang: str = "en") -> dict: def get_database(lang: str = "en") -> dict:
if lang not in get_database._dbs: if lang not in get_database._dbs:
current_folder = pathlib.Path(__file__).parents[0] current_folder = pathlib.Path(__file__).parents[0]
@ -116,8 +134,15 @@ class WordInfo(object):
return self._is_vertical return self._is_vertical
def create_word_grid(w: int, h: int, lang_code: str = "en", target_density=0.5): def create_word_grid(w: int, h: int, lang_code: str = "en", target_density: float = 0.5, difficulty: int = 0):
logging.info("generate new crossword") logging.info("generate new crossword with params: w:%s h:%s lang:%s density:%s difficulty:%s",
str(w),
str(h),
lang_code,
str(target_density),
str(difficulty))
t_num_translations = get_difficulty_threshold(lang = lang_code, difficulty = difficulty)
database = get_database(lang=lang_code) database = get_database(lang=lang_code)
list_words = list(database.keys()) list_words = list(database.keys())
@ -145,9 +170,13 @@ def create_word_grid(w: int, h: int, lang_code: str = "en", target_density=0.5):
index = random.randint(0, n_words-1) index = random.randint(0, n_words-1)
word = list_words[index][:] word = list_words[index][:]
while len(word) >= max_length or not word.isalnum() or len(word) <= min_length: num_translations = database[word]['num_translations']
t = t_num_translations
while len(word) >= max_length or not word.isalnum() or len(word) <= min_length or num_translations < t:
index = random.randint(0, n_words-1) index = random.randint(0, n_words-1)
word = list_words[index][:] word = list_words[index][:]
num_translations = database[word]['num_translations']
return word return word

View File

@ -4,7 +4,7 @@ from . import crossword
class Session(object): class Session(object):
def __init__(self, days_to_expire:int = 2) -> None: def __init__(self, days_to_expire: int = 2) -> None:
self.crossword = None self.crossword = None
self.datetime_created = dt.datetime.utcnow() self.datetime_created = dt.datetime.utcnow()
self.connected_sockets = set() self.connected_sockets = set()
@ -38,14 +38,15 @@ class Session(object):
def get_datetime_created(self) -> dt.datetime: def get_datetime_created(self) -> dt.datetime:
return self.datetime_created return self.datetime_created
def create_crossword(self, width: int = 20, height: int = 20, lang: str = "en"): def create_crossword(self, width: int = 20, height: int = 20, lang: str = "en", difficulty: int = 0):
self.crossword = crossword.Crossword(width=width, self.crossword = crossword.Crossword(width=width,
height=height, height=height,
lang_code=lang) lang_code=lang,
difficulty=difficulty)
def get_crossword(self, lang: str = "en") -> crossword.Crossword: def get_crossword(self, lang: str = "en", difficulty: int = 0) -> crossword.Crossword:
if self.crossword is None: if self.crossword is None:
self.create_crossword(lang = lang) self.create_crossword(lang=lang, difficulty=difficulty)
return self.crossword return self.crossword
@ -61,4 +62,3 @@ class Session(object):
return True return True
return False return False