From 1ff5f22caf83044c09548af131eaa58c0721310d Mon Sep 17 00:00:00 2001 From: Marek Susniak Date: Sat, 15 Jun 2024 16:02:09 +0200 Subject: [PATCH] Laboratorium #12 --- lab/lab_12.ipynb | 517 +++++++++++++++++++++++++++++++---------------- 1 file changed, 338 insertions(+), 179 deletions(-) diff --git a/lab/lab_12.ipynb b/lab/lab_12.ipynb index c4dc223..daadd21 100644 --- a/lab/lab_12.ipynb +++ b/lab/lab_12.ipynb @@ -1,181 +1,340 @@ { - "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", - "
\n", - "

Komputerowe wspomaganie tłumaczenia

\n", - "

12. Key logging [laboratoria]

\n", - "

Rafał Jaworski (2021)

\n", - "
\n", - "\n", - "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "virtual-accreditation", + "metadata": { + "id": "virtual-accreditation" + }, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Komputerowe wspomaganie tłumaczenia

\n", + "

12. Key logging [laboratoria]

\n", + "

Rafał Jaworski (2021)

\n", + "
\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": { + "id": "featured-afghanistan" + }, + "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": { + "id": "severe-protein" + }, + "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": { + "id": "constant-underground" + }, + "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": { + "id": "analyzed-lodging" + }, + "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": { + "id": "incredible-stress" + }, + "source": [ + "Zapoznajmy się najpierw z programem typu key logger:" + ] + }, + { + "cell_type": "markdown", + "id": "arctic-horror", + "metadata": { + "id": "arctic-horror" + }, + "source": [ + "`sudo pip3 install keyboard`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "broken-workstation", + "metadata": { + "id": "broken-workstation" + }, + "outputs": [], + "source": [ + "!pip install keyboard\n", + "\n", + "import keyboard\n", + "\n", + "\n", + "def report_key(event):\n", + " print(event)\n", + "\n", + "keyboard.on_release(callback=report_key)\n", + "keyboard.wait()" + ] + }, + { + "cell_type": "markdown", + "id": "polish-census", + "metadata": { + "id": "polish-census" + }, + "source": [ + "UWAGA! Aby uruchomić powyższy kod na Linuxie konieczne są uprawnienia administratora (pytanie poza konkursem - dlaczego?)" + ] + }, + { + "cell_type": "markdown", + "id": "incoming-hands", + "metadata": { + "id": "incoming-hands" + }, + "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.\n" + ] + }, + { + "cell_type": "code", + "source": [ + "import keyboard\n", + "import datetime\n", + "\n", + "# Funkcja zapisu do pliku\n", + "def log_key(event):\n", + " with open(\"key_log.txt\", \"a\") as log_file:\n", + " log_file.write(f\"{datetime.datetime.now()}: {event.name}\\n\")\n", + "\n", + "keyboard.on_release(callback=log_key)\n", + "keyboard.wait()" + ], + "metadata": { + "id": "CjzM4sFTGIfJ" + }, + "id": "CjzM4sFTGIfJ", + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "id": "valuable-bearing", + "metadata": { + "id": "valuable-bearing" + }, + "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": { + "id": "boxed-maple" + }, + "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", + "execution_count": null, + "id": "possible-holder", + "metadata": { + "id": "possible-holder" + }, + "outputs": [], + "source": [ + "import datetime\n", + "\n", + "def read_log_file(file_path):\n", + " with open(file_path, \"r\") as file:\n", + " lines = file.readlines()\n", + " return lines\n", + "\n", + "def parse_log_lines(lines):\n", + " key_events = []\n", + " for line in lines:\n", + " timestamp_str, key = line.strip().split(\": \")\n", + " timestamp = datetime.datetime.strptime(timestamp_str, \"%Y-%m-%d %H:%M:%S.%f\")\n", + " key_events.append((timestamp, key))\n", + " return key_events\n", + "\n", + "def calculate_typing_speed(key_events):\n", + " total_chars = 0\n", + " total_words = 0\n", + " start_time = None\n", + " end_time = None\n", + " last_time = None\n", + " time_intervals = []\n", + "\n", + " for timestamp, key in key_events:\n", + " if start_time is None:\n", + " start_time = timestamp\n", + " if last_time is not None and (timestamp - last_time).total_seconds() > 5:\n", + " start_time = timestamp\n", + " last_time = timestamp\n", + " total_chars += 1\n", + " if key == 'space':\n", + " total_words += 1\n", + " end_time = timestamp\n", + "\n", + " if total_chars == 0:\n", + " return 0, 0 # No typing detected\n", + "\n", + " total_time = (end_time - start_time).total_seconds() / 60 # in minutes\n", + " cpm = total_chars / total_time\n", + " wpm = total_words / total_time\n", + "\n", + " return cpm, wpm\n", + "\n", + "\n", + "\n", + "def calculate_typing_speed(file_name):\n", + " log_lines = read_log_file(file_name)\n", + " key_events = parse_log_lines(log_lines)\n", + " cpm, wpm = calculate_typing_speed(key_events)\n", + "\n", + " print(f\"Średnia prędkość pisania: {cpm:.2f} znaków na minutę\")\n", + " print(f\"Średnia prędkość pisania: {wpm:.2f} słów na minutę\")\n", + " return cpm, wpm\n", + "\n", + "calculate_typing_speed(\"key_log.txt\")" + ] + }, + { + "cell_type": "markdown", + "id": "ceramic-birth", + "metadata": { + "id": "ceramic-birth" + }, + "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": { + "id": "great-cable" + }, + "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", + "execution_count": 4, + "id": "close-riverside", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 305 + }, + "id": "close-riverside", + "outputId": "f26a611b-3cba-4e96-f922-8af210c7bf45" + }, + "outputs": [ + { + "output_type": "error", + "ename": "NameError", + "evalue": "name 'read_log_file' is not defined", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 32\u001b[0;31m \u001b[0mreport_pauses\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfind_pauses\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"key_log.txt\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfind_pauses\u001b[0;34m(file_name, min_pause_duration)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfind_pauses\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmin_pause_duration\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mlog_lines\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mread_log_file\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile_name\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mkey_events\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparse_log_lines\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlog_lines\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mpauses\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfind_pauses\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey_events\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mprevious_time\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'read_log_file' is not defined" + ] + } + ], + "source": [ + "def find_pauses(file_name, min_pause_duration=3):\n", + " log_lines = read_log_file(file_name)\n", + " key_events = parse_log_lines(log_lines)\n", + " pauses = find_pauses(key_events)\n", + " previous_time = None\n", + " context = []\n", + "\n", + " for i, (timestamp, key) in enumerate(key_events):\n", + " if previous_time:\n", + " pause_duration = (timestamp - previous_time).total_seconds()\n", + " if pause_duration > min_pause_duration:\n", + " start_context = max(0, i-20)\n", + " end_context = min(len(key_events), i+20)\n", + " context_before = ''.join(key[1] for key in key_events[start_context:i])\n", + " context_after = ''.join(key[1] for key in key_events[i:end_context])\n", + " pauses.append((pause_duration, context_before, context_after))\n", + " previous_time = timestamp\n", + " context.append(key)\n", + "\n", + " pauses.sort(reverse=True, key=lambda x: x[0])\n", + " return pauses\n", + "\n", + "def report_pauses(pauses):\n", + " for pause in pauses:\n", + " duration, context_before, context_after = pause\n", + " print(f\"Przerwa: {duration:.2f} sekund\")\n", + " print(f\"Kontekst przed: {context_before[-20:]}\")\n", + " print(f\"Kontekst po: {context_after[:20]}\")\n", + " print(\"-\" * 40)\n", + "\n", + "\n", + "report_pauses(find_pauses(\"key_log.txt\"))\n" + ] + } + ], + "metadata": { + "author": "Rafał Jaworski", + "email": "rjawor@amu.edu.pl", + "lang": "pl", + "subtitle": "12. Key logging", + "title": "Komputerowe wspomaganie tłumaczenia", + "year": "2021", + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + }, + "colab": { + "provenance": [] + } }, - { - "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:" - ] - }, - { - "cell_type": "markdown", - "id": "arctic-horror", - "metadata": {}, - "source": [ - "`sudo pip3 install keyboard`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "broken-workstation", - "metadata": {}, - "outputs": [], - "source": [ - "import keyboard\n", - "\n", - "\n", - "def report_key(event):\n", - " print(event)\n", - "\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." - ] - }, - { - "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", - "execution_count": 1, - "id": "possible-holder", - "metadata": {}, - "outputs": [], - "source": [ - "def calculate_typing_speed():\n", - " return 0" - ] - }, - { - "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", - "execution_count": 2, - "id": "close-riverside", - "metadata": {}, - "outputs": [], - "source": [ - "def find_pauses():\n", - " return []" - ] - } - ], - "metadata": { - "author": "Rafał Jaworski", - "email": "rjawor@amu.edu.pl", - "lang": "pl", - "subtitle": "12. Key logging", - "title": "Komputerowe wspomaganie tłumaczenia", - "year": "2021", - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file