KWT-2024/lab/lab_12.ipynb

400 lines
15 KiB
Plaintext
Raw Normal View History

2024-04-13 08:20:53 +02:00
{
"cells": [
{
"cell_type": "markdown",
"id": "virtual-accreditation",
"metadata": {},
"source": [
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Komputerowe wspomaganie tłumaczenia </h1>\n",
"<h2> 12. <i>Key logging</i> [laboratoria]</h2> \n",
"<h3>Rafał Jaworski (2021)</h3>\n",
"</div>\n",
"\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
]
},
{
"cell_type": "markdown",
"id": "featured-afghanistan",
"metadata": {},
"source": [
"Badania nad komputerowym wspomaganiem tłumaczenia często prowadzone są przy użyciu metodologii testowania interfejsów użytkownika - UI/UX testing. Program typu CAT traktuje się wówczas jak każdy inny program komputerowy i przeprowadza testy wydajności i użyteczności."
]
},
{
"cell_type": "markdown",
"id": "severe-protein",
"metadata": {},
"source": [
"Testy takie prowadzone są zawsze na użytkownikach końcowych, w tym przypadku - na tłumaczach. Podstawowym celem testów jest próba zaobserwowania faktycznego sposobu pracy tłumacza - które funkcje programu są przez niego wykorzystywane najczęściej, jakich innych narzędzi poza CAT-em używa on do swojej pracy, które funkcje programu działają zgodnie, a które niezgodnie z intuicją użytkownika oraz wiele innych czynników. Aby wszystkie te analizy były możliwe, konieczne jest zgromadzenie jak największej ilości danych dotyczących przebiegu testu."
]
},
{
"cell_type": "markdown",
"id": "constant-underground",
"metadata": {},
"source": [
"Testy są przede wszystkim nagrywane. Nagrywany jest zarówno ekran komputera (screen capture), jak i sam użytkownik pracujący przy komputerze. To jednak nie wszystko - często stosuje się specjalne techniki eye-trackingu, które są w stanie określić, w który punk ekranu użytkownik aktualnie patrzy. Dane pozyskane w ten sposób używane są do analizy czasu znalezienia przez użytkownika potrzebnej mu funkcji oraz zidentyfikowania miejsc, gdzie tej funkcji poszukiwał. Można również wyznaczyć obszary ekranu, które często skupiają uwagę użytkownika. "
]
},
{
"cell_type": "markdown",
"id": "analyzed-lodging",
"metadata": {},
"source": [
"Dodatkowo stosuje się jeszcze jedną technikę, która jest szczególnie przydatna z punktu widzenia analizy procesu tłumaczenia. Wykonuje się pełny key logging, tj. zapisuje się każde uderzenie użytkownika w dowolny klawisz na klawiaturze wraz z precyzyjnym czasem tego uderzenia. Dane pozyskane w ten sposób pozwalają na przeprowadzenie szeregu interesujących analiz."
]
},
{
"cell_type": "markdown",
"id": "incredible-stress",
"metadata": {},
"source": [
"Zapoznajmy się najpierw z programem typu key logger:"
]
},
{
2024-05-30 16:27:55 +02:00
"cell_type": "code",
"execution_count": 1,
"id": "c5c37655",
2024-04-13 08:20:53 +02:00
"metadata": {},
2024-05-30 16:27:55 +02:00
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting keyboard\n",
" Downloading keyboard-0.13.5-py3-none-any.whl.metadata (4.0 kB)\n",
"Downloading keyboard-0.13.5-py3-none-any.whl (58 kB)\n",
" ---------------------------------------- 0.0/58.1 kB ? eta -:--:--\n",
" ------- -------------------------------- 10.2/58.1 kB ? eta -:--:--\n",
" -------------- ------------------------- 20.5/58.1 kB 320.0 kB/s eta 0:00:01\n",
" --------------------- ------------------ 30.7/58.1 kB 259.2 kB/s eta 0:00:01\n",
" ---------------------------------------- 58.1/58.1 kB 382.9 kB/s eta 0:00:00\n",
"Installing collected packages: keyboard\n",
"Successfully installed keyboard-0.13.5\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
2024-04-13 08:20:53 +02:00
"source": [
2024-05-30 16:27:55 +02:00
"pip install keyboard"
2024-04-13 08:20:53 +02:00
]
},
{
"cell_type": "code",
2024-05-30 16:27:55 +02:00
"execution_count": 1,
2024-04-13 08:20:53 +02:00
"id": "broken-workstation",
"metadata": {},
2024-05-30 16:27:55 +02:00
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"KeyboardEvent(K up)\n",
"KeyboardEvent(R up)\n",
"KeyboardEvent(Y up)\n",
"KeyboardEvent(S up)\n",
"KeyboardEvent(T up)\n",
"KeyboardEvent(I up)\n",
"KeyboardEvent(A up)\n",
"KeyboardEvent(N up)\n"
]
}
],
"source": [
"import keyboard\n",
"\n",
"\n",
"def report_key(event):\n",
" print(event.scan_code)\n",
"\n",
"keyboard.on_release(callback=report_key)\n",
"keyboard.wait()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "abb08f92",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"75\n",
"77\n"
]
}
],
2024-04-13 08:20:53 +02:00
"source": [
"import keyboard\n",
"\n",
"\n",
"def report_key(event):\n",
2024-05-30 16:27:55 +02:00
" print(event.scan_code)\n",
2024-04-13 08:20:53 +02:00
"\n",
"keyboard.on_release(callback=report_key)\n",
"keyboard.wait()"
]
},
{
"cell_type": "markdown",
"id": "polish-census",
"metadata": {},
"source": [
"UWAGA! Aby uruchomić powyższy kod na Linuxie konieczne są uprawnienia administratora (pytanie poza konkursem - dlaczego?)"
]
},
{
"cell_type": "markdown",
"id": "incoming-hands",
"metadata": {},
"source": [
"### Ćwiczenie 1: Wykorzystując powyższy kod napisz keylogger, który zapisuje wszystkie uderzenia w klawisze do pliku. Format pliku jest dowolny, każdy wpis musi zawierać precyzyjną godzinę uderzenia oraz uderzony klawisz. Uruchom program i przepisz paragraf dowolnie wybranego tekstu."
]
},
2024-05-30 16:27:55 +02:00
{
"cell_type": "code",
"execution_count": 50,
"id": "15ff8fa5",
"metadata": {},
"outputs": [],
"source": [
"import keyboard\n",
"import datetime\n",
"\n",
"def report_key(event):\n",
" with open('pause.txt', 'a') as f:\n",
" timestamp = datetime.datetime.now().strftime('%H:%M:%S')\n",
" f.write(f'{timestamp}\\t{event.name}\\t{event.scan_code}\\n')\n",
" \n",
"\n",
"keyboard.on_release(callback=report_key)\n",
"keyboard.wait()\n",
"\n",
"#https://www.netia.pl/pl/blog/co-to-jest-keylogger-i-jak-go-wykryc\n",
"# wynik pierwszego paragraphu po drugim nagłówki w pliku keylogger.txt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d90b504",
"metadata": {},
"outputs": [],
"source": []
},
2024-04-13 08:20:53 +02:00
{
"cell_type": "markdown",
"id": "valuable-bearing",
"metadata": {},
"source": [
"Celem powyższego ćwiczenia jest pozyskanie danych testowych. Dalsze analizy będziemy prowadzili już bez key loggera, starając się korzystać jedynie z danych zapisanych w pliku. Oczywiście, jeśli zajdzie taka konieczność, można w każdej chwili wygenerować sobie nowy plik."
]
},
{
"cell_type": "markdown",
"id": "boxed-maple",
"metadata": {},
"source": [
"### Ćwiczenie 2: Napisz program, który wyliczy średnią prędkość pisania. Wykryj, kiedy użytkownik zaczął pisać. Nie bierz pod uwagę przerw dłuższych niż 5 sekund. Podaj prędkość pisania w znakach na minutę oraz słowach na minutę."
]
},
{
"cell_type": "code",
2024-05-30 16:27:55 +02:00
"execution_count": 78,
2024-04-13 08:20:53 +02:00
"id": "possible-holder",
"metadata": {},
2024-05-30 16:27:55 +02:00
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Łączny czas pisania = 2:14 \n",
"Napisano 256 znaków na minutę\n",
"Napisano 37 słów na minutę\n"
]
}
],
2024-04-13 08:20:53 +02:00
"source": [
2024-05-30 16:27:55 +02:00
"from datetime import datetime\n",
"\n",
2024-04-13 08:20:53 +02:00
"def calculate_typing_speed():\n",
2024-05-30 16:27:55 +02:00
" with open('keylogger.txt', 'r') as f:\n",
" start_time = None\n",
" end_time = None\n",
" chars = 0\n",
" words = 0\n",
" \n",
" break_time = 0\n",
" last_time = None\n",
"\n",
" lines = f.readlines()\n",
" length = len(lines)\n",
" for i in range(length):\n",
"\n",
" time, key, code = lines[i].strip().split('\\t')\n",
"\n",
" if start_time is None:\n",
" start_time = time\n",
" elif i == length - 1:\n",
" end_time = time\n",
"\n",
" if code in \"42, 54, 541, 75 , 77\": #shift, alt, left, right,\n",
" pass\n",
" elif code == '14': #backspace\n",
" chars -= 1\n",
" elif code == '57' or code == '28': #space, enter\n",
" words += 1\n",
" else:\n",
" chars += 1\n",
" \n",
" if last_time:\n",
" s = datetime.strptime(time, \"%H:%M:%S\")\n",
" e = datetime.strptime(last_time, \"%H:%M:%S\") \n",
" time_difference = e - s\n",
" \n",
" if last_time and time_difference.total_seconds() > 5:\n",
" break_time += time_difference.total_seconds()\n",
" \n",
" last_time = time\n",
" \n",
" s = datetime.strptime(start_time, \"%H:%M:%S\")\n",
" e = datetime.strptime(end_time, \"%H:%M:%S\")\n",
" time_difference = e - s\n",
" seconds = time_difference.total_seconds() - break_time \n",
" \n",
" chars_per_m = chars / (seconds // 60) \n",
" words_per_m = words / (seconds // 60) \n",
"\n",
" return (seconds,int(chars_per_m), int(words_per_m))\n",
"\n",
"seconds, chars, words = calculate_typing_speed()\n",
"\n",
"print(f'Łączny czas pisania = {int(seconds//60)}:{int(seconds%60)} ')\n",
"print(f'Napisano {chars} znaków na minutę')\n",
"print(f'Napisano {words} słów na minutę')\n",
"\n"
2024-04-13 08:20:53 +02:00
]
},
{
"cell_type": "markdown",
"id": "ceramic-birth",
"metadata": {},
"source": [
"Wróćmy teraz do procesu tłumaczenia. Analiza uderzeń klawiszy wykonanych podczas tłumaczenia pozwala wykryć dłuższe pauzy. Pauzy te najczęściej wskazują miejsca, w których tłumacz musi się głębiej zastanowić nad tłumaczeniem danego słowa lub frazy. Przerwę tę wykorzystuje na przykład na sprawdzenie tłumaczenia lub definicji w słowniku, przeglądanie wyników z pamięci tłumaczeń lub korzystanie z innych pomocy (eye-tracking mógłby w tym przypadku rozstrzygnąć, czym w istocie zajmuje się w tym momencie tłuamcz). Jest też możliwe, że tłumacz poświęca pauzę na tzw. cognitive pause-and-unload - rodzaj zamyślenia, pozwalający oczyścić myśli. Z punktu widzenia projektowania systemu wspomagającego tłumaczenie niezwykle istotna jest informacja, nad czym tłumacz musi się dłużej zastanowić. Minimalizacja liczby i czasu trwania takich przerw jest szansą na usprawnienie procesu tłumaczenia."
]
},
{
"cell_type": "markdown",
"id": "great-cable",
"metadata": {},
"source": [
"### Ćwiczenie 3: Napisz program do wykrywania przerw w pisaniu. Raportuj długość oraz miejsce wystąpienia przerwy podając 20-znakowy kontekst z każdej strony. Wykryj każdą przerwę dłuższą niż 3 sekundy, posortuj wyniki malejąco po długości przerwy."
]
},
{
"cell_type": "code",
2024-05-30 16:27:55 +02:00
"execution_count": 5,
2024-04-13 08:20:53 +02:00
"id": "close-riverside",
"metadata": {},
2024-05-30 16:27:55 +02:00
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pauza: 6.0s Ilość wciśniętych klawiszy do pauzy: 331 -> text: dzania baza danych (D|H|BMS). Historia SQL\n",
"Pauza: 8.0s Ilość wciśniętych klawiszy do pauzy: 680 -> text: z dnych to korzystani|P|e z SQl-a. Pierwsza\n",
"Pauza: 12.0s Ilość wciśniętych klawiszy do pauzy: 341 -> text: za danych (DBMS). Hi|S|storia SQL zostal o\n",
"Pauza: 13.0s Ilość wciśniętych klawiszy do pauzy: 1327 -> text: SQL: . SQL DML2. SQL|enter| DDL . SQL DCL .tab\n",
"Pauza: 15.0s Ilość wciśniętych klawiszy do pauzy: 1147 -> text: zona przez brytyjskďż|S|˝ wytwornIe lotnicz\n"
]
}
],
2024-04-13 08:20:53 +02:00
"source": [
2024-05-30 16:27:55 +02:00
"from datetime import datetime\n",
"\n",
2024-04-13 08:20:53 +02:00
"def find_pauses():\n",
2024-05-30 16:27:55 +02:00
" with open('pause.txt', 'r') as f:\n",
" breaks = []\n",
" \n",
" last_time = None\n",
" lines = f.readlines()\n",
" length = len(lines)\n",
" text = \"\"\n",
" q = 0\n",
" for i in range(length):\n",
"\n",
" time, key, code = lines[i].strip().split('\\t')\n",
" if code in \"42, 54, 541, 75 , 77\": #shift, alt, left, right,\n",
" q += 1\n",
" elif code == '14': #backspace\n",
" text = text[:-1]\n",
" q += 2\n",
" elif code == '57' or code == '28': #space, enter\n",
" text += \" \"\n",
" else:\n",
" text += key\n",
" \n",
" \n",
" if last_time:\n",
" s = datetime.strptime(time, \"%H:%M:%S\")\n",
" e = datetime.strptime(last_time, \"%H:%M:%S\") \n",
" time_difference = (s-e).total_seconds()\n",
" \n",
" if last_time and time_difference > 5:\n",
" if i-20 >= 0:\n",
" breaks.append([time_difference, [text[i-q-20:i+1-q],key,\"\"],i-q,i])\n",
" else:\n",
" breaks.append([time_difference, [text[:i+1-q],key,\"\"],i-q,i])\n",
" last_time = time\n",
" \n",
" for break_ in breaks:\n",
" i = break_[2]\n",
" if i+20 <= length:\n",
" break_[1][2] = text[i+1:i+20]\n",
" else:\n",
" break_[1][2] = text[i+1:] \n",
" \n",
" breaks = sorted(breaks, key=lambda x: x[0])\n",
" return breaks\n",
"\n",
"\n",
"for pause in find_pauses():\n",
" print(f\"Pauza: {pause[0]}s Ilość wciśniętych klawiszy do pauzy: {pause[3]} -> text: {pause[1][0]}|{pause[1][1]}|{pause[1][2]}\")"
2024-04-13 08:20:53 +02:00
]
}
],
"metadata": {
"author": "Rafał Jaworski",
"email": "rjawor@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
2024-05-30 16:27:55 +02:00
"lang": "pl",
2024-04-13 08:20:53 +02:00
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
2024-05-30 16:27:55 +02:00
"version": "3.12.1"
},
"subtitle": "12. Key logging",
"title": "Komputerowe wspomaganie tłumaczenia",
"year": "2021"
2024-04-13 08:20:53 +02:00
},
"nbformat": 4,
"nbformat_minor": 5
}