Archive for ‘Uncategorized’

Marzec 1, 2015

Zachowywanie prywatności w sieciach społecznościowych

- autor: tsissput

Z pewnością każdy z nas zauważył, że sieci społecznościowe wdarły się szturmem do naszego życia i z uwagi na swoją ogromną popularność nieprędko z niego znikną. W 2013 roku blisko77 90% polskich internautów korzystało z serwisów społecznościowych (dane firmy badawczej Gemius). Co więcej, około 12% pracodawców przyznaje się do przeglądania facebookowych profili kandydatów na stanowisko przed ich zatrudnieniem (dane z roku 2007!). Wraz ze wzrostem popularności serwisów typu Facebook, Twitter, Youtube, coraz większa waga przykładana jest (i słusznie!) do zachowywania prywatności w sieciach społecznościowych.

Żeby dokładnie zrozumieć poruszane w niniejszej notce zagadnienia wprowadzimy model sieci społecznościowej w postaci grafu, w którym wierzchołki odnoszą się do użytkowników, natomiast krawędzie do relacji pomiędzy nimi. Gdy mówimy o prywatności w takiej sieci, musimy uwzględnić wiele aspektów, między innymi:

  • istnienie użytkownika w sieci – jeśli osoba postronna (nazwijmy ją atakującym) dowie się, że dany użytkownik jest w konkretnej sieci (np. sieci reprezentującej milionerów), prywatność zostanie naruszona,
  • parametry wierzchołka takie jak np. jego stopień – jeśli atakujący odkryje ilość połączeń danego użytkownika, może dowiedzieć się o jego priorytecie w sieci,
  • połączenie z inną jednostką sieci – np. podczas transakcji finansowej gdy dwa wierzchołki mają połączenie gdy nastąpiła wymiana środków – również narusza prywatność,
  • wrażliwe dane, które mogą być przypięte do użytkownika (np. ciężka choroba).

Aby móc myśleć o zachowaniu prywatności w sieci, należy wiedzieć w jaki sposób są one „atakowane”. Wyróżniamy ataki aktywne – takie, w których do ataku używane są nowe wierzchołki wprowadzane do sieci, które dołączają się do starych wierzchołków oraz ataki pasywne, w których nie są dodawane ani wierzchołki, ani krawędzie. Atakujący najczęściej zanim zdobędzie poufne dane konkretnego użytkownika musi znać jego otoczenie – wiedza o sąsiadujących wierzchołkach, znajomość topologii mogą wiele „pomóc” atakującemu. Aby utrudnić atakującemu identyfikację konkretnego wierzchołka wprowadza się tzw. anonimizację danych. Jak sama nazwa wskazuje, służy ona po to, by zachować anonimowość poprzez „wystawienie” na zewnątrz sieci z takimi wierzchołkami, aby niemożliwe było ich rozróżnienie.

K-­anonimizacja (K-anonymity)

K­anonimizacja polega na „zaciemnianiu” niektórych danych, aby istniało co najmniej K – 1 węzłów, które będą takie same, a co za tym idzie nierozróżnialne, anonimowe. Innymi słowy nie ma możliwości, aby w sieci istniał jakiś jeden niepowtarzalny wierzchołek (np. gdyby zawierał nr telefonu komórkowego i byśmy nie „zaciemnili” tego numeru – byłoby to niemożliwe). Poniżej przykład 2­anonimizacji. Oryginalna tabela przedstawiająca wierzchołki w sieci:

tab1

Po 2-­anonimizacji ta sama tabela będzie wyglądała następująco:

tab3

W anonimizacji dąży się do tego, aby żaden z obiektów nie wskazywał na konkretny podmiot/przedmiot w sposób jednoznaczny. Ciekawostka: aby jednoznacznie zidentyfikować 87% obywateli USA, „wystarczy” znać datę urodzenia, płeć oraz kod pocztowy.

K­anonimizacja nie musi dotyczyć wyłącznie samych danych – może również dotyczyć np. stopnia wierzchołka (K­degree anonymity). Efekt działania tej anonimizacji jest następujący: dla każdego wierzchołka uzyskujemy co najmniej K – 1 wierzchołków o tym samym stopniu. Nigdy nie będzie sytuacji, że jakiś wierzchołek będzie miał unikatową liczbę połączeń z innymi wierzchołkami. Wykonywane jest to przez algorytm odpowiednio dodający fałszywe i usuwający prawdziwe krawędzie. Empiryczne badania pokazały, że można zachować topologiczną użyteczność grafu zaspokajając założenia K­stopniowej anonimizacji.

Oprócz tych dwóch K­anonimizacji istnieje również K­anonimizacja sąsiadów (K­neighbourhood anonymity), która z kolei wymaga, aby dla wierzchołka istniało K – 1 innych wierzchołków, dla których podgraf bezpośrednich sąsiadów będzie izomorficzny z podgrafem bezpośrednich sąsiadów ów wierzchołka. Innymi słowy – aby w sieci nie istniał żaden wierzchołek o unikatowym zestawie najbliższych sasiadów.

Anonimizacja poprzez losowość

Losowe dodawanie/usuwanie elementów grafu jest kolejną często stosowaną strategią zachowywania prywatności w sieciach. W tej strategii poprzez wprowadzanie fałszywego szumu utrudniamy odczytywanie i eksplorację sieci przez atakującego. Dodatkowo możemy zachowywać niektóre własności grafu np. poprzez dodanie wierzchołkowi k losowych relacji do innych wierzchołków oraz usunięcie k losowych relacji od „starych” wierzchołków zawsze zachowujemy stopień wierzchołka.

Jeśli z n wierzchołków zrobilibyśmy macierz A o wymiarach n * n i uzupełnili wewnątrz pola: 1 – jeśli między wierzchołkiem, który odpowiada wierszowi, a wierzchołkiem, który odpowiada kolumnie jest relacja oraz 0 – gdy relacji nie ma, to wynik procesu anonimizacji poprzez losowość przedstawilibyśmy jako sumę macierzy A + E, gdzie macierz E byłaby „macierzą mieszania”. W macierzy E mielibyśmy wartości +1, jeśli krawędź między odpowiadającymi wierzchołkami została dodana, oraz ­1, gdy usunięta.

Przykład:

tab4

Macierz wynikowa:
tab5

Widać, że w „zafałszowanej” macierzy wynikowej połączenia są inne, natomiast mając „macierz mieszania” jesteśmy w stanie łatwo powrócić do macierzy oryginalnej.

