Passed
Push — master ( 250f8d...b94cb9 )
by torrua
02:57
created

app.bot.telegram.keyboards   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 114
dl 0
loc 181
rs 10
c 0
b 0
f 0
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
    entity_predy,
7
    t,
8
    cbd,
9
    Action,
10
    Mark,
11
)
12
13
14
def get_delimiter(number_of_items: int) -> int:
15
16
    allowed_range = list(range(MIN_NUMBER_OF_BUTTONS, MIN_NUMBER_OF_BUTTONS + 11))
17
    lst = [(number_of_items % i, i) for i in allowed_range]
18
    delimiter = min(lst, key=lambda x: abs(x[0] - MIN_NUMBER_OF_BUTTONS))[1]
19
    for i in lst:
20
        if i[0] == 0:
21
            delimiter = i[1]
22
            break
23
    return delimiter
24
25
26
def get_slice_end(slice_start: int, number_of_items: int) -> int:
27
    last_allowed_item = slice_start + get_delimiter(number_of_items)
28
    slice_end = min(last_allowed_item, number_of_items)
29
    return slice_end
30
31
32
def keyboard_data(slice_start: int, items: list):
33
    """
34
    :param items:
35
    :param slice_start:
36
    :return:
37
    """
38
    slice_end = get_slice_end(slice_start, len(items))
39
    current_item_set = items[slice_start:slice_end]
40
41
    kb_items = [
42
        {
43
            t: item.name,
44
            cbd: callback_from_info(
45
                {
46
                    Mark.entity: entity_predy,
47
                    Mark.action: Action.send_card,
48
                    Mark.record_id: item.id,
49
                }
50
            ),
51
        }
52
        for item in current_item_set
53
    ]
54
    return Keyboa(items=kb_items, items_in_row=3)()
55
56
57
def keyboard_navi(
58
    index_start: int, number_of_items: int, word_id: int, action_mark: str
59
):
60
    """
61
    :param action_mark:
62
    :param word_id:
63
    :param number_of_items:
64
    :param index_start:
65
    :return:
66
    """
67
68
    delimiter = get_delimiter(number_of_items)
69
    if number_of_items <= delimiter:
70
        return None
71
72
    index_end = get_slice_end(index_start, number_of_items)
73
74
    text_arrow_back = "❮❮"
75
    text_arrow_forward = "❯❯"
76
    button_back, button_forward = None, None
77
78
    common_data = {
79
        Mark.entity: entity_predy,
80
        Mark.action: action_mark,
81
        Mark.record_id: word_id,
82
    }
83
84
    if index_start != 0:
85
        data_cbd_predy_kb_back = {
86
            **common_data,
87
            Mark.slice_start: index_start - delimiter,
88
        }
89
        button_back = {
90
            t: text_arrow_back,
91
            cbd: callback_from_info(data_cbd_predy_kb_back),
92
        }
93
94
    if index_end != number_of_items:
95
        data_cbd_predy_kb_forward = {
96
            **common_data,
97
            Mark.slice_start: index_end,
98
        }
99
        button_forward = {
100
            t: text_arrow_forward,
101
            cbd: callback_from_info(data_cbd_predy_kb_forward),
102
        }
103
104
    nav_row = [b for b in [button_back, button_forward] if b]
105
    return Keyboa(nav_row, items_in_row=2)()
106
107
108
def kb_close():
109
    """
110
    :return:
111
    """
112
    return Keyboa({t: "Close", cbd: "close"})()
113
114
115
def keyboard_show_hide(title: str, word_id: int, action_mark: str):
116
    """
117
    :return:
118
    """
119
120
    cbd_predy = {
121
        Mark.entity: entity_predy,
122
        Mark.action: action_mark,
123
        Mark.record_id: word_id,
124
    }
125
    button = [
126
        {t: title, cbd: callback_from_info(cbd_predy)},
127
    ]
128
    return Keyboa(button)()
129
130
131
def combine_and_close(func):
132
    def wrapper(self, *args, **kwargs):
133
        kb_combo = func(self, *args, **kwargs)
134
        kb_combo.append(kb_close())
135
        return Keyboa.combine(tuple(kb_combo))
136
137
    return wrapper
138
139
140
class WordKeyboard:
141
142
    def __init__(self, word):
143
        self.word = word
144
145
    def get_title(self, show: bool, items_type: str):
146
        show_text = "Show" if show else "Hide"
147
148
        match items_type:
149
            case "parent":
150
                return (
151
                    f"{show_text} Parent"
152
                    + f"{f's ({len(self.word.parents)})' if len(self.word.parents) > 1 else ''}"
153
                )
154
            case "djifoa":
155
                return (
156
                    f"{show_text} Djifoa"
157
                    + f"{f' ({len(self.word.affixes)})' if len(self.word.affixes) else ''}"
158
                )
159
            case "complex":
160
                return (
161
                    f"{show_text} Complex"
162
                    + f"{f'es ({len(self.word.complexes)})' if len(self.word.complexes) > 1 else ''}"
163
                )
164
            case _:
165
                return show_text
166
167
    def keyboard_cpx(self, action: str = "", slice_start: int = 0):
168
        """
169
        :param action:
170
        :param slice_start:
171
        :return:
172
        """
173
174
        match action:
175
            case Action.kb_cpx_show:
176
                return self.get_kb_cpx_show(slice_start)
177
178
            case Action.kb_afx_show:
179
                return self.get_kb_afx_show()
180
181
            case Action.kb_pnt_show:
182
                return self.get_kb_pnt_show()
183
184
            case _:
185
                return self.get_default_keyboard()
186
187
    @combine_and_close
188
    def get_kb_pnt_show(self):
189
        kb_combo = []
190
191
        title_parents = self.get_title(show=False, items_type="parent")
192
        kb_hide_parents = keyboard_show_hide(
193
            title_parents, self.word.id, Action.kb_pnt_hide
194
        )
195
        kb_data = keyboard_data(0, self.word.parents)
196
        kb_combo.extend([kb_hide_parents, kb_data])
197
198
        return kb_combo
199
200
    @combine_and_close
201
    def get_kb_cpx_show(self, slice_start):
202
        kb_combo = []
203
        if self.word.affixes:
204
            title_djifoa = self.get_title(show=True, items_type="djifoa")
205
            kb_hide_djifoa = keyboard_show_hide(
206
                title_djifoa, self.word.id, Action.kb_afx_show
207
            )
208
            kb_combo.append(kb_hide_djifoa)
209
210
        if self.word.complexes:
211
            title_cpx = self.get_title(show=False, items_type="complex")
212
            kb_hide_cpx = keyboard_show_hide(
213
                title_cpx, self.word.id, Action.kb_cpx_hide
214
            )
215
            kb_data = keyboard_data(slice_start, self.word.complexes)
216
217
            kb_navi = keyboard_navi(
218
                slice_start,
219
                len(self.word.complexes),
220
                self.word.id,
221
                Action.kb_cpx_show,
222
            )
223
            kb_combo.extend([kb_hide_cpx, kb_data, kb_navi])
224
225
        return kb_combo
226
227
    @combine_and_close
228
    def get_kb_afx_show(self):
229
        kb_combo = []
230
        if self.word.affixes:
231
            title_djifoa = self.get_title(show=False, items_type="djifoa")
232
            kb_hide_djifoa = keyboard_show_hide(
233
                title_djifoa, self.word.id, Action.kb_afx_hide
234
            )
235
            kb_data = keyboard_data(0, self.word.affixes)
236
            kb_combo.extend([kb_hide_djifoa, kb_data])
237
        if self.word.complexes:
238
            title_cpx = self.get_title(show=True, items_type="complex")
239
            kb_hide_cpx = keyboard_show_hide(
240
                title_cpx, self.word.id, Action.kb_cpx_show
241
            )
242
            kb_combo.append(kb_hide_cpx)
243
244
        return kb_combo
245
246
    @combine_and_close
247
    def get_default_kb_for_predy(self):
248
        kb_combo = []
249
250
        if self.word.affixes:
251
            title_djifoa = self.get_title(show=True, items_type="djifoa")
252
            kb_hide_djifoa = keyboard_show_hide(
253
                title_djifoa, self.word.id, Action.kb_afx_show
254
            )
255
            kb_combo.append(kb_hide_djifoa)
256
257
        if self.word.complexes:
258
            title_cpx = self.get_title(show=True, items_type="complex")
259
            kb_hide_cpx = keyboard_show_hide(
260
                title_cpx, self.word.id, Action.kb_cpx_show
261
            )
262
            kb_combo.append(kb_hide_cpx)
263
264
        return kb_combo
265
266
    @combine_and_close
267
    def get_default_kb_for_parentable(self):
268
        title_parent = self.get_title(show=True, items_type="parent")
269
        kb_hide_parent = keyboard_show_hide(
270
            title_parent, self.word.id, Action.kb_pnt_show
271
        )
272
        return [kb_hide_parent]
273
274
    def get_default_keyboard(self):
275
        if self.word.type.parentable:
276
            return self.get_default_kb_for_parentable()
277
        else:
278
            return self.get_default_kb_for_predy()
279