Spis treści

GameList - portal społecznościowy zrzeszający graczy (t)

Michał Bocheński, Paweł Chrost, Krzysztof Ćwierk, Mateusz Dymczyk

Projekt stanowi podstawę bazodanową dla projektu realizowanego z przedmiotu Technologie i Programowanie WWW.

Sformułowanie zadania projektowego

Przedmiotem projektu jest stworzenie portalu społecznościowego dla graczy. Ma on na celu zrzeszenie społeczności graczy w jednym miejscu w celu umożliwienia znalezienia ludzi o podobnych zainteresowaniach oraz wymiany poglądów na temat wspólnych pasji. Głównym czynnikiem, który skłonił nas do stworzenia takiego portalu jest brak rozwiązań na rynku, które trafiałyby w gusta większości społeczności graczy - jest to główny powód dla którego ludzie będą tym zainteresowani, a co za tym idzie również i różnego rodzaju sponsorzy i reklamodawcy.

Opis istniejących rozwiązań

Innowacyjność rozwiązania

Nasze rozwiązanie jest połączeniem portalu społecznościowego (takiego jak last.fm czy myanimelist.com) z bazą wiedzy o grach (takiej jak np. gamefaqs.com), dzięki czemu użytkownicy będą w stanie wyszukiwać nowye gry oraz dyskutować o nich z innymi użytkownikami. Rozwiązanie takie nie istnieje obecnie na rynku, dzięki czemu jest ono w stanie przyciągnąć rzeszę potencjalnych użytkowników. Z przeprowadzonych przez nas badań rynku społeczność jest niezadowolona z braku podobnego rozwiązania.

Wstępna analiza wymagań użytkownika