Anonimizacja przez generalizację

W odróżnieniu od K­anonimizacji oraz anonimizacji przez losowość, które modyfikowały strukturę grafu (dodawały/usuwały krawędzie), anonimizacja przez generalizację polega na grupowaniu wierzchołków w klastry (albo grupowaniu relacji), w których można odpowiednio ukryć wrażliwe dane. Najlepszym przykładem może być przedział wiekowy, do którego „wrzucimy” wierzchołek, a w którym już znajdują się inne wierzchołki. Podczas generalizacji niestety musimy się liczyć z utratą części danych lub precyzji – np. zamiast wieku 24 mamy przedział wiekowy (na przykład <20; 40>).

Efektem generalizacji mógłby być np. graf złożony z superwierzchołków zawierających co najmniej K „zwykłych” wierzchołków, a pomiędzy superwierzchołkami byłyby superrelacje, czyli krawędzie pomiędzy superwierzchołkami o wadze równej ilości połączeń między wierzchołkami z dwóch stron superrelacji. Generalizacja jest skutecznym sposobem na anonimizację, aczkolwiek stosowanym w przypadku gdy możemy sobie pozwolić na utratę precyzji.

Przykład generalizacji można przedstawić na znanej już tabeli:

tab1

Po generalizacji oraz dodatkowym „zaciemnieniu” innych danych mamy:

tab2

Metody zachowywania prywatności w sieciach społecznościowych są wciąż w początkowym stadium (porównując np. do danych tabularnych). Wynika to przede wszystkim z tego, że są one znacznie bardziej skomplikowane, dlatego też zachowanie w nich anonimowości jest większym wyzwaniem. Natomiast można się spodziewać szybkiego rozwoju tej dziedziny ze względu na coraz większe zapotrzebowanie na ochronę danych, które „wystawione są” w serwisach już codziennego użytku.

Nie wyobrażam sobie dalszego rozwoju serwisów społecznościowych bez usprawniania ochrony danych w nich przechowywanych. Chociaż w tej chwili zadziwiająco duży odsetek użytkowników korzystających z najpopularniejszych z serwisów nie wydaje się być zainteresowany zachowywaniem prywatności myślę i mam nadzieję, że w najbliższej przyszłości to się zmieni. Aby tak było wraz z rozwijaniem technologii konieczne jest rozwijanie również świadomości użytkowników i ich wiedzy na temat niebezpieczeństw związanych ze zdradzaniem zbyt wielu informacji o sobie w serwisach, w których „żyją”.

Źródła:
http://mic.psnc.pl/download/pgnet_111013_1.pdf
https://www.cs.sfu.ca/~jpei/publications/SocialNetworkAnonymization_survey.pdf
http://webpages.uncc.edu/xwu/publ/ppsn.pdf

Reklamy
Styczeń 28, 2015

Kliki Politechniki

- autor: tsissput

Introduction:

The goal is to visualize PUT Computer Science Institute scientist according to their publications, who they make publications with, when they make it etc. We had only wide-audience available data and such was used. Document is structured as follows:

  1. In process section one can find information how the experiment was conducted.
  2. Statistical data sections gives some insights on quantitative measures of PUT scientists and publications.
  3. Finally Visualization section presents result graphs of scientists.

Process:

We decided to obtain data from google scholar for obvious reasons. Unfortunately no real API exists what would make our task much easier. Eventually we ended up parsing HTML with open source Python library. Unfortunately like quite a few libraries which had been tested before it was not working properly and we needed to introduce a few improvements.

In program we create graph in which each author corresponds to a node and each edge represents a fact of being co-author of the same article. Weight of such edge is number of citations and additional attributes are title and publish date. Additionally nodes, apart from name, contain information about total number of publications and citations as well as scientific degree and division within faculty of computer science the scientist work for. Data format is suitable to be imported to Gephi but also easely adjusted to other formats.

Statistical data:

In total we analyzed about 80 scientists out of total 120 due to their absence on google scholar. Here are some interesting charts (click on picture to see it in full size):

Scientific degrees and number of dempartment employees pie charts

total cytowania

Total number of publications and citations per division

total cytowania

Total citations of each article

total cytowania

Total number of citations per author

total cytowania

Total number of publications per author

total cytowania

Visualization:

Here we go with visualization of the data. We’ve used Python formatted csv files imported to Gephi. Mind that authors (nodes), have proper number of citations and publications but edges (being co-author of the same article) are created exclusively by articles made by at least two Poznań Univeristy of Technology workers (it still gives meaningful results but reader has to be aware it).

  1. Who is the most cited scientist from PUT? MostCited – labels
  2.  Who has the biggest number of publications? Full – publications
  3. Graph divided to clusters and then colored by Modularity Class pretty much visualizes CS subdivisions (real existing ones) Modularity Class – labels
  4. How far are you from Jan Węglarz? JW Heat Map according to common publications JW Heat
  5. You may also want to check Mikołaj Morzy MM Heat and Agnieszka Ławrynowicz AL Heat new heat maps
  6. Who has the biggest betweenness measure? Simple: Betweeness
  7. Last, but not least: who has the biggest number of PUT Publications-friends: Degree labels

Thanks for reading!

Authors: 100376 , 98436, 98758

Styczeń 25, 2015

Linked data

- autor: tsissput

W dzisiejszych czasach prawie każdy posiada komputer z dostępem do Internetu. Każdy kto przegląda sieć, szukając informacji, czytając artykuły wykorzystuje linked data. Mechanizm ten wykorzystuje Semantic Web którego celem jest połączenie różnych danych.  Obecnie nasze komputery bez naszej pomocy nic by same nie zrobiły, to my kierujemy nimi wskazując im poprawną drogę, dzięki nam wykorzystują swoją siłę – bez nas były by tylko blaszaną puszką. Linked data umożliwia powstanie nowych aplikacji. Obecnie istniejące przeglądarki powiązanych danych, umożliwiają przeglądanie i wyszukiwanie między źródłami wzdłuż połączeń między danymi. Mechanizmy te przeszukują sieć powiązanych danych między wieloma źródłami, dzięki czemu możliwe jest wykonanie ekspresyjnych zapytań o wielkich możliwościach w bazach danych.

Linked data to najefektywniejsze metody na temat tworzenia rozwiązań między danymi pochodzącymi z różnych źródeł w sieci. Przedstawione dane mogą być zróżnicowane tak jak bazy danych z różnych organizacji. Linked data można nazwać systemem który łączy precyzyjnie dane i wiarygodne źródła.

