aboutsummaryrefslogtreecommitdiff
path: root/src/Chelleport/KeySequence.hs
blob: 1bc50a51abf43ea86b8433d066c5ab36bbc9e979 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
module Chelleport.KeySequence where

import Data.List (isPrefixOf, nub)
import qualified Data.Map as Map
import qualified SDL

type Cell = [Char]

type KeySequence = [Char]

type KeyGrid = [[Cell]]

-- padded :: Int -> a -> [a] -> [a]
-- padded 0 _ ls = ls
-- padded n x ls
--   | length ls > n = ls
--   | otherwise = padded (n - 1) x (ls ++ [x])

-- safeHead :: a -> [a] -> a
-- safeHead def [] = def
-- safeHead _ (x : _) = x

nextChars :: KeySequence -> KeyGrid -> Maybe [Char]
nextChars keys cells =
  case matches of
    [] -> Nothing
    _ -> Just $ nub result
  where
    matches = concatMap (filter (isPrefixOf keys)) cells
    result = concatMap (take 1 . drop (length keys)) matches

findWithIndex :: (x -> Maybe r) -> Int -> [x] -> Maybe (Int, r)
findWithIndex _pred _index [] = Nothing
findWithIndex predicate index (x : ls) =
  case predicate x of
    Just item -> Just (index, item)
    Nothing -> findWithIndex predicate (index + 1) ls

findMatchPosition :: KeySequence -> KeyGrid -> Maybe (Int, Int)
findMatchPosition keys = findWithIndex findMatch 0
  where
    findMatch =
      fmap fst . findWithIndex (\c -> if c == keys then Just () else Nothing) 0

isValidKey :: SDL.Keycode -> Bool
isValidKey key = Map.member key keycodeMapping

generateKeyCells :: (Int, Int) -> KeySequence -> KeyGrid
generateKeyCells (rows, columns) hintKeys =
  (\row -> getCellSeq row <$> [1 .. columns]) <$> [1 .. rows]
  where
    getCellSeq row col = [getPrefixHoriz row col, getPrefixVert row col, getKey row col]
    getKey row col = hintKeys !! index
      where
        index = (secRow * (columns `div` 2) + secCol) `mod` length hintKeys
        secCol = (col - 1) `mod` (columns `div` 2)
        secRow = (row - 1) `mod` (rows `div` 2)
    getPrefixHoriz _row col
      | col <= (columns `div` 2) = 'H'
      | otherwise = 'L'
    getPrefixVert row _col
      | row <= (rows `div` 2) = 'K'
      | otherwise = 'J'

toKeyChar :: SDL.Keycode -> Maybe Char
toKeyChar key = Map.lookup key keycodeMapping

eventToKeycode :: SDL.KeyboardEventData -> SDL.Keycode
eventToKeycode = SDL.keysymKeycode . SDL.keyboardEventKeysym

keycodeMapping :: Map.Map SDL.Keycode Char
keycodeMapping =
  Map.fromList
    [ (SDL.KeycodeA, 'A'),
      (SDL.KeycodeB, 'B'),
      (SDL.KeycodeC, 'C'),
      (SDL.KeycodeD, 'D'),
      (SDL.KeycodeE, 'E'),
      (SDL.KeycodeF, 'F'),
      (SDL.KeycodeG, 'G'),
      (SDL.KeycodeH, 'H'),
      (SDL.KeycodeI, 'I'),
      (SDL.KeycodeJ, 'J'),
      (SDL.KeycodeK, 'K'),
      (SDL.KeycodeL, 'L'),
      (SDL.KeycodeM, 'M'),
      (SDL.KeycodeN, 'N'),
      (SDL.KeycodeO, 'O'),
      (SDL.KeycodeP, 'P'),
      (SDL.KeycodeR, 'R'),
      (SDL.KeycodeS, 'S'),
      (SDL.KeycodeT, 'T'),
      (SDL.KeycodeU, 'U'),
      (SDL.KeycodeV, 'V'),
      (SDL.KeycodeW, 'W'),
      (SDL.KeycodeX, 'X'),
      (SDL.KeycodeY, 'Y'),
      (SDL.KeycodeZ, 'Z'),
      (SDL.Keycode0, '0'),
      (SDL.Keycode1, '1'),
      (SDL.Keycode2, '2'),
      (SDL.Keycode3, '3'),
      (SDL.Keycode4, '4'),
      (SDL.Keycode5, '5'),
      (SDL.Keycode6, '6'),
      (SDL.Keycode7, '7'),
      (SDL.Keycode8, '8'),
      (SDL.Keycode9, '9')
    ]