Funkcjonalności główne (must)
Funkcjonalności dodatkowe (should)
Funkcjonalności dodatkowe (could)
Funkcjonalności dodatkowe (won't)

Przypadki użycia

  1. Scenariusze dla Użytkownika niezalogowanego:
    1. Rejestracja w serwisie
      • Podanie loginu
      • Podanie i potwierdzenie hasła
      • Podanie adresu e-mail
    2. Wyszukiwanie gier
      • Przeglądanie opisów gier
      • Przeglądanie recenzji gier
      • Przeglądanie ocen gier
    3. Wyszukiwanie innych użytkowników
      • Przeglądanie profili użytkowników
  2. Scenariusze dla Użytkownika zarejestrowanego:
    1. Dostęp do serwisu:
      • Zalogowanie do systemu
      • Przypomnienie hasła użytkownika
    2. Zarządzanie kontem:
      • Zmiana danych użytkownika
      • Dodawanie/usuwanie gier do list
      • Dodawanie/usuwanie przyjaciół
    3. Gry
      • Wyszukiwanie gier
      • Przeglądanie opisów gier
      • Przeglądanie recenzji gier
      • Przeglądanie ocen gier
      • Dodawanie recenzji gier
      • Dodawanie rekomendacji do gier
      • Ocenianie gier
    4. Fora
      • Przeglądanie for gier
      • Postowanie na forach
    5. Wyszukiwanie innych użytkowników
      • Przeglądanie profili użytkowników
      • Przeglądanie użytkowników o podobnych zainteresowaniach
  3. Scenariusze dla Administratora:
    1. Zarządzanie użytkownikami:
      • Zmiana danych użytkownika
      • Usuwanie użytkownika
      • Zmiana uprawnień użytkownika
    2. Zarządzanie treścią serwisu:
      • Moderacja serwisu

Identyfikacja funkcji

Use Case Diagram

Diagram FHD

Budowa i analiza diagramu przepływu danych

Diagram kontekstowy

Diagramy systemowe

Projekt bazy danych

Diagram ERR

Struktura tabel

CREATE SCHEMA IF NOT EXISTS `GLADM` DEFAULT CHARACTER SET utf8 COLLATE DEFAULT collation ;
USE `GLADM`;
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_CATEGORIES`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_CATEGORIES` (
  `cat_code` VARCHAR(10) NOT NULL ,
  `cat_name` VARCHAR(255) NOT NULL ,
  PRIMARY KEY (`cat_code`) );
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_PLATFORMS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_PLATFORMS` (
  `pl_code` VARCHAR(10) NOT NULL ,
  `pl_name` VARCHAR(100) NOT NULL ,
  PRIMARY KEY (`pl_code`) );
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_COMPANIES`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_COMPANIES` (
  `cmp_id` INT NOT NULL AUTO_INCREMENT ,
  `cmp_name` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`cmp_id`) );
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_GAMES`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_GAMES` (
  `gm_id` INT NOT NULL AUTO_INCREMENT ,
  `gm_cat_code` VARCHAR(10) NOT NULL ,
  `gm_pl_code` VARCHAR(10) NOT NULL ,
  `gm_cmp_id` INT NOT NULL ,
  `gm_name` VARCHAR(100) NOT NULL ,
  `gm_release_date` DATE NULL ,
  `gm_avg_score` TINYINT NULL ,
  `gm_description` TEXT NULL ,
  `gm_avatar_path` TINYTEXT NULL ,
  PRIMARY KEY (`gm_id`) ,
  INDEX `GLK_GM_CAT` (`gm_cat_code` ASC) ,
  INDEX `GLK_GM_PL` (`gm_pl_code` ASC) ,
  INDEX `GLK_GM_CMP` (`gm_cmp_id` ASC) ,
  CONSTRAINT `GLK_GM_CAT`
    FOREIGN KEY (`gm_cat_code` )
    REFERENCES `GLADM`.`GLT_CATEGORIES` (`cat_code` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_GM_PL`
    FOREIGN KEY (`gm_pl_code` )
    REFERENCES `GLADM`.`GLT_PLATFORMS` (`pl_code` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_GM_CMP`
    FOREIGN KEY (`gm_cmp_id` )
    REFERENCES `GLADM`.`GLT_COMPANIES` (`cmp_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_USERS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_USERS` (
  `usr_id` INT NOT NULL AUTO_INCREMENT ,
  `usr_name` VARCHAR(30) NOT NULL ,
  `usr_gender` VARCHAR(1) NOT NULL ,
  `usr_email` VARCHAR(120) NOT NULL ,
  `usr_age` INT NULL ,
  `usr_location` VARCHAR(45) NULL ,
  `usr_avatar_path` TINYTEXT NULL ,
  `usr_pwd` INT NULL ,
  PRIMARY KEY (`usr_id`) );
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_REVIEWS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_REVIEWS` (
  `rev_id` INT NOT NULL AUTO_INCREMENT ,
  `rev_gm_id` INT NOT NULL ,
  `rev_usr_id` INT NOT NULL ,
  `rev_grade` TINYINT NULL ,
  `rev_text` TEXT NOT NULL ,
  PRIMARY KEY (`rev_id`) ,
  INDEX `GLK_REV_GM` (`rev_gm_id` ASC) ,
  INDEX `GLK_REV_USR` (`rev_usr_id` ASC) ,
  CONSTRAINT `GLK_REV_GM`
    FOREIGN KEY (`rev_gm_id` )
    REFERENCES `GLADM`.`GLT_GAMES` (`gm_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_REV_USR`
    FOREIGN KEY (`rev_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_STORED_STATUS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_STORED_STATUS` (
  `ss_code` VARCHAR(10) NOT NULL ,
  `ss_name` VARCHAR(120) NOT NULL ,
  PRIMARY KEY (`ss_code`) );
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_STORED_GAMES`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_STORED_GAMES` (
  `sgm_id` INT NOT NULL AUTO_INCREMENT ,
  `sgm_usr_id` INT NOT NULL ,
  `sgm_gm_id` INT NOT NULL ,
  `sgm_ss_code` VARCHAR(10) NOT NULL ,
  `sgm_date_added` DATE NOT NULL ,
  PRIMARY KEY (`sgm_id`) ,
  INDEX `GLK_SGM_USR` (`sgm_usr_id` ASC) ,
  INDEX `GLK_SGM_GM` (`sgm_gm_id` ASC) ,
  INDEX `GLK_SGM_SS` (`sgm_ss_code` ASC) ,
  CONSTRAINT `GLK_SGM_USR`
    FOREIGN KEY (`sgm_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_SGM_GM`
    FOREIGN KEY (`sgm_gm_id` )
    REFERENCES `GLADM`.`GLT_GAMES` (`gm_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_SGM_SS`
    FOREIGN KEY (`sgm_ss_code` )
    REFERENCES `GLADM`.`GLT_STORED_STATUS` (`ss_code` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_SHOUTBOXES`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_SHOUTBOXES` (
  `sbx_id` INT NOT NULL AUTO_INCREMENT ,
  `sbx_usr_id` INT NOT NULL ,
  `sbx_usr_sender_id` INT NOT NULL ,
  `sbx_text` TEXT NOT NULL ,
  `sbx_date_added` DATE NOT NULL ,
  PRIMARY KEY (`sbx_id`) ,
  INDEX `GLK_SBX_USR` (`sbx_usr_id` ASC, `sbx_usr_sender_id` ASC) ,
  CONSTRAINT `GLK_SBX_USR`
    FOREIGN KEY (`sbx_usr_id` , `sbx_usr_sender_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` , `usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_FRIENDS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_FRIENDS` (
  `frd_id` INT NOT NULL AUTO_INCREMENT ,
  `frd_usr_id` INT NOT NULL ,
  `frd_usr_friend_id` INT NOT NULL ,
  PRIMARY KEY (`frd_id`) ,
  INDEX `GLK_FRD_USR` (`frd_usr_id` ASC, `frd_usr_friend_id` ASC) ,
  CONSTRAINT `GLK_FRD_USR`
    FOREIGN KEY (`frd_usr_id` , `frd_usr_friend_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` , `usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_RECOMMENDATIONS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_RECOMMENDATIONS` (
  `rec_id` INT NOT NULL AUTO_INCREMENT ,
  `rec_usr_id` INT NOT NULL ,
  `rec_gm_id` INT NOT NULL ,
  `rec_gm_recom_id` INT NOT NULL ,
  `rec_text` TEXT NOT NULL ,
  `rec_date_added` DATE NOT NULL ,
  PRIMARY KEY (`rec_id`) ,
  INDEX `GLK_REC_USR` (`rec_usr_id` ASC) ,
  INDEX `GLK_REC_GM` (`rec_gm_id` ASC, `rec_gm_recom_id` ASC) ,
  CONSTRAINT `GLK_REC_USR`
    FOREIGN KEY (`rec_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_REC_GM`
    FOREIGN KEY (`rec_gm_id` , `rec_gm_recom_id` )
    REFERENCES `GLADM`.`GLT_GAMES` (`gm_id` , `gm_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_NEWS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_NEWS` (
  `new_id` INT NOT NULL AUTO_INCREMENT ,
  `new_usr_id` INT NOT NULL ,
  `new_title` VARCHAR(255) NOT NULL ,
  `new_text` LONGTEXT NOT NULL ,
  `new_date_added` DATE NOT NULL ,
  PRIMARY KEY (`new_id`) ,
  INDEX `GLK_NEW_USR` (`new_usr_id` ASC) ,
  CONSTRAINT `GLK_NEW_USR`
    FOREIGN KEY (`new_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_FORUMS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_FORUMS` (
  `for_id` INT NOT NULL AUTO_INCREMENT ,
  `for_gm_id` INT NOT NULL ,
  `for_name` VARCHAR(150) NOT NULL ,
  `for_description` MEDIUMTEXT NULL ,
  PRIMARY KEY (`for_id`) ,
  INDEX `GLK_FOR_GM` (`for_gm_id` ASC) ,
  CONSTRAINT `GLK_FOR_GM`
    FOREIGN KEY (`for_gm_id` )
    REFERENCES `GLADM`.`GLT_GAMES` (`gm_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_TOPICS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_TOPICS` (
  `top_id` INT NOT NULL AUTO_INCREMENT ,
  `top_for_id` INT NOT NULL ,
  `top_usr_id` INT NOT NULL ,
  `top_title` VARCHAR(80) NOT NULL ,
  `top_text` TEXT NOT NULL ,
  `top_date_added` DATE NOT NULL ,
  `top_views` INT NOT NULL ,
  `top_closed` TINYINT(1) NOT NULL DEFAULT 0 ,
  `top_important` TINYINT(1) NOT NULL DEFAULT 0 ,
  PRIMARY KEY (`top_id`) ,
  INDEX `GLK_TOP_FOR` (`top_for_id` ASC) ,
  INDEX `GLK_TOP_USR` (`top_usr_id` ASC) ,
  CONSTRAINT `GLK_TOP_FOR`
    FOREIGN KEY (`top_for_id` )
    REFERENCES `GLADM`.`GLT_FORUMS` (`for_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_TOP_USR`
    FOREIGN KEY (`top_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);
 
 
-- -----------------------------------------------------
-- Table `GLADM`.`GLT_POSTS`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `GLADM`.`GLT_POSTS` (
  `post_id` INT NOT NULL AUTO_INCREMENT ,
  `post_topic_id` INT NOT NULL ,
  `post_usr_id` INT NOT NULL ,
  `post_content` MEDIUMTEXT NOT NULL ,
  `post_date_added` DATE NOT NULL ,
  PRIMARY KEY (`post_id`) ,
  INDEX `GLK_POST_TOP` (`post_topic_id` ASC) ,
  INDEX `GLK_POST_USR` (`post_usr_id` ASC) ,
  CONSTRAINT `GLK_POST_TOP`
    FOREIGN KEY (`post_topic_id` )
    REFERENCES `GLADM`.`GLT_TOPICS` (`top_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `GLK_POST_USR`
    FOREIGN KEY (`post_usr_id` )
    REFERENCES `GLADM`.`GLT_USERS` (`usr_id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);

Baza zaprojektowana została w języku MySQL z wykorzystaniem MySQL Workbench 5.1 OSS. Struktura tabel spełnia założenia 3 postaci normalnej.

Wykorzystane technologie

Interfejs użytkownika całej aplikacji został stworzony w technologii Flex 4 przy pomocy pluginu Flex Builder do IDE Eclipse.

Logika biznesowa została napisana w technologii JEE z uwzględnieniem Serwletów, JPA dla warstwy persystencji oraz P(lain)O(ld)J(ava)O(bject)

Połączenie front-endu (Flex) z logiką (JEE) zrealizowane zostało przy użyciu darmowej technologii BlazeDS. Do serializacji i przesyłania danych pomiędzy Flexem a JEE używany jest protokół AMF3. AMF (Action Message Format) to binarny format używany do serjalizacji obiektów ActionScript. Jest on wykorzystywany do wymiany danych pomiędzy Flexem a back endem Javowym znajdującym się na serwerze przy użyciu BlazeDS. BlazeDS to serwerowa technologia zdalnego przekazywania, która umożliwia

Kontener aplikacji webowej: Tomcat 6.0

Hibernate

Hibernate

Hibernate jest biblioteką służącą do mapowania obiektowo-relacyjnego (ORM) dla języka Java, która zapewnia framework dla mapowania modeli domeny obiektowej do tradycyjnej bazy relacyjnej. Hibernate roziązuje opór konfliktu obiektowo-relacyjnego poprzez zastąpienie bezpośredniego dostępu do bazy związanego z persystencją wysoko pozimowymi funkcjami. Hibernate zamiast używać przetwarzania bytecode'u czy generacji kodu korzysta z refleksji czasu wykonania w celu zdeterminowania właściwości persystencyjnych klasy. Obiekty, które mają być przechowywane są zdefiniowane w dokumencie mapujacym (lub oznaczone odpowiednimi adnotacjami w kodzie), który służy do opisu pól do persystencji oraz asocjacji, jak również wszystkich podklas i proxy persystowanego obiektu. Dokumenty mapujące są kompilowane podczas startu aplikacji i zapewniają framework z niezbędnymi informacjami dla klasy. Dodatkowo są one używane przy operacjach pomocniczych, takich jak generowanie schematu bazy danych. Głównym zadaniem Hibernate jest mapowanie klas Javowych do tabel bazy danych (oraz z typów Javowych do typów SQL). Hibernate daje nam również mechanizmy służace do tworzenia zapytań bazy danych. Generuje on wywołania SQL i zwalnia użytkownika od ręcznego przetwarzania danych wynikowych oraz konwersacji obiektowych, dzięki czemu aplikacja jest przenośna do wszystkich wspieranych SQLowych baz danych.

Architektura.

Architektura Hibernate składa się z 3 głównych komponentów:

Mapowanie

Mapowanie klas Javowych do tabel bazy danych jest uzyskiwane poprzez konfigurację plików XMLowych lub adnotacje. Podczas używania XMLi, Hibernate generuje szkieletowy kod źródłowy dla przechowywanych klas. Jest to niepotrzebne w wypadku stosowania adnotacji. Hibernate do utrzymania schematu bazy danych może użyć XMLa bądź adnotacji. Hibernate zapewnia również metody obsługujące związki typu „jeden-do-wielu” oraz „wiele-do-wielu” pomiędzy klasami. Możliwe jest również zarządzanie refleksyjnymi asocjacjami typu „jeden-do-wielu”, gdzie obiekt jest związany z wieloma instancjami tego samego typu. Hibernate wspiera mapowanie własnych typów danych. Dzięki temu poniższy scenariusz jest możliwy:

Persystencja

Hibernate zapewnia transparentną persystencję dla P(lain)O(old)J(ava)O(object). Jedynym wymaganiem dla persystencji obiektu jest posiadanie przez klasę bezargumentowego konstruktora, który nie musi być jednak public. Poprawne zachowanie w niektórych aplikacjach również wymaga specjalnego przeciążenia metod equals() oraz hashCode(). Kolekcje obiektów są na ogół w Javie przechowywane jako obiekty typu Set czy Lista. W Javie 5+ można również używać typów generycznych. Hibernate może być skonfigurowany w sposób umożliwiający „lazy load” powiązanych kolekcji (domyślna opcja w Hibernate 3). Powiązane obiekty mogą być skonfigurowane do kaskadowania operacji z jednego do drugiego. Dla przykładu, nadklasa, np. typu Album, może być skonfigurowana do kaskadowania swoje operacje zapisz i/lub usuń do swojej podklasy typu Ścieżka. To może zmniejszyć czas tworzenia aplikacji oraz zapewnić integrację referencyjną. Funkcja „dirty checking” zapobiega niepotrzebnym akcjom zapisu do bazy poprzez wykonywanie uaktualnień SQL tylko na zmodyfikowanych właściwościach obiektu.

Hibernate Query Language (HQL)

Hibernate zapewnia również programiście język zainspirowany SQLem nazwany Hibernate Query Language (HQL), który pozwala aby SQLo podobne zapytania były pisane pod obiekty danych Hibernate'a. „Criteria queries” jest to obiektowo zorientowana alternatywa dla HQLa (używa się ją poprzez adnotacje).

Zdefiniowanie interfejsów do prezentacji, edycji i obsługi danych