Dzieje się tak za pomocą:

odnośników URI

składni RDF

 

Odnośniki URI czyli Universal Resource Identifier to internetowym standardem który pozwala rozpoznać zasoby w sieci. Z reguły jest to duża ilość znaków, zapisana według standardów. Przykładem jest URL, który wskazuje także metodę dostępu.

Składnia URI wygląda następująco:

-wzór skrócony hierarchiczny zaczyna się od ukośnika / np :// przykładem może być link do strony http://www.wikipedia.org

<schemat> : <część hierarchiczna> [ ? <zapytanie> ] [ # <fragment> ]

-wzór skrócony niehierarchiczny, występuje tylko dwukropek : przykład mailto:jakas-osoba@wikipedia.org

URI odnoszą się do konkretnych ludzi, zdarzeń ale także pojęć, można je również wykorzystywać do poznania danych z dysku naszego komputera, różnego rodzaju notatek, kontaktów, wiadomości czy plików. Podsumowując pojęcie URI jest narzędziem do identyfikacji ogółu.

Kolejny aspekt to odnośniki RDF – metody które pozwalają na przedstawienie zasobów sieci Web, oparte są na XML głównym ich zadaniem jest wyświetlenie informacji zawartych w sieci w taki sposób aby były łatwo zrozumiałe dla komputerów. Celem odnośników RDF jest stworzenie standardu zapisu danych o danych, w których nie było by chaosu jak w znacznikach <meta>. Pozwoliło by to na automatyczne przetwarzanie treści i jednocześnie umożliwiło by łatwiejsze poszukiwanie informacji oraz śledzenie danych na interesujący nas temat.

Linked Open Data oraz semantic web stają się coraz popularniejsze, co za tym idzie coraz więcej ludzi stara się mieć swój wkład w tej dziedzinie. Liczba entuzjastów rośnie bardzo szybko, a sami zainteresowani tym tematem starają się wprowadzić coraz to lepsze metody uzyskania dostępu do danych. Ponad to osoby zaangażowane w projekt Linked Data robią wszystko co mogą aby udostępnić publicznie dostęp do danych, które są w obecnych czasach zamknięte przez rządy czy służby, myślę że szczególnie zainteresowanie miałyby dane dotyczące nauk ścisłych. Materiały w Linked Data stale rosną, a razem z nimi liczba wiarygodnych danych.

 

 

Bibliografia

http://pl.wikipedia.org/wiki/Uniform_Resource_Identifier

http://www.archiwistyka.pl/artykuly/artykuly_i_felietony/530

http://pl.wikipedia.org/wiki/Resource_Description_Framework

http://www.w3.org/standards/semanticweb/data

Autor 119919

Listopad 11, 2013

Wykorzystanie Dbpedii Spotlight w pracy z danymi publicznymi

- autor: tsissput

Dominik Filipiak, 94419

Jak powszechnie wiadomo, w internecie można znaleźć wszelakie dane na rozmaite tematy. Ich katalogowanie jest obecnie niezwykle popularnym trendem, co generuje serwisy zbierające takie dane, a nawet kompleksowe rozwiązania takie jak CKAN [1]. Wykonano także wiele pracy, aby sklasyfikować takie dane. Przetwarzanie wejściowych danych na postać trójek RDF-owych to jeden z możliwych kierunków. Przyjrzyjmy się teraz jak w nadawaniu znaczeń może przydać nam się niezwykle ciekawy projekt, jakim jest DBpedia Spotlight. Wykorzystamy wcześniej wymienione technologie do transformacji plików CSV na RDF wzbogacanych o własności i ich wartości pobieranych jako zasoby z DBpedii.

DBpedia jest efektem próby usystematyzowania danych zebranych na Wikipedii. Poprzez ekstrakcję strukturalna crawler pobiera dane na temat każdego artykułu. Część informacji na Wikipedii jest usystematyzowana – specjalne pola, tzw. infoboksy da się łatwo mapować na RDF-owe trójki.

Screenshot 2013-11-10 18.25.25

Tak przetworzony artykuł trafia na DBpedię w postaci trójek:

Screenshot 2013-11-10 18.26.31

Projekt DBpedia spotlight dostarcza narzędzie pozwalające wyszukiwać w tekście zasobów znajdujących się na DBpedii. Narzędzie może być wykorzystane również do znajdowania kategorii odpowiadających zadanemu zbiorowi pojęć, co stanowi użyteczne narzędzie w temacie, którym dziś się zajmujemy. Pod adresem http://dbpedia-spotlight.github.io/demo/ znajduje się interaktywne demo możliwości tego systemu. Dla programisty kluczową funkcją jest jednak to, że zostało udostępnione publiczne wygodne REST-owe API służące do operowania na Spotlighcie. Serwisy oparte na wcześniej wspomnianym systemie CKAN służą do gromadzenia dużych zbiorów danych publicznych. Dzięki systemowi grupowania, tagów oraz linkowaniu zasobów w różnych formatach do zbiorów danych możliwe jest szybkie wydobywanie interesujących nas informacji. Programiści z pewnością docenią API, które pozwala w wygodny sposób operować na zgromadzonych zasobach. Część z danych udostępniona jest już w postaci RDF-owych trójek, część jako arkusze XLS, inne natomiast są zamieszczone jako proste pliki CSV.

Spróbujemy użyć projektu Spotlight przy przetwarzaniu plików z CSV. Przy wykorzystaniu API, odpytamy system o wszystkie zbiory związane z danymi w Wielkiej Brytanii:

http://publicdata.eu/api/search/dataset?q=tags:uk&all_fields=1

Otrzymamy listę wszystkich zbiorów związanych z Wielką Brytanią w formacie JSON. To, co nas interesuje to przede wszystkim zawarte tam linki do zasobów. Warto zauważyć, że pole res_format mówi nam o formacie zasobów. Tak więc po przefiltrowaniu odpowiedzi tak, żeby uzyskać tylko zasoby w formacie CSV otrzymamy zbiór linków z plikami do pobrania. Po ściągnięciu tych zbiorów możemy wykorzystać API projektu Spotlight do próby nadania polom znaczeń. Jak wiadomo, plik CSV to nic innego jak zwykły plik tekstowy, gdzie poszczególne rekordy oddzielone są przecinkami, a każdy wiersz wypisany jest w osobnej linii. Dodatkowo, jeżeli rekord zawiera znaki specjalne, to jest on ujęty w cudzysłów. Pierwsza linia zazwyczaj zawiera nagłówki kolumn, a pierwsze rekordy w kolejnych liniach to opcjonalne nagłówki wierszy. Załóżmy, że przy pracy z wybranym plikiem wiersz odpowiedzialny za nagłówki zawiera trzy kolumny: Poland, Great Britain oraz USA. Aby otrzymać linki do zasobów, należy zadać odpowiednie zapytanie:

http://spotlight.dbpedia.org/rest/annotate/?text=Poland+Great+Britain+USA

Spotlight rozpozna w zapytaniu trzy kraje. Teraz, mając wskaźniki na reprezentacje RDF-ową, można spróbować podjąć się klasyfikacji tych pojęć. W odpowiedzi na zapytanie otrzymujemy również zbiór typów przypisanych do wskazanego pojęcia. I tak, dla naszego przykładowego zapytania (dla słowa „Poland”), otrzymamy:

Screenshot 2013-11-10 19.04.32

Jak widać termin został słusznie rozpoznany jako kraj. Analogicznie jest dla pozostałych pojęć. Dzięki temu można np. spróbować oznaczyć kategorię nadrzędną w tabeli jako kraje, lub po prostu użyć tego wyniku przy transformacji tabel na format RDF. Wyszukiwanie zasobów tekście jest jednak niezwykle czasochłonne, co trzeba mieć na uwadze przy pracy z tak dużymi zbiorami jak wcześnie wspomniane publicdata.eu. Dlatego też istotne jest wybranie z wejściowego pliku tylko istotnych dla nas informacji. Człowiekowi łatwo jest ocenić co jest nagłówkiem, a co polem z danymi w pliku CSV. Aby zmaksymalizować szybkość automatycznego przetwarzania tych plików, należy napisać coś na kształt prostej heurystyki.

W artykule [3] podjęto się próby sprowadzenia tabeli w formacie CSV do postaci kanonicznego modelu. Wypunktowano też wiele związanych z tym problemów. Warto jednak zauważyć, że tamtejsze podejście nie zakłada występowania nagłówków wierszy, co generuje dodatkowe problemy. Najbardziej intuicyjną metodą przy wybieraniu pojęć jest odrzucenie pól z danymi – zazwyczaj są to liczby. Dlatego pierwszym krokiem jest określenie „wysokości” nagłówków kolumn oraz „szerokości” pół określających nagłówki wierszy. Niestety nie jest to zadanie proste, gdyż nie można zawsze założyć, że w polu na dane znajdować się będą tylko liczby. Czasem może być to tekst (np. „Not available”), lub też puste pole. Część kolumn może zawierać w sobie inne, co ma graficznie reprezentować relację podrzędności. Oczywiście jest to też aplikowane dla wierszy. Przy liniowym przetwarzaniu plików może to generować problemy związane z rozpoznawaniem wielkości, gdy np. kolumna „Kraj” będzie rozgałęziać się na „Polska” oraz „Anglia” – jak łatwo sobie wyobrazić, „Kraj” będzie miał szerokość równą 2, ale będzie zajmował tylko jedno pole, drugie natomiast będzie puste. Są to jednak problemy na poziomie implementacji rozwiązania programistycznego i jedynym ich odbiciem na całość jest zdecydowane spowolnienie działania. Wykorzystując prosty program do implementacji powyższego rozwiązania, spróbujmy teraz przetworzyć plik z danymi dotyczącymi straży pożarnej mieszczącej się w Londynie.

Screenshot 2013-11-10 19.27.39

Kolumny zostaną zmapowane na:

http://dbpedia.org/resource/Code

http://dbpedia.org/resource/Area

http://dbpedia.org/resource/Emergency

(…)

Natomiast wiersze zostaną zmapowane na:

http://dbpedia.org/resource/City_of_London

http://dbpedia.org/resource/London_Borough_of_Barking_and_Dagenham

http://dbpedia.org/resource/London_Borough_of_Barnet

http://dbpedia.org/resource/London_Borough_of_Bexley

http://dbpedia.org/resource/London_Borough_of_Brent

(…)

Dysponując takimi danymi mapowanie do postaci trójek jest znacznie prostsze i efektywniejsze, gdyż nie musimy tworzyć zasobów reprezentujących dzielnice Londynu, a możemy wykorzystać te już istniejące. Z taką reprezentacją wystarczy tylko odpytać Dbpedię o właściwości danego zasobu (np. poprzez zapytanie w języku SPARQL poprzez framework Apache Jena). Poniżej przykład zasobu w formacie .ttl:

<http:/cs.put.poznan.pl/data/fire_brigade#1>

rdf:type yago:LondonBoroughs ;

dbpprop:shortName „Camden”;

(…)

dbpprop:url „http://www.camden.gov.uk/”.

Spotlight nie jest oczywiście narzędziem doskonałym. Jest znane wiele przypadków, gdzie trudno jednoznacznie nadać znaczenie dla danego słowa. Dla przykładu, termin „Jaguar” można oznaczać znanego producenta samochodów, jak i również zwierze z rodziny kotowatych. Dlatego tak ważne jest rozpoznanie wg kontekstu. Struktura typów zbioru pojęć nie jest niestety drzewiasta, stanowi ona tzw. „siatkę”. Dobór algorytmu próbującego uogólnić taką strukturę jest kluczowy i stanowi obszerny temat na kolejny artykuł. Może zdarzyć się też tak, że program źle wywnioskuje z kontekstu nasze pojęcie. Dla przykładu, kiedy mówimy o krajach, z termem „Germany” związany jest zasób „West Germany”. Intuicyjnie wiemy, że znacznie trafniejszym wyborem byłby link kierujący nas do obecnych Niemiec, jednak dla analizatora nie jest to takie oczywiste. W prezentowanym podejściu zajęliśmy się zasobami w języku angielskim, ponieważ niestety nie jest jeszcze dostępna wersja projektu Spotlight przeznaczona do pracy z polskim językiem. Warto jednak śledzić temat, gdyż w przyszłości może to być niezwykle przydatny oręż w przetwarzaniu polskojęzycznych danych publicznych.

[1] http://ckan.org/

[2] https://github.com/dbpedia-spotlight/dbpedia-spotlight/wiki

[3] http://svn.aksw.org/papers/2013/ISemantics_CSV2RDF/public.pdf

 

Luty 22, 2013

Semantyczny rejestr usług sieciowych

- autor: tsissput

Cel projektu

Pomysł na semantyczny opis i wyszukiwanie usług sieciowych nie jest nowy, ale jak dotąd nie powstało rozwiązanie, które spotkałoby się z powszechną akceptacją.  Powodów takiego stanu rzeczy należy upatrywać przede wszystkim w skomplikowanym i trudnym w opisie modelu Big Web Services opartym na protokole SOAP. Sprowadza się on w zasadzie do zdalnego wywoływania metod za pośrednictwem rozbuchanego, nadmiarowego i pod wieloma względami dublującego funkcjonalność protokołów transportowych (np. HTTP) formatu XML, co wiąże się z nieograniczoną dowolnością wykonywanych operacji.  Każda próba wzbogacenia takich usług o informację semantyczną wymaga zarówno dodatkowego powiększenia i tak już „ciężkiej” koperty SOAPowej, jak też bardzo indywidualnego podejścia do semantycznego opisu każdej usługi z osobna.

W związku z powyższym, zdecydowaliśmy się ograniczyć zakres projektu do usług zgodnych z paradygmatem REST. Pozwala to na wprowadzenie swojego rodzaju „wspólnego mianownika” dla opisywanych usług, który wynika ze ściśle określonego związku architektury usług z wykorzystanym protokołem transportowym (praktycznie zawsze HTTP lub HTTPS). Ogromnym ułatwieniem jest tu porzucenie potencjalnie nieskończonej (w przypadku usług typu Big Web Services) przestrzeni możliwych operacji, na rzecz tej, którą tworzą metody protokołu HTTP. Ponadto, w przypadku usług RESTowych, mamy pewność, że zakres operacji jest jasno określony przez adres URL zasobu. Nie jest konieczne wnikanie w ciało żądania by określić na jakich danych wykonujemy jakąś czynność.

Należy wspomnieć, że sam paradygmat REST jest pojęciem o bardzo wysokim poziomie abstrakcji i sam w sobie nie definiuje żadnych szczegółów implementacji usług. W projekcie zakładamy zgodność usług z jego konkretną interpretacją opartą na protokole HTTP, a mianowicie z architekturą zorientowaną na zasoby (ang. Resource Oriented Architecture – ROA). Termin ten został zaproponowany przez Leonarda Richardsona i Sama Ruby’ego w książce Semantic Web Services (wyd. O’Reilly).

verbs

Kolejną rzeczą, na którą należy zwrócić uwagę jest fakt, że koncepcja globalnych rejestrów usług nie zyskała powszechnej aprobaty. Samo skłonienie setek niezależnych podmiotów do utrzymywania takich rejestrów jest zadaniem trudnym. Opracowując nasze rozwiązanie nie kierowaliśmy się ambicjami stworzenia takiego rejestru. Nasza aplikacja jest przeznaczona do użytku w zastosowaniach lokalnych, na skalę pojedynczych przedsiębiorstw czy systemów informatycznych

Semantyka

Ograniczenie się do opisu usług RESTowych pozwoliło na opracowanie stosunkowo nieskomplikowanej ontologii opisującej architekturę zorientowaną na zasoby. Do opisu każdej usługi potrzeba w ogólności trzech elementów:

  • Ontologii REST-HTTP opisującej pojęcia związane z ROA, takie jak: zasób, adres URL, nagłówek HTTP, ciało odpowiedzi, operacja tworzenia zasobu, metoda GET, etc.
  • Ontologii dziedzinowej opisującej biznesową interpretację zasobów. Pojęcia w niej zawarte to na przykład: pacjent, kolejka na badanie, wpis w karcie, grupa krwi, etc. Należy tu wspomnieć, że w ogólności każda usługa może być opisana przy pomocy dowolnej liczby ontologii dziedzinowych, które mogą być łączone w celu poszerzenia opisu semantycznego.
  • Ontologii opisującej konkretną usługę zawierającej przede wszystkim instancje klas zdefiniowanych w pozostałych ontologiach.

Pozwala to na elastyczne mapowanie udostępnianych przez usługi zasobów w kontekście ROA na abstrakcyjne zasoby opisane w ontologiach.

Zakłada się ponadto, że każdy złożony zasób (na przykład Lekarz) interpretowany jako instancja pewnej klasy z ontologii, składa się z pewnej liczby podzasobów atomowych o typach prostych reprezentowanych przy pomocy typowanych literałów.  Zarówno zasoby złożone, jak i atomowe, są wiązane w stosunku 1:1 z pojęciami z ontologii dziedzinowej.

Oto kilka przykładów zapytań w języku naturalnym, które można wyrazić przy pomocy opisanego powyżej zestawu ontologii:

  • Znajdź usługę, która umożliwia pobranie kolekcji pacjentów leczonych na zapalenie płuc bez podawania dodatkowych parametrów
  • Znajdź usługę, która pozwoli na utworzenie nowego zasobu oznaczającego pojęcie pacjent w kontekście kolejki na badanie rentgenowskie, przy założeniu że znam PESEL, imię i nazwisko pacjenta.
  • Dysponuję numerem książeczki ubezpieczeniowej pacjenta. Jakich jeszcze parametrów potrzebuję by wykonać zapytanie tworzące zasób reprezentujący tego pacjenta przy pomocy usługi X?

Implementacja rejestru

Oczywiście sama ontologia to za mało by wykorzystać takie zapytania w praktyce. Dokonaliśmy implementacji usługi RESTowej pozwalającej na wgrywanie ontologii i udostępniającej końcówkę SPARQL  wykorzystywaną do wykonywania zapytań do ontologii.

Wykorzystaliśmy w tym celu bibliotekę Apache Jena udostępniającą interfejsy do manipulacji danych semantycznych i ich przechowywania w bazie danych oraz silnik SPARQL. Interfejst REST usługi oparto na bibliotece Jersey implementującej standard JAX-RS. Widoki stworzono w technologii JSP.

semreg2

Plany na przyszłość

Opracowana aplikacja stwarza szereg interesujących możliwości. Dzięki semantycznemu opisowi publikowanych usług możliwe jest tworzenie klientów aplikacyjnych, które zamiast jawnie wywoływać konkretne usługi posiadać będą jedynie zdefiniowaną w sposób deklaratywny informację o tym jaką operację należy wykonać i na jakim zasobie. Dzięki wykorzystaniu rejestru, potrzebna będzie jedynie informacja o tym, na jakie pojęcie w dziedzinie biznesowej przekłada się dany zasób.

Łatwo sobie wyobrazić sytuację, w której klient pobiera listę dostępnych usług oraz wymaganych przez nie parametrów, a następnie odpytuje rejestr w celu znalezienia usług udostępniających dane, które są potrzebne jako parametry żądania. Jeszcze prostszym zadaniem jest kompozycja formularzy HTML pozwalających na wprowadzenie wymaganych przez usługi danych przez użytkownika. Potencjalnym klientem rejestru jest rozwijany na Politechnice Poznańskiej silnik procesów biznesowych ROsWeL (ang. Resource Oriented Workflow Language).

roswelLogoWidePlainBlack50pxhi

Korzystanie z rejestru zostałoby znacznie ułatwione gdyby opis usług w językach RDF i OWL był generowany w pewnym stopniu automatycznie. Można to zrealizować przy pomocy biblioteki opartej o mechanizm adnotacji w języku Java, w sposób podobny do tego, w jaki na podstawie adnotacji JAX-RS lub JAX-WS generowane są dokumenty WADL i WSDL. W gestii programisty usług pozostałoby wtedy tylko umieszczenie odpowiednich adnotacji semantycznych obok adnotacji JAX-RS definiujących parametry i typy obiektów zwracanych przez usługi.

Powyższe założenia zamierzamy zrealizować w ramach pracy magisterskiej.

Tomasz Niedźwiedź i Paweł Pawłowski

Luty 21, 2013

SignedNetworkGenerator

- autor: tsissput
  • Przemysław Wróblewski 89846
  • Marcin Wojdowski 89843

Program ma za zadanie generowanie sieci z wiązaniami ujemnymi i dodatnimi.

Program realizuje następujący scenariusz:

  1. Załadowanie danych konfiguracyjnych
  2. Pobranie z fabryki NetworkFactory2 głównego algorytmu przetwarzania, impl w pakiecie org.tsiss.sng.network.creators
  3. W zależności od głównego algorytmu przetwarzania klass wspierajacych przetwarzanie. Przykładowe wartości z pliku ApplicationContext:
    1.  ac.getProbability(); – zwraca model prawdopodobienstwa dla procesu tworzenia krawedzi wewnątrz grupy i na zewnątrz(osobne).
    2. ac.getGroupChooser(); – zwraca model wyboru grupy do przydziałów nowych elementów.
    3. ac.getExtNegativeEdge(); – zwraca model wyboru docelowego wierzchołka dla negatywnej zewnętrznej krawedzi
    4. ac.getExtPositiveEdge();- zwraca model wyboru docelowej grupy dla negatywnej zewnętrznej krawedzi
    5. ac.getNodeChooser();- zwraca model wyboru docelowego wierzchołka dla wybranej grupy
    6. ac.getAgeFunction();- zwraca funkcje postarzająca krawędzie.

Głównym plikiem konfiguracyjnym projektu jest plik sng.properties.

W środku znajdziemy następujące przykładowe parametry:

  • nodes=40 ­– ilośc węzłów
  • iterations=40000 – ilośc iteracji algorytmu
  • edges=220 – max ilość krawędzi
  • negative-edge=1 – możliwość tworzenia negatywnych krawedzi
  • bidirected=true – czy sieć jest skierowana
  • minimum-edge-weight=-5.0
  • maximum-edge-weight=5.0
  • output-file=d:\\sng\\sng.gdf – plik wyjsciowy
  • output-type=GDFFile – format wyjsciowy
  • groups=5 – ilość dostępnych grup
  • AgeFunction=LinearFunction – nazwa klasy użytej jako funkcja postarzania(pakiet: org.tsiss.sng.edge.age)
  • probability  = ParametrizedProbability – nazwa klasy użytej jako funkcji określającej możliwość powstania krawędzi (pakiet: org.tsiss.sng.probability.create.edge)
  1. — parametry specyficzne dla danej klasy
  2. ParametrizedProbability.createInternalEdgeProb=0.8
  3. ParametrizedProbability.createExternalEdgeProb=0.6
  4. ParametrizedProbability.isNegativeEdgeProb=0.5
  •  groupChooser=PopularPreference – nazwa klasy użytej jako funkcji wybierającej docelową grupę dla nowego obiektu (pakiet: org.tsiss.sng.probability.choose.group)
  •  nodeChooser  = NodeDegreePreference – nazwa klasy użytej jako funkcji wybierającej wierzchołek z podanego zbioru, np. Wybranej grupy (pakiet: org.tsiss.sng.probability.choose.node)
  1.  — parametry specyficzne dla danej klasy
  2. NodeDegreePreference.handicap = 2
  3. NodeDegreePreference.degreeWeight =1.5
  • externalNegativeEdge = GroupNegativePreferenceWithPositiveInfluence – nazwa klasy użytej jako funkcji wybierającej docelową grupę dla nowej negatywnej krawedzi (pakiet: org.tsiss.sng.probability.choose.group)
  1. — parametry specyficzne dla danej klasy
  2. GroupNegativePreference.handicap = 1
  • externalPositiveEdge = GroupPositivePreference – nazwa klasy użytej jako funkcji wybierającej docelową grupę dla nowej pozytywnej krawedzi (pakiet: org.tsiss.sng.probability.choose.group)
  1. — parametry specyficzne dla danej klasy
  2. GroupPositivePreference.handicap = 2

Jak widzimy po skompilowaniu projektu możemy zmieniać mechanizm działania aplikacji bez potrzeby ponownej przebudowy projektu.
Możliwości aplikacji możemy rozszerzać dodając nowe implementacje klas.
Należy jednak pamiętać,że wszystkie klasy utworzone w pakiecie org.tsiss.sng.probability.* i org.tsiss.sng.edge.age należy zarejestrować w odpowiedniej enumeracji w pakiecie org.tsiss.sng.enum.

Sytuacja jest podobna z formatami wyjściowymi utworzonej sieci (pakiet: org.tsiss.sng.outputs).
Niestety format UCINet wymaga poprawek.

Specyficzne parametry dla danych klas:

Jeżeli zaszłaby potrzeba pobrania z pliku konf. Specyficznego nowego parametru, zapisujemy go wg. schematu:

„NazwaKlasy.nazwaParametru=Wartość”

Po dodaniu parametru należy go zarejestrować w enumeracji org.tsiss.sng.enum.ApplicationOption.java, np:

AGE_FUNCTION(„ageFun”, „AgeFunction”,true,”Name algorithm used to determine age function”,”NoFunction”),

PARAM_NAME(„shortName”, „LongName”,true,”Description”,”DefaultValue”),

Jeżeli mamy już zarejstrowany parameter w klasie ApplicationContext dodajemy:

  1. pole przechowujace wartość naszego paramteru
  2. w metodzie setApplicationValue, dodajemy warunek case i metode konwersji naszego paramteru z klasy String
  3. utworzenie gettera dla pola z pkt 1.

To wszystko.

Jeżeli z jakiś względów użytkownik, nie może zarejestrować, dodać wpisu, może wykorzystać metode ApplicationContext.getProperty(String key, String defaultValue), by pobrać wartośc parametru prosto z pliku sng.properties. Jednak należy pamiętać, że powyższe rozwiązanie nie jest zalecane.

Źródła projektu dostępne pod adresem: http://sirius.cs.put.poznan.pl/~inf89843/tpd2/tsiss/sng.zip

Przykładowo wygenerowane sieci: http://sirius.cs.put.poznan.pl/~inf89843/tpd2/tsiss/sng_net.rar

Uruchamanie:

“java –jar SignedNetworkGenerator.jar plik_konf.properties”

Jako jedyny parametr funkcja przyjmuje relatywną ścieżkę do pliku konfiguracyjnego. Jeżeli użytkownik pominie parametr, aplikacja spróbuje załadować plik sng.properties z katalogu aplikacji.

Miłego korzystania:)

