České vysoké učení technické v Praze Fakulta elektrotechnická. Remote Flash Usability testing



Podobné dokumenty
Návrh a tvorba WWW stránek 1/14. PHP a databáze

!!Via!AUREA,!s.r.o.!

5. POČÍTAČOVÉ CVIČENÍ

Internet cvičení. ZS 2009/10, Cvičení 3., Tomáš Pop. DISTRIBUTED SYSTEMS RESEARCH GROUP

17. července :51 z moravec@yahoo.com

Měřící systém se vzdáleným přístupem. Databáze

DUM 14 téma: Interakce s uživatelem

Bottle -- příklad. Databáze. Testovací data. id Jedinečný identifikátor řádku: Bude typu INT s AUTO_INCREMENT a nastavíme ho jako primární klíč

Rezervační systém Tvorba WWW stránek

Základy HTML, URL, HTTP, druhy skriptování, formuláře

Střední odborná škola a Střední odborné učiliště, Hořovice

Skriptování na straně serveru a klienta

Obchodní akademie a Jazyková škola s právem státní jazykové zkoušky Jihlava

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

Použití databází na Webu

Formuláře. Internetové publikování. Formuláře - příklad

Vyšší odborná škola a Střední škola,varnsdorf, příspěvková organizace. Šablona 14 VY 32 INOVACE

Instalace a první spuštění Programu Job Abacus Pro

Informační systém pro e-learning manuál

Informační systém webhostingu

Úvodem 9. Zpětná vazba od čtenářů 10 Zdrojové kódy ke knize 10 Errata 10. Než začneme 11

Databázové systémy Cvičení 5.2

Semestrální práce z DAS2 a WWW

Databáze prodejců. Tlačítka. Vytvoří kartu nového prodejce (Alt+N); Změní vybraného prodejce Uloží nového prodejce nebo změnu (Alt+U);

1 Administrace systému Moduly Skupiny atributů Atributy Hodnoty atributů... 4

MySQL sežere vaše data

Verzování a publikace dat na webu za pomoci PostgreSQL

XSLT pomocí JavaScriptu v Mozille (... Opeře a Safari)

Nastavení propojení s eshopem

1. Webový server, instalace PHP a MySQL 13

Analýza Redakční systém blogu (ADA274, BYS037, RAB020, SIV021)

Audit DB. Referát. Vypracoval: Zdeněk Doležal MFF UK Praha 11/5/06

Sentech AL 7000 C. Instalace a ovládání programu BREATH

PHP PHP je skriptovací programovací jazyk dynamických internetových stránek PHP je nezávislý na platformě

Databázové systémy. - SQL * definice dat * aktualizace * pohledy. Tomáš Skopal

MS SQL Server 2008 Management Studio Tutoriál

PHP a Large Objecty v PostgreSQL

Úvod do PHP s přihlédnutím k MySQL

Práce s programem MPVaK

JavaScript 101. "Trocha života do statických stránek"

Javascript. Javascript - jazyk

MOŽNOSTI KOMUNIKACE FLASH ANIMACÍ S OKOLÍM

SRSW4IT Inventarizační SW. Prezentace aplikace. Vedoucí DP: ing. Lukáš Macura Autor: Bc. Petr Mrůzek

Sada 1 - PHP. 09. Formuláře

Instalace a konfigurace OpenAdmin tool na M$ a Linuxu

Elektronická komunikace s ČSSZ

SignEditor 1 - návod k použití

Univerzita Pardubice. Centrální správa dokumentů

Databáze I. Přednáška 4

Tvorba WWW stránek. přehled technologií používaných na webu principy jednotlivých technologií a možnosti jejich vzájemného kombinování

Dokumentace k produktu IceWarp Notifikační nástroj

Na vybraném serveru vytvoříme MySQL databázi. Soubory scratch.jpa, kickstart.php a en-gb.kickstart.ini nahrajeme na vybraný server.

WNC::WebNucleatCreator

CMSSS manuál k použití

Implementace LMS MOODLE. na Windows 2003 Server a IIS 6.0

