Warning: include_once(/var/www/html/pmwiki-2.2.86/cookbook/soap4pmwiki/soap4pmwiki.php): failed to open stream: No such file or directory in /var/www/html/fields/dbp13/local/config.php on line 4

Warning: include_once(): Failed opening '/var/www/html/pmwiki-2.2.86/cookbook/soap4pmwiki/soap4pmwiki.php' for inclusion (include_path='.:/opt/php/lib/php') in /var/www/html/fields/dbp13/local/config.php on line 4

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/fields/dbp13/local/config.php:4) in /var/www/html/pmwiki-2.2.86/pmwiki.php on line 1250
Datenbankpraktikum SS 2013 - MMOG - Spieler Allianzen Und Nachrichten Kontaktliste

Kontaktliste und die Spielerübersicht

Konstantin Obermann

Die Spielerübersicht ist eine Auflistung aller Spieler mit ihren Highscores und ihrer Allianzen. Da es mit steigender Spieleranzahl sehr unübersichtlich werden kann, Spieler zu finden, haben wir die Kontaktliste implementiert.

Die Kontaktliste erlaubt es dem Spieler, Freunde hinzuzufügen, Nachrichten zu senden und deren on-/offline Status einsehen. Der Nutzer profitiert von dieser Beziehung dadurch, dass er und sein Kontakt sich gegenseitig im Falle eines Angriffs helfen oder Handel betreiben können.

Planung

Die Beziehung zwischen den User und der Tabelle Relationship

Problemstellung

Es gab zwei grundlegende Fragen:

  • Wie kommt man am schnellsten an alle Freunde des Spielers, wenn nur einer von ihnen "friend" sein kann?
  • Wie implementieren wir das Konzept der Einladungen, sodass es einen Status "pending" gibt, damit gegenseitiges Einverständnis erreicht werden kann?
    • Lösungsidee: wir versehen die Relationship mit einem String-Attribut "status". Dieser kann sein:
    • "pending"
    • "accepted"
    • "declined"

Jedoch haben wir uns aufgrund der hohen Unübersichtlichkeit nicht für dieses Konzept entschieden.

Implementierung

Model

User

Dem User werden sowohl die Relationships selbst, als auch die Freunde zugewiesen.

user.rb:

  has_many :relationships
  has_many :friends, :through => :relationship, :source => :friend
  has_many :users, :through => :relationship, :source => :user
  has_many :reverse_relationships, foreign_key: "friend_id", class_name: "Relationship"

Hier fällt auf, dass der User nicht nur mehrere "friends" hat, sonder auch mehrere "user". Das liegt an unserer Implementierung der Relationships. Das Konzept ist folgendermaßen zu erklären:

Aufteilung in Spieler und Freund

In der Tabelle Relationship werden für jeweils eine Beziehung zwei Einträge erstellt:

1)spieler1-->spieler2

2)spieler2-->spieler1

Dadurch wird die Suche und die Auflistung aller Freunde des Spielers einfacher.
Beispiel(ruby console): User.find_by_username("demo").friends listet alle Freunde des Spielers demo auf. Aufgrund unserer Implementation funktioniert das auch in die entgegengesetzte Richtung: User.find_by_username("demo2").friends.
-----

Gegenseitige Zustimmung

Um zu verhindern, dass ein Spieler willkürlich andere Spieler hinzufügt, haben wir das Konzept Requestsystem entwickelt.

Beide Relationships werden mit der folgenden Methode erstellt, nachdem die Anfrage(Request) von dem anderen Spieler angenommen wurde.

  def make_friendship!(other_user)
    relationship.create!(friend_id: other_user.id)
    other_user.relationship.create!(friend_id: self.id)
    return true
  end 

Damit es zu keinen nil-Exceptions während des Freundschaftskündigung kommt, wird in der folgenden Methode überprüft, ob die Relationship existiert.

  def end_friendship!(other_user)    
    relother=Relationship.where(user: other_user, friend: self).first
    relself=Relationship.where(user: self, friend: other_user).first
    if (relother==nil or relself==nil)
      return false
    else
      relother.destroy
      relself.destroy
      return true
    end
  end

Relationship

Die Relationship-Tabelle hat zwei Spalten: user und friend, welche jeweils auf einen User verweisen. Ein User kann sich nicht selbst als Freund hinzufügen.

relationship.rb:

  belongs_to :user, class_name: 'User'
  belongs_to :friend, class_name: 'User'

Folgende Hilfsmethode prüft, ob ein Spieler das Recht hat, die aktuelle Relationship aufzulösen.
Als Parameter wird ein Objekt des Typs User übergeben und die Methode liefert true, wenn dieser User in der aktuellen Relationship existiert.

  def delete_permission?(user)
    return (user==self.user or user==self.friend)
  end

Controller

User

Der Nutzercontroller wird von Devise gesteuert und kann nicht eingesehen werden. siehe Nutzerverwaltung Abschnitt Controller.

Relationship

Damit die Nutzerparameter richtig übergeben werden und die Kontakte des jeweiligen Spielers korrekt angezeigt werden, muss dieser zuerst mit Devise authentifiziert werden:

  before_filter :authenticate_user!

Die destroy Methode ruft die oben erwähnte end_friendship! methode des Spielers auf. Als Parameter wird die Referenz friend der aktuellen Relationship übergeben, welche bearbeitet wird.

  def destroy
    current_user.end_friendship!(@relationship.friend)
    respond_to do |format|
      format.html { redirect_to relationships_url }
    end
  end

View

Die index.html.erb ist so implementiert, dass diese nur Kontakte des current_user auflistet. Durch die Authentifizierung im relationship_controller, stellen wir somit einen persönlichen und sicheren Sichtbarkeitsbereich für jeden Spieler her.

Ansicht der Freundesliste

Wenn der Spieler keine Kontakte besitzt, wird er benachrichtigt:

<% if current_user.friends.first==nil %>

      <i>Du hast keine Kontakte hinzugefügt</i>
  • Der "Nachricht schreiben" Button leitet an new_message_path weiter und übergibt zusätzlich als Parameter den Namen des Kontakts, an den die Nachricht verschickt werden soll.
  • Der "entfernen" Button ruft die destroy Methode in relationship_controller auf.

Ein weiteres Feature ist die zusätzliche Anzeige der Freundesliste, welche zu jedem Zeitpunkt sichtbar ist. Unabhängig davon, in welcher View der Spieler sich gerade befindet.

Kontaktliste mit Statusanzeige

Hier wird zusätzlich noch der online-Status des Spielers angezeigt, sowie ein Button zum Verschicken einer Nachricht.

Die Spielerübersicht

Diese View listet alle Spieler auf mit ihrem Rang(abhängig von der Punktzahl) und ihrer Allianz.

Die Übersicht aller Spieler

Eine Seite dieser Ansicht zeigt bis zu 10 Spieler an. Es ist möglich, nach unterschiedlichen Spalten zu sortieren und Spieler zu suchen.

Fazit

Anfangs hatten wir Schwierigkeiten, dieses Modell umzusetzen, da sehr viele Sachen beachtet werden mussten. Es kam zu zahlreichen Fehlern mit nicht-existierenden und/oder redundanten Relationships, weil es dafür keine zentrale Regelung gab.

Mit dem Konzept des Requestsystems mussten wir zwar große Teile des Relationship-Modells umschreiben, jedoch hat es uns erlaubt, einen sicheren und platzsparenden invite-request-Vorgang zu schaffen.


Page last modified on August 23, 2013, at 04:14 PM