Luty 19, 2013

Semantic WoW

- autor: tsissput

Cel projektu

Celem projektu było stworzenie i wizualizacja grafu powiązań pomiędzy graczami World of Warcraft – jednej z najpopularniejszych gier MMORPG w sieci. Niezbędne dane pobrano korzystając z WoW API do bazy danych, przetworzono i uzyskano graf w formacie Netdraw VNA. Wizualizacji dokonano z użyciem programu Gephi.

Zastosowane technologie

Informacje z WoW API pobrano z użyciem aplikacji konsolowej napisanej w języku Java. Dane przechowywano w bazie MongoDB, zaś przetwarzanie odbywało się przy pomocy wspomnianej aplikacji oraz skryptów JavaScript. Dalszych operacji na grafie oraz wizualizacji dokonano w programie Gephi.

Zaimplementowana aplikacja

Jak wspomniano aplikacja jest konsolowa, umożliwia następujące operacje:

  • wczytanie pliku z nazwami gildii,
  • pobieranie nie ściągniętych gildii (na podstawie wczytanej listy nazw),
  • pobieranie nie ściągniętych postaci (na podstawie listy nazw członków gildii),
  • oba powyższe,
  • usunięcie zawartości bazy danych,
  • wygenerowanie pliku z grafem na podstawie pobranych danych przetworzonych za pomocą skryptów JS.

