This is an old revision of the document!
There are a clear tendency towards the use of social Web applications (eg. Twitter, Google Reader, Waze, Facebook, etc). The analysis of the flow of information in these applications is interesting nowadays. Whereas this analysis is commonly realized by dynamic graphs, an alternative way is the use of the vector clock algorithm1).
The analysis of popularity of user posts is a novel topic in Twitter 2). This analysis allows a user to know the popularity of every post published by him, which is measured by the number of republications that its followers did of a post (aka retweet in Twitter). For example, if a user has three followers (Kuky, Blanca, Toti) and publishes the post “There is a new version of OTM!” and Mike and Kuky republish this post, then the popularity of this post is two. Instead, if nobody republishes this post, the popularity of this news is zero.
The following Web page shows two instantiations of a toy social Web application 3). If a user writes his name, this user is able to publish posts and republish posts received of the other user because both users (of each application) follow each other. Every midnight, this Web application analysis the popularity of all different posts of a user. The measurement of the popularity of a post is the number of republications.
NOTE: AT THIS MOMENT, THE SERVER PRESENTS A BUG THAT DOES NOT PERMIT TO WORK APPROPRIATELY Toggle between the code and example
The popularity of a post is carried out by the following sequence:
var popularity = causalSeq(callPublish, repeatUntil(callRepublication, event("midnight")))
This sequence matches and counts all republications of a post until the midnight event happens. The republications that are considered must be caused by a received post, ie a user that republishes a post received. This sequence begins the matching process when the callPublish pointcut matches:
var callPublish = call(publish).and(function(jp, env){ return env.bind("id", jp.args[0]).bind("post", jp.args[1]).bind("counter", 0); });
This pointcut matches the call of the publish function and returns an environment that contains the id of the post, the post, and a counter initialized to zero. This counter is used to count the republications of the post. Whenever callPublish matches, the callRepublication pointcut should match to continue the matching of the sequence:
var callRepublication = function (jp, env){ return jp.isCustom("republication") && getPost(jp) == env.post ? env.bind("counter", env.counter + 1) : false; };
This pointcut matches an event of republication4) in which the post of republication is the same of the post of publication. If this pointcut matches, it returns an environment that contains the counter incremented by one. This pointcut matches republications until the midnight event happens, meaning that the sequence matches.
If a user commonly publishes several posts, it is necessary to have different sequences that matches, ie one sequence by every different post. For example, if the user publishes the post m1 twice and m2 once, we only need a sequence for m1 and a sequence for m2 to analyze the popularity of all posts of the user. To achieve this goal, it is necessary to spawn a sequence by every different post. OTM allows developers to customize the spawning semantics of a Trace-based Mechanism using a plain javascript function:
var newPosts = function(steps, index, env, jp){ var currentEnvs = //get e of current sequences return !currentEnvs.some(function(currentEnv){ return currentEnv.post == env.post; }); };
Finally, the definition and deployment of the tm that analyzes the popularity of posts is:
var tm = { kind: AFTER, seqExp: causalSeq(callPublish, repeatUntil(callRepublication, event("midnight"))), advice: function(jp, env){ addCounterToPublication(env.id, env.counter); }, spawn: newPosts }; deploy(tm);