|
|
@ -44,84 +44,77 @@ import java.util.Map;
|
|
|
|
public class MessageClassifier {
|
|
|
|
public class MessageClassifier {
|
|
|
|
private static boolean loaded = false;
|
|
|
|
private static boolean loaded = false;
|
|
|
|
private static boolean dirty = false;
|
|
|
|
private static boolean dirty = false;
|
|
|
|
private static Map<Long, Map<String, Integer>> classMessages = new HashMap<>();
|
|
|
|
private static final Map<Long, Map<String, Integer>> classMessages = new HashMap<>();
|
|
|
|
private static Map<Long, Map<String, Map<String, Integer>>> wordClassFrequency = new HashMap<>();
|
|
|
|
private static final Map<Long, Map<String, Map<String, Integer>>> wordClassFrequency = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
private static final int MIN_MATCHED_WORDS = 10;
|
|
|
|
private static final int MIN_MATCHED_WORDS = 10;
|
|
|
|
private static final double COMMON_WORD_FACTOR = 0.75;
|
|
|
|
private static final double COMMON_WORD_FACTOR = 0.75;
|
|
|
|
private static final double CHANCE_THRESHOLD = 2.0;
|
|
|
|
private static final double CHANCE_THRESHOLD = 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
static void classify(EntityMessage message, EntityFolder target, Context context) {
|
|
|
|
static void classify(EntityMessage message, EntityFolder target, Context context) {
|
|
|
|
if (!isEnabled(context))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
load(context);
|
|
|
|
if (!isEnabled(context))
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
return;
|
|
|
|
Log.e(ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (target != null && !canClassify(target.type))
|
|
|
|
if (target != null && !canClassify(target.type))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
|
|
|
|
|
|
|
EntityFolder folder = db.folder().getFolder(message.folder);
|
|
|
|
EntityFolder folder = db.folder().getFolder(message.folder);
|
|
|
|
if (folder == null)
|
|
|
|
if (folder == null)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
EntityAccount account = db.account().getAccount(folder.account);
|
|
|
|
EntityAccount account = db.account().getAccount(folder.account);
|
|
|
|
if (account == null)
|
|
|
|
if (account == null)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!canClassify(folder.type))
|
|
|
|
if (!canClassify(folder.type))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
File file = message.getFile(context);
|
|
|
|
File file = message.getFile(context);
|
|
|
|
if (!file.exists())
|
|
|
|
if (!file.exists())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
String text;
|
|
|
|
String text = HtmlHelper.getFullText(file);
|
|
|
|
try {
|
|
|
|
if (TextUtils.isEmpty(text))
|
|
|
|
text = HtmlHelper.getFullText(file);
|
|
|
|
return;
|
|
|
|
} catch (IOException ex) {
|
|
|
|
|
|
|
|
Log.w(ex);
|
|
|
|
|
|
|
|
text = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (TextUtils.isEmpty(text))
|
|
|
|
load(context);
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!classMessages.containsKey(account.id))
|
|
|
|
if (!classMessages.containsKey(account.id))
|
|
|
|
classMessages.put(account.id, new HashMap<>());
|
|
|
|
classMessages.put(account.id, new HashMap<>());
|
|
|
|
if (!wordClassFrequency.containsKey(account.id))
|
|
|
|
if (!wordClassFrequency.containsKey(account.id))
|
|
|
|
wordClassFrequency.put(account.id, new HashMap<>());
|
|
|
|
wordClassFrequency.put(account.id, new HashMap<>());
|
|
|
|
|
|
|
|
|
|
|
|
String classified = classify(account.id, folder.name, text, target == null, context);
|
|
|
|
String classified = classify(account.id, folder.name, text, target == null, context);
|
|
|
|
|
|
|
|
|
|
|
|
EntityLog.log(context, "Classifier" +
|
|
|
|
EntityLog.log(context, "Classifier" +
|
|
|
|
" folder=" + folder.name +
|
|
|
|
" folder=" + folder.name +
|
|
|
|
" message=" + message.id +
|
|
|
|
" message=" + message.id +
|
|
|
|
"@" + new Date(message.received) +
|
|
|
|
"@" + new Date(message.received) +
|
|
|
|
":" + message.subject +
|
|
|
|
":" + message.subject +
|
|
|
|
" class=" + classified);
|
|
|
|
" class=" + classified);
|
|
|
|
|
|
|
|
|
|
|
|
Integer m = classMessages.get(account.id).get(folder.name);
|
|
|
|
Integer m = classMessages.get(account.id).get(folder.name);
|
|
|
|
if (target == null) {
|
|
|
|
if (target == null) {
|
|
|
|
m = (m == null ? 1 : m + 1);
|
|
|
|
m = (m == null ? 1 : m + 1);
|
|
|
|
classMessages.get(account.id).put(folder.name, m);
|
|
|
|
classMessages.get(account.id).put(folder.name, m);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (m != null && m > 0)
|
|
|
|
if (m != null && m > 0)
|
|
|
|
classMessages.get(account.id).put(folder.name, m - 1);
|
|
|
|
classMessages.get(account.id).put(folder.name, m - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Log.i("Classifier classify=" + folder.name + " messages=" + classMessages.get(account.id).get(folder.name));
|
|
|
|
Log.i("Classifier classify=" + folder.name + " messages=" + classMessages.get(account.id).get(folder.name));
|
|
|
|
|
|
|
|
|
|
|
|
dirty = true;
|
|
|
|
dirty = true;
|
|
|
|
|
|
|
|
|
|
|
|
if (classified != null) {
|
|
|
|
if (classified != null) {
|
|
|
|
EntityFolder f = db.folder().getFolderByName(account.id, classified);
|
|
|
|
EntityFolder f = db.folder().getFolderByName(account.id, classified);
|
|
|
|
if (f != null && f.download && f.auto_classify && !f.id.equals(folder.id))
|
|
|
|
if (f != null && f.download && f.auto_classify && !f.id.equals(folder.id))
|
|
|
|
EntityOperation.queue(context, message, EntityOperation.MOVE, f.id);
|
|
|
|
EntityOperation.queue(context, message, EntityOperation.MOVE, f.id);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
|
|
|
Log.e(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|