cmd

Architektura aplikacji

Ze względu na sposób udostępniania danych przez WoW Api, aplikacja wymaga nazw gildii, których ma dotyczyć analiza (względnie nazw wszystkich gildii na serwerze). Informację tę uzyzkano z serwisu WoW Progress i wczytywano z plików.
arch

Model ORM

Do mapowania obiektowo relacyjnego wykrorzystano bibliotekę Morphia współpracującą ze biblioteką Java sterowników bazy MongoDB.
orm

Uzyskane dane

Pobrano informację o graczach serwera Arathor-EU należących do gildii uzyskanych z WoW Progress. Dane pobierano na przestrzeni 5 dni w pierwszej połowie stycznia 2013. Po zapisie do bazy danych jej rozmiar wynosił ponad 35GB.

Pobrano informacje o 302 gildiach oraz 38 629 postaciach. Ze względu na rozmiary danych i przyjęty sposób analizy połączeń zdecydowano się przetworzyć jedynie postaci z 5 najlepszych (pod względem liczby punktów osiągnięć):

  • Alliance of Destiny
  • Maligned
  • Velvet Glove
  • Retired
  • Blacksail Pirates

Do tych gildii należy 1760 postaci powiązanych łącznie z 650 kontami graczy.

Graf uzyskany na podstawie top 5 gildii

