summaryrefslogtreecommitdiff
path: root/bin/keymatrix.py
blob: f4e99f679fb1030c4e25914093264a3c3ad888c7 (plain)
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
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
from __future__ import division
import sys

from blessings import Terminal


def main():
    """
    Displays all known key capabilities that may match the terminal.
    As each key is pressed on input, it is lit up and points are scored.
    """
    term = Terminal()
    score = level = hit_highbit = hit_unicode = 0
    dirty = True

    def refresh(term, board, level, score, inp):
        sys.stdout.write(term.home + term.clear)
        level_color = level % 7
        if level_color == 0:
            level_color = 4
        bottom = 0
        for keycode, attr in board.items():
            sys.stdout.write(u''.join((
                term.move(attr['row'], attr['column']),
                term.color(level_color),
                (term.reverse if attr['hit'] else term.bold),
                keycode,
                term.normal)))
            bottom = max(bottom, attr['row'])
        sys.stdout.write(term.move(term.height, 0)
                         + 'level: %s score: %s' % (level, score,))
        sys.stdout.flush()
        if bottom >= (term.height - 5):
            sys.stderr.write(
                ('\n' * (term.height // 2)) +
                term.center(term.red_underline('cheater!')) + '\n')
            sys.stderr.write(
                term.center("(use a larger screen)") +
                ('\n' * (term.height // 2)))
            sys.exit(1)
        for row, inp in enumerate(inps[(term.height - (bottom + 2)) * -1:]):
            sys.stdout.write(term.move(bottom + row+1))
            sys.stdout.write('%r, %s, %s' % (inp.__str__() if inp.is_sequence
                                             else inp, inp.code, inp.name, ))
            sys.stdout.flush()

    def build_gameboard(term):
        column, row = 0, 0
        board = dict()
        spacing = 2
        for keycode in sorted(term._keycodes.values()):
            if (keycode.startswith('KEY_F')
                    and keycode[-1].isdigit()
                    and int(keycode[len('KEY_F'):]) > 24):
                continue
            if column + len(keycode) + (spacing * 2) >= term.width:
                column = 0
                row += 1
            board[keycode] = {'column': column,
                              'row': row,
                              'hit': 0,
                              }
            column += len(keycode) + (spacing * 2)
        return board

    def add_score(score, pts, level):
        lvl_multiplier = 10
        score += pts
        if 0 == (score % (pts * lvl_multiplier)):
            level += 1
        return score, level

    gb = build_gameboard(term)
    inps = []

    with term.raw(), term.keypad(), term.location():
        inp = term.inkey(timeout=0)
        while inp != chr(3):
            if dirty:
                refresh(term, gb, level, score, inps)
                dirty = False
            inp = term.inkey(timeout=5.0)
            dirty = True
            if (inp.is_sequence and
                    inp.name in gb and
                    0 == gb[inp.name]['hit']):
                gb[inp.name]['hit'] = 1
                score, level = add_score(score, 100, level)
            elif inp and not inp.is_sequence and 128 <= ord(inp) <= 255:
                hit_highbit += 1
                if hit_highbit < 5:
                    score, level = add_score(score, 100, level)
            elif inp and not inp.is_sequence and ord(inp) > 256:
                hit_unicode += 1
                if hit_unicode < 5:
                    score, level = add_score(score, 100, level)
            inps.append(inp)

    with term.cbreak():
        sys.stdout.write(term.move(term.height))
        sys.stdout.write(
            u'{term.clear_eol}Your final score was {score} '
            u'at level {level}{term.clear_eol}\n'
            u'{term.clear_eol}\n'
            u'{term.clear_eol}You hit {hit_highbit} '
            u' 8-bit characters\n{term.clear_eol}\n'
            u'{term.clear_eol}You hit {hit_unicode} '
            u' unicode characters.\n{term.clear_eol}\n'
            u'{term.clear_eol}press any key\n'.format(
                term=term,
                score=score, level=level,
                hit_highbit=hit_highbit,
                hit_unicode=hit_unicode)
        )
        term.inkey()

if __name__ == '__main__':
    main()