require 'dbi'
require 'scruffy'
require 'socket'
# HTML Formatting - Note: keep the header for XHTML/SVG support.
htmlHeader = <<-'EOS'
EOS
begin
dbh = DBI.connect("DBI:Mysql:webarchive:localhost", "root", "password")
row = dbh.select_one("SELECT VERSION()")
puts "Server version: " + row[0]
# Open connection on port 9090
server = TCPServer.new(9090)
while true
Thread.start(server.accept) do |session|
#p "#{session} spawned - processing request\n"
request = session.gets
# filter all non '/term1/term2' requests (otherwise crash on /favicon.ico)
if not request.chomp.split[1].to_s =~ /^(\/(.*)\/(.*))/
p "#{Time.now.strftime('[Request at %I:%M:%S]')} Malformed request: #{request}"
session.close
next
end
session.print "HTTP/1.1 200/OK\rContent-type: application/xhtml+xml\r\n\r\n"
session.print htmlHeader
## Log request to console...
terms = request.split[1].split("/")[1,2]
p "#{Time.now.strftime('[Request at %I:%M:%S]')} #{terms.join(' ')}"
newsSources = dbh.select_all("select id, resource from types")
sourceID = newsSources.collect { |r| r[0] }
dates = ['2004 9', '2004 10', '2004 11', '2004 12', '2005 1', '2005 2', '2005 3', '2005 4', '2005 5' ]
results, aggregate = [], []
terms.each { |q|
sourceID.each { |s|
query = "select count(*) as occurence, DATE_FORMAT(date, '%Y %c') as date
from news where type = #{s} and (headline like '%#{q}%' or story like '%#{q}%')
group by DATE_FORMAT(date, '%c,%y') order by DATE_FORMAT(date, '%Y %c')"
result = dbh.select_all(query)
map = [0, 0, 0, 0, 0, 0, 0, 0, 0]
result.each { |r| map[dates.index(r[1])] = r[0] }
results.push(map)
}
# Count-all query (area chart)
query = "select count(*) as occurence, DATE_FORMAT(date, '%Y %c') as date
from news where (headline like '%#{q}%' or story like '%#{q}%')
group by DATE_FORMAT(date, '%c,%y') order by DATE_FORMAT(date, '%Y %c')"
result = dbh.select_all(query)
map = [0, 0, 0, 0, 0, 0, 0, 0, 0]
result.each { |r| map[dates.index(r[1])] = r[0] }
results.push(map)
}
# Count-all query (area chart)
query = "select count(*) as occurence, DATE_FORMAT(date, '%Y %c') as date
from news where (headline like '%#{terms[1]}%#{terms[0]}%' or headline like '%#{terms[0]}%#{terms[1]}%' or story like '%#{terms[0]}%#{terms[1]}%' or story like '%#{terms[1]}%#{terms[0]}%')
group by DATE_FORMAT(date, '%c,%y') order by DATE_FORMAT(date, '%Y %c')"
result = dbh.select_all(query)
map = [0, 0, 0, 0, 0, 0, 0, 0, 0]
result.each { |r| map[dates.index(r[1])] = r[0] }
aggregate.push(map)
# AND NOT
query = "select count(*) as occurence, DATE_FORMAT(date, '%Y %c') as date
from news where (headline like '%#{terms[0]}%' or story like '%#{terms[0]}%') and not (headline like '%#{terms[1]}%' or story like '%#{terms[1]}%')
group by DATE_FORMAT(date, '%c,%y') order by DATE_FORMAT(date, '%Y %c')"
result = dbh.select_all(query)
map = [0, 0, 0, 0, 0, 0, 0, 0, 0]
result.each { |r| map[dates.index(r[1])] = r[0] }
aggregate.push(map)
query = "select count(*) as occurence, DATE_FORMAT(date, '%Y %c') as date
from news where (headline like '%#{terms[1]}%' or story like '%#{terms[1]}%') and not (headline like '%#{terms[0]}%' or story like '%#{terms[0]}%')
group by DATE_FORMAT(date, '%c,%y') order by DATE_FORMAT(date, '%Y %c')"
result = dbh.select_all(query)
map = [0, 0, 0, 0, 0, 0, 0, 0, 0]
result.each { |r| map[dates.index(r[1])] = r[0] }
aggregate.push(map)
# Build overall comparison graph
graph = Scruffy::Graph.new(:theme => Scruffy::Themes::Keynote.new)
graph.value_formatter = Scruffy::Formatters::Number.new(:precision => 0)
graph.title = "#{terms[0].capitalize} vs #{terms[1].capitalize}"
graph.renderer = Scruffy::Renderers::Split.new(:split_label => "#{terms[0].capitalize} (Top) / #{terms[1].capitalize} (Bottom)")
graph.point_markers = ['Sept', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May']
graph.add :area, "#{terms[0].capitalize}", results[3], :category => :top
graph.add :area, "#{terms[1].capitalize}", results[7], :category => :bottom
results.each { |e|
tableName = newsSources[results.index(e)%3][1].chomp('_news')
graph.add :line, tableName, e, :category => :top if results.index(e) < 3
graph.add :line, tableName, e, :category => :bottom if results.index(e) > 3 and results.index(e) < 7
}
# chop off the XML declarations from XML generated by scruffy and send back to client
svg = graph.render(:width => 800).split("\n")
session.print svg[2, svg.size].join("\n")
# Build cubed graph with specific stats
graph = Scruffy::Graph.new
graph.title = "Drill down"
graph.renderer = Scruffy::Renderers::Cubed.new
graph.point_markers = ['Sept', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May']
graph.add :bar, "#{terms[0].capitalize}", results[3], :categories => [:top_left]
graph.add :bar, "#{terms[1].capitalize}", results[7], :categories => [:bottom_left]
graph.add :line, "#{terms[0].capitalize} AND #{terms[1].capitalize}", aggregate[0], :categories => [:top_right]
graph.add :line, "#{terms[0].capitalize} NOT #{terms[1].capitalize}", aggregate[1], :categories => [:bottom_right]
graph.add :line, "#{terms[1].capitalize} NOT #{terms[0].capitalize}", aggregate[2], :categories => [:bottom_right]
# chop off the XML declarations from XML generated by scruffy and send back to client
svg = graph.render(:width => 800).split("\n")
session.print svg[2, svg.size].join("\n")
session.print ""
session.print ""
session.close
end
end
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
ensure
dbh.disconnect if dbh
end