Postaci są opisane takimi atrybutami jak: średni poziom przedmiotów, klasa, rasa, płeć, poziom postaci, oraz informacją czy jest to główna postać gracza. Wiele postaci gracza udało się identyfikować na podstawie identycznej listy osiągnięć zdobywanych w tym samym momencie. Za główną uznawano tę o najwyższym poziomie w danej gildii (tak więc gracz mógł mieć więcej niż jedną główną postać). Krawędź przechowuje również informację o tym, czy łączy dwie główne postaci, oraz o minimalnej rozbieżności czasowej w zdobyciu osiągnięcia przez obie postaci.

Jako że WoW API nie udostępnia bezpośrednio informacji o tym jak gracze dobierają się w drużyny, dwie postaci połączono krawędzie jeżeli zdobyli osiągnięcie w podobnym czasie (założono, że zdobywali go wspólnie), lub są w tej samej drużynie pvp. Wagą krawędzi ustanowiono liczbę osiągnięć, które zostały zdobyte w podobnym (w odstępie pięciu minut) czasie.

W rezultacie otrzymano:

  • 48792 Krawędzi
  • 36859 krawędzi między głównymi postaciami
  • 153 krawędzie pvp

W pierwszym pliku  krawędzie poprowadzono jedynie pomiędzy głównymi postaciami, oraz pomiędzy wszystkimi postaciami danego gracza. W drugim  umieszczono wszystkie krawędzie.

