/** * MIT License * * Copyright (c) 2017 zgqq * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package mah.plugin.support.orgnote; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import mah.action.AbstractAction; import mah.action.ActionEvent; import mah.mode.AbstractMode; import mah.plugin.PluginException; import mah.plugin.command.PluginCommandSupport; import mah.plugin.support.orgnote.config.Config; import mah.plugin.support.orgnote.source.Orgmode2; import mah.common.util.IoUtils; import mah.ui.layout.ClassicPostLayout; import mah.ui.pane.post.PostImpl; import mah.ui.window.Window; import mah.ui.window.WindowManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * Created by zgq on 16-12-19. */ public class ReviewNoteCommand extends PluginCommandSupport { private static final Logger LOGGER = LoggerFactory.getLogger(ReviewNoteCommand.class); private ClassicPostLayout layout; public ReviewNoteCommand() { init(); } private void init() { addInitializeEventHandler(event -> { layout = getLayoutFactory().createClassicPostLayout(); layout.registerMode(new OrgnoteReviewMode(),event1 -> event1.getMode() .updateActionHandler(ReviewNoteCommand.this)); }); addTriggerEventHandler(event -> { trigger(); }); } private static JSONObject selectNode(List<JSONObject> list, Config config) { for (int i = config.getNodeIndex(); i < list.size(); i++) { JSONObject node = list.get(i); Long lastReviewTime = node.getLong("lastReviewTime"); if (lastReviewTime == null || lastReviewTime == 0) { config.setNodeIndex(i); return node; } long lrTime = lastReviewTime; long ntime = Calendar.getInstance().getTimeInMillis(); int familiarDegree = node.getIntValue("familiarDegree"); if (ntime >= (familiarDegree * 24 * 3600) + lrTime) { config.setNodeIndex(i); return node; } } return null; } private String getDataDir() { return getPluginDataDir("import"); } private String getImportDir() { return getPluginDataDir("import"); } public int checkData(Config config) { //Import File importDataDir = new File(getImportDir()); if (!importDataDir.exists()) { importDataDir.mkdirs(); return 0; } if (importDataDir.isDirectory()) { int importQuantity = 0; for (File dataFile : importDataDir.listFiles()) { String filename = IoUtils.getFilename(dataFile.getName()); if (!config.contains(filename + ".json")) { String content; try { content = Orgmode2.toJson(dataFile.getAbsolutePath()); String filepath = getDataDir() + filename + ".json"; IoUtils.createFileIfNotExists(filepath); IoUtils.writeToFile(filepath, content); config.addDataFilename(filename + ".json"); ++importQuantity; } catch (IOException e) { throw new RuntimeException(e); } } } return importQuantity; } return 0; } private String getConfigFile() { return getFileStoredInPluginDataDir("config.json"); } private Config readConfig() { Config config; try { String con = IoUtils.toString(getConfigFile()); config = JSONObject.parseObject(con, Config.class); if (config == null) { config = new Config(); } } catch (IOException e) { if (e instanceof FileNotFoundException) { try { IoUtils.createFileIfNotExists(getConfigFile()); config = new Config(); } catch (IOException e1) { throw new RuntimeException("Run error!", e1); } } else { throw new RuntimeException("Run error!", e); } } return config; } private void createDirectoryIfNotExists(String dir) { File dirObj = new File(dir); if (!dirObj.exists()) { dirObj.mkdirs(); } } private void checkInstallDir() { createDirectoryIfNotExists(getDataDir()); createDirectoryIfNotExists(getImportDir()); } private void trigger() { synchronized (this) { LOGGER.info("trigger note command"); checkInstallDir(); nextNode(); } } public void nextNode() { Config config = readConfig(); checkData(config); JSONObject note; List<JSONObject> list = new ArrayList<>(); if (config.dataEmpty()) { note = new JSONObject(); note.put("title", "没有数据"); note.put("content", "没有数据"); } else { String reviewContent = null; try { reviewContent = IoUtils.toString(getDataDir() + config.getCurrentFilename()); } catch (IOException e) { throw new PluginException(e); } list = JSON.parseObject(reviewContent, List.class); note = selectNode(list, config); if (note == null) { note = new JSONObject(); note.put("title", "No review item available!"); } } Config.setSource(config, list); currentNode = note; JSONArray contentLine = note.getJSONArray("contentLines"); final StringBuilder contentsb = new StringBuilder(); if (contentLine != null) { contentLine.forEach(str -> contentsb.append(str).append("\n")); } PostImpl post = new PostImpl.Builder(note.getString("title"), contentsb.toString()).build(); layout.setPost(post); Config.update(getConfigFile()); } private JSONObject currentNode; public JSONObject getCurrentNote() { return currentNode; } @Override public String getName() { return "ReviewNote"; } public static class OrgnoteReviewMode extends AbstractMode { public static final String NAME = "orgnote_review_mode"; public OrgnoteReviewMode() { super(NAME); } @Override public void init() { registerAction(new Quit("Quit")); registerAction(new Forget("Forget")); registerAction(new Remember("Remember")); } } public abstract static class ReviewAction extends AbstractAction { public ReviewAction(String name) { super(name,ReviewNoteCommand.class); } } public static class Quit extends ReviewAction { public Quit(String name) { super(name); } @Override public void actionPerformed(ActionEvent actionEvent) { ReviewNoteCommand source = (ReviewNoteCommand) actionEvent.getSource(); JSONObject currentNote = source.getCurrentNote(); int quitCount = currentNote.getIntValue("quitCount"); currentNote.put("quitCount", quitCount + 1); Config.updateReviewList(source.getDataDir()); Window currentWindow = WindowManager.getInstance().getCurrentWindow(); currentWindow.useDefaultLayoutAsCurrentLayout(); } } public static class Forget extends ReviewAction { public Forget(String name) { super(name); } @Override public void actionPerformed(ActionEvent actionEvent) { ReviewNoteCommand source = (ReviewNoteCommand) actionEvent.getSource(); JSONObject jsonObject = source.getCurrentNote(); int forgetCount = jsonObject.getIntValue("forgetCount"); int familiarDegree = 0; jsonObject.put("forgetCount", forgetCount + 1); jsonObject.put("familiarDegree", familiarDegree); jsonObject.put("lastReviewTime", new Date()); Config.updateReviewList(source.getDataDir()); source.nextNode(); } } public static class Remember extends ReviewAction { public Remember(String name) { super(name); } @Override public void actionPerformed(ActionEvent actionEvent) { ReviewNoteCommand source = (ReviewNoteCommand) actionEvent.getSource(); JSONObject jsonObject = source.getCurrentNote(); int familiarDegree = jsonObject.getIntValue("familiarDegree"); int rememberCount = jsonObject.getIntValue("rememberCount"); if (familiarDegree == 0) { familiarDegree = 10; } familiarDegree = (int) (familiarDegree * 1.3); jsonObject.put("rememberCount", rememberCount + 1); jsonObject.put("familiarDegree", familiarDegree); jsonObject.put("lastReviewTime", new Date()); Config.updateReviewList(source.getDataDir()); source.nextNode(); } } }