Passed
Push — master ( e4d22c...95ad34 )
by torrua
01:32
created

WordKeyboard._keyboard_complete()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
from callbaker import callback_from_info
2
from keyboa import Keyboa
3
4
from app.bot.telegram import MIN_NUMBER_OF_BUTTONS
5
from app.bot.telegram.variables import (
6
    mark_entity,
7
    entity_predy,
8
    mark_action,
9
    action_predy_kb_cpx_show,
10
    mark_record_id,
11
    mark_slice_start,
12
    t,
13
    cbd,
14
    action_predy_kb_cpx_hide,
15
    action_predy_send_card,
16
)
17
18
19
class WordKeyboard:
20
    def __init__(self, word):
21
        self.word = word
22
23
    def get_items(self):
24
        if self.word.type.parentable:
25
            return self.word.parents
26
        return self.word.complexes
27
28
    def get_title(self):
29
        if self.word.type.parentable:
30
            return "Parent" + f"{'s' if len(self.word.parents) > 1 else ''}"
31
        return "Complex" + f"{'es' if len(self.word.complexes) > 1 else ''}"
32
33
    def _keyboard_navi(self, index_start: int):
34
        """
35
        :param index_start:
36
        :return:
37
        """
38
39
        total_num = len(self.get_items())
40
        delimiter = self._get_delimiter(total_num)
41
        if total_num <= delimiter:
42
            return None
43
44
        index_end = self.get_slice_end(index_start, total_num)
45
46
        text_arrow_back = "\U0000276E" * 2
47
        text_arrow_forward = "\U0000276F" * 2
48
        button_back, button_forward = None, None
49
50
        common_data = {
51
            mark_entity: entity_predy,
52
            mark_action: action_predy_kb_cpx_show,
53
            mark_record_id: self.word.id,
54
        }
55
        if index_start != 0:
56
            cbd_predy_kb_cpx_back = {
57
                **common_data,
58
                mark_slice_start: index_start - delimiter,
59
            }
60
            button_back = {
61
                t: text_arrow_back,
62
                cbd: callback_from_info(cbd_predy_kb_cpx_back),
63
            }
64
65
        if index_end != len(self.word.complexes):
66
            cbd_predy_kb_cpx_forward = {
67
                **common_data,
68
                mark_slice_start: index_end,
69
            }
70
            button_forward = {
71
                t: text_arrow_forward,
72
                cbd: callback_from_info(cbd_predy_kb_cpx_forward),
73
            }
74
75
        nav_row = [b for b in [button_back, button_forward] if b]
76
        return Keyboa(nav_row, items_in_row=2)()
77
78
    def _keyboard_hide(self):
79
        """
80
        :return:
81
        """
82
83
        text_hide = f"Hide {self.get_title()}"
84
        cbd_predy_kb_cpx_hide = {
85
            mark_entity: entity_predy,
86
            mark_action: action_predy_kb_cpx_hide,
87
            mark_record_id: self.word.id,
88
        }
89
        button_predy_kb_cpx_hide = [
90
            {t: text_hide, cbd: callback_from_info(cbd_predy_kb_cpx_hide)},
91
        ]
92
        return Keyboa(button_predy_kb_cpx_hide)()
93
94
    def _keyboard_show(self):
95
        """
96
        :return:
97
        """
98
        total_num = len(self.get_items())
99
        number = f" ({total_num})" if total_num > 1 else ""
100
        text_cpx_show = f"Show {self.get_title()}{number}"
101
        cbd_predy_kb_cpx_show = {
102
            mark_entity: entity_predy,
103
            mark_action: action_predy_kb_cpx_show,
104
            mark_record_id: self.word.id,
105
        }
106
        button_show = [
107
            {t: text_cpx_show, cbd: callback_from_info(cbd_predy_kb_cpx_show)},
108
        ]
109
        return Keyboa.combine((Keyboa(button_show)(), kb_close()))
110
111
    @staticmethod
112
    def _get_delimiter(total_number_of_items: int):
113
        """
114
        :param total_number_of_items:
115
        :return:
116
        """
117
        allowed_range = list(range(MIN_NUMBER_OF_BUTTONS, MIN_NUMBER_OF_BUTTONS + 11))
118
        lst = [(total_number_of_items % i, i) for i in allowed_range]
119
        delimiter = min(lst, key=lambda x: abs(x[0] - MIN_NUMBER_OF_BUTTONS))[1]
120
        for i in lst:
121
            if i[0] == 0:
122
                delimiter = i[1]
123
                break
124
        return delimiter
125
126
    def _keyboard_data(self, slice_start: int):
127
        """
128
        :param slice_start:
129
        :return:
130
        """
131
        items = self.get_items()
132
        slice_end = self.get_slice_end(slice_start, len(items))
133
        current_item_set = items[slice_start:slice_end]
134
135
        kb_items = [
136
            {
137
                t: item.name,
138
                cbd: callback_from_info(
139
                    {
140
                        mark_entity: entity_predy,
141
                        mark_action: action_predy_send_card,
142
                        mark_record_id: item.id,
143
                    }
144
                ),
145
            }
146
            for item in current_item_set
147
        ]
148
        return Keyboa(items=kb_items, alignment=True, items_in_row=4)()
149
150
    def keyboard_cpx(self, show_list: bool = False, slice_start: int = 0):
151
        """
152
        :param show_list:
153
        :param slice_start:
154
        :return:
155
        """
156
157
        if not len(self.get_items()):
158
            return kb_close()
159
160
        if not show_list:
161
            return self._keyboard_show()
162
163
        return self._keyboard_complete(slice_start)
164
165
    def _keyboard_complete(self, slice_start: int):
166
        kb_data = self._keyboard_data(slice_start)
167
        kb_navi = self._keyboard_navi(slice_start)
168
        kb_hide = self._keyboard_hide()
169
        kb_combo = (kb_hide, kb_data, kb_navi, kb_close())
170
        return Keyboa.combine(kb_combo)
171
172
    def get_slice_end(self, slice_start: int, total_num: int) -> int:
173
        current_delimiter = self._get_delimiter(total_num)
174
        last_allowed_item = slice_start + current_delimiter
175
        slice_end = min(last_allowed_item, total_num)
176
        return slice_end
177
178
179
def kb_close():
180
    """
181
    :return:
182
    """
183
    return Keyboa({t: "Close", cbd: "close"})()
184