Wizualizacja

Poniższe rysunki przedstawiają grafy, w którym krawędzie poprowadzono jedynie między głównymi postaciami. Pierwsze dwie ilustrują wspólne zdobywanie osiągnięć, podczas gdy w trzecim zawarto informacje o grze arenowej. Na dwóch początkowych obrazkach pozostawiono jedynie krawędzie między postaciami, które przynajmniej jedno osiągnięcie zdobyły w tym samym momencie, i to tylko te, których waga przekraczała 40. Wielkość wierzchołka odpowiada jego wartości pagerank, zaś kolor wskazuje przynależność do gildii (na pierwszym), poziom posiadanego ekwipunku (na drugim).

guilds_circle_2guilds_circlepvp

Luty 18, 2013

Co słychać w mediach społecznościowych?

- autor: tsissput

Założenia projektu

Celem projektu było stworzenie prototypu aplikacji umożliwiającej analizę wiadomości gazetowych pod kątem popularności, którą uzyskały w serwisach społecznościowych.

Wynik realizacji projektu

Utworzone zostały dwa moduły. Pierwszy z nich odpowiedzialny jest za ciągłą akwizycję wpisów z kanałów RSS wylistowanych w pliku tekstowym. Informacje o kanałach RSS i ich wpisach zapisywane są w bazie danych.

