Package net.sphene.goim.stats

Source Code of net.sphene.goim.stats.StatsCollectorBot

/*
* Gamers Own Instant Messenger
* Copyright (C) 2005-2006 Herbert Poul (kahless@sphene.net)
* http://goim.sphene.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package net.sphene.goim.stats;

import galena.Kernel;
import galena.addins.modules.database.DB;
import galena.addins.modules.database.DB.DBConnection;
import galena.message.Message;
import galena.message.StandAloneMessageHandler;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sphene.galena.addins.AddinImplementationDefinition;
import net.sphene.galena.addins.AddinInterfaceDefinition;
import net.sphene.galena.addins.AddinInterfaceMethodDefinition;
import net.sphene.galena.addins.GalenaArgsInterface;
import net.sphene.galena.addins.GalenaViewAddin;
import net.sphene.goim.stats.game.GameStatusExtension;

import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;

@AddinInterfaceDefinition(
    defaultcommandprefix = "jabberstatscollector"
)
@AddinImplementationDefinition(
    author = "Herbert Poul",
    requirements = { "galena.addins.modules.database.PgSQL" }
)
public class StatsCollectorBot extends GalenaViewAddin {

  private DB db;
 
  private String jid = "stats@localhost";
  private String password = "";
  private String host = null;
  private String resource = "StatsCollectorBot";
  private int port = 5222;

  protected XMPPConnection connection;
 
  protected Map<String, PresenceWrapper> presences;
 
  public DB getDB() { return db; }
  public static class PresenceWrapper {
    Date date;
    Presence presence;
    public PresenceWrapper(Date date, Presence presence) {
      this.date = date; this.presence = presence;
    }
  }

  @Override
  public void init(Object[] requirements) {
    this.db = (DB)requirements[0];
    doConnect();
  }
  @Override
  public void registerHandler() {
    super.registerHandler();
    kernel.registerMessageHandler(new StandAloneMessageHandler(null) {

      @Override
      protected int handleMessage(Message msg) {
        // TODO Auto-generated method stub
        return 0;
      } }.setMessagetype(Message.MSG_FINALIZE));
  }
  public void doConnect() {
    new Thread("StatsCollectorBot") {
      public void run() {
        while(!connect()) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e1) {
            e1.printStackTrace();
          }
        }
      }
    }.start();
  }
  public boolean connect() {
    try {
      //XMPPConnection.DEBUG_ENABLED = true;
      connection = new XMPPConnection(host,port,StringUtils.parseServer(jid));
      presences = new HashMap<String,PresenceWrapper>();
      connection.addPacketListener(new PacketListener() {
        public void processPacket(Packet packet) {
          System.out.println("Received packet: " + packet.toXML());
          if(!(packet instanceof Presence)) return;
          //System.out.println(" -- IS Presence packet");
          Presence presence = (Presence)packet;
          if(presence.getType() == Presence.Type.SUBSCRIBE) {
            Presence response = new Presence(Presence.Type.SUBSCRIBED);
            response.setTo(presence.getFrom());
            connection.sendPacket(response);
            Presence req = new Presence(Presence.Type.SUBSCRIBE);
            req.setTo(presence.getFrom());
            connection.sendPacket(req);
          } else if(presence.getType() == Presence.Type.AVAILABLE) {
            PresenceWrapper oldWrapper = presences.put(presence.getFrom(),new PresenceWrapper(new Date(),presence));
            if(oldWrapper != null)
              logPresence(oldWrapper);
          } else if(presence.getType() == Presence.Type.UNAVAILABLE) {
            PresenceWrapper oldWrapper = presences.remove(presence.getFrom());
            if(oldWrapper != null)
              logPresence(oldWrapper);
          }
        } }, new AndFilter());//new PacketTypeFilter(Presence.class));
      connection.addConnectionListener(new ConnectionListener(){
        public void connectionClosed() {
          doConnect();
        }
        public void connectionClosedOnError(Exception e) {
          e.printStackTrace();
        }});
      login();
      return true;
    } catch (XMPPException e) {
      e.printStackTrace();
      if(e.getXMPPError() != null && e.getXMPPError().getCode() == 401) {
        Kernel.debug(this,"Unauthorized.. trying to register ..",-1);
        AccountManager manager = new AccountManager(connection);
        try {
          manager.createAccount(StringUtils.parseName(jid),password);
          login();
          return true;
        } catch (XMPPException e1) {
          e1.printStackTrace();
          return false;
        }
      } else {
        return false;
      }
    }
  }
  protected void logPresence(PresenceWrapper oldWrapper) {
    DBConnection db = this.db.getDBConnection(false);
    int id = db.sendInsert(null,"goim_presence_log","jid,resource,mode,start,\"end\"",
        StringUtils.parseBareAddress(oldWrapper.presence.getFrom()).toLowerCase(),
        StringUtils.parseResource(oldWrapper.presence.getFrom()),
        oldWrapper.presence.getMode().toString(),
        oldWrapper.date,
        new Date());
    db.commit();
    Iterator i = oldWrapper.presence.getExtensions();
    while(i.hasNext()) {
      PacketExtension ex = (PacketExtension)i.next();
      if(ex instanceof GameStatusExtension) {
        GameStatusExtension status = (GameStatusExtension)ex;
        String gameId = status.gameId;
        String destination;
        if(status.gameId.equals("lfss2")) {
          destination = status.atts.get("servername");
        } else {
          destination = GameStatusExtension.formatSocketAddress(status.target);
        }
        db.sendInsert(null,"goim_server","game,destination,presence",gameId,destination,id);
        db.commit();
      }
    }
    db.close();
  }
  public void login() throws XMPPException {
    connection.login(StringUtils.parseName(jid),password,resource);
    connection.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
    System.out.println("Logged In.");
  }

  @Override
  public void beforeInit(Message msg) {
    super.beforeInit(msg);
    jid = msg.getOption("jid",jid);
    password = msg.getOption("password",password);
    host = msg.getOption("host",StringUtils.parseServer(jid));
    port = Integer.parseInt(msg.getOption("port",Integer.toString(port)));
    resource = msg.getOption("resource",resource);
  }

  @AddinInterfaceMethodDefinition(
      userlevel = 0
  )
  public String test() {
    return "Just testing...";
  }
  @AddinInterfaceMethodDefinition(
      userlevel = 9
  )
  public void logAllPresences(GalenaArgsInterface args) {
    synchronized (presences) {
      for( String jid : presences.keySet() ) {
        logPresence(presences.get(jid));
        presences.remove(jid);
      }
    }
  }
  public Presence getPresenceOf(String user) {
    return connection.getRoster().getPresence(user);
  }
  public Roster getRoster() { return connection.getRoster(); }
 
 
  /**
   * Aggregates the statistics for all users in the roster.
   * @param args
   * @param jid
   */
  @AddinInterfaceMethodDefinition(
      userlevel = 9
  )
  public void aggregateAllStatisticsOfRoster(GalenaArgsInterface args) {
    Iterator i = getRoster().getEntries();
    while(i.hasNext()) {
      RosterEntry entry = (RosterEntry)i.next();
      System.out.println("Aggregating Statistics for user: " + entry.getUser());
      aggregateStatistics(args,entry.getUser());
    }
  }
  /**
   * Aggregates the statistics of a single user.
   * @param args
   * @param jid
   */
  @AddinInterfaceMethodDefinition(
      userlevel = 9
  )
  public void aggregateStatistics(GalenaArgsInterface args, String jid) {
    jid = jid.toLowerCase();
    DBConnection db = this.db.getDBConnection(true);
    // First check if user has an entry in the JID table.
    int jidID;
    {
      List<Map<String,Object>> jidentry = db.getListOfMaps("SELECT * FROM goim_stats_jid WHERE jid = ?",jid);
      if(jidentry != null && jidentry.size() > 0)
        jidID = (Integer)jidentry.get(0).get("id");
      else
        jidID = db.sendInsert(args.getUser(),"goim_stats_jid","jid",jid);
    }
    boolean dontlogthisday = false;
    // Now check when the last day entry was made.
    List<Map<String,Object>> listOfPresenceLog;
    {
      List<Map<String,Object>> lastDayEntry = db.getListOfMaps("SELECT * FROM goim_stats_day WHERE jid = ? ORDER BY day DESC LIMIT 1",jidID);
      if(lastDayEntry != null && lastDayEntry.size() > 0) {
        Date lastDay = (Date)lastDayEntry.get(0).get("day");
        Integer id = (Integer)lastDayEntry.get(0).get("id");
        Calendar cal = Calendar.getInstance();
        cal.setTime(lastDay);
        // We recalculate the last day ...
        db.sendDelete(args.getUser(),"goim_stats_game","day = ?",id);
        db.sendDelete(args.getUser(),"goim_stats_presencestatus","day = ?",id);
        db.sendDelete(args.getUser(),"goim_stats_day","id = ?",id);
        // To recalculate the last day we also need to recalculate
        // the day before so we get presences which started there and
        // lasted until this day.
        cal.add(Calendar.DAY_OF_MONTH,-1);
        listOfPresenceLog = db.getListOfMaps("SELECT * FROM goim_presence_log WHERE jid = ? AND start > ? ORDER BY start",jid,cal.getTime());
        dontlogthisday = true;
      } else {
        // No entry yet
        listOfPresenceLog = db.getListOfMaps("SELECT * FROM goim_presence_log WHERE jid = ? ORDER BY start",jid);
      }
    }
    Calendar currday = null; // The start of the current day.
    Calendar nextday = null; // The start of the next day (ie. the end of the current)
    HashMap<String,Long> gamesPlayed = new HashMap<String,Long>();
    HashMap<String,Long> presenceModes = new HashMap<String,Long>();
   
    HashMap<String,Long> nextGamesPlayed = new HashMap<String,Long>();
    HashMap<String,Long> nextPresenceModes = new HashMap<String,Long>();
    /// OK .. really BAD algorithm .. but it works ... somehow .. i guess/hope ?!
    for(Map<String,Object> logEntry : listOfPresenceLog) {
      Date start = (Date)logEntry.get("start");
      Date end = (Date)logEntry.get("end");
      String mode = (String)logEntry.get("mode");
      if(nextday == null) {
        nextday = Calendar.getInstance();
        currday = Calendar.getInstance();
        nextday.clear();
        Calendar startcal = Calendar.getInstance();
        startcal.setTime(start);
        nextday.set(Calendar.YEAR,startcal.get(Calendar.YEAR));
        nextday.set(Calendar.MONTH,startcal.get(Calendar.MONTH));
        nextday.set(Calendar.DAY_OF_MONTH,startcal.get(Calendar.DAY_OF_MONTH));
        currday = (Calendar)nextday.clone();
        nextday.add(Calendar.DAY_OF_MONTH,1);
      } else {
        if(start.after(nextday.getTime())) {
          System.out.println("Day: " + nextday.getTime().toString() + " .... " + start.toString());
          if(!dontlogthisday)
            logDay(args, jidID, currday, gamesPlayed, presenceModes);
          dontlogthisday = false;
         
          gamesPlayed = nextGamesPlayed;
          presenceModes = nextPresenceModes;
          nextGamesPlayed = new HashMap<String,Long>();
          nextPresenceModes = new HashMap<String,Long>();
          currday = (Calendar)nextday.clone();
          nextday.add(Calendar.DAY_OF_MONTH,1);
        }
      }
      if(start.after(nextday.getTime())) continue;
      long durationForNextDay = 0;
      long durationInMilliSeconds = end.getTime() - start.getTime();
      if(end.after(nextday.getTime())) {
        long tmpdur = nextday.getTime().getTime() - start.getTime();
        durationForNextDay = (durationInMilliSeconds - tmpdur);
        durationInMilliSeconds = tmpdur;
      }
     
      {
        Long d = presenceModes.get(mode);
        if(d == null) d = durationInMilliSeconds;
        else d = d + durationInMilliSeconds;
        presenceModes.put(mode,d);
       
        if(durationForNextDay > 0) {
          d = nextPresenceModes.get(mode);
          if(d == null) d = durationForNextDay;
          else d = d + durationForNextDay;
          nextPresenceModes.put(mode,d);
        }
      }
      List<Map<String,Object>> games = db.getListOfMaps("SELECT * FROM goim_server WHERE presence = ?",logEntry.get("id"));
      for(Map<String,Object> game : games) {
        String gameName = (String)game.get("game");
        Long d = gamesPlayed.get(gameName);
        if(d == null) d = durationInMilliSeconds;
        else d = d + durationInMilliSeconds;
        gamesPlayed.put(gameName,d);
       
        if(durationForNextDay > 0) {
          d = nextGamesPlayed.get(gameName);
          if(d == null) d = durationForNextDay;
          else d = d + durationForNextDay;
          nextGamesPlayed.put(gameName,d);
        }
      }
    }
    if(currday != null && !dontlogthisday)
      logDay(args, jidID, currday, gamesPlayed, presenceModes);
    db.close();
  }
  private void logDay(GalenaArgsInterface args, int jidID, Calendar currday, HashMap<String, Long> gamesPlayed, HashMap<String, Long> presenceModes) {
    // Log day ...
    int dayID = db.sendInsert(args.getUser(),"goim_stats_day","day,jid",/*start*/currday.getTime(),jidID);
    for(String presence : presenceModes.keySet()) {
      long durationMilli = presenceModes.get(presence);
      int durationMinute = (int)(durationMilli / 1000 / 60);
      db.sendInsert(args.getUser(),"goim_stats_presencestatus","day,duration,mode",dayID,durationMinute,presence);
      System.out.println("   Presence: " + presence + " duration: " + durationMinute);
    }
    for(String game : gamesPlayed.keySet()) {
      long durationMilli = gamesPlayed.get(game);
      int durationMinute = (int)(durationMilli / 1000 / 60);
      db.sendInsert(args.getUser(),"goim_stats_game","day,duration,game",dayID,durationMinute,game);
    }
  }
}
TOP

Related Classes of net.sphene.goim.stats.StatsCollectorBot

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.