diff --git a/setup.cfg b/setup.cfg
index 34bc04a03a21dc5b94ec56075e89f30b47245f05..111254a4581d8fb9496ac1e5ce1a4b49136a8385 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = ilp_keyboard_layout_optimization
-version = 0.0.2a9
+version = 0.0.3
 description =
     The QAP variant of keyboard layout optimization, i.e. character to key assignments
 long_description = file: README.md
diff --git a/src/ilp_keyboard_layout_optimization/data_aquisition/positions.py b/src/ilp_keyboard_layout_optimization/data_aquisition/positions.py
new file mode 100644
index 0000000000000000000000000000000000000000..06d5fac6dbdc03f375ad0ffbbeba21b6a0df86fb
--- /dev/null
+++ b/src/ilp_keyboard_layout_optimization/data_aquisition/positions.py
@@ -0,0 +1,33 @@
+from dataclasses import dataclass
+from itertools import product
+
+from ..type_aliases import Col, Mod, Pos, PosTuple, Row, Side
+
+
+@dataclass
+class Positions:
+    """An instance provides a tuple of relevant positions on our Corne keyboard
+
+    Attributes
+    ----------
+    poss : PosTuple
+        the relevant positions to assign chars to on our Corne keyboard
+    """
+
+    poss: PosTuple
+
+    def __init__(self):
+        poss = set(
+            product(
+                Side,
+                Mod,
+                (Col.PINKY, Col.RING, Col.MIDDLE, Col.INDEX, Col.INNERMOST),
+                Row,
+            )
+        )
+        for mod in (Mod.SHIFT, Mod.NONE, Mod.LOWER):
+            poss.add(Pos(Side.RIGHT, mod, Col.OUTERMOST, Row.HOME))
+        for col in (Col.PINKY, Col.RING, Col.MIDDLE, Col.INDEX, Col.INNERMOST):
+            for side in Side:
+                poss.remove(Pos(side, Mod.LOWER, col, Row.UPPER))
+        self.poss = tuple(poss)
diff --git a/src/ilp_keyboard_layout_optimization/ilp.py b/src/ilp_keyboard_layout_optimization/ilp.py
index 0c03cca4b72a685f055a6aefec1b528d1bb605e4..53f0301cff03d2d87c0bafe1fd7506393cc9b4ed 100644
--- a/src/ilp_keyboard_layout_optimization/ilp.py
+++ b/src/ilp_keyboard_layout_optimization/ilp.py
@@ -19,10 +19,10 @@ from .type_aliases import (
 class KeyboardOptimization:
     """Instances of this class represent instances of the keyboard layout QAP
 
-    The IP variant of an optimization of character to key assignments can be modeled
-    as a so-called quadratic assignment problem (QAP). The task is to assign a set of
-    characters to a set of keys on a keyboard. The way in which they should be
-    arranged has to meet certain criteria such as for instance: characters that are
+    The IP variant of an optimization of character to position assignments can be
+    modeled as a so-called quadratic assignment problem (QAP). The task is to assign a
+    set of characters to a set of positions on a keyboard. The way in which they should
+    be arranged has to meet certain criteria such as for instance: characters that are
     often typed after one another should not be assigned to positions, that are supposed
     to be pressed by the same finger.
 
@@ -47,82 +47,82 @@ class KeyboardOptimization:
         self.quad_char_pos_costs: QuadCosts = {}
         self.model: Model = Model("Keyboard Layout Optimization")
 
-    def set_up_model(self, char_key_costs: LinCosts, quad_char_key_costs: QuadCosts):
+    def set_up_model(self, char_pos_costs: LinCosts, quad_char_pos_costs: QuadCosts):
         """Set up all the variables and initialize the costs for the SCIP model"""
-        for (char, key) in self.char_key_assigns_keys:
-            self.char_pos_assigns[char, key] = self.model.addVar(
-                name=f"{key}={char}", vtype="B"
+        for (char, pos) in self.char_pos_assigns_keys:
+            self.char_pos_assigns[char, pos] = self.model.addVar(
+                name=f"{pos}={char}", vtype="B"
             )
-        for (char, char_2, key, key_2) in self.quad_char_key_assigns_keys:
-            self.quad_char_pos_assigns[char, char_2, key, key_2] = self.model.addVar(
-                name=f"{key}={char}_and_{key_2}={char_2}", vtype="C", lb=0, ub=1
+        for (char, char_2, pos, pos_2) in self.quad_char_pos_assigns_keys:
+            self.quad_char_pos_assigns[char, char_2, pos, pos_2] = self.model.addVar(
+                name=f"{pos}={char}_and_{pos_2}={char_2}", vtype="C", lb=0, ub=1
             )
-        assert len(quad_char_key_costs) == len(self.quad_char_pos_assigns)
-        assert len(char_key_costs) == len(self.char_pos_assigns)
-        self.char_pos_costs = char_key_costs
-        self.quad_char_pos_costs = quad_char_key_costs
+        assert len(quad_char_pos_costs) == len(self.quad_char_pos_assigns)
+        assert len(char_pos_costs) == len(self.char_pos_assigns)
+        self.char_pos_costs = char_pos_costs
+        self.quad_char_pos_costs = quad_char_pos_costs
 
         constr = {}
         for char in self.chars.monos:
             self.model.addCons(
-                quicksum(self.char_pos_assigns[char, key] for key in self.poss) == 1,
+                quicksum(self.char_pos_assigns[char, pos] for pos in self.poss) == 1,
                 f"AllCharacterAssignedOnce({char})",
             )
-            for (key, key_2) in self.key_pairs:
+            for (pos, pos_2) in self.pos_pairs:
                 self.model.addCons(
                     quicksum(
-                        self.quad_char_pos_assigns[char, char_2, key, key_2]
+                        self.quad_char_pos_assigns[char, char_2, pos, pos_2]
                         for char_2 in self.chars.monos
                         if char_2 != char
                     )
-                    <= self.char_pos_assigns[char, key],
-                    f"QuadCharacterAssignedLEQThanPosition({char},{key},{key_2})",
+                    <= self.char_pos_assigns[char, pos],
+                    f"QuadCharacterAssignedLEQThanPosition({char},{pos},{pos_2})",
                 )
                 self.model.addCons(
                     quicksum(
-                        self.quad_char_pos_assigns[char_2, char, key_2, key]
+                        self.quad_char_pos_assigns[char_2, char, pos_2, pos]
                         for char_2 in self.chars.monos
                         if char_2 != char
                     )
-                    <= self.char_pos_assigns[char, key],
-                    f"QuadCharacterAssignedLEQThanSecondPosition({char},{key_2},{key})",
+                    <= self.char_pos_assigns[char, pos],
+                    f"QuadCharacterAssignedLEQThanSecondPosition({char},{pos_2},{pos})",
                 )
             for char_2 in self.chars.monos:
-                for key in self.poss:
+                for pos in self.poss:
                     if char_2 != char:
                         self.model.addCons(
                             quicksum(
-                                self.quad_char_pos_assigns[char, char_2, key, key_2]
-                                for key_2 in self.poss
-                                if key_2 != key
+                                self.quad_char_pos_assigns[char, char_2, pos, pos_2]
+                                for pos_2 in self.poss
+                                if pos_2 != pos
                             )
-                            <= self.char_pos_assigns[char, key],
+                            <= self.char_pos_assigns[char, pos],
                             f"QuadCharacterAssignedLEQThanCharacter({char},{char_2},"
-                            f"{key})",
+                            f"{pos})",
                         )
                         self.model.addCons(
                             quicksum(
-                                self.quad_char_pos_assigns[char_2, char, key_2, key]
-                                for key_2 in self.poss
-                                if key_2 != key
+                                self.quad_char_pos_assigns[char_2, char, pos_2, pos]
+                                for pos_2 in self.poss
+                                if pos_2 != pos
                             )
-                            <= self.char_pos_assigns[char, key],
+                            <= self.char_pos_assigns[char, pos],
                             f"QuadCharacterAssignedLEQThanSecondCharacter({char_2},"
-                            f"{char},{key})",
+                            f"{char},{pos})",
                         )
 
-        for (char, char_2, key, key_2) in self.quad_char_key_assigns_keys:
+        for (char, char_2, pos, pos_2) in self.quad_char_pos_assigns_keys:
             self.model.addCons(
-                self.char_pos_assigns[char, key] + self.char_pos_assigns[char_2, key_2]
-                <= 1 + self.quad_char_pos_assigns[char, char_2, key, key_2],
-                f"IntegrableQuadAssign({char},{key_2},{key})",
+                self.char_pos_assigns[char, pos] + self.char_pos_assigns[char_2, pos_2]
+                <= 1 + self.quad_char_pos_assigns[char, char_2, pos, pos_2],
+                f"IntegrableQuadAssign({char},{pos_2},{pos})",
             )
 
-        for key in self.poss:
-            constr[key] = self.model.addCons(
-                quicksum(self.char_pos_assigns[char, key] for char in self.chars.monos)
+        for pos in self.poss:
+            constr[pos] = self.model.addCons(
+                quicksum(self.char_pos_assigns[char, pos] for char in self.chars.monos)
                 == 1,
-                f"AllPositionsAssignedOnce({key})",
+                f"AllPositionsAssignedOnce({pos})",
             )
 
         self.model.setObjective(
@@ -157,14 +157,14 @@ class KeyboardOptimization:
     def visualize_solution(self):
         """Rudimentary visualize the optimization result on the console"""
         solution_assignments = []
-        for (char, key) in self.char_key_assigns_keys:
+        for (char, pos) in self.char_pos_assigns_keys:
             print(
-                f"({char}, {key}): "
-                f"{self.model.getVal(self.char_pos_assigns[char, key])}, "
-                f"cost: {self.char_pos_costs[char, key]}"
+                f"({char}, {pos}): "
+                f"{self.model.getVal(self.char_pos_assigns[char, pos])}, "
+                f"cost: {self.char_pos_costs[char, pos]}"
             )
-            if self.model.getVal(self.char_pos_assigns[char, key]) == 1:
-                solution_assignments.append((char, key))
+            if self.model.getVal(self.char_pos_assigns[char, pos]) == 1:
+                solution_assignments.append((char, pos))
 
         assert "('u', 'left_pinky_home')" in str(solution_assignments)
         # assert "('a', 'left_middle_home')" in str(solution_assignments)
@@ -181,13 +181,13 @@ class KeyboardOptimization:
         print(f"{str(solution_assignments)}")
 
     @property
-    def char_key_assigns_keys(self) -> Iterable[CharPosPair]:
-        """An iterator for the pairs of (special) characters and corresponding keys"""
+    def char_pos_assigns_keys(self) -> Iterable[CharPosPair]:
+        """An iterator for the pairs of characters and corresponding positions"""
         return product(self.chars.monos, self.poss)
 
     @property
-    def quad_char_key_assigns_keys(self) -> Iterable[CharPosQuadruple]:
-        """An iterator for quadruples of character pairs and corresponding key pairs"""
+    def quad_char_pos_assigns_keys(self) -> Iterable[CharPosQuadruple]:
+        """An iterator for quadruples of char. pairs and corresponding position pairs"""
         flattened_tuple_of_quads = chain.from_iterable(
             chain.from_iterable(
                 product(permutations(self.chars.monos, 2), permutations(self.poss, 2))
@@ -197,6 +197,6 @@ class KeyboardOptimization:
         return zip(*iter_of_quads)
 
     @property
-    def key_pairs(self) -> Iterable:
-        """An iterator for all pairs of keys that are possible"""
+    def pos_pairs(self) -> Iterable:
+        """An iterator for all pairs of positions that are possible"""
         return permutations(self.poss, 2)
diff --git a/src/ilp_keyboard_layout_optimization/optimize.py b/src/ilp_keyboard_layout_optimization/optimize.py
index 714ef970718e28ac1819d8eb5df1f7d7dd506219..10f89d070896899624b60334c2c0e5c78da81d4b 100644
--- a/src/ilp_keyboard_layout_optimization/optimize.py
+++ b/src/ilp_keyboard_layout_optimization/optimize.py
@@ -34,7 +34,7 @@ def prepare_costs(
     """
     _linear_costs = {}
     _quad_costs = {}
-    for (char, pos) in optimization_problem.char_key_assigns_keys:
+    for (char, pos) in optimization_problem.char_pos_assigns_keys:
         if (
             (char == "u" and pos == "left_pinky_home")
             or (char == "n" and pos == "right_index_home")
@@ -46,7 +46,7 @@ def prepare_costs(
             continue
         _linear_costs[char, pos] = 1.0
 
-    for (char, char_2, pos, pos_2) in optimization_problem.quad_char_key_assigns_keys:
+    for (char, char_2, pos, pos_2) in optimization_problem.quad_char_pos_assigns_keys:
         if (
             (
                 char == "u"
@@ -74,7 +74,7 @@ def prepare_costs(
 
 
 if __name__ == "__main__":
-    test_chars = Chars(("a", "e", "i", "u", "n", "r", "t", "d"))
+    test_chars = Chars(("aeiunrtd"))
     test_poss = (
         "left_pinky_home",
         "left_ring_home",
diff --git a/src/ilp_keyboard_layout_optimization/type_aliases.py b/src/ilp_keyboard_layout_optimization/type_aliases.py
index 6160ee22f3d0527b7de5f13a5ea6c9ce5f3fef1c..4634a16a6763bfc8b5f3565e434888ee7c866dd8 100644
--- a/src/ilp_keyboard_layout_optimization/type_aliases.py
+++ b/src/ilp_keyboard_layout_optimization/type_aliases.py
@@ -6,22 +6,73 @@ __all__ = [
     "CharPosPair",
     "CharPosQuadruple",
     "CharTuple",
+    "Col",
     "LinCosts",
     "LinVars",
+    "Mod",
     "Pos",
     "PosPair",
     "PosTuple",
     "ProbDict",
     "QuadCosts",
     "QuadVars",
+    "Row",
+    "Side",
 ]
 
 from collections import defaultdict
+from enum import auto, Enum
+from typing import NamedTuple
 
 Char = str
 """A (special) character"""
-Pos = str
-"""A position"""
+
+
+class Side(Enum):
+    """Side of a position, i.e. if usually reached with the left or the right hand"""
+
+    LEFT = auto()
+    RIGHT = auto()
+
+
+class Mod(Enum):
+    """Modifier keys needed to reach a position"""
+
+    NONE = 0
+    SHIFT = 1
+    UPPER = 3
+    LOWER = 4
+    NAV = 2
+
+
+class Col(Enum):
+    """Column of a position"""
+
+    OUTERMOST = 0
+    PINKY = 1
+    RING = 2
+    MIDDLE = 3
+    INDEX = 4
+    INNERMOST = 5
+
+
+class Row(Enum):
+    """Column of a position"""
+
+    UPPER = 0
+    HOME = 1
+    LOWER = 2
+
+
+class Pos(NamedTuple):
+    """A position including side, modifiers, column and row"""
+
+    side: Side
+    mod: Mod
+    col: Col
+    row: Row
+
+
 CharPosPair = tuple[Char, Pos]
 """A pair of a (special) character and a position"""
 Bigram = str
diff --git a/src/ilp_keyboard_layout_optimization/visualize.py b/src/ilp_keyboard_layout_optimization/visualize.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6f90c537d7ac14e9bce11816cc03d26d5da7ea6
--- /dev/null
+++ b/src/ilp_keyboard_layout_optimization/visualize.py
@@ -0,0 +1,220 @@
+from typing import Dict
+
+from ilp_keyboard_layout_optimization.type_aliases import (
+    Char,
+    Col,
+    Mod,
+    Pos,
+    PosTuple,
+    Row,
+    Side,
+)
+
+
+def make_layer_strs(poss: Dict[PosTuple, Char]):
+    """Create UNICODE string of the different layers"""
+    home_str = """
+    UNMODIFIED:
+    -------------------------------------     -------------------------------------
+    |  ⇥  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ←  |
+    -------------------------------------     -------------------------------------
+    |  ⎈  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  {}  |
+    -------------------------------------     -------------------------------------
+    |  ⇧  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ⇧  |
+    -------------------------------------     -------------------------------------
+    """
+    shifted_str = """
+    SHIFT:
+    -------------------------------------     -------------------------------------
+    |  ⇥  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ←  |
+    -------------------------------------     -------------------------------------
+    |  ⎈  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  {}  |
+    -------------------------------------     -------------------------------------
+    |  ⇧  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ⇧  |
+    -------------------------------------     -------------------------------------
+    """
+    lowered_str = """
+    LOWER:
+    -------------------------------------     -------------------------------------
+    | F1  | F2  | F3  | F4  | F5  | F6  |     | F7  | F8  | F9  | F10 | F11 | F12 |
+    -------------------------------------     -------------------------------------
+    |  ⇕  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  {}  |
+    -------------------------------------     -------------------------------------
+    |  ⎇  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |AltGr|
+    -------------------------------------     -------------------------------------
+    """
+    raised_str = """
+    UPPER:
+    -------------------------------------     -------------------------------------
+    |  ⇥  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ⌦  |
+    -------------------------------------     -------------------------------------
+    |  ⎈  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ⇕  |
+    -------------------------------------     -------------------------------------
+    |  ⇧  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |AltGr|
+    -------------------------------------     -------------------------------------
+    """
+    nav_str = """
+    NAV:
+    -------------------------------------     -------------------------------------
+    |  ⇥  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ←  |
+    -------------------------------------     -------------------------------------
+    |     |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |     |
+    -------------------------------------     -------------------------------------
+    |  ⇧  |  {}  |  {}  |  {}  |  {}  |  {}  |     |  {}  |  {}  |  {}  |  {}  |  {}  |  ⇧  |
+    -------------------------------------     -------------------------------------
+    """
+    return (
+        home_str.format(
+            poss.get((Side.LEFT, Mod.NONE, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.RING, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.RING, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.RING, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.RING, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.OUTERMOST, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.PINKY, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.RING, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NONE, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.RING, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NONE, Col.PINKY, Row.LOWER), " "),
+        )
+        + shifted_str.format(
+            poss.get((Side.LEFT, Mod.SHIFT, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.RING, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.RING, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.RING, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.RING, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.OUTERMOST, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.PINKY, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.RING, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.RING, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.LOWER), " "),
+        )
+        + lowered_str.format(
+            poss.get((Side.LEFT, Mod.LOWER, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.RING, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.RING, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.OUTERMOST, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.PINKY, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.RING, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.RING, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.LOWER, Col.PINKY, Row.LOWER), " "),
+        )
+        + raised_str.format(
+            poss.get((Side.LEFT, Mod.UPPER, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.RING, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.RING, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.RING, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.RING, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.PINKY, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.RING, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.RING, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.UPPER, Col.PINKY, Row.LOWER), " "),
+        )
+        + nav_str.format(
+            poss.get((Side.LEFT, Mod.NAV, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.RING, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INDEX, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.RING, Row.UPPER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.PINKY, Row.UPPER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.RING, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INDEX, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.RING, Row.HOME), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.PINKY, Row.HOME), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.PINKY, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.RING, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.LEFT, Mod.NAV, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.INDEX, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.RING, Row.LOWER), " "),
+            poss.get((Side.RIGHT, Mod.NAV, Col.PINKY, Row.LOWER), " "),
+        )
+    )
diff --git a/test/test_initialization.py b/test/test_initialization.py
index 3e502a2e6018b9f7beb913774c2e398c83b95d68..ed759fd341446deaa14d9128e9f5001a36b6993c 100644
--- a/test/test_initialization.py
+++ b/test/test_initialization.py
@@ -2,13 +2,14 @@ from itertools import permutations
 
 import pytest
 
+from ilp_keyboard_layout_optimization.data_aquisition.chars import Chars
 from ilp_keyboard_layout_optimization.ilp import KeyboardOptimization
-from ilp_keyboard_layout_optimization.types import CharTuple
+from ilp_keyboard_layout_optimization.type_aliases import CharTuple
 
 
 @pytest.fixture(scope="session")
-def three_chars() -> CharTuple:
-    return "a", "b", "c"
+def three_chars() -> Chars:
+    return Chars(("a", "b", "c"))
 
 
 @pytest.fixture(scope="session")
@@ -29,28 +30,28 @@ def test_keyboard_optimization_init(three_chars, three_poss):
 
 def test_keyboard_optimization_char_pos_assigns_keys(three_chars, three_poss):
     linear_keys = tuple(
-        KeyboardOptimization(three_chars, three_poss).char_key_assigns_keys
+        KeyboardOptimization(three_chars, three_poss).char_pos_assigns_keys
     )
-    assert len(linear_keys) == len(three_chars) * len(three_poss)
-    for char in three_chars:
+    assert len(linear_keys) == len(three_chars.chars) * len(three_poss)
+    for char in three_chars.chars:
         for pos in three_poss:
             assert (char, pos) in linear_keys
 
 
 def test_keyboard_optimization_quad_char_pos_assigns_keys(three_chars, three_poss):
     quadratic_keys = tuple(
-        KeyboardOptimization(three_chars, three_poss).quad_char_key_assigns_keys
+        KeyboardOptimization(three_chars, three_poss).quad_char_pos_assigns_keys
     )
-    assert len(quadratic_keys) == len(three_chars) * (len(three_chars) - 1) * len(
-        three_poss
-    ) * (len(three_poss) - 1)
-    for (char, char_2) in permutations(three_chars, 2):
+    assert len(quadratic_keys) == len(three_chars.chars) * (
+        len(three_chars.chars) - 1
+    ) * len(three_poss) * (len(three_poss) - 1)
+    for (char, char_2) in permutations(three_chars.monos, 2):
         for (pos, pos_2) in permutations(three_poss, 2):
             assert (char, char_2, pos, pos_2) in quadratic_keys
 
 
 def test_keyboard_optimization_quad_poss(three_chars, three_poss):
-    quad_poss = tuple(KeyboardOptimization(three_chars, three_poss).key_pairs)
+    quad_poss = tuple(KeyboardOptimization(three_chars, three_poss).pos_pairs)
     assert len(quad_poss) == len(three_poss) * (len(three_poss) - 1)
     for pos in three_poss:
         for pos_2 in three_poss:
diff --git a/test/test_positions.py b/test/test_positions.py
new file mode 100644
index 0000000000000000000000000000000000000000..5075c09245826cd7650cc3a584ec73f65e018946
--- /dev/null
+++ b/test/test_positions.py
@@ -0,0 +1,348 @@
+from typing import Callable, Dict
+
+import pytest
+from hypothesis import given, strategies as hst
+from hypothesis.strategies import composite
+
+from ilp_keyboard_layout_optimization.data_aquisition.positions import Positions
+from ilp_keyboard_layout_optimization.type_aliases import Char, Col, Mod, Pos, Row, Side
+from ilp_keyboard_layout_optimization.visualize import make_layer_strs
+
+
+@pytest.fixture(scope="session")
+def positions():
+    return Positions()
+
+
+@composite
+def assigns(draw: Callable):
+    assignments: Dict[Pos, Char] = {}
+    default_positions: Positions = Positions()
+    for pos in default_positions.poss:
+        assignments[pos] = draw(hst.characters())
+    return assignments
+
+
+def test_class_positions_available():
+    assert Positions
+
+
+def test_init_positions(positions):
+    assert positions
+
+
+def test_positions_content(positions):
+    test_poss = positions.poss
+    assert test_poss
+
+
+def test_positions_missing_left_outermost_column(positions):
+    missing_poss = (
+        Pos(Side.LEFT, mod, Col.OUTERMOST, row) for mod in Mod for row in Row
+    )
+    for pos in missing_poss:
+        assert pos not in positions.poss
+
+
+def test_positions_missing_lower_upper_row(positions):
+    missing_poss = (
+        Pos(side, Mod.LOWER, col, Row.UPPER) for side in Side for col in Col
+    )
+    for pos in missing_poss:
+        assert pos not in positions.poss
+
+
+def test_positions_missing_right_outermost_lower_key(positions):
+    missing_poss = (Pos(Side.RIGHT, mod, Col.OUTERMOST, Row.LOWER) for mod in Mod)
+    for pos in missing_poss:
+        assert pos not in positions.poss
+
+
+def test_positions_missing_right_outermost_upper_key(positions):
+    missing_poss = (
+        Pos(Side.RIGHT, mod, Col.OUTERMOST, Row.UPPER)
+        for mod in (Mod.SHIFT, Mod.UPPER, Mod.NONE)
+    )
+    for pos in missing_poss:
+        assert pos not in positions.poss
+
+
+def test_positions_missing_right_outermost_home_key(positions):
+    missing_poss = (
+        Pos(Side.RIGHT, mod, Col.OUTERMOST, Row.HOME) for mod in (Mod.NAV, Mod.UPPER)
+    )
+    for pos in missing_poss:
+        assert pos not in positions.poss
+
+
+def test_positions_inners(positions):
+    poss = (
+        Pos(side, mod, col, row)
+        for side in Side
+        for mod in Mod
+        for col in (Col.PINKY, Col.RING, Col.MIDDLE, Col.INDEX, Col.INNERMOST)
+        for row in (Row.HOME, Row.LOWER)
+    )
+    for pos in poss:
+        assert pos in positions.poss
+
+
+def test_positions_uppers(positions):
+    poss = (
+        Pos(side, mod, col, Row.UPPER)
+        for side in Side
+        for mod in (Mod.NONE, Mod.SHIFT, Mod.UPPER, Mod.NAV)
+        for col in (Col.PINKY, Col.RING, Col.MIDDLE, Col.INDEX, Col.INNERMOST)
+    )
+    for pos in poss:
+        assert pos in positions.poss
+
+
+def test_positions_right_outermost_home_key(positions):
+    poss = (
+        Pos(Side.RIGHT, mod, Col.OUTERMOST, Row.HOME)
+        for mod in (Mod.NONE, Mod.SHIFT, Mod.LOWER)
+    )
+    for pos in poss:
+        assert pos in positions.poss
+
+
+@given(assigns())
+def test_positions_with_visualization(assignments):
+    layout = make_layer_strs(assignments)
+    assert layout
+    assert (
+        "UNMODIFIED:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.PINKY, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INNERMOST, Row.UPPER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.PINKY, Row.UPPER]}  "
+        f"|  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  "
+        f""
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.PINKY, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INNERMOST, Row.HOME]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.PINKY, Row.HOME]}  "
+        f""
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.OUTERMOST, Row.HOME]}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.PINKY, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NONE, Col.INNERMOST, Row.LOWER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NONE, Col.PINKY, Row.LOWER]}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "SHIFT:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.PINKY, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.UPPER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.UPPER]}  "
+        f"|  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.PINKY, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.HOME]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.HOME]}  "
+        f""
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.OUTERMOST, Row.HOME]}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.PINKY, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.LOWER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.LOWER]}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "LOWER:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        "| F1  | F2  | F3  | F4  | F5  | F6  |     | F7  | F8  | F9  | F10 | F11 "
+        "| F12 |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇕  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.PINKY, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.HOME]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.PINKY, Row.HOME]}  "
+        f""
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.OUTERMOST, Row.HOME]}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎇  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.PINKY, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.LOWER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.LOWER, Col.PINKY, Row.LOWER]}  "
+        "|AltGr|\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "UPPER:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.PINKY, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.UPPER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.PINKY, Row.UPPER]}  "
+        f"|  ⌦  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.PINKY, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.HOME]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.PINKY, Row.HOME]}  "
+        f"|  ⇕  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.PINKY, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.LOWER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.UPPER, Col.PINKY, Row.LOWER]}  "
+        "|AltGr|\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "NAV:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.PINKY, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.MIDDLE, Row.UPPER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INDEX, Row.UPPER]}  "
+        f""
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INNERMOST, Row.UPPER]}  |     "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INDEX, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.UPPER]}  "
+        f""
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.RING, Row.UPPER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.PINKY, Row.UPPER]}  |  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|     "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.PINKY, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INNERMOST, Row.HOME]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INDEX, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.RING, Row.HOME]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.PINKY, Row.HOME]}  "
+        f"|     |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.PINKY, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.LEFT, Mod.NAV, Col.INNERMOST, Row.LOWER]}  "
+        f"|     "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.INDEX, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.RING, Row.LOWER]}  "
+        f"|  {assignments[Side.RIGHT, Mod.NAV, Col.PINKY, Row.LOWER]}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------"
+    ) in layout
diff --git a/test/test_probabilities.py b/test/test_probabilities.py
index 314cf2284f182b7f95d4a0a38e665ee96b11f689..d4886dbad8ecfe328f3a01eebb2d7ae9c1be5c58 100644
--- a/test/test_probabilities.py
+++ b/test/test_probabilities.py
@@ -285,8 +285,8 @@ def test_init_extract_monogram_data(chars_probs):
     assert chars_probs._extract_monogram_data()
 
 
