Source code for dacy.augmenters.keyboard

"""
Functions for character augmentation based on keyboard layout.
"""

from typing import Dict, Generator, Set, Tuple, List

from pydantic import BaseModel


qwerty_en_array = {
    "default": [
        ["`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="],
        ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"],
        ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'"],
        ["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"],
    ],
    "shifted": [
        ["~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "+"],
        ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}", "|"],
        ["A", "S", "D", "F", "G", "H", "J", "K", "L", ":", '"'],
        ["Z", "X", "C", "V", "B", "N", "M", "<", ">", "?"],
    ],
}


qwerty_da_array = {
    "default": [
        ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "+", "´"],
        ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "å", "¨"],
        ["a", "s", "d", "f", "g", "h", "j", "k", "l", "æ", "ø", "'"],
        ["<", "z", "x", "c", "v", "b", "n", "m", ",", ".", "-"],
    ],
    "shifted": [
        ["!", '"', "#", "€", "%", "&", "/", "(", ")", "=", "?", "`"],
        ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "Å", "^"],
        ["A", "S", "D", "F", "G", "H", "J", "K", "L", "Æ", "Ø", "*"],
        [">", "Z", "X", "C", "V", "B", "N", "M", ";", ":", "_"],
    ],
}
KEYBOARDS = {
    "QWERTY_EN": qwerty_en_array,
    "QWERTY_DA": qwerty_da_array,
}


[docs]class Keyboard(BaseModel): """A Pydantic dataclass object for constructing Keyboard setup. Args: keyboard_array (Dict[str, str]): An array corresponding to a keyboard. This should include two keys a "default" and a "shifted". Each containing an array of non-shifted and shifted keys respectively. shift_distance (int): The distance given by the shift operator. Defaults to 3. Returns: Keyboard: a Keyboard object """ keyboard_array: Dict[str, List[List[str]]] shift_distance: int = 3
[docs] def coordinate(self, key: str) -> Tuple[int, int]: """get coordinate for key Args: key (str): keyboard key Returns: Tuple[int, int]: key coordinate on keyboard """ for arr in self.keyboard_array: for x, row in enumerate(self.keyboard_array[arr]): for y, k in enumerate(row): if key == k: return (x, y) raise ValueError(f"key {key} was not found in keyboard array")
[docs] def is_shifted(self, key: str) -> bool: """is the key shifted? Args: key (str): keyboard key Returns: bool: a boolean indicating whether key is shifted. """ for x in self.keyboard_array["shifted"]: if key in x: return True return False
[docs] def euclidian_distance(self, key_a: str, key_b: str) -> int: """Returns euclidian distance between two keys Args: key_a (str): keyboard key key_b (str): keyboard key Returns: int: The euclidian distance between two keyboard keys. """ x1, y1 = self.coordinate(key_a) x2, y2 = self.coordinate(key_b) shift_cost = ( 0 if self.is_shifted(key_a) == self.is_shifted(key_b) else self.shift_distance ) return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5 + shift_cost
[docs] def all_keys(self): """yields all keys in keyboard. Yields: all keys in keyboard. """ for arr in self.keyboard_array: for x, _ in enumerate(self.keyboard_array[arr]): for k in self.keyboard_array[arr][x]: yield k
[docs] def get_neighboors(self, key: str, distance: int = 1) -> Set[int]: """gets the neighbours of a key with a specified distance. Args: key (str): A keyboard key distance (int, optional): The euclidian distance of neightbours. Defaults to 1. Returns: Set[int]: The neighbours of a key with a specified distance. """ l = [] for k in self.all_keys(): if k == key: continue if self.euclidian_distance(key, k) <= distance: l.append(k) return l
[docs] def create_distance_dict(self, distance: int = 1) -> dict: return {k: self.get_neighboors(k, distance=distance) for k in self.all_keys()}