Drugi moduł zajmuje się pobieraniem informacji o zainteresowaniu, jakie wzbudziły wiadomości w serwisach społecznościowych. Prototypowa aplikacja zbiera informacje o liczbie tweetów na serwisie Twitter zawierających link do badanego artykułu oraz liczbę udostępnień artykułu na portalu Facebook. Pobrane dane zapisywane są w bazie danych. Moduł ten generuje również pliki csv z zestawieniem najpopularniejszych artykułów ogółem oraz najpopularniejszych w każdym z kanałów RSS. 

Rozwój projektu

Kolejnymi krokami rozwoju aplikacji mogą być:

– rozszerzenie modułu zbierającego informacje o zainteresowaniu o kolejne serwisy społecznościowe

– opracowanie funkcji oceny zainteresowania na podstawie informacji ze wszystkich serwisów

– stworzenie modułu analizującego artykuły pod kątem cech wspólnych, próba klastrowania wiadomości, w celu odnalezienia zależności między treścią i tematyką artykułu a wzbudzonym zainteresowaniem

– dodanie interfejsu graficznego

Wykorzystane technologie

– Java

– PostgresSQL

– biblioteka do obsługi kanałów RSS: ROME http://rometools.org/

– lekka i bardzo wygodna biblioteka odpowiedzialna za integrację z bazą danych, ORM: jOOQ http://www.jooq.org/

– Twiiter API

– Facebook API

Kod źródłowy + przykładowe wyniki działania aplikacji

https://github.com/k-cz/tsiss

 

 

Autor

Kacper Skory

 

Tagi:
Luty 13, 2013

Event Finder czyli wszystkie interesujące wydarzenia w jednym miejscu

- autor: tsissput

Celem projektu było stworzenie aplikacji, która ułatwi użytkownikom dostęp do informacji na temat zbliżających się wydarzeń. Dzięki wybraniu interesujących nas kategorii oraz miast otrzymujemy dostosowaną grupę wydarzeń. Dzięki temu nie trzeba przekopywać się przez treści zupełnie nas nie interesujące. Wydarzenia oraz kategorie są dodawane przez użytkowników i to oni dbają o dostarczenie jak najciekawszej treści.
MainPage
Na zaprezentowanym obrazku widać dwa wydarzenia, są to koncerty z kategorii muzyki rockowej. Wydarzenia wybierane są na podstawie ustawień użytkownika, tak więc w systemie widnieją innego typu wydarzenia, natomiast użytkownik widzi dobrane dla niego. Ma oczywiście możliwość przejrzenia wszystkich wydarzeń, jednak jest w tym celu zrealizowany inny widok. Wydarzenia na które użytkownik planuje się wybrać są oznaczana na niebiesko.
Oczywiście jak na portal społecznościowy przystało nie może obyć się bez interakcji między użytkownikami. Możliwe jest śledzenie wybranych osób dzięki czemu dostajemy spis wydarzeń na jakie się wybierają. Dodatkowo każde wydarzenie może zostać skomentowane przez użytkowników.
Inwigiluj

Do stworzenia aplikacji wykorzystaliśmy technologię .Net, język C#, logika biznesowa została zrealizowana z wykorzystaniem technologii WCF dzięki czemu istnieje możliwość stworzenia dodatkowych interface’ów użytkownika. Domyślny interface został zrealizowany z wykorzystaniem technologii MVC oraz styli CSS Twitter Bootstrap.

Autorzy
Tomasz Bartoszewski
Marcin Wolicki

Luty 12, 2013

Facebookowe rozszerzenie dla sklepów Magento

- autor: tsissput

Ogólnym założeniem projektu jest wykorzystanie zasięgu i danych zbieranych przez Facebooka w celu zwiększenia sprzedaży w sklepie internetowym.

Zaprezentowane tutaj rozwiązanie jest modułem dla sklepów opartych o platformę Magento. Oznacza to, że każdy sklep oparty o tą modułową platformę może poprać stworzone rozszerzenie i od ręki zacząć korzystać z udostępnionej funkcjonalności.

magento_friendlist
Widok sugestii prezentów dla znajomych

Pierwszą zachętą do korzystania z naszego sklepu jest możliwość założenia konta i późniejszego logowanie się w sklepie z wykorzystaniem Facebooka – nikt nie lubi pamiętać wielu haseł, a tak za jednym kliknięciem mamy już konto i jesteśmy zalogowani.

Drugi krok, który potencjalnie może przełożyć się na wzrost sprzedaży to dodanie guzika „Lubię to!” wraz z Facebookowymi metadanymi.

Magento Panel Administracyjny
Widok panelu administracyjnego – wybór fan page – widoczne propozycje słów kluczowych i szczegóły wybranego fan page

Trzeci największy krok to sugestie prezentów dla Facebookowych znajomych. Sugestie prezentów pochodzą z dwóch prostych źródeł:
Pierwszym są produkty polubione w naszym sklepie przez znajomego. Drugim są tak zwane „Punkty Zainteresowań” które tworzymy samodzielnie w panelu administracyjnym. Na punkt zainteresowań składają się produkty które będą wyświetlane jako sugestie prezentów oraz Facebookowe Fan Page. Jeżeli nasz znajomy polubi przynajmniej jeden z wymienionych Fan Page produkty znajdujące się w tym punkcie zainteresowań zostaną mu zasugerowane. W przypadku uniwersalnego modułu dla nieznanych nam sklepów trudnym jest zaproponowanie mechanizmu który automatycznie powiąże odpowiednie Fan Page z odpowiednimi produktami – to zadanie spada na administratora sklepu. Prostą pomocą dla wyszukiwania odpowiednich Fan Page propozycje słów kluczowych zbierane ze słów kluczowych wybranych produktów.

Zapraszam do przeklikania się przez działające demo i ograniczenia się z wandalizmem przy przeglądaniu opcji panelu administracyjnego (użytkownik: fdemo hasło: tsiss-put1234)

Autor: Kamil Balwierz