-def test_init_extract_bigram_data(chars_probs):
-    assert chars_probs._extract_bigram_data()
+def test_init_extract_bigram_data(custom_chars_probs):
+    assert custom_chars_probs._extract_bigram_data()
 
 
 def test_init_custom_bigram_data(custom_chars_probs):
diff --git a/test/test_types.py b/test/test_types.py
index a3e2385b1fd3192ff446fe8eae1bdfde8b7b8e36..97c1a6a0d5ca02fc804580024c9de578fecd1361 100644
--- a/test/test_types.py
+++ b/test/test_types.py
@@ -1,4 +1,5 @@
 from collections import defaultdict
+from enum import EnumMeta
 
 from ilp_keyboard_layout_optimization.costs import FreqTuple
 from ilp_keyboard_layout_optimization.type_aliases import (
@@ -7,14 +8,18 @@ from ilp_keyboard_layout_optimization.type_aliases import (
     CharPosPair,
     CharPosQuadruple,
     CharTuple,
+    Col,
     LinCosts,
     LinVars,
+    Mod,
     Pos,
     PosPair,
     PosTuple,
     ProbDict,
     QuadCosts,
     QuadVars,
+    Row,
+    Side,
 )
 
 
@@ -27,11 +32,27 @@ def test_char():
     assert Char == str
 
 
-def test_key():
-    assert Pos == str
+def test_pos():
+    assert issubclass(Pos, tuple)
 
 
-def test_char_key_pair():
+def test_pos_row():
+    assert "row" in Pos._fields
+
+
+def test_pos_mod():
+    assert "mod" in Pos._fields
+
+
+def test_pos_side():
+    assert "side" in Pos._fields
+
+
+def test_pos_col():
+    assert "col" in Pos._fields
+
+
+def test_char_pos_pair():
     assert CharPosPair == tuple[Char, Pos]
 
 
@@ -39,6 +60,122 @@ def test_bigram():
     assert Bigram == str
 
 
+def test_col():
+    assert isinstance(Col, EnumMeta)
+
+
+def test_col_outermost():
+    assert Col.OUTERMOST
+
+
+def test_col_pinky():
+    assert Col.PINKY
+
+
+def test_col_ring():
+    assert Col.RING
+
+
+def test_col_middle():
+    assert Col.MIDDLE
+
+
+def test_col_index():
+    assert Col.INDEX
+
+
+def test_col_innermost():
+    assert Col.INNERMOST
+
+
+def test_col_innermost_minus_index():
+    assert Col.INNERMOST.value - Col.INDEX.value == 1
+
+
+def test_col_innermost_minus_middle():
+    assert Col.INNERMOST.value - Col.MIDDLE.value == 2
+
+
+def test_col_innermost_minus_ring():
+    assert Col.INNERMOST.value - Col.RING.value == 3
+
+
+def test_col_innermost_minus_pinky():
+    assert Col.INNERMOST.value - Col.PINKY.value == 4
+
+
+def test_col_innermost_minus_outermost():
+    assert Col.INNERMOST.value - Col.OUTERMOST.value == 5
+
+
+def test_mod():
+    assert isinstance(Mod, EnumMeta)
+
+
+def test_mod_none():
+    assert Mod.NONE
+
+
+def test_mod_shift():
+    assert Mod.SHIFT
+
+
+def test_mod_upper():
+    assert Mod.UPPER
+
+
+def test_mod_lower():
+    assert Mod.LOWER
+
+
+def test_mod_nav():
+    assert Mod.NAV
+
+
+def test_mod_none_equals_zero():
+    assert Mod.NONE.value == 0
+
+
+def test_mod_nav_equals_two():
+    assert Mod.NAV.value == 2
+
+
+def test_row():
+    assert isinstance(Row, EnumMeta)
+
+
+def test_row_upper():
+    assert Row.UPPER
+
+
+def test_row_lower():
+    assert Row.LOWER
+
+
+def test_row_home():
+    assert Row.HOME
+
+
+def test_row_lower_minus_home():
+    assert Row.LOWER.value - Row.HOME.value == 1
+
+
+def test_row_lower_minus_home():
+    assert Row.LOWER.value - Row.UPPER.value == 2
+
+
+def test_side():
+    assert isinstance(Side, EnumMeta)
+
+
+def test_side_left():
+    assert Side.LEFT
+
+
+def test_side_right():
+    assert Side.RIGHT
+
+
 def test_pos_pair():
     assert PosPair == tuple[Pos, Pos]
 
@@ -60,7 +197,7 @@ def test_lin_vars():
 
 
 def test_quad_pos_quadruple():
-    assert CharPosQuadruple == tuple[Char, Pos, Char, Pos]
+    assert CharPosQuadruple == tuple[Char, Char, Pos, Pos]
 
 
 def test_quad_costs():
diff --git a/test/test_visualize.py b/test/test_visualize.py
new file mode 100644
index 0000000000000000000000000000000000000000..84d1965fa4f8130f9c9b50fb5143f40271a17872
--- /dev/null
+++ b/test/test_visualize.py
@@ -0,0 +1,944 @@
+from hypothesis import given
+from hypothesis.strategies import characters as chrs
+
+from ilp_keyboard_layout_optimization.type_aliases import Col, Mod, Pos, Row, Side
+from ilp_keyboard_layout_optimization.visualize import make_layer_strs
+
+
+def test_make_layer_strs_function():
+    assert make_layer_strs
+
+
+def test_make_layer_strs_len():
+    assert len(make_layer_strs({})) == 3023
+
+
+def test_make_layer_strs_all_modifiers_there():
+    layout_string = make_layer_strs({})
+    for mod in Mod:
+        if mod.name == "NONE":
+            assert "UNMODIFIED" in layout_string
+        else:
+            assert mod.name in layout_string
+    print(layout_string)
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_unmodified_upper(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.UPPER): char0,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.UPPER): char1,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.UPPER): char2,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.UPPER): char3,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.UPPER): char4,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.UPPER): char5,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.UPPER): char6,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.UPPER): char7,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.UPPER): char8,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.UPPER): char9,
+        },
+    )
+    assert (
+        f"|  ⇥  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  ←  |" in layout_string
+    )
+
+
+@given(
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+)
+def test_make_layer_strs_with_unmodified_home(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9, char10
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.HOME): char0,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.HOME): char1,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.HOME): char2,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.HOME): char3,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.HOME): char4,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.HOME): char5,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.HOME): char6,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.HOME): char7,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.HOME): char8,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.HOME): char9,
+            Pos(Side.RIGHT, Mod.NONE, Col.OUTERMOST, Row.HOME): char10,
+        },
+    )
+    assert (
+        f"|  ⎈  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  {char10}  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_unmodified_lower(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.LOWER): char0,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.LOWER): char1,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.LOWER): char2,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.LOWER): char3,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.LOWER): char4,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.LOWER): char5,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.LOWER): char6,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.LOWER): char7,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.LOWER): char8,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.LOWER): char9,
+        },
+    )
+    assert (
+        f"|  ⇧  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        "|  ⇧  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_shifted_upper(
+    char_1, char_2, char_3, char_4, char_5, char_6, char_7, char_8, char_9, char_0
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.UPPER): char_1,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.UPPER): char_2,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.UPPER): char_3,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.UPPER): char_4,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.UPPER): char_5,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.UPPER): char_6,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.UPPER): char_7,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.UPPER): char_8,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.UPPER): char_9,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.UPPER): char_0,
+        },
+    )
+    assert (
+        f"|  ⇥  |  {char_1}  |  {char_2}  |  {char_3}  |  {char_4}  |  {char_5}  "
+        f"|     |  {char_6}  |  {char_7}  |  {char_8}  |  {char_9}  |  {char_0}  "
+        f"|  ←  |" in layout_string
+    )
+
+
+@given(
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+)
+def test_make_layer_strs_with_shifted_home(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9, char10
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.HOME): char0,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.HOME): char1,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.HOME): char2,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.HOME): char3,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.HOME): char4,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.HOME): char5,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.HOME): char6,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.HOME): char7,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.HOME): char8,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.HOME): char9,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.OUTERMOST, Row.HOME): char10,
+        },
+    )
+    assert (
+        f"|  ⎈  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  {char10}  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_shifted_lower(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.LOWER): char0,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.LOWER): char1,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.LOWER): char2,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.LOWER): char3,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.LOWER): char4,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.LOWER): char5,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.LOWER): char6,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.LOWER): char7,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.LOWER): char8,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.LOWER): char9,
+        },
+    )
+    assert (
+        f"|  ⇧  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        "|  ⇧  |" in layout_string
+    )
+
+
+@given(
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+)
+def test_make_layer_strs_with_lower_home(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9, char10
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.LOWER, Col.PINKY, Row.HOME): char0,
+            Pos(Side.LEFT, Mod.LOWER, Col.RING, Row.HOME): char1,
+            Pos(Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.HOME): char2,
+            Pos(Side.LEFT, Mod.LOWER, Col.INDEX, Row.HOME): char3,
+            Pos(Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.HOME): char4,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.HOME): char5,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INDEX, Row.HOME): char6,
+            Pos(Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.HOME): char7,
+            Pos(Side.RIGHT, Mod.LOWER, Col.RING, Row.HOME): char8,
+            Pos(Side.RIGHT, Mod.LOWER, Col.PINKY, Row.HOME): char9,
+            Pos(Side.RIGHT, Mod.LOWER, Col.OUTERMOST, Row.HOME): char10,
+        },
+    )
+    assert (
+        f"|  ⇕  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  {char10}  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_lower_lower(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.LOWER, Col.PINKY, Row.LOWER): char0,
+            Pos(Side.LEFT, Mod.LOWER, Col.RING, Row.LOWER): char1,
+            Pos(Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.LOWER): char2,
+            Pos(Side.LEFT, Mod.LOWER, Col.INDEX, Row.LOWER): char3,
+            Pos(Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.LOWER): char4,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.LOWER): char5,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INDEX, Row.LOWER): char6,
+            Pos(Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.LOWER): char7,
+            Pos(Side.RIGHT, Mod.LOWER, Col.RING, Row.LOWER): char8,
+            Pos(Side.RIGHT, Mod.LOWER, Col.PINKY, Row.LOWER): char9,
+        },
+    )
+    assert (
+        f"|  ⎇  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        "|AltGr|" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_upper_upper(
+    char_1, char_2, char_3, char_4, char_5, char_6, char_7, char_8, char_9, char_0
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.UPPER): char_1,
+            Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.UPPER): char_2,
+            Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.UPPER): char_3,
+            Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.UPPER): char_4,
+            Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.UPPER): char_5,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.UPPER): char_6,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.UPPER): char_7,
+            Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.UPPER): char_8,
+            Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.UPPER): char_9,
+            Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.UPPER): char_0,
+        },
+    )
+    assert (
+        f"|  ⇥  |  {char_1}  |  {char_2}  |  {char_3}  |  {char_4}  |  {char_5}  "
+        f"|     |  {char_6}  |  {char_7}  |  {char_8}  |  {char_9}  |  {char_0}  "
+        f"|  ⌦  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_upper_home(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    assert (
+        f"|  ⎈  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  ⇕  |"
+        in make_layer_strs(
+            {
+                Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.HOME): char0,
+                Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.HOME): char1,
+                Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.HOME): char2,
+                Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.HOME): char3,
+                Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.HOME): char4,
+                Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.HOME): char5,
+                Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.HOME): char6,
+                Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.HOME): char7,
+                Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.HOME): char8,
+                Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.HOME): char9,
+            },
+        )
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_upper_lower(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    assert (
+        f"|  ⇧  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        "|AltGr|"
+        in make_layer_strs(
+            {
+                Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.LOWER): char0,
+                Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.LOWER): char1,
+                Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.LOWER): char2,
+                Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.LOWER): char3,
+                Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.LOWER): char4,
+                Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.LOWER): char5,
+                Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.LOWER): char6,
+                Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.LOWER): char7,
+                Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.LOWER): char8,
+                Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.LOWER): char9,
+            },
+        )
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_nav_upper(
+    char_1, char_2, char_3, char_4, char_5, char_6, char_7, char_8, char_9, char_0
+):
+    layout_string = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.UPPER): char_1,
+            Pos(Side.LEFT, Mod.NAV, Col.RING, Row.UPPER): char_2,
+            Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.UPPER): char_3,
+            Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.UPPER): char_4,
+            Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.UPPER): char_5,
+            Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.UPPER): char_6,
+            Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.UPPER): char_7,
+            Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.UPPER): char_8,
+            Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.UPPER): char_9,
+            Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.UPPER): char_0,
+        },
+    )
+    assert (
+        f"|  ⇥  |  {char_1}  |  {char_2}  |  {char_3}  |  {char_4}  |  {char_5}  "
+        f"|     |  {char_6}  |  {char_7}  |  {char_8}  |  {char_9}  |  {char_0}  "
+        f"|  ←  |" in layout_string
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_nav_home(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    assert (
+        f"|     |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|     |"
+        in make_layer_strs(
+            {
+                Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.HOME): char0,
+                Pos(Side.LEFT, Mod.NAV, Col.RING, Row.HOME): char1,
+                Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.HOME): char2,
+                Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.HOME): char3,
+                Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.HOME): char4,
+                Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.HOME): char5,
+                Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.HOME): char6,
+                Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.HOME): char7,
+                Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.HOME): char8,
+                Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.HOME): char9,
+            },
+        )
+    )
+
+
+@given(chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs(), chrs())
+def test_make_layer_strs_with_nav_lower(
+    char0, char1, char2, char3, char4, char5, char6, char7, char8, char9
+):
+    assert (
+        f"|  ⇧  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        "|  ⇧  |"
+        in make_layer_strs(
+            {
+                Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.LOWER): char0,
+                Pos(Side.LEFT, Mod.NAV, Col.RING, Row.LOWER): char1,
+                Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.LOWER): char2,
+                Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.LOWER): char3,
+                Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.LOWER): char4,
+                Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.LOWER): char5,
+                Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.LOWER): char6,
+                Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.LOWER): char7,
+                Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.LOWER): char8,
+                Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.LOWER): char9,
+            },
+        )
+    )
+
+
+@given(
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+    chrs(),
+)
+def test_make_layer_strs_with_all_positions_set_manually_randomly(
+    char0,
+    char1,
+    char2,
+    char3,
+    char4,
+    char5,
+    char6,
+    char7,
+    char8,
+    char9,
+    char10,
+    char11,
+    char12,
+    char13,
+    char14,
+    char15,
+    char16,
+    char17,
+    char18,
+    char19,
+    char110,
+    char20,
+    char21,
+    char22,
+    char23,
+    char24,
+    char25,
+    char26,
+    char27,
+    char28,
+    char29,
+    char_31,
+    char_32,
+    char_33,
+    char_34,
+    char_35,
+    char_36,
+    char_37,
+    char_38,
+    char_39,
+    char_30,
+    char40,
+    char41,
+    char42,
+    char43,
+    char44,
+    char45,
+    char46,
+    char47,
+    char48,
+    char49,
+    char410,
+    char50,
+    char51,
+    char52,
+    char53,
+    char54,
+    char55,
+    char56,
+    char57,
+    char58,
+    char59,
+    char60,
+    char61,
+    char62,
+    char63,
+    char64,
+    char65,
+    char66,
+    char67,
+    char68,
+    char69,
+    char610,
+    char70,
+    char71,
+    char72,
+    char73,
+    char74,
+    char75,
+    char76,
+    char77,
+    char78,
+    char79,
+    char8_1,
+    char8_2,
+    char8_3,
+    char8_4,
+    char8_5,
+    char8_6,
+    char8_7,
+    char8_8,
+    char8_9,
+    char8_0,
+    char90,
+    char91,
+    char92,
+    char93,
+    char94,
+    char95,
+    char96,
+    char97,
+    char98,
+    char99,
+    char100,
+    char101,
+    char102,
+    char103,
+    char104,
+    char105,
+    char106,
+    char107,
+    char108,
+    char109,
+    char11_1,
+    char11_2,
+    char11_3,
+    char11_4,
+    char11_5,
+    char11_6,
+    char11_7,
+    char11_8,
+    char11_9,
+    char11_0,
+    char120,
+    char121,
+    char122,
+    char123,
+    char124,
+    char125,
+    char126,
+    char127,
+    char128,
+    char129,
+    char130,
+    char131,
+    char132,
+    char133,
+    char134,
+    char135,
+    char136,
+    char137,
+    char138,
+    char139,
+):
+    layout = make_layer_strs(
+        {
+            Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.LOWER): char130,
+            Pos(Side.LEFT, Mod.NAV, Col.RING, Row.LOWER): char131,
+            Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.LOWER): char132,
+            Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.LOWER): char133,
+            Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.LOWER): char134,
+            Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.LOWER): char135,
+            Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.LOWER): char136,
+            Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.LOWER): char137,
+            Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.LOWER): char138,
+            Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.LOWER): char139,
+            Pos(Side.LEFT, Mod.LOWER, Col.PINKY, Row.HOME): char60,
+            Pos(Side.LEFT, Mod.LOWER, Col.RING, Row.HOME): char61,
+            Pos(Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.HOME): char62,
+            Pos(Side.LEFT, Mod.LOWER, Col.INDEX, Row.HOME): char63,
+            Pos(Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.HOME): char64,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.HOME): char65,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INDEX, Row.HOME): char66,
+            Pos(Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.HOME): char67,
+            Pos(Side.RIGHT, Mod.LOWER, Col.RING, Row.HOME): char68,
+            Pos(Side.RIGHT, Mod.LOWER, Col.PINKY, Row.HOME): char69,
+            Pos(Side.RIGHT, Mod.LOWER, Col.OUTERMOST, Row.HOME): char610,
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.UPPER): char0,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.UPPER): char1,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.UPPER): char2,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.UPPER): char3,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.UPPER): char4,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.UPPER): char5,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.UPPER): char6,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.UPPER): char7,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.UPPER): char8,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.UPPER): char9,
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.HOME): char10,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.HOME): char11,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.HOME): char12,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.HOME): char13,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.HOME): char14,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.HOME): char15,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.HOME): char16,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.HOME): char17,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.HOME): char18,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.HOME): char19,
+            Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.HOME): char120,
+            Pos(Side.LEFT, Mod.NAV, Col.RING, Row.HOME): char121,
+            Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.HOME): char122,
+            Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.HOME): char123,
+            Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.HOME): char124,
+            Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.HOME): char125,
+            Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.HOME): char126,
+            Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.HOME): char127,
+            Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.HOME): char128,
+            Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.HOME): char129,
+            Pos(Side.LEFT, Mod.NAV, Col.PINKY, Row.UPPER): char11_1,
+            Pos(Side.LEFT, Mod.NAV, Col.RING, Row.UPPER): char11_2,
+            Pos(Side.LEFT, Mod.NAV, Col.MIDDLE, Row.UPPER): char11_3,
+            Pos(Side.LEFT, Mod.NAV, Col.INDEX, Row.UPPER): char11_4,
+            Pos(Side.LEFT, Mod.NAV, Col.INNERMOST, Row.UPPER): char11_5,
+            Pos(Side.RIGHT, Mod.NAV, Col.INNERMOST, Row.UPPER): char11_6,
+            Pos(Side.RIGHT, Mod.NAV, Col.INDEX, Row.UPPER): char11_7,
+            Pos(Side.RIGHT, Mod.NAV, Col.MIDDLE, Row.UPPER): char11_8,
+            Pos(Side.RIGHT, Mod.NAV, Col.RING, Row.UPPER): char11_9,
+            Pos(Side.RIGHT, Mod.NAV, Col.PINKY, Row.UPPER): char11_0,
+            Pos(Side.RIGHT, Mod.NONE, Col.OUTERMOST, Row.HOME): char110,
+            Pos(Side.LEFT, Mod.NONE, Col.PINKY, Row.LOWER): char20,
+            Pos(Side.LEFT, Mod.NONE, Col.RING, Row.LOWER): char21,
+            Pos(Side.LEFT, Mod.NONE, Col.MIDDLE, Row.LOWER): char22,
+            Pos(Side.LEFT, Mod.NONE, Col.INDEX, Row.LOWER): char23,
+            Pos(Side.LEFT, Mod.NONE, Col.INNERMOST, Row.LOWER): char24,
+            Pos(Side.RIGHT, Mod.NONE, Col.INNERMOST, Row.LOWER): char25,
+            Pos(Side.RIGHT, Mod.NONE, Col.INDEX, Row.LOWER): char26,
+            Pos(Side.RIGHT, Mod.NONE, Col.MIDDLE, Row.LOWER): char27,
+            Pos(Side.RIGHT, Mod.NONE, Col.RING, Row.LOWER): char28,
+            Pos(Side.RIGHT, Mod.NONE, Col.PINKY, Row.LOWER): char29,
+            Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.LOWER): char100,
+            Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.LOWER): char101,
+            Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.LOWER): char102,
+            Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.LOWER): char103,
+            Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.LOWER): char104,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.LOWER): char105,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.LOWER): char106,
+            Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.LOWER): char107,
+            Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.LOWER): char108,
+            Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.LOWER): char109,
+            Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.HOME): char90,
+            Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.HOME): char91,
+            Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.HOME): char92,
+            Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.HOME): char93,
+            Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.HOME): char94,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.HOME): char95,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.HOME): char96,
+            Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.HOME): char97,
+            Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.HOME): char98,
+            Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.HOME): char99,
+            Pos(Side.LEFT, Mod.UPPER, Col.PINKY, Row.UPPER): char8_1,
+            Pos(Side.LEFT, Mod.UPPER, Col.RING, Row.UPPER): char8_2,
+            Pos(Side.LEFT, Mod.UPPER, Col.MIDDLE, Row.UPPER): char8_3,
+            Pos(Side.LEFT, Mod.UPPER, Col.INDEX, Row.UPPER): char8_4,
+            Pos(Side.LEFT, Mod.UPPER, Col.INNERMOST, Row.UPPER): char8_5,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INNERMOST, Row.UPPER): char8_6,
+            Pos(Side.RIGHT, Mod.UPPER, Col.INDEX, Row.UPPER): char8_7,
+            Pos(Side.RIGHT, Mod.UPPER, Col.MIDDLE, Row.UPPER): char8_8,
+            Pos(Side.RIGHT, Mod.UPPER, Col.RING, Row.UPPER): char8_9,
+            Pos(Side.RIGHT, Mod.UPPER, Col.PINKY, Row.UPPER): char8_0,
+            Pos(Side.LEFT, Mod.LOWER, Col.PINKY, Row.LOWER): char70,
+            Pos(Side.LEFT, Mod.LOWER, Col.RING, Row.LOWER): char71,
+            Pos(Side.LEFT, Mod.LOWER, Col.MIDDLE, Row.LOWER): char72,
+            Pos(Side.LEFT, Mod.LOWER, Col.INDEX, Row.LOWER): char73,
+            Pos(Side.LEFT, Mod.LOWER, Col.INNERMOST, Row.LOWER): char74,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INNERMOST, Row.LOWER): char75,
+            Pos(Side.RIGHT, Mod.LOWER, Col.INDEX, Row.LOWER): char76,
+            Pos(Side.RIGHT, Mod.LOWER, Col.MIDDLE, Row.LOWER): char77,
+            Pos(Side.RIGHT, Mod.LOWER, Col.RING, Row.LOWER): char78,
+            Pos(Side.RIGHT, Mod.LOWER, Col.PINKY, Row.LOWER): char79,
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.UPPER): char_31,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.UPPER): char_32,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.UPPER): char_33,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.UPPER): char_34,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.UPPER): char_35,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.UPPER): char_36,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.UPPER): char_37,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.UPPER): char_38,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.UPPER): char_39,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.UPPER): char_30,
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.HOME): char40,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.HOME): char41,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.HOME): char42,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.HOME): char43,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.HOME): char44,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.HOME): char45,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.HOME): char46,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.HOME): char47,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.HOME): char48,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.HOME): char49,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.OUTERMOST, Row.HOME): char410,
+            Pos(Side.LEFT, Mod.SHIFT, Col.PINKY, Row.LOWER): char50,
+            Pos(Side.LEFT, Mod.SHIFT, Col.RING, Row.LOWER): char51,
+            Pos(Side.LEFT, Mod.SHIFT, Col.MIDDLE, Row.LOWER): char52,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INDEX, Row.LOWER): char53,
+            Pos(Side.LEFT, Mod.SHIFT, Col.INNERMOST, Row.LOWER): char54,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INNERMOST, Row.LOWER): char55,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.INDEX, Row.LOWER): char56,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.MIDDLE, Row.LOWER): char57,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.RING, Row.LOWER): char58,
+            Pos(Side.RIGHT, Mod.SHIFT, Col.PINKY, Row.LOWER): char59,
+        },
+    )
+    assert (
+        "\n    "
+        "UNMODIFIED:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  |  {char0}  |  {char1}  |  {char2}  |  {char3}  |  {char4}  "
+        f"|     |  {char5}  |  {char6}  |  {char7}  |  {char8}  |  {char9}  "
+        f"|  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  |  {char10}  |  {char11}  |  {char12}  |  {char13}  |  {char14}  "
+        f"|     |  {char15}  |  {char16}  |  {char17}  |  {char18}  |  {char19}  "
+        f"|  {char110}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  |  {char20}  |  {char21}  |  {char22}  |  {char23}  |  {char24}  "
+        f"|     |  {char25}  |  {char26}  |  {char27}  |  {char28}  |  {char29}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "SHIFT:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  |  {char_31}  |  {char_32}  |  {char_33}  |  {char_34}  |  {char_35}  "
+        f"|     |  {char_36}  |  {char_37}  |  {char_38}  |  {char_39}  |  {char_30}  "
+        f"|  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  |  {char40}  |  {char41}  |  {char42}  |  {char43}  |  {char44}  "
+        f"|     |  {char45}  |  {char46}  |  {char47}  |  {char48}  |  {char49}  "
+        f"|  {char410}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  |  {char50}  |  {char51}  |  {char52}  |  {char53}  |  {char54}  "
+        f"|     |  {char55}  |  {char56}  |  {char57}  |  {char58}  |  {char59}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "LOWER:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        "| F1  | F2  | F3  | F4  | F5  | F6  |     | F7  | F8  | F9  | F10 | F11 "
+        "| F12 |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇕  |  {char60}  |  {char61}  |  {char62}  |  {char63}  |  {char64}  "
+        f"|     |  {char65}  |  {char66}  |  {char67}  |  {char68}  |  {char69}  "
+        f"|  {char610}  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎇  |  {char70}  |  {char71}  |  {char72}  |  {char73}  |  {char74}  "
+        f"|     |  {char75}  |  {char76}  |  {char77}  |  {char78}  |  {char79}  "
+        "|AltGr|\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "UPPER:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  |  {char8_1}  |  {char8_2}  |  {char8_3}  |  {char8_4}  |  {char8_5}  "
+        f"|     |  {char8_6}  |  {char8_7}  |  {char8_8}  |  {char8_9}  |  {char8_0}  "
+        f"|  ⌦  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⎈  |  {char90}  |  {char91}  |  {char92}  |  {char93}  |  {char94}  "
+        f"|     |  {char95}  |  {char96}  |  {char97}  |  {char98}  |  {char99}  "
+        f"|  ⇕  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  |  {char100}  |  {char101}  |  {char102}  |  {char103}  |  {char104}  "
+        f"|     |  {char105}  |  {char106}  |  {char107}  |  {char108}  |  {char109}  "
+        "|AltGr|\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    \n    "
+        "NAV:\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇥  |  {char11_1}  |  {char11_2}  |  {char11_3}  |  {char11_4}  "
+        f"|  {char11_5}  |     |  {char11_6}  |  {char11_7}  |  {char11_8}  "
+        f"|  {char11_9}  |  {char11_0}  |  ←  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|     |  {char120}  |  {char121}  |  {char122}  |  {char123}  |  {char124}  "
+        f"|     |  {char125}  |  {char126}  |  {char127}  |  {char128}  |  {char129}  "
+        f"|     |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        f"|  ⇧  |  {char130}  |  {char131}  |  {char132}  |  {char133}  |  {char134}  "
+        f"|     |  {char135}  |  {char136}  |  {char137}  |  {char138}  |  {char139}  "
+        "|  ⇧  |\n    "
+        f"-------------------------------------     "
+        f"-------------------------------------\n    "
+        in layout
+    )