/*
This file is part of OpenMyEWB.
OpenMyEWB 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 3 of the License, or
(at your option) any later version.
OpenMyEWB 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 OpenMyEWB. If not, see <http://www.gnu.org/licenses/>.
OpenMyEWB is Copyright 2005-2009 Nicolas Kruchten (nicolas@kruchten.com), Francis Kung, Engineers Without Borders Canada, Michael Trauttmansdorff, Jon Fishbein, David Kadish
*/
package ca.myewb.frame.servlet;
import java.awt.BasicStroke;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TreeMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardPieItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.DataUtilities;
import org.jfree.data.DefaultKeyedValues;
import org.jfree.data.KeyedValues;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.MovingAverage;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.SortOrder;
import ca.myewb.frame.ErrorMessage;
import ca.myewb.frame.Helpers;
import ca.myewb.frame.HibernateUtil;
import ca.myewb.frame.Permissions;
import ca.myewb.frame.RedirectionException;
import ca.myewb.frame.SafeHibList;
import ca.myewb.model.DailyStatsModel;
import ca.myewb.model.GroupChapterModel;
import ca.myewb.model.GroupModel;
import ca.myewb.model.UserModel;
public class GraphServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
Logger log = Logger.getLogger(this.getClass());
try
{
Session s = HibernateUtil.currentSession();
HttpSession httpSession = req.getSession();
UserModel currentUser = WrapperServlet.getUser(Helpers.getDefaultURL(), log, s, httpSession);
String url = req.getRequestURI();
if (!currentUser.isMember(Helpers.getGroup("Exec")))
{
log.warn(currentUser.getUsername() + "tried to access GraphServlet!");
httpSession.setAttribute("message", new ErrorMessage("You can't access the graphs!"));
throw new RedirectionException(Helpers.getDefaultURL());
}
JFreeChart chart = null;
if (url.contains("genderpie"))
{
chart = getGenderPie(s);
}
else if (url.contains("languagepie"))
{
chart = getLanguagePie(s);
}
else if (url.contains("studentpie"))
{
chart = getStudentPie(s);
}
else if (url.contains("chapterrankpie"))
{
chart = getChapterRankPie(s, url);
}
else if (url.contains("rankpie"))
{
chart = getRankPie();
}
else if (url.contains("nochapterpie"))
{
chart = getNoChapterPie();
}
else if (url.contains("chapterpie"))
{
chart = getChapterPie(s);
}
else if (url.contains("postpie"))
{
chart = getPostPie(s);
}
else if (url.contains("post2pie"))
{
chart = getPost2Pie(s);
}
else if (url.contains("post3pie"))
{
chart = getPost3Pie(s);
}
else if (url.contains("provincepie"))
{
chart = getProvincePie(s);
}
else if (url.contains("lastlogin"))
{
chart = getLastLogin(s);
}
else if (url.contains("daily4stats"))
{
chart = getDailyStats(s);
}
else if (url.contains("daily2stats"))
{
chart = getDaily2Stats(s);
}
else if (url.contains("daily3stats"))
{
chart = getDaily3Stats(s);
}
else if (url.contains("dailyintegratedstats"))
{
chart = getDailyIntegratedStats(s);
}
else if (url.contains("logins"))
{
chart = getLogins(s);
}
else if (url.contains("dailynewstats"))
{
chart = getNewDailyStats(s);
}
else if (url.contains("birthyears"))
{
chart = getBirthyears(s);
}
else if (url.contains("listmemberships") || url.contains("chaptermemberships"))
{
chart = getListMemberships(s,
Integer.parseInt(url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.'))),
currentUser
);
}
res.setContentType("image/png");
OutputStream out = res.getOutputStream();
if (url.contains("listmemberships"))
{
ChartUtilities.writeChartAsPNG(out, chart, 700, 500);
}
else
{
ChartUtilities.writeChartAsPNG(out, chart, 800, 600);
}
}
catch (RedirectionException re)
{
log.info("Clean redirect: " + re.getTargetURL());
res.sendRedirect(re.getTargetURL());
}
catch (Exception e)
{
log.error("graph servlet error", e);
res.sendError(500, e.toString());
}
}
private static Date getStartDate()
{
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -14);
return cal.getTime();
}
private JFreeChart getDailyIntegratedStats(Session s) throws CloneNotSupportedException
{
JFreeChart chart;
List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
.setDate(0,new Date()).setDate(1, GraphServlet.getStartDate()))).list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeriesCollection theData2 = new TimeSeriesCollection();
TimeSeries users = new TimeSeries("Total Users",Day.class);
theData.addSeries(users);
TimeSeries regulars = new TimeSeries("Regular Members",Day.class);
theData2.addSeries(regulars);
int numUsers = Helpers.getGroup("Org").getNumMembers();
int numReg = Helpers.getGroup("Regular").getNumMembers();
for (DailyStatsModel ds : stats)
{
Day theDay = new Day(ds.getDay());
users.add(theDay, numUsers);
regulars.add(theDay, numReg);
numUsers -= (ds.getMailinglistsignups() + ds.getSignups() - ds.getDeletions());
numReg -= (ds.getRegupgrades() - ds.getRegdowngrades());
}
chart = ChartFactory.createTimeSeriesChart("Membership",
"Day", "Users",
theData, true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
NumberAxis axis2=new NumberAxis("Regular Members");
plot.setRangeAxis(1,axis2);
plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
plot.setDataset(1, MovingAverage.createMovingAverage(theData2, "", 14, 0));
plot.mapDatasetToRangeAxis(1,1);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer(0);
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer = (XYLineAndShapeRenderer) renderer.clone();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
plot.setRenderer(1, renderer);
return chart;
}
private JFreeChart getBirthyears(Session s)
{
JFreeChart chart;
XYSeriesCollection seriesCollection = new XYSeriesCollection();
List logins = s.createQuery("select count(*), birth from UserModel where birth!=0 group by birth order by birth").list();
XYSeries theData = new XYSeries("Ages");
seriesCollection.addSeries(theData);
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
theData.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer)tuple[1], (Long)tuple[0]);
}
logins = s.createQuery("select count(*), birth from UserModel where birth!=0 and gender='f' group by birth order by birth").list();
XYSeries theData2 = new XYSeries("Female");
seriesCollection.addSeries(theData2);
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
theData2.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer)tuple[1], (Long)tuple[0]);
}
logins = s.createQuery("select count(*), birth from UserModel where birth!=0 and gender='m' group by birth order by birth").list();
XYSeries theData3 = new XYSeries("Male");
seriesCollection.addSeries(theData3);
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
theData3.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer)tuple[1], (Long)tuple[0]);
}
chart = ChartFactory.createXYLineChart("Age Distribution",
"Age", "Number of Users",
seriesCollection,
PlotOrientation.VERTICAL,
true, true, true);
XYPlot plot = (XYPlot)chart.getPlot();
plot.getDomainAxis().setUpperBound(80);
plot.getDomainAxis().setLowerBound(15);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getLogins(Session s)
{
JFreeChart chart;
XYSeriesCollection seriesCollection = new XYSeriesCollection();
XYSeries theData = new XYSeries("Logins");
seriesCollection.addSeries(theData);
List logins = s.createQuery("select count(*), logins from UserModel where logins!=0 and logins<=100 group by logins order by logins desc").list();
Integer numLogins = ((Long)s.createQuery("select count(*) from UserModel where logins>100").uniqueResult()).intValue();
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
numLogins += ((Long)tuple[0]).intValue();
theData.add((Integer)tuple[1], numLogins);
}
XYSeries theData3 = new XYSeries("Female");
seriesCollection.addSeries(theData3);
logins = s.createQuery("select count(*), logins from UserModel where gender='f' and logins!=0 and logins<=100 group by logins order by logins desc").list();
numLogins = ((Long)s.createQuery("select count(*) from UserModel where gender='f' and logins>100").uniqueResult()).intValue();
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
numLogins += ((Long)tuple[0]).intValue();
theData3.add((Integer)tuple[1], numLogins);
}
XYSeries theData2 = new XYSeries("Male");
seriesCollection.addSeries(theData2);
logins = s.createQuery("select count(*), logins from UserModel where gender='m' and logins!=0 and logins<=100 group by logins order by logins desc").list();
numLogins = ((Long)s.createQuery("select count(*) from UserModel where gender='m' and logins>100").uniqueResult()).intValue();
for(int i=0; i<logins.size(); i++)
{
Object[] tuple = (Object[])logins.get(i);
numLogins += ((Long)tuple[0]).intValue();
theData2.add((Integer)tuple[1], numLogins);
}
chart = ChartFactory.createXYLineChart("Logins Distribution",
"Number of Logins", "Number of Users",
seriesCollection,
PlotOrientation.VERTICAL,
true, true, true);
XYPlot plot = (XYPlot)chart.getPlot();
plot.getDomainAxis().setUpperBound(100);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getLastLogin(Session s) throws CloneNotSupportedException
{
Integer numCurrentLogins = ((Long)s.createQuery("select count(*) from UserModel " +
"where currentLogin is not null and currentLogin >= :date")
.setDate("date", getStartDate())
.uniqueResult()).intValue();
List currentStats = s.createSQLQuery("SELECT DATE(currentLogin) as date, count( * ) as lastLogins " +
"FROM users where currentLogin is not null and currentLogin >= :date " +
"GROUP BY DATE( currentLogin )")
.addScalar("date", Hibernate.DATE)
.addScalar("lastLogins", Hibernate.INTEGER)
.setDate("date", getStartDate())
.list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeriesCollection theData2 = new TimeSeriesCollection();
TimeSeries current = new TimeSeries("Num Latest Sign-ins",Day.class);
theData.addSeries(current);
TimeSeries current2 = new TimeSeries("Signed-in Users Since",Day.class);
theData2.addSeries(current2);
for (Object ds : currentStats)
{
Date date = (Date) ((Object[])ds)[0];
Day day = new Day(date);
Integer integer = (Integer)((Object[])ds)[1];
current.add(day, integer);
numCurrentLogins -= integer.intValue();
current2.add(day, numCurrentLogins);
}
JFreeChart chart = ChartFactory.createTimeSeriesChart("Sign-in Recency",
"Day", "Sign-ins",
theData,
true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
NumberAxis axis2=new NumberAxis("Users");
plot.setRangeAxis(1,axis2);
plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
plot.setDataset(1, theData2);
plot.mapDatasetToRangeAxis(1,1);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer(0);
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
renderer = (XYLineAndShapeRenderer) renderer.clone();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
plot.setRenderer(1, renderer);
return chart;
}
private JFreeChart getDaily3Stats(Session s)
{
JFreeChart chart;
List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
.setDate(0,new Date()).setDate(1, GraphServlet.getStartDate()))).list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeries regUpgrades = new TimeSeries("Regular Upgrades",Day.class);
theData.addSeries(regUpgrades);
TimeSeries renewals = new TimeSeries("Regular Renewals",Day.class);
theData.addSeries(renewals);
TimeSeries regDowngrades = new TimeSeries("Regular Downgrades",Day.class);
theData.addSeries(regDowngrades);
for (DailyStatsModel ds : stats)
{
Day theDay = new Day(ds.getDay());
regUpgrades.add(theDay, ds.getRegupgrades());
renewals.add(theDay, ds.getRenewals());
regDowngrades.add(theDay, ds.getRegdowngrades());
}
chart = ChartFactory.createTimeSeriesChart("Regular membership changes (14-day moving avg)",
"Day", "Occurrences",
MovingAverage.createMovingAverage(theData, "", 14, 0) , true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
plot.getRangeAxis().setUpperBound(10);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot
.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
renderer.setSeriesStroke(2, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getDaily2Stats(Session s)
{
JFreeChart chart;
List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
.setDate(0,new Date()).setDate(1, GraphServlet.getStartDate()))).list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeries signups = new TimeSeries("signups", Day.class);
theData.addSeries(signups);
TimeSeries mlSignups = new TimeSeries("Mailing list signups", Day.class);
theData.addSeries(mlSignups);
TimeSeries mlUpgrades = new TimeSeries("Mailing list upgrades", Day.class);
theData.addSeries(mlUpgrades);
TimeSeries deletions = new TimeSeries("Deletions", Day.class);
theData.addSeries(deletions);
for (DailyStatsModel ds : stats)
{
Day theDay = new Day(ds.getDay());
signups.add(theDay, ds.getSignups());
deletions.add(theDay, ds.getDeletions());
mlSignups.add(theDay, ds.getMailinglistsignups());
mlUpgrades.add(theDay, ds.getMailinglistupgrades());
}
chart = ChartFactory.createTimeSeriesChart("Account changes (14-day moving avg)",
"Day", "Occurrences",
MovingAverage.createMovingAverage(theData, "", 14, 0), true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
plot.getRangeAxis().setUpperBound(25);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot
.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
renderer.setSeriesStroke(2, new BasicStroke(2.0f));
renderer.setSeriesStroke(3, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getDailyStats(Session s)
{
JFreeChart chart;
List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
.setDate(0,new Date()).setDate(1, GraphServlet.getStartDate()))).list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeries signins = new TimeSeries("Raw Signins", Day.class);
TimeSeries posts = new TimeSeries("Posts", Day.class);
TimeSeries replies = new TimeSeries("Replies", Day.class);
TimeSeries whiteboards = new TimeSeries("Whiteboards", Day.class);
TimeSeries files = new TimeSeries("Files", Day.class);
for (DailyStatsModel ds : stats)
{
Day theDay = new Day(ds.getDay());
signins.add(theDay, ds.getSignins());
posts.add(theDay, ds.getPosts());
replies.add(theDay, ds.getReplies());
whiteboards.add(theDay, ds.getWhiteboardEdits());
files.add(theDay, ds.getFilesadded());
}
String title = "Usage (14-day moving avg)";
theData.addSeries(MovingAverage.createMovingAverage(signins, "Signins", 14, 0));
theData.addSeries(MovingAverage.createMovingAverage(posts, "Posts", 14, 0));
theData.addSeries(MovingAverage.createMovingAverage(replies, "Replies", 14, 0));
theData.addSeries(signins);
theData.addSeries(MovingAverage.createMovingAverage(whiteboards, "Whiteboard Edits", 14, 0));
theData.addSeries(MovingAverage.createMovingAverage(files, "Files Uploaded", 14, 0));
chart = ChartFactory.createTimeSeriesChart(title,
"Day", "Occurrences",
theData, true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
plot.getRangeAxis().setUpperBound(400);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
renderer.setSeriesStroke(2, new BasicStroke(2.0f));
renderer.setSeriesStroke(3, new BasicStroke(2.0f));
renderer.setSeriesStroke(4, new BasicStroke(2.0f));
renderer.setSeriesStroke(5, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getNewDailyStats(Session s)
{
JFreeChart chart;
List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
.setDate(0,new Date()).setDate(1, GraphServlet.getStartDate()))).list();
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeries events = new TimeSeries("Events Created", Day.class);
TimeSeries mailings = new TimeSeries("Event Mailings", Day.class);
for (DailyStatsModel ds : stats)
{
Day theDay = new Day(ds.getDay());
events.add(theDay, ds.getEvents());
mailings.add(theDay, ds.getEventMailings());
}
String title = "Usage";
theData.addSeries(MovingAverage.createMovingAverage(events, "Events Created", 14, 0));
theData.addSeries(MovingAverage.createMovingAverage(mailings, "Event Mailings", 14, 0));
chart = ChartFactory.createTimeSeriesChart(title,
"Day", "Occurrences",
theData, true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
return chart;
}
private JFreeChart getProvincePie(Session s)
{
JFreeChart chart;
String[] provinces =
{
"PE", "YT", "NT", "NU", "ON",
"QC", "AB", "BC", "NL", "MB", "NB", "NS",
"SK"
};
DefaultPieDataset ds = new DefaultPieDataset();
String query = "select count(*) from UserModel as u where u.province=?";
int total = 0;
for (String province : provinces)
{
Integer integer = ((Long)s.createQuery(query)
.setString(0, province)
.list().get(0)).intValue();
total += integer;
ds.setValue(province,
integer);
}
chart = ChartFactory.createPieChart("Province Breakdown (for " + total + " known addresses)",
ds, false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getPostPie(Session s)
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
int numPosts = 0;
int numTypePosts = 0;
String query;
query = "select count(*) from PostModel as p where p.poster.gender='m' and p.emailed=true and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Emails by Males", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender='m' and " +
"p.parent is null and p.emailed=false and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Posts by Males", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender='m' and " +
"p.parent is not null and p.emailed=false and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Replies by Males", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender!='f' and p.poster.gender!='m' and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("All Posts by Unknown Gender", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender='f' and " +
"p.parent is not null and p.emailed=false and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Replies by Females", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender='f' and " +
"p.parent is null and p.emailed=false and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Posts by Females", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.poster.gender='f' and p.emailed=true and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();;
ds.setValue("Emails by Females", numTypePosts);
numPosts += numTypePosts;
chart = ChartFactory.createPieChart("Post Type/Author Gender Breakdown (for "
+ numPosts
+ " posts)", ds,
false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getPost2Pie(Session s)
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
int numPosts = 0;
int numTypePosts = 0;
String query = "select count(*) from PostModel as p where p.group.id=1 and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Org List", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.admin=false and p.group.postName not like 'anyone in the%' and " +
"p.group.public=true and p.group.parent is null and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("General Public Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.admin=false and " +
"p.group.public=false and p.group.parent is null and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("General Private Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.admin=true and p.group.visible=true" +
" and p.group.id != 1 and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("All-exec Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.id = 14 and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Deleted Posts", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.postName like 'anyone in the%' and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Chapter Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.parent!=null and " +
"p.group.shortname='exec' and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Chapter-exec Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.parent!=null and " +
"p.group.shortname!='exec' and p.group.public=true and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Chapter Public Lists", numTypePosts);
numPosts += numTypePosts;
query = "select count(*) from PostModel as p where p.group.parent!=null and " +
"p.group.shortname!='exec' and p.group.public=false and p.date>?";
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.list().get(0)).intValue();
ds.setValue("Chapter Private Lists", numTypePosts);
numPosts += numTypePosts;
chart = ChartFactory.createPieChart("Post Group Breakdown (for "
+ numPosts
+ " posts)", ds,
false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getPost3Pie(Session s)
{
DefaultKeyedValues data = new DefaultKeyedValues();
int numPosts = 0;
int numTypePosts = 0;
String query = "select count(*) from PostModel as p where p.date > ? and " +
"(p.group=? or p.group.parent=?)";
for (GroupChapterModel chapter: GroupChapterModel.getChapters())
{
numTypePosts = ((Long)s.createQuery(query).setDate(0, GraphServlet.getStartDate())
.setEntity(1, chapter).setEntity(2, chapter).list().get(0)).intValue();
numPosts += numTypePosts;
data.addValue(chapter.getShortname(), numTypePosts);
}
return getChapterPareto(data,
"Posts by Chapter (for "+ numPosts + " posts)",
"Posts", "Number of Posts");
}
private JFreeChart getChapterPie(Session s)
{
DefaultKeyedValues data = new DefaultKeyedValues();
for (GroupChapterModel chapter: GroupChapterModel.getChapters())
{
data.addValue(chapter.getShortname(), chapter.getNumMembers());
}
return getChapterPareto(data,
"Chapter Membership Breakdown By Chapter",
"Membership", "Number of Members");
}
private JFreeChart getChapterPareto(DefaultKeyedValues data, String title, String quantity, String range)
{
JFreeChart chart;
data.sortByValues(SortOrder.DESCENDING);
KeyedValues cummulative = DataUtilities.getCumulativePercentages(data);
CategoryDataset dataset = DatasetUtilities.createCategoryDataset(quantity, data);
// create the chart...
chart = ChartFactory.createBarChart(
title, // chart title
"Chapter", // domain axis label
range, // range axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true,
false
);
CategoryPlot plot = chart.getCategoryPlot();
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setLowerMargin(0.02);
domainAxis.setUpperMargin(0.02);
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
// set the range axis to display integers only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();
CategoryDataset dataset2 = DatasetUtilities.createCategoryDataset("Cummulative", cummulative);
NumberAxis axis2 = new NumberAxis("Percent");
axis2.setNumberFormatOverride(NumberFormat.getPercentInstance());
axis2.setUpperBound(1);
axis2.setLowerBound(0);
plot.setRangeAxis(1, axis2);
plot.setDataset(1, dataset2);
plot.setRenderer(1, renderer2);
plot.mapDatasetToRangeAxis(1, 1);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
return chart;
}
private JFreeChart getNoChapterPie()
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
Integer numChapter = Helpers.getGroup("Chapter").getNumMembers();
ds.setValue("in a chapter", numChapter);
ds.setValue("not in a chapter",
Helpers.getGroup("Org").getNumMembers() - numChapter);
chart = ChartFactory.createPieChart("Chapter Membership Breakdown",
ds, false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getRankPie()
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
int numRegular = Helpers.getGroup("Regular").getNumMembers();
int numAssociate = Helpers.getGroup("Associate").getNumMembers();
int numUsers = Helpers.getGroup("Org").getNumMembers();
ds.setValue("Regular Members", numRegular);
ds.setValue("Associate Members", numAssociate);
ds.setValue("Mailing list Members", numUsers - numAssociate - numRegular);
chart = ChartFactory.createPieChart("Status breakdown for " + numUsers + " members", ds,
false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getChapterRankPie(Session s, String url)
{
String[] path = url.split("/");
String lastPiece = path[path.length -1];
Integer chapterId = new Integer(lastPiece.substring(0, lastPiece.length()-4));
GroupChapterModel chapter = (GroupChapterModel) s.get(GroupChapterModel.class, chapterId);
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
String query = "select count(*) as num from roles r1, roles r2 " +
"where r1.userid=r2.userid and r1.groupid=? and r1.level='m' and r2.level='m' " +
"and r1.end is null and r2.end is null and r2.groupid=?";
int numRegular = ((Integer)s.createSQLQuery(query)
.addScalar("num", Hibernate.INTEGER)
.setInteger(0, chapter.getId())
.setInteger(1, Helpers.getGroup("Regular").getId())
.list().get(0)).intValue();
int numAssociate = ((Integer)s.createSQLQuery(query)
.addScalar("num", Hibernate.INTEGER)
.setInteger(0, chapter.getId())
.setInteger(1, Helpers.getGroup("Associate").getId())
.list().get(0)).intValue();
int numUsers = chapter.getNumMembers();
ds.setValue("Regular Members", numRegular);
ds.setValue("Associate Members", numAssociate);
ds.setValue("Mailing list Members", numUsers - numAssociate - numRegular);
chart = ChartFactory.createPieChart("Status breakdown for " + numUsers + " chapter members", ds,
false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getStudentPie(Session s)
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
String query = "select count(*) from UserModel as u where u.student='y'";
int numStudent = ((Long)s.createQuery(query).list().get(0)).intValue();
query = "select count(*) from UserModel as u where u.student='n'";
int numNonStudent = ((Long)s.createQuery(query).list().get(0)).intValue();
int numRegular = Helpers.getGroup("Regular").getNumMembers();
int numAssociate = Helpers.getGroup("Associate").getNumMembers();
ds.setValue("Student users", numStudent);
ds.setValue("Unspecified", numAssociate + numRegular - numStudent - numNonStudent);
ds.setValue("Non-Student users", numNonStudent);
chart = ChartFactory.createPieChart("Student Status Breakdown for Associate/Regular members",
ds, false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getLanguagePie(Session s)
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
String query = "select count(*) from UserModel as u where u.language='en'";
int numEn = ((Long)s.createQuery(query).list().get(0)).intValue();
query = "select count(*) from UserModel as u where u.language='fr'";
int numFr = ((Long)s.createQuery(query).list().get(0)).intValue();
int numRegular = Helpers.getGroup("Regular").getNumMembers();
int numAssociate = Helpers.getGroup("Associate").getNumMembers();
ds.setValue("English", numEn);
ds.setValue("Unspecified", numAssociate + numRegular - numEn - numFr);
ds.setValue("French", numFr);
chart = ChartFactory.createPieChart("Preferred Language Breakdown for Associate/Regular members",
ds, false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getGenderPie(Session s)
{
JFreeChart chart;
DefaultPieDataset ds = new DefaultPieDataset();
String query = "select count(*) from UserModel as u where u.gender='f'";
int numFemale = ((Long)s.createQuery(query).list().get(0)).intValue();
query = "select count(*) from UserModel as u where u.gender='m'";
int numMale = ((Long)s.createQuery(query).list().get(0)).intValue();
int numRegular = Helpers.getGroup("Regular").getNumMembers();
int numAssociate = Helpers.getGroup("Associate").getNumMembers();
ds.setValue("Female users", numFemale);
ds.setValue("Unspecified", numAssociate + numRegular - numFemale - numMale);
ds.setValue("Male users", numMale);
chart = ChartFactory.createPieChart("Gender Breakdown for Associate/Regular members", ds,
false, false, false);
PiePlot plot = ((PiePlot)chart.getPlot());
StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
new DecimalFormat("0"),
new DecimalFormat("0.0%"));
plot.setLabelGenerator(n);
return chart;
}
private JFreeChart getListMemberships(Session s, int groupId, UserModel currentUser)
{
final int NUM_MONTHS = 6;
Logger log = Logger.getLogger(this.getClass());
JFreeChart chart;
Date startDate;
TreeMap<Day, Integer> memberChange = new TreeMap<Day, Integer>();
GroupModel g = (GroupModel)s.get(GroupModel.class, groupId);
if (g == null)
{
log.warn("Someone requested chapter stats with a bad group id");
}
else if (!Permissions.canAdministerGroupMembership(currentUser, g))
{
log.warn(currentUser.getUsername() + "tried to access list memberships graph!");
}
Calendar cal = GregorianCalendar.getInstance();
Date now = cal.getTime();
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.add(Calendar.MONTH, -NUM_MONTHS);
startDate = cal.getTime();
//Set Initial Number of Members
int initMembers = g.getNumMembers() + g.getNumRecipients();
//Pull a list of all of the membership start dates
List starts = s.createQuery("SELECT rm.start, count(*) " +
"FROM RoleModel as rm " +
"WHERE rm.group = :group " +
"AND (rm.level = 'r' OR rm.level = 'm') " +
"AND rm.start > :startDate " +
"GROUP BY rm.start "
).setEntity("group", g).setDate("startDate", startDate).list();
for( Object o : starts )
{
Day date = new Day((Date)(((Object[])o)[0]));
int change = ((Long)(((Object[])o)[1])).intValue();
memberChange.put(date, change);
initMembers -= change;
}
//Pull a list of all of the membership end dates
List ends = s.createQuery("SELECT rm.end, count(*) " +
"FROM RoleModel as rm " +
"WHERE rm.group = :group " +
"AND (rm.level = 'r' OR rm.level = 'm') " +
"AND rm.end > :startDate " +
"GROUP BY rm.end "
).setEntity("group", g).setDate("startDate", startDate).list();
for( Object o : ends )
{
Day date = new Day((Date)(((Object[])o)[0]));
int change = ((Long)(((Object[])o)[1])).intValue();
if( memberChange.containsKey(date) )
{
memberChange.put(date,
memberChange.get(date)-change);
}
else
{
memberChange.put(date, -change);
}
initMembers += change;
}
TimeSeriesCollection theData = new TimeSeriesCollection();
TimeSeries signups = new TimeSeries("List Membership", Day.class);
theData.addSeries(signups);
while( startDate.before(now))
{
Day d = new Day(startDate);
if(memberChange.containsKey(d))
{
initMembers += memberChange.get(d);
}
signups.add(d, initMembers);
cal.add(Calendar.DATE, 1);
startDate = cal.getTime();
}
chart = ChartFactory.createTimeSeriesChart("List Members",
"Day", "Number of Members", theData, true, true,
true);
XYPlot plot = (XYPlot)chart.getPlot();
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
return chart;
}
}