package edu.stanford.nlp.sempre.interactive;
import java.io.File;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import com.google.common.base.Strings;
import edu.stanford.nlp.sempre.Derivation;
import edu.stanford.nlp.sempre.Example;
import edu.stanford.nlp.sempre.Json;
import edu.stanford.nlp.sempre.Rule;
import fig.basic.IOUtils;
import fig.basic.LogInfo;
/**
* Tracks rule usage via a citation system. A rule is cited when a user makes
* use of that rule in a derivation.
*
* @author sidaw
*/
public class CitationTracker {
public static final String IDPrefix = "id:";
public static final String HeadPrefix = "head:";
public static final String BodyPrefix = "body:";
String uid = "undefined";
Example ex;
public CitationTracker(String uid, Example ex) {
this.uid = uid;
this.ex = ex;
}
public synchronized void citeRule(Rule rule) {
writeLog(rule);
writeSummary(rule);
}
// The summary is ONE SINGLE line of json, has cite, self, and head
private synchronized void writeSummary(Rule rule) {
String author = getAuthor(rule);
String summaryPath = Paths.get(InteractiveUtils.opts.citationPath, encode(author), encode(getHead(rule)) + ".json")
.toString();
File file = new File(summaryPath);
file.getParentFile().mkdirs();
Map<String, Object> summary;
try {
String line = IOUtils.readLineEasy(summaryPath);
if (line == null)
summary = defaultMap(rule);
else
summary = Json.readMapHard(line);
boolean selfcite = author.equals(uid);
if (!selfcite) {
summary.put("cite", (Integer) summary.get("cite") + 1);
rule.source.cite++;
} else {
summary.put("self", (Integer) summary.get("self") + 1);
rule.source.self++;
}
} catch (Exception e) {
summary = defaultMap(rule);
e.printStackTrace();
}
String jsonStr = Json.writeValueAsStringHard(summary);
PrintWriter out = IOUtils.openOutHard(file);
out.println(jsonStr);
out.close();
}
private Map<String, Object> defaultMap(Rule rule) {
Map<String, Object> summary = new LinkedHashMap<>();
summary.put("cite", 0);
summary.put("self", 0);
summary.put("private", true);
summary.put("head", getHead(rule));
summary.put("body", getBody(rule));
return summary;
}
private synchronized void writeLog(Rule rule) {
String head = getHead(rule);
String author = getAuthor(rule);
String logPath = Paths.get(InteractiveUtils.opts.citationPath, encode(author), encode(head) + ".json.log")
.toString();
File file = new File(logPath);
file.getParentFile().mkdirs();
Map<String, Object> jsonMap = new LinkedHashMap<>();
jsonMap.put("user", this.uid);
// jsonMap.put("body", decode(getBody(rule)));
jsonMap.put("time", LocalDateTime.now().toString());
jsonMap.put("tokens", ex.getTokens());
// jsonMap.put("head", decode(headCode));
jsonMap.put("author", author);
String jsonStr = Json.writeValueAsStringHard(jsonMap);
PrintWriter out = IOUtils.openOutAppendHard(file);
out.println(jsonStr);
out.close();
}
public void citeAll(Derivation deriv) {
if (deriv.rule != null && deriv.rule.isInduced()) {
LogInfo.logs("CitationTracker: user %s is citing rule: %s", this.uid, deriv.rule.toString());
citeRule(deriv.rule);
}
if (deriv.children == null)
return;
for (Derivation d : deriv.children) {
citeAll(d);
}
}
static String getAuthor(Rule rule) {
try {
String author = rule.source.uid;
if (Strings.isNullOrEmpty(author))
return "__noname__";
else
return author;
} catch (Exception e) {
e.printStackTrace();
return "__noname__";
}
}
static String getHead(Rule rule) {
return rule.source.head;
}
static String getBody(Rule rule) {
return String.join(". ", rule.source.body);
}
public static String encode(String utt) {
try {
return URLEncoder.encode(utt, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Base64.getUrlEncoder().encodeToString(utt.getBytes());
// return Base64.getUrlEncoder().encodeToString(utt.getBytes());
}
public static String decode(String code) {
try {
return URLDecoder.decode(code, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Base64.getUrlDecoder().decode(code).toString();
}
}