Platební systém XPAY [

Django. Webový framework pro Python Projekt = webová stránka Aplikace = určitá funkcionalita webu

Podklad pro tvorbu ilayer typu

Úvod do FlexiBee REST API. Petr Ferschmann FlexiBee Systems s.r.o.

Faxový server společnosti PODA s.r.o.

7. Integrita a bezpečnost dat v DBS

7. Integrita a bezpečnost dat v DBS

Obsah. Stručná historie World Wide Webu 7

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Internet cvičení. ZS 2009/10, Cvičení 4., PHP. Tomáš Pop. DISTRIBUTED SYSTEMS RESEARCH GROUP

Sada 1 - PHP. 14. Úvod do jazyka SQL

Import a export dat EU peníze středním školám Didaktický učební materiál

Mapa Česka:

Rozcestník virtuálních světů

Modul Outlook2Money.

Příprava prostředí pro výuku PHP a MySQL

Fre Prahy 10. Do svého u se můžete přihlásit odkudkoliv na webové adrese

DELTA - STŘEDNÍ ŠKOLA INFORMATIKY A EKONOMIE, s.r.o. Obor informační technologie AJAX ESHOP. Maturitní projekt. Třída:

Programování v jazyce JavaScript

AUTOMATICKÉ ŘÍZENÍ S INTERNETOVOU KOMUNIKACÍ V PHP Automatic Control with Internet Communication in PHP

Maturitní témata z předmětu PROGRAMOVÉ VYBAVENÍ pro šk. rok 2012/2013

ČERV. Hra Červ je psána pomocí příkazů Javascriptu a standardních příkazů HTML.

Plánování a vývoj základního frameworku

Vývoj moderních technologií při vyhledávání. Patrik Plachý SEFIRA spol. s.r.o.

1 Webový server, instalace PHP a MySQL 13

AJAX. Dynamické změny obsahu stránek

4. Nastavení programu

Další nutný soubor je laydiv.js, ve kterém jsou uloženy funkce pro zobrazování virů na ploše a funkce pro odkaz na Teachers Guide.

TMservice. Služba operačního systému Windows pro měření teploty čidlem TM

MySQL. mysql> CREATE DATABASE nova CHARACTER SET latin2 COLLATE latin2_czech_cs; Query OK, 1 row affected (0.02 sec)

Instalace a konfigurace web serveru. WA1 Martin Klíma

Manuál k programu KaraokeEditor

Aplikace BSMS. Uživatelská příručka - 1 -

Poznámky k verzi Remote support platform 3.1

People Counter v2. Ver. 2.0

Současný svět Projekt č. CZ.2.17/3.1.00/32038, podpořený Evropským sociálním fondem v rámci Operačního programu Praha adaptabilita

[APLIKACE PRO PŘEHRÁVÁNÍ VIDEA - PROJEKT MIAMI - SERVEROVÁ ČÁST]

Delphi popis prostředí

Instalace. Produkt je odzkoušen pro MS SQL server 2008 a Windows XP a Windows 7. Pro jiné verze SQL server a Windows nebyl testován.

První kapitola úvod do problematiky

ČSOB Business Connector Instalační příručka

Uživatelská příručka MWA Modul Podpora vzdálených kalibrací dle ILAC

MySQLi (objektově) Příklad vytvoření instance třídy včetně parametrů pro připojení: $mysqli = new mysqli('localhost', 'login', 'heslo', 'databaze');

Principy fungování WWW serverů a browserů. Internetové publikování

Vazba ESO9 na MS Outlook a MS Exchange

Transkript:

České vysoké učení technické v Praze Fakulta elektrotechnická Semestrální práce z předmětu Návrh uživatelského rozhraní Remote Flash Usability testing Autor: Email: skrivl1@fel.cvut.cz Datum: 28.5.2006

Zadání Navrhněte systém, který zaznamená interakci člověka (stisky kláves, pohyb kurzoru myši, klikání myši, dragování objektů, atd.) s flash animací. Tento systém poté umožní zpětné přehrání těchto interakcí. Vámi navržený systém by měl obsahovat tlačítka na pozastavení, zastavení a převinutí zaznamenaných akcí. Návrh řešení Celý systém lze rozdělit na dvě oddělitelné části část určená pro záznam (recorder) a část určená pro pozdější přehrání zaznamenaných akcí (player). Recorder Recoder lze realizovat dvěma způsoby, buď jako flash animaci, která do sebe vloží zaznamenávanou flash animaci nebo jako samostatný soubor *.as obsahující pouze zdrojový text ActionScriptu, který se přilinkuje k testované flash animaci. Událostní model funguje tak, že existují odesílatelé událostí (dispatcher), ke kterým se mohou zaregistrovat posluchači (listener) obsahující funkce (metody) obsluhující danou událost. Odesílatele i posluchače událostí lze v ActionScriptu 2.0 vytvořit, nám však k záznamu událostí stačí vytvořit jen posluchače obsluhujícího události myši a klávesnice a zaregistrovat ho u globálního odesílatele událostí Mouse, v případě myši, a Key, v případě klávesnice. Tito odesílatelé přímo odrážejí reakce uživatele. V rozumných programovacích jazycích získá metoda posluchače jako parametr objekt reprezentující událost nesoucí veškeré informace o dané události. Potom stačí tento objekt serializovat a uložit pro pozdější načtení playerem. Bohužel v ActionScriptu 2.0 se tento parametr nepředává a je třeba informace o události získávat z globálních proměnných (např. _xmouse, _ymouse) nebo z globálního odesílatele událostí (např. Key.getAscii(), Key.getCode()), avšak po posbírání informací již nic nebrání uložení události. Player Úkolem playeru je načíst a deserializovat nebo jinak zrekonstruovat recorderem uložený objekt události a ve správný čas ho pomocí odesílatele, u kterého jsou zaregistrováni všichni posluchači přehrávané flash animace, předat těmto posluchačům. Na to flash animace zareaguje stejně jako by byla akce právě vyvolána uživatelem. Toto je jediné správné řešení problému. Bohužel v ActionScriptu 2.0 je znemožněno hned ze dvou důvodů. Prvním důvodem je výše zmíněné předávání objektu události posluchači jako parametru. Tím, že se informace o události musí číst z globálních proměnných je třeba je při vyslání naší události nastavit na příslušné hodnoty, avšak ne všechny lze změnit. Druhým vážnějším důvodem je nemožnost vyslání události pomocí globálních odesílatelů Mouse a Key, ke kterým jsou zaregistrováni všichni posluchači přehrávané flash animace. Věřím, že v některé z příštích verzí ActionScriptu již toto možné bude a že 1

samotné odeslání nastaví příslušné globální proměnné, čímž odpadne i prvně zmíněný problém, nebo dokonce začne používat předávání objektu události jako parametru posluchači. Paradoxem této situace je, že lze vytvořit jakýsi objekt události i vlastního odesílatele události, který již námi vytvořenou událost odeslat umí. Bohužel u našeho odesílatele nejsou zaregistrováni posluchači přehrávané flash animace. Ideální by tedy bylo, kdyby šlo přesměrovat registrace posluchačů z globálních odesílatelů Key a Mouse na našeho odesílatele a tím dokonce zastínit interakci uživatele v době přehrávání flash animace, což ovšem samožřejmě nejde. Další řešení již není zcela ideální, ale pokud by bylo možné získat z odesílatele veškeré posluchače, které jsou u něho zaregistrováni, bylo by možné volat obslužné funkce (metody) ručně. Ovšem ani toto odesílatelé událostí v ActionScriptu 2.0 neumožňují. Implementace Recorder Při implementaci recorderu jsme sáhli po variantě samostatného souboru obsahujícího zdrojový text ActionScriptu *.as, který se bude linkovat s flash animací, ve které chceme odchytávat interakce uživatele. Pro ukládání dat jsme zvolili cestu přes PHP skript, přestože současná verze produktu Macromedia Flash 8.0 umí ukládat do souboru pomocí JavaScriptu, protože chceme ukládat interakce do databáze MySQL. Pro komunikaci s PHP skriptem používáme XML verze 1.0. Na začátku pomocí PHP skriptu získáme z databáze číslo nového uživatele a toto číslo v databázi rezervujeme s událostí start, dále vytvoříme dva posluchače obsluhující události onkeydown, onkeyup, onmousedown, onmouseup a onmousemove. V obsluze těchto událostí se tvoří XML soubor, který obsahuje číslo uživatele, url flash animace, čas události, číslo snímku, na kterém došlo k události, druh události a další informace o události. Čas události se měří od první interakce uživatele (první událost je v čase 0). Události jsou odesílány v průběhu záznamu po předem daném množství událostí. Záznam končí zavřením flash animace, ale v tuto chvíli je potřeba odeslat poslední zaznamenané události. O nedokonalosti událostního modelu v ActionScriptu 2.0 již bylo v tomto dokumentu řečeno mnohé a proto čtenáře jistě nepřekvapí, že neobsahuje událost ukončení přehrávače flash animace. Tímto faktem vstupuje do hry JavaScript, mimochodem jazyk podobný ActionScriptu, a omezení zaznamenávání interakcí uživatele pouze s flash animací umístěné v HTML stránce. JavaScript totiž umožňuje nejen zachytit událost ukončení setrvání HTML stránky v prohlížeči, ale dokonce volat zpřístupněné funkce ActionScriptu v přehrávané flash animaci. Pro snazší pochopení provázání jednotlivých programovacích jazyků a toků dat slouží následující obrázek: 2

Ve chvíli uzavření prohlížeče, načtení jiné stránky či obnovení stránky je JavaScriptem odchycena událost onunload a JavaScript volá funkci ActionScriptu onclose(). Tato funkce přidá poslední událost end s časovým razítkem a odešle poslední události skriptu PHP. PHP skript obsluhuje požadavky ActionScriptu tak, že buď načte z databáze číslo posledního uživate, to zvýší a předá zpět flash animaci, nebo přijme XML soubor, ten přečte a pomocí SQL uloží data v něm obsažená do databáze. Než začneme databázi jako uložiště událostí využívat je třeba v ní vytvořit tabulku. Naše tabulka obsahuje atributy: ID, UrlSwf, UserID, Frame, Time, Kind, MouseX, MouseY, Ascii, KeyCode. Player Z důvodů uvedených v části o návrhu řešení není v současné době možné implementovat player podle prvotní vize v ActionScriptu 2.0. Možným řešením je buď vyčkat příchodu vyšších verzí ActionScriptu nebo jiných technologií spojených s Macromedia Flashem nebo sáhnout po jiných nastrojích jakými může být například Win32 API, jenž bude posílat události přímo přehrávači flash animace. Instalace Recorder Pro správnou funkci recorderu je nutné mít: 1. zdrojový soubor recorderu (recorder.as - příloha č. 1) 2. zdrojový soubor testované flash animace (*.fla) 3. html stránku, která bude obsahovat flash animaci (recorder.html - příloha č. 3) 4. PHP skript pro ukládání událostí (save.php - příloha č. 2) 5. schéma tabulky (sql.txt - příloha č. 4) 6. funkční webový server s podporou PHP skriptů 7. databázový server MySQL 3

1. Ve zdrojovém souboru recorderu (recorder.as) je třeba modifikovat cestu k PHP skriptu určenému k ukládání událostí: _global.php_name = "http://www.server.cz/save.php"; a volitelně je možné změnit po kolika událostech má docházet k odesílání: _global.send_count = 50; 2. Zdrojový soubor testované flash animace je třeba modifikovat tak, že na první snímek animace vložíme akci: #include "recorder.as" Na konci toho řádku nesmí být středník. Tato akce způsobí přilinkování souboru recorder.as k flash animaci. Pokud se soubor recorder.as nachází v jiném adresáři nebo je přejmenován, je třeba změnit cestu a název vkládaného souboru. Pak již stačí jen spuštěním animaci znovu přeložit. 3. V html stránce je třeba modifikovat cestu k flash animaci a to hned na dvou místech: <param name="movie" value="animace.swf"> a <embed src="animace.swf"... Pokud budete vytvářet stránku svoji, upozorňuji, že je nezbytně nutné, aby obsahovala <param name="allowscriptaccess" value="always" /> v tagu objekt flash animace a AllowScriptAccess="always" v tagu embeded. Bez tohoto by nefungovala komunikace mezi JavaScriptem a ActionScriptem. V mnohých zdrojích se dočtete, že hodnota always je u atributu AllowScriptAccess automatická bez uvedení, ale není to pravda. 4. V PHP skriptu je třeba správně nastavit adresu k MySQL serveru: $SQL_Server="mysql.server.cz"; uživatelské jméno v MySQL: $SQL_Login="user name"; heslo: $SQL_Password="password"; databázi: $SQL_Databaze="databaze"; 4

a název tabulky, kterou vytvoříme za chvíli: $SQL_Table="recorder"; 5. Podle tohoto schématu je třeba vytvořit tabulku v databázi. Pokud chcete zvolit jiný název tabulky nezapomeňte správně nastavit v PHP skriptu proměnnou $SQL_Table (část 4.). Jiné zásahy do schématu se provádět nemusí. Body 6 a 7 přesahují rámec tohoto textu a nejsou ani cílem, stačí mít funkční webový server s podporou PHP skriptů. Do jeho adresáře s publikovanými html a php stránkami přikopírovat soubory: nově přeloženou flash animaci (*.swf) html stránku, která bude obsahovat flash animaci (recorder.html) PHP skript pro ukládání událostí (save.php) Zároveň Vám musí fungovat MySQL server a musíte mít správně nastavené veškeré výše zmíněné proměnné (cesty, jména, hesla...) a vytvořenou tabulku (bod 5.). Pak již stačí zadat do prohlížeče adresu: http://adresavasehowebovehoserveru/cesta/recorder.html. Měla by se Vám zobrazit html stránka obsahující vaši flash animaci. Při první interakci s touto animací se začnou veškeré interakce zaznamenávat (včetně té první) a záznam skončí až při uzavření okna prohlížeče, načtení jiné stránky nebo obnovení stránky(v tom případě může začít záznam znovu pod novým uživatelem). Závěr Ač celý dokument vyznívá proti produktu Macromedia Flash a ActionScriptu, je třeba říci, že se jedná o velmi kvalitní kreslící a prezentační nástroj, ve kterém lze dokonce tvořit aplikace a hry, je uživatelsky přívětivý, intuitivní a velmi dobře se v něm pracuje. ActionScript samotný je jazyk, který prochází vývojem a tím se stává stále mocnějším nástrojem. Podle mého názoru jeho událostní model není zatím zcela vyzrálý, avšak je třeba si uvědomit, že na podobné účely není určený ani navržený a pro běžné aplikace je plně dostačující. Celá práce byla realizována v Macromedia Flashi 8.0 Trial version a je pravděpodobné, že v nižších verzích nebude korektně fungovat zvláště zpřístupnění funkcí z ActionScriptu pro JavaScript. (ExternalInterface.addCallback("onClose", null, onclose);) Zdroje http://www.macromedia.com http://www.adobe.com/cfusion/tdrc/index.cfm?product=flashpro&loc=en_us Trial version 5

http://www.brajeshwar.com/reference/as2/ http://livedocs.macromedia.com/flash/mx2004/ http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/ http://www.kirupa.com/developer/oop2/as2oopindex.htm http://www.actionscript.org/tutorials.shtml http://flash.jakpsatweb.cz/ 6

Příloha č. 1 - recorder.as import flash.external.*; // option variable _global.php_name = "http://www.server.cz/save.php"; _global.send_count = 50; // do not change _global.capture_count = 0; _global.t0 = 0; _global.user = 0; // create XML _global.eventxml = new XML(); _global.eventxml.contenttype = "text/xml"; _global.eventxml.xmldecl = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; _global.eventxml.appendchild( EventXML.createElement("swfEvents") ); _global.userxml = new XML(); _global.nothingxml = new XML(); //read user ID randomize = Math.random()*Math.random(); _global.userxml.load(_global.php_name+"?id="+randomize); _global.userxml.onload = useronload; function useronload(success:boolean) { if (success) { if (_global.userxml.firstchild.nextsibling.nodename == "user") { _global.user = _global.userxml.firstchild.nextsibling.firstchild.nodevalue; _level0.vypis=_global.user; else { fatal_error("recorder: Connection failed! (2)"); else { fatal_error("recorder: Connection failed! (1)"); //print error function fatal_error(mess:string){ _level0.createemptymovieclip("error", _level0.getnexthighestdepth()); _level0.error.createtextfield("mess", 1, 0, 0, 200, 20); _level0.error.mess.background=true; _level0.error.mess.backgroundcolor = 0xFF0000; _level0.error.mess.text = mess; //end capture function onclose() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("end") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createTextNode(time-_global.t0) ); ESend(); ExternalInterface.addCallback("onClose", null, onclose); //save events function ESend() { //set user and url _global.eventxml.firstchild.insertbefore(eventxml.createelement("user"), _global.eventxml.firstchild.firstchild); _global.eventxml.firstchild.firstchild.appendchild( EventXML.createTextNode(_global.user) ); _global.eventxml.firstchild.insertbefore(eventxml.createelement("url"), _global.eventxml.firstchild.firstchild); _global.eventxml.firstchild.firstchild.appendchild( EventXML.createTextNode(_level0._url) ); //send XML randomize = Math.random()*Math.random(); _global.eventxml.sendandload(_global.php_name+"?id="+randomize,_global.nothingxml); 7

//create new XML _global.capture_count = 0; _global.eventxml = new XML(); _global.eventxml.contenttype = "text/xml"; _global.eventxml.xmldecl = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; _global.eventxml.appendchild( EventXML.createElement("swfEvents") ); //save events function EventsSend() { _global.capture_count++; if((_global.capture_count > _global.send_count)&&(_global.user!=0)){ ESend(); //create mouselistener var mouselistener:object = new Object(); mouselistener.onmousedown = function() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("event") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("time") ); EventXML.createTextNode(time- _global.t0) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("frame") ); EventXML.createTextNode(_level0._currentframe) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("kind") ); EventXML.createTextNode("onMouseDown") ); _global.mouse_x = _xmouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_x") ); EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_y") ); EventXML.createTextNode(mouse_y) ); EventsSend(); ; mouselistener.onmouseup = function() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("event") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("time") ); EventXML.createTextNode(time- _global.t0) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("frame") ); EventXML.createTextNode(_level0._currentframe) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("kind") ); EventXML.createTextNode("onMouseUp") ); _global.mouse_x = _xmouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_x") ); EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_y") ); EventXML.createTextNode(mouse_y) ); EventsSend(); ; mouselistener.onmousemove = function() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("event") ); 8

_global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("time") ); EventXML.createTextNode(time- _global.t0) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("frame") ); EventXML.createTextNode(_level0._currentframe) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("kind") ); EventXML.createTextNode("onMouseMove") ); _global.mouse_x = _xmouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_x") ); EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("mouse_y") ); EventXML.createTextNode(mouse_y) ); EventsSend(); ; Mouse.addListener(mouseListener); //create keylistener var keylistener:object = new Object(); keylistener.onkeydown = function() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("event") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("time") ); EventXML.createTextNode(time- _global.t0) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("frame") ); EventXML.createTextNode(_level0._currentframe) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("kind") ); EventXML.createTextNode("onKeyDown") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("ascii") ); EventXML.createTextNode(Key.getAscii()) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("code") ); EventXML.createTextNode(Key.getCode()) ); EventsSend(); ; keylistener.onkeyup = function() { time=gettimer(); if(_global.t0==0){ _global.t0=time; _global.eventxml.lastchild.appendchild( EventXML.createElement("event") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("time") ); EventXML.createTextNode(time- _global.t0) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("frame") ); EventXML.createTextNode(_level0._currentframe) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("kind") ); EventXML.createTextNode("onKeyUp") ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("ascii") ); EventXML.createTextNode(Key.getAscii()) ); _global.eventxml.lastchild.lastchild.appendchild( EventXML.createElement("code") ); EventXML.createTextNode(Key.getCode()) ); EventsSend(); ; Key.addListener(keyListener); 9

