package udacity.storm; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.StormSubmitter; import backtype.storm.spout.SpoutOutputCollector; import backtype.storm.task.OutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.testing.TestWordSpout; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.TopologyBuilder; import backtype.storm.topology.base.BaseRichSpout; import backtype.storm.topology.base.BaseRichBolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import backtype.storm.tuple.Values; import backtype.storm.utils.Utils; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import com.lambdaworks.redis.RedisClient; import com.lambdaworks.redis.RedisConnection; import udacity.storm.tools.*; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; /** * A bolt that prints the word and count to redis */ public class ReportBolt extends BaseRichBolt { // place holder to keep the connection to redis transient RedisConnection<String,String> redis; HashMap<String, Integer> URLCounter; HashMap<String, Double> sentimentURL; Rankings rankableList; @Override public void prepare( Map map, TopologyContext topologyContext, OutputCollector outputCollector) { // instantiate a redis connection RedisClient client = new RedisClient("localhost",6379); URLCounter = new HashMap<String, Integer>(); sentimentURL = new HashMap<String, Double>(); // initiate the actual connection redis = client.connect(); } public Integer getURLCount(String url_) { if(URLCounter.containsKey(url_)) { return URLCounter.get(url_); } else { return 1; } } public String getMostFrequentURL() { ValueComparator bvc = new ValueComparator(URLCounter); TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc); String result = ""; int MAX = 20; int counter = 0; for (String key : sorted_map.keySet()) { result = result + (key + "," + sorted_map.get(key)); counter++; if(counter > 20) break; } return result; //return "no tweet"; } public void observeURL(String url_) { if(URLCounter.containsKey(url_)) { URLCounter.put(url_, URLCounter.get(url_) + 1); } else { URLCounter.put(url_, 1); } } @Override public void execute(Tuple tuple) { String tweet = tuple.getStringByField("tweet"); String tweetWord = tuple.getStringByField("tweetWord"); String county_id = tuple.getStringByField("county_id"); String noun = tuple.getStringByField("noun"); String verb = tuple.getStringByField("verb"); String object = tuple.getStringByField("do"); String matchedEmoticon = tuple.getStringByField("matchedEmoticon"); String url = tuple.getStringByField("url"); double matchedEmoticonScore= tuple.getIntegerByField("matchedEmoticonScore")*1.0; double sentiment = tuple.getDoubleByField("sentiment"); System.out.println("\t\t\tDEBUG ReportBolt: " + String.valueOf(matchedEmoticonScore) + ", Tweet Sentiment:" + String.valueOf(sentiment) + "URL: " + getMostFrequentURL()); double alpha = 0.01; double URLSentiment = sentiment; if(sentimentURL.containsKey(url)) URLSentiment = (1-alpha)*sentimentURL.get(url) + alpha * Math.max(sentiment, matchedEmoticonScore/5); sentimentURL.put(url, URLSentiment); observeURL(url); redis.publish("WordCountTopology", county_id + "DELIMITER" + tweet + "DELIMITER" + String.valueOf(sentiment) + "DELIMITER" + getMostFrequentURL()); //redis.publish("WordCountTopology", county_id + "DELIMITER" + noun + " " + verb + " " + object + "DELIMITER" + String.valueOf(sentiment)); //String enrichedURL = tuple.getStringByField("word"); //System.out.print(tuple.toString() + "\n"); // publish the word count to redis using word as the key //redis.publish("WordCountTopology", word + ":" + Long.toString(count)); //redis.publish("WordCountTopology", tweets + "|" + Long.toString(count)); } public void declareOutputFields(OutputFieldsDeclarer declarer) { // nothing to add - since it is the final bolt } }