-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinfo.py
More file actions
238 lines (191 loc) · 18.6 KB
/
Copy pathinfo.py
File metadata and controls
238 lines (191 loc) · 18.6 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
import winreg
import pyautogui
import ctypes
import re
from collections import Counter
from decimal import *
FILES = 'data'
DAY = 60 * 60 * 24
getcontext().prec = 1402
def zeros(x):
return Decimal('.' + x * '0') if x > 0 else Decimal(f'1e{abs(x)}')
def rond(num, rounding_accuracy):
return num.quantize(rounds[rounding_accuracy], ROUND_HALF_UP)
invisible_win_title = 'невидимое окно'
temp_scopes, temp_scopes_with_smth = r'(?:\(-?\)|U-?u)', r'(?:\(.*?\)|U.*?u)'
calc_geometry_state_change_expression = r'Максимум \d+ символ(?:|а|ов)|Калькулятор теперь (?:вверху|в центре|внизу)'
pattern_checking_on_empty_scopes = fr'(?:[+\-/•:^√]|mod|div)*(?:(?:(?:d(?!iv))?(?:arc)?(?:sin|cos|c?tg)|d?arc|lg|ln){temp_scopes}|log{temp_scopes}by{temp_scopes_with_smth}|log{temp_scopes_with_smth}by{temp_scopes}|{temp_scopes})'
def count_matches(list1, list2):
intersection = Counter(list1) & Counter(list2)
return sum(intersection.values())
def reunite(words):
return [f'{(r'\s*').join(['\\' + symb if symb in '()|' else symb for symb in word])}' for word in words]
darc_generator = tuple([f'{i}{j}' for i in ('darc', 'arc', 'd') for j in ('sin', 'cos', 'ctg', 'tg', '')])
ddarc_gen = tuple([f'{i}{j}' for i in ('darc', 'arc', 'd', '') for j in ('sin', 'cos', 'ctg', 'tg')])
united_symbols = darc_generator + ('log', 'div', 'mod', 'sin', 'cos', 'ctg') + ('ln', 'lg', 'tg', 'by')
united_symbols_with_scopes = (tuple(f'{i}{j}' for j in ('|', '(') for i in darc_generator)
+ ('log(', 'sin(', 'cos(', 'ctg(', ')by(') + ('log|', 'sin|', 'cos|', 'ctg|', '|by|', '|by(', ')by|') + ('ln|', 'lg|', 'tg|') + ('ln(', 'lg(', 'tg('))
united_symbols_without_scopes = darc_generator + ('sin', 'cos', 'ctg', 'tg', 'ln', 'lg') # порядок важен, сначала котангенс а лишь потом тангенс, чтобы удалялся ctg а не c tg
full_funcs_with_Uu = tuple((f'{i}{j}' for i in ('sin', 'cos', 'tg', 'ctg', 'lg', 'ln') for j in ('()', 'Uu'))) + tuple((f'log{i}by{j}' for i in ('()', 'Uu') for j in ('()', 'Uu')))
special_keys = ('Up', 'Down', 'Left', 'Right', 'Control_L', 'Return', 'grave', 'Tab', 'changed text', 'Win_L'
'Control_R', 'Shift_L', 'Shift_R', 'Alt_L', 'Alt_R', 'Escape', 'Caps_Lock', 'apostrophe', 'quotedbl', 'braceleft', 'braceright')
ghost_keys = ('Up', 'Down', 'Left', 'Right', 'Control_L', 'Control_R', 'Shift_L', 'Shift_R', 'Alt_L', 'Alt_R', 'Caps_Lock')
keys_after_dot = ('minus', 'equal', 'slash', 'semicolon', 'backslash', 'bracketleft', 'bracketright')
last_key = None
rounds = [zeros(_) for _ in (400, 380, 360, 305, 100)]
ending_symbols = list('+-•:^,%@k.') + list(united_symbols)
correct_answer_num_symbols = '0123456789Ee-+.•^() '
last_time_main_win_geometry_change = 0
last_val_before_geometry_change = 'если это вставится, значение использовали до его определения !!!техническая ошибка разработчиков!!!'
last_time_round_change = 0
num_construct = r'((?:\d+\.?\d*|\.\d+)(?:e-?\d*\.?\d*)?|[φπe])'
tokenator = r'(d?(?:arc)?(?:sin|cos|c?tg)|d?arc|ln|lg|√|log|by|(?<![\d.])e(?![\d.])|d(?!iv)|\+|=|!|div|mod|\||•|/|:|\^|(?:(?<!\()(?<![\d.]e))\-|\(|\))'
super_tokenator = r'(sin|cos|c?tg|arc|ln|lg|√|log|by|(?<![\d.])e(?![\d.])|d(?!iv)|\+|=|!|div|mod|\||•|/|:|\^|(?:(?<!\()(?<![\d.]e))\-|\(|\)|[\dφπe.])'
max_denominator = 10000
max_history_length, min_history_length = 10000, 100
word_ends1 = ('е', 'я', 'й')
word_ends2 = ('', 'а', 'ов')
def relatives(arg1, arg2):
relative = 0
for (arg1, arg2) in ((arg1, arg2), (arg2, arg1)):
if arg1 == arg2:
relative = max(relative, 1)
if (arg1, arg2) in (('sin', 'cos'), ('tg', 'ctg'), ('lg', 'ln')):
relative = max(relative, 0.9)
if 'arc' + arg1 == arg2 or 'd' + arg1 == arg2 or arg1 == 'arc' and arg2 == 'd' or (arg1, arg2) in (('sin', 'tg'), ('cos', 'ctg'), ('lg', 'log'), ('ln', 'log')):
relative = max(relative, 0.85)
if 'darc' + arg1 == arg2:
relative = max(relative, 0.8)
if re.search(r'sin|cos|c?tg|d|arc', arg1) and re.search(r'sin|cos|c?tg|d|arc', arg2):
relative = max(relative, 0.65)
if re.search(fr'-?{num_construct}', arg1) and re.search(fr'-?{num_construct}', arg2):
relative = max(relative, count_matches(arg1, arg2) / max(len(arg1), len(arg2)))
for indx, i in enumerate(('√', '!', 'mod', 'div', '^', '|', '•', ':', '+', '-')):
if arg1 == i != arg2:
relative = max(relative, 1 - (0.98, 0.95, 0.9, 0.6, 0.35)[indx // 2])
relative = max(relative, 0.1)
return relative
def clear_q_with_content(example, cursor_place):
return re.sub(r'(?:q.*|q?)$', '', example[:cursor_place]) + example[cursor_place:]
def clear_space_and_bracks_with_content(example):
return re.sub(r' ?\[.*\]', '', example)
def get_correct_ending(num, word_endings):
if num % 10 in [0, 5, 6, 7, 8, 9] or num % 100 in [11, 12, 13, 14]:
return word_endings[2]
elif num % 10 == 1:
return word_endings[0]
else:
return word_endings[1]
text_help_calc = (" строка-калькулятор | быстрый ввод • мгновенное вычисление • точный ответ\n\n"
"Приоритет операций, быстрые клавиши для их вызова (чтобы лишний раз не нажимать shift) и ассоциации к запоминанию\n"
" .0. Константы: π≈3.14 [p] (Pi), e≈2.718 [e], φ≈1.618 [F] (Fi); десятичная дробь [.] [,]\n"
" .1. Скобки: () [[] или o] (скобки – rOund brackets); модуль: | [\\] [a] (Absolute)\n"
" .2. Факториал от числа x: x! [f] (Factorial)\n"
" .3. Корень: √ [r] (Root | Radical), N√M=N^(1/M), не путать с N•√M\n"
" .4. Логарифмы: logAbyB [l] (Log), ln [n] (Natural log), lg [g] (General log), by [b]. Тригонометрия: sin [s]; cos [c]; tg [t]; ctg [C]\n"
" .5. Степень: ^ [w] poWer [xx]\n"
" .6. Умножение: • [x]; деление: [/]; остаток от деления: mod [m] [%]; деление нацело: div [d] [//]\n"
" .7. Сложение: + [=]; вычитание: [-]\n"
"\nУправление окнами и копированием\n"
" ● '?' или ctrl+/ — инструкция (помощь), ctrl+h — последние примеры (история)\n"
" ● ctrl+пробел переключает фокус между калькулятором-строкой и окном, которое у тебя перед глазами\n"
" ● [esc] ESCape, ctrl+w закрывают окно в фокусе приложения, а левая кнопка мыши открывает/закрывает окно истории\n"
" ● [`] (где [ё]) очищает поле ввода, ['] копирует пример в буфер обмена, [\"] копирует ответ, [enter] заменяет пример в поле ввода на ответ\n"
" ● двойным нажатием можно выделить пример целиком\n"
" ● enter, ['], [\"], ctrl+s, либо первое удаление числа после ввода примера добавляет пример в историю\n"
" ● ctrl+↑, ctrl+↓, ctrl+alt+↑, ctrl+alt+↓ прокручивают историю\n"
" ● ctrl+shift+z перемещает на один пример в прошлое, ctrl+shift+y — в будущее, прокрутка колеса в поле ввода прокручивает историю с подсветкой\n"
" ● ctrl+z перемещает на 1 действие назад, ctrl+y — вперёд, также делает shift+скролл вверх-низ, нажатия/скроллы по ленте действий крутят быстрее\n"
" ● При вставке текста из истории или других источников, он форматируется под строку или другое окно на уровне символов\n"
"\nРедактирование поля ввода (условимся, что 'I' — это курсор, или каретка)\n"
" ⬥ При стирании '•√I' через [⌫] после нажатия [r] останется '√I'\n"
" ⬥ '/100' [P] (percent — процент), '•10^' [E] (2•10^5 кратко 2e5), [;] пишет '(1/I)' и [.] пишет '0.', если перед курсором не цифра\n"
" ⬥ '^2' [u] (похожа на график x^2), '^3' [j] (на клавиатуре похожа на x^3), '^4' [U] (x^4), '^5' [J] (x^5), '^(-I)' [y]\n"
" ⬥ поставит 3 нуля [z] (zeros — нули), тысячу [k] (kilo), млн [M] (million), млрд [B] (billion), трлн [T] (trillion), квдрлн [Q] (quadrillion)\n"
" ⬥ при [цифра] после '0' введётся '.' с цифрой, при [z] после '.' введётся на одну '0' меньше, после '0' тоже самое с '.' впереди\n"
" ⬥ [v] вводит v (variable), после него введите число, которое подскажет таблице, куда вставлять значения из строк или столбцов в порядке нумерации\n"
" ⬥ после получения результата вычисления нескольких рядов или колонок, они астоматически скопируются, это ответы можно вставить в поля таблицы\n"
" ⬥ '•' ставится автоматически. При 'I' после 'π' или '1' появится '/' (удобно вводить радианы 'k•π/m'), после любого знака [•] введёт '2•'\n"
" ⬥ '•' не ставится при [|], только с [a], так как пример можно понять по-разному ('|5+5|7+8|2+2|', как '|5+5|•7+8•|2+2|' или '|5+5•|7+8|•2+2|')\n"
" ⬥ [/] — '1/' (после '√•^' — '2/'), [+] после '•/^√' введётся с '2', иначе заменится на '1'; после '.' ставь любой знак, кроме [.] — появится '5'\n"
"\nЛайфхаки и преимущества!\n"
" ★ Можно написать пример даже если фокус в окне инструкции или истории\n"
" ★ Быстрый ввод примера, точные тригонометрические и логарифмические вычисления\n"
" ★ Считает даже выражения вида (-32)^(3/5), (-5.2)!, (-11)mod(-3), log(4)by(-2)\n"
" ★ Учёт недостающих символов '2+2)•3•|1+1' → '(2+2)•3•|1+1|', очищенный пример от лишних скобок в истории '(|(2+2)|•3' → '|2+2|•3'\n"
" ★ Автоматическое добавление необходимых знаков при вводе примера, работает с примером с пробелами так, как если б их не было\n"
" ★ Раскладка меняется на английскую на время фокусировки на приложении, потом возвращается на предыдущую\n"
" ★ Много подсказок: калькулятор, не считавший примеры 2 недели, подскажет, как открыть инструкцию применения\n"
" ★ При вставке табличных данные (даже с пустыми ячейками) разделяются плюсами, так будет посчитана сумма данных\n"
" ★ Открой строку за 15 секунд после закрытия и пример останется. Иначе перейдёт в историю, если в ответе не число — удалится\n"
"\nНастройки и вид\n"
" ⚙ История. окно истории можно смахнуть вбок по тачпаду, либо утащить вбок за бегунок на полосе прокрутки\n"
" ⚙ Размещение. Перетаскивай строку мышкой (если тащищь в границу, она свернётся), через ctrl+↑ или написав 'y#', '-y#' (y — отступ сверху, -y снизу)\n"
" ⚙ Низ экрана: '1-#' или '-#', при 'y' от 0 до 1 не включительно, это число высот экрана, а не пикселей, 'y' можно писать примерами: '4^2/7#'\n"
" ⚙ Округление. По умолчанию: пиши где угодно в примере q, до нужного знака: qA (A от -23 до 17) и оно подействует через секунду\n"
" ⚙ Настрой размер памяти истории, вводя hx#, где x — максимальное число примеров\n"
" ⚙ Меняй тему со светлой на тёмную, с тёмной на светлую через ctrl+t (theme)\n"
" ⚙ Увеличивай и уменьшай текст комбинациями [ctrl]+[±] или сведением/разведением двух пальцев на тачпаде\n"
" ⚙ Разворачивай/сворачивай через ctrl+↓. Строка свернётся когда прокрутке колеса листать историю некуда, развернётся при обратном движении\n"
" Также можно сворачивать строку при перетаскивании окна к стенке в то время, когда окно уже на границе\n"
"\nПредупреждения и ограничения\n"
f" ❗ Для тригонометрических функций сокращения рациональных дробей со знаменателем менее {max_denominator} — градусы, остальное — радианы\n"
" ❗ Если модуль ответа не находится в диапазоне от 10^(-285) до 10^995 и при этом не равен нулю, вычисление не точно\n"
" ❗ Если калькулятор закрылся на более, чем 15 секунд, округляется всё снова по умолчанию\n"
" ❗ Приложение не даст вам открыть более 1 дополнительного окна во избежание бардака\n"
" ❗ 2^2^2^2=2^2^4=2^16=65536, 3k3k19683=3k27=3, -A^(-B)≠(-A)^(-B), √A!=√(A!)\n"
" ❗ Округлять можно от 23 знаков перед запятой до 17 знаков после\n"
" ❗ Знак умножить обязателен: нельзя 5sin90, можно 5•sin90")
def is_dark_theme():
# Путь к ключу реестра, где хранятся настройки темы
registry_path = r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"
value_name = "AppsUseLightTheme" # Значение, которое определяет светлую или тёмную тему
try:
# Открываем ключ реестра
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, registry_path)
# Читаем значение
value, _ = winreg.QueryValueEx(registry_key, value_name)
# Закрываем ключ
winreg.CloseKey(registry_key)
# Если значение 0, то тема тёмная, иначе светлая
return value == 0
except FileNotFoundError:
# Если ключ или значение не найдены, предполагаем светлую тему (или обработайте ошибку по-другому)
return False
# --------------------
screen_width, screen_height = pyautogui.size()
# Получить высоту панели задач
def get_taskbar_height():
SPI_GETWORKAREA = 48
rect = ctypes.wintypes.RECT()
ctypes.windll.user32.SystemParametersInfoW(SPI_GETWORKAREA, 0, ctypes.byref(rect), 0)
taskbar_height = screen_height - (rect.bottom - rect.top)
return taskbar_height
class FakeWindow():
def focus_get(self):
return
def focus_set(self):
pass
def destroy(self):
pass
def winfo_viewable(self):
return False
def title(self):
return invisible_win_title
def wm_state(self):
return 'iconic'
def is_russian_layout() -> bool:
"""
Проверяет, активна ли русская раскладка клавиатуры в текущем окне.
Возвращает True для русской раскладки, False для остальных случаев.
"""
user32 = ctypes.windll.user32
# Получаем дескриптор активного окна и его поток
hwnd = user32.GetForegroundWindow()
thread_id = user32.GetWindowThreadProcessId(hwnd, None)
# Получаем идентификатор раскладки клавиатуры
keyboard_layout = user32.GetKeyboardLayout(thread_id)
language_id = keyboard_layout & 0xFFFF # Извлекаем младшие 16 бит
# Русская раскладка имеет код 0x0419
return language_id == 0x0419
keyboard_layout_memory = ('en', 'ru')[is_russian_layout()]