Příloha č. 2 save.php <?php //option variable - SQL $SQL_Server="mysql.server.cz"; $SQL_Login="user name"; $SQL_Password="password"; $SQL_Databaze="databaze"; $SQL_Table="recorder"; //do not change //connect database $Spojeni = mysql_connect($sql_server, $SQL_Login, $SQL_Password); if ($Spojeni) { $DB = mysql_select_db($sql_databaze, $Spojeni); if ($DB) { mysql_query("set CHARACTER SET utf8"); if(isset($http_raw_post_data)){ //save XML $dom = domxml_open_mem($http_raw_post_data); $root = $dom->document_element(); $url="unknown"; $user=0; // zero is ban $frame=0; $time=0; //parse XML function parse_node($node) { global $SQL_Table, $url, $user, $frame, $time; if ($node->has_child_nodes()) { foreach($node->child_nodes() as $n) { if ($n->node_name()=='url'){ foreach($n->child_nodes() as $text) { $url=$text->node_value(); if ($n->node_name()=='user'){ foreach($n->child_nodes() as $text) { $user=$text->node_value(); if ($n->node_name()=='end'){ foreach($n->child_nodes() as $text) { $endtime=$text->node_value(); if($user!=0){ $UP = mysql_query("insert INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind) VALUES('$url',$user, 0, $endtime, 'end')"); if ($n->node_name()=='event'){ foreach($n->child_nodes() as $text) { if ($text->node_name()=='time'){ foreach($text->child_nodes() as $value) { $time=$value->node_value(); if ($text->node_name()=='frame'){ foreach($text->child_nodes() as $value) { $frame=$value->node_value(); if ($text->node_name()=='kind'){ foreach($text->child_nodes() as $value) { $kind=$value->node_value(); if ($text->node_name()=='mouse_x'){ foreach($text->child_nodes() as $value) { $mouse_x=$value->node_value(); 10

