diff --git a/src/main.py b/src/main.py index a5278e1..f019188 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,7 @@ import sys import time import random +import string from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal from ui import Ui_MainWindow @@ -10,13 +11,14 @@ class TypingThread(QThread): progress = pyqtSignal(int) finished = pyqtSignal() - def __init__(self, text, interval, type_enter, chars_per_stroke, randomize_interval): + def __init__(self, text, interval, type_enter, chars_per_stroke, randomize_interval, mistake_percentage): super().__init__() self.text = text self.interval = interval self.type_enter = type_enter self.chars_per_stroke = chars_per_stroke self.randomize_interval = randomize_interval + self.mistake_percentage = mistake_percentage self.running = True self.keyboard = Controller() @@ -29,7 +31,7 @@ def run(self): i += 1 else: chunk = self.text[i:i + self.chars_per_stroke] - self.keyboard.type(chunk) + self.type_with_mistake(chunk) i += self.chars_per_stroke if self.randomize_interval: @@ -41,6 +43,32 @@ def run(self): self.progress.emit(int(i / len(self.text) * 100)) self.finished.emit() + def type_with_mistake(self, chunk): + for char in chunk: + if random.random() < self.mistake_percentage / 100: + # Make a typo + wrong_char = random.choice(string.ascii_lowercase) + self.keyboard.type(wrong_char) + time.sleep(self.interval * 2) # Pause after typo + + # Type a few more characters + extra_chars = ''.join(random.choices(string.ascii_lowercase, k=random.randint(1, 3))) + self.keyboard.type(extra_chars) + time.sleep(self.interval * 3) # Pause after extra chars + + # Backspace to correct the mistake + for _ in range(len(extra_chars) + 1): + self.keyboard.press(Key.backspace) + self.keyboard.release(Key.backspace) + time.sleep(self.interval * 0.5) + + # Type the correct character + self.keyboard.type(char) + else: + # Type normally + self.keyboard.type(char) + time.sleep(self.interval) + def stop(self): self.running = False @@ -64,19 +92,20 @@ def start_typing(self): type_enter = self.enterCheckBox.isChecked() chars_per_stroke = int(self.charPerStrokeSpinBox.value()) randomize_interval = self.randomizeIntervalCheckBox.isChecked() + mistake_percentage = int(self.mistakePercentageSpinBox.value()) except ValueError: - QMessageBox.critical(self, "Error", "Invalid input for delay, interval, or chars per stroke.") + QMessageBox.critical(self, "Error", "Invalid input for delay, interval, chars per stroke, or mistake percentage.") return self.startButton.setEnabled(False) self.stopButton.setEnabled(True) if delay > 0: - QTimer.singleShot(delay * 1000, lambda: self.initiate_typing(text, interval, type_enter, chars_per_stroke, randomize_interval)) + QTimer.singleShot(delay * 1000, lambda: self.initiate_typing(text, interval, type_enter, chars_per_stroke, randomize_interval, mistake_percentage)) else: - self.initiate_typing(text, interval, type_enter, chars_per_stroke, randomize_interval) + self.initiate_typing(text, interval, type_enter, chars_per_stroke, randomize_interval, mistake_percentage) - def initiate_typing(self, text, interval, type_enter, chars_per_stroke, randomize_interval): - self.thread = TypingThread(text, interval, type_enter, chars_per_stroke, randomize_interval) + def initiate_typing(self, text, interval, type_enter, chars_per_stroke, randomize_interval, mistake_percentage): + self.thread = TypingThread(text, interval, type_enter, chars_per_stroke, randomize_interval, mistake_percentage) self.thread.progress.connect(self.update_progress) self.thread.finished.connect(self.typing_finished) self.progressBar.setValue(0) diff --git a/src/translations/Chinese.json b/src/translations/Chinese.json index 1a31340..72a7f30 100644 --- a/src/translations/Chinese.json +++ b/src/translations/Chinese.json @@ -32,6 +32,10 @@ { "component": "randomizeIntervalCheckBox", "text": "随机化间隔" + }, + { + "component": "mistakePercentageLabel", + "text": "错误百分比:" } ] } diff --git a/src/translations/English.json b/src/translations/English.json index a6a7dcb..f1e6f36 100644 --- a/src/translations/English.json +++ b/src/translations/English.json @@ -32,6 +32,10 @@ { "component": "randomizeIntervalCheckBox", "text": "Randomize Interval" + }, + { + "component": "mistakePercentageLabel", + "text": "Mistake Percentage:" } ] } \ No newline at end of file diff --git a/src/translations/French.json b/src/translations/French.json index b44d8b9..4866a55 100644 --- a/src/translations/French.json +++ b/src/translations/French.json @@ -32,6 +32,10 @@ { "component": "randomizeIntervalCheckBox", "text": "Intervalle Aléatoire" + }, + { + "component": "mistakePercentageLabel", + "text": "Pourcentage d'erreur :" } ] } \ No newline at end of file diff --git a/src/translations/Norwegian.json b/src/translations/Norwegian.json index 9f8486c..eaf885c 100644 --- a/src/translations/Norwegian.json +++ b/src/translations/Norwegian.json @@ -32,6 +32,10 @@ { "component": "randomizeIntervalCheckBox", "text": "Tilfeldig Intervall" + }, + { + "component": "mistakePercentageLabel", + "text": "Feilprosent:" } ] } \ No newline at end of file diff --git a/src/ui.py b/src/ui.py index 931c11f..595a468 100644 --- a/src/ui.py +++ b/src/ui.py @@ -20,9 +20,9 @@ def __init__(self): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(600, 500) - MainWindow.setMinimumSize(QtCore.QSize(600, 500)) - MainWindow.setMaximumSize(QtCore.QSize(600, 500)) + MainWindow.resize(600, 600) + MainWindow.setMinimumSize(QtCore.QSize(600, 600)) + MainWindow.setMaximumSize(QtCore.QSize(600, 600)) MainWindow.setWindowIcon(QtGui.QIcon("logo.png")) if sys.platform == "win32" and hasattr(ctypes.windll, "shell32"): ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("Chainsaw Human Typing") @@ -30,7 +30,7 @@ def setupUi(self, MainWindow): self.centralwidget.setObjectName("centralwidget") self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget) - self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 561, 461)) + self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 560, 560)) self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) @@ -74,6 +74,15 @@ def setupUi(self, MainWindow): self.charPerStrokeSpinBox.setObjectName("charPerStrokeSpinBox") self.settingsLayout.addWidget(self.charPerStrokeSpinBox) + self.mistakePercentageLabel = QtWidgets.QLabel(self.horizontalLayoutWidget) + self.mistakePercentageLabel.setObjectName("mistakePercentageLabel") + self.settingsLayout.addWidget(self.mistakePercentageLabel) + + self.mistakePercentageSpinBox = QtWidgets.QSpinBox(self.horizontalLayoutWidget) + self.mistakePercentageSpinBox.setRange(0, 100) + self.mistakePercentageSpinBox.setObjectName("mistakePercentageSpinBox") + self.settingsLayout.addWidget(self.mistakePercentageSpinBox) + self.randomizeIntervalCheckBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget) self.randomizeIntervalCheckBox.setObjectName("randomizeIntervalCheckBox") self.settingsLayout.addWidget(self.randomizeIntervalCheckBox) @@ -150,7 +159,6 @@ def change_language(self): f.write(self.current_language) self.update_ui_text() - def update_ui_text(self): translation = self.translations.get(self.current_language, self.translations["English"]) for item in translation["MainWindow"]: