package neeleval;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.FileUtils;

public class Main {
    
    private int no_tweets = 0;
    private int no_pairs = 0;
    
    private int no_correct = 0;
    private int no_found = 0;
    
    HashMap<String, List<Pair>> readSet(String filename) throws Exception 
    {
        HashMap<String, List<Pair>> result = new HashMap<String, List<Pair>>();
        List<String> lines = FileUtils.readLines(new File(filename), "utf8");
        
        for (String line : lines) {
            String[] tokens = line.split("\t");
        
            if ( (tokens.length -1) % 2  == 1 ) throw new Exception("Malformed File " + filename);
                
            String tweetid = tokens[0];
            ArrayList<Pair> pairs = new ArrayList<Pair>();
            for (int i=1; i<tokens.length; i++) {
                Pair p = new Pair(tokens[i], tokens[i+1]);
                i++;
                pairs.add(p);
            }
            result.put(tweetid, pairs);
        }
            
        return result;
    }

    void eval(Map<String, List<Pair>> gs, Map<String, List<Pair>> ts) 
    {
        no_tweets = gs.size();

        for(Entry<String,List<Pair>> e : gs.entrySet() ) 
        {
            String gs_tweetid = e.getKey();
            List<Pair> gs_pairs = e.getValue(); 
            
            no_pairs += gs_pairs.size();
            
            if ( ts.containsKey(gs_tweetid) )
            {
                List<Pair> ts_pairs = ts.get(gs_tweetid);
                no_found += ts_pairs.size();
                
                // preserve the order
                for (int i = 0; i < gs_pairs.size() && i < ts_pairs.size(); i++) 
                    no_correct += gs_pairs.get(i).compareTo(ts_pairs.get(i));    
            }
        }
    }
    
    double precision () {
        return no_correct / (1.0 * no_found);
    }
    
    double recall () {
        return no_correct / (1.0 * no_pairs);
    }
    
    double F1 () {
        return (2 * precision() * recall() )/ (1.0 * (precision() + recall()) );
    }
    
    void print() 
    {
        System.out.printf("processed %d tweets with %d pairs; "+
                          "found: %d; correct: %d.\n", no_tweets, no_pairs, no_found, no_correct);
        System.out.printf("precision:  %.3f; recal: %.3f; F1:  %.3f\n", precision(), recall(), F1());
    }
    
    public static void main(String[] args) 
    {
        Main main = new Main();

        try {
            if(args.length < 2)
                throw new Exception("Missing inputs");
            
            // read gold set and test set
            Map<String, List<Pair>> gs = main.readSet (args[0]);        
            Map<String, List<Pair>> ts = main.readSet (args[1]);
                
            main.eval(gs,ts);
            main.print();            
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

@@ -12,16 +12,57 @@
 leval;%0A%0A
+import org.apache.commons.io.FileUtils;%0A%0A
 import j
@@ -206,49 +206,8 @@
 y;%0A%0A
-import org.apache.commons.io.FileUtils;%0A%0A
 publ
@@ -1691,32 +1691,91 @@
                 
+no_correct += longestCommonSubsequence(gs_pairs, ts_pairs);
 %0A               
@@ -1775,70 +1775,116 @@
     
+%7D%0A
     
-// preserve the order
+    %7D
 %0A    
+%7D%0A%0A
     
-        for (int i = 0; i %3C 
+int longestCommonSubsequence(List%3CPair%3E gs_pairs, List%3CPair%3E ts_pairs) %7B%0A        if (
 gs_p
@@ -1899,14 +1899,15 @@
 e() 
-&& i %3C
+== 0 %7C%7C
  ts_
@@ -1918,23 +1918,22 @@
 s.size()
-; i++) 
+ == 0)
 %0A       
@@ -1937,38 +1937,38 @@
         
-        no_correct += 
+return 0;%0A        if (
 gs_pairs
@@ -1972,17 +1972,17 @@
 irs.get(
-i
+0
 ).compar
@@ -2002,51 +2002,364 @@
 get(
-i
+0)) == 1)%0A            return 1 + longestCommonSubsequence(gs_pairs.subList(1, gs_pairs.size()), ts_pairs.subList(1, ts_pairs.size()
 ));
+%0A
     
-%0A            %7D%0A        %7D%0A    %7D
+    return Math.max(%0A                longestCommonSubsequence(gs_pairs, ts_pairs.subList(1, ts_pairs.size())),%0A                longestCommonSubsequence(gs_pairs.subList(1, gs_pairs.size()), ts_pairs)%0A        );
 %0A    
+%7D%0A
 %0A   

use Longest Common Subsequence for instance evaluation