if ($text->node_name()=='mouse_y'){ foreach($text->child_nodes() as $value) { $mouse_y=$value->node_value(); if ($text->node_name()=='ascii'){ foreach($text->child_nodes() as $value) { $ascii=$value->node_value(); if ($text->node_name()=='code'){ foreach($text->child_nodes() as $value) { $code=$value->node_value(); if (($kind=="onkeyup") ($kind=="onkeydown")){ if($user!=0){ $UP = mysql_query("insert INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind,Ascii,KeyCode) VALUES('$url',$user, $frame, $time, '$kind', $ascii, $code)"); $kind=""; $ascii=0; $code=0; else{ if($user!=0){ $UP = mysql_query("insert INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind,MouseX,MouseY) VALUES('$url',$user, $frame, $time, '$kind', $mouse_x, $mouse_y)"); $kind=""; $mouse_x=0; $mouse_y=0; parse_node($root); $dom->free(); else{ //read and send user ID $result = mysql_query("select COALESCE( MAX( UserID ), 0 ) AS MAXUSER FROM $SQL_Table"); $row = mysql_fetch_array($result); $maxid = $row['maxuser']; $maxid++; $UP = mysql_query("insert INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind) VALUES('unknown',$maxid, 0, 0, 'start')");?> header("content-type: text/xml"); echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; echo "<user>"; echo $maxid; echo "</user>"; @mysql_close ($Spojeni); 11

Příloha č. 3 recorder.html <html> <head> <title>nur - FLASH - Recorder</title> <script type="text/javascript"> /* <![CDATA[ */ function onclose(){ window.document.myflash.onclose(); /* ]]> */ </script> </head> <body onunload="onclose();alert('recording was finished!');return true;"> <p> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swf lash.cab#version=8,0,0,0" width="550" height="400" id="myflash"> <param name="movie" value="animace.swf"> <param name="allowscriptaccess" value="always" /> <param name="quality" value="high"> <embed src="animace.swf" quality="high" width="550" height="400" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?p1_pr od_version=shockwaveflash" name="myflash" swliveconnect="true" AllowScriptAccess="always"> </embed> </object> </p> </body> </html> 12

Příloha č. 4 sql.txt CREATE TABLE `recorder` ( `ID` INT NOT NULL AUTO_INCREMENT, `UrlSwf` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL, `UserID` INT NOT NULL, `Frame` INT NOT NULL, `Time` INT UNSIGNED NOT NULL, `Kind` VARCHAR( 20 ) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL, `MouseX` MEDIUMINT, `MouseY` MEDIUMINT, `Ascii` TINYINT UNSIGNED, `KeyCode` SMALLINT, PRIMARY KEY ( `ID` ) ); 13