package com.shuzijun.leetcode.plugin.manager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.base.Function; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimaps; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.shuzijun.leetcode.plugin.model.Constant; import com.shuzijun.leetcode.plugin.model.Question; import com.shuzijun.leetcode.plugin.model.Tag; import com.shuzijun.leetcode.plugin.setting.PersistentConfig; import com.shuzijun.leetcode.plugin.utils.*; import com.shuzijun.leetcode.plugin.window.WindowFactory; import org.apache.commons.lang.StringUtils; import java.util.*; /** * @author shuzijun */ public class QuestionManager { private static List<Question> QUESTIONLIST = null; private final static String ALLNAME = "all.json"; private final static String TRANSLATIONNAME = "translation.json"; public static List<Question> getQuestionService(Project project, String url) { List<Question> questionList = null; HttpRequest httpRequest = HttpRequest.get(url); HttpResponse response = HttpRequestUtils.executeGet(httpRequest); if (response != null && response.getStatusCode() == 200) { questionList = parseQuestion(response.getBody()); JSONObject jsonObject = JSONObject.parseObject(response.getBody()); ApplicationManager.getApplication().invokeAndWait(() -> { WindowFactory.updateTitle(project, jsonObject.getString("user_name")); }); } else { LogUtils.LOG.error("Request question list failed, status:" + response == null ? "" : response.getStatusCode()); } if (questionList != null && !questionList.isEmpty()) { String filePath = PersistentConfig.getInstance().getTempFilePath() + ALLNAME; FileUtils.saveFile(filePath, JSON.toJSONString(questionList)); QUESTIONLIST = questionList; } return questionList; } public static List<Question> getQuestionCache() { if (QUESTIONLIST != null) { return QUESTIONLIST; } String filePath = PersistentConfig.getInstance().getTempFilePath() + ALLNAME; String body = FileUtils.getFileBody(filePath); if (StringUtils.isBlank(body)) { return Lists.newArrayList(); } else { List<Question> questionList = JSON.parseArray(body, Question.class); QUESTIONLIST = questionList; return questionList; } } public static List<Tag> getDifficulty() { List<String> keyList = Lists.newArrayList(Constant.DIFFICULTY_EASY, Constant.DIFFICULTY_MEDIUM, Constant.DIFFICULTY_HARD); List<Question> questionList = getQuestionCache(); ImmutableListMultimap<String, Question> questionImmutableMap = Multimaps.index(questionList.iterator(), new Function<Question, String>() { @Override public String apply(Question question) { String difficulty; if (question.getLevel() == 1) { difficulty = Constant.DIFFICULTY_EASY; } else if (question.getLevel() == 2) { difficulty = Constant.DIFFICULTY_MEDIUM; } else if (question.getLevel() == 3) { difficulty = Constant.DIFFICULTY_HARD; } else { difficulty = Constant.DIFFICULTY_UNKNOWN; } return difficulty; } }); List<Tag> difficultyList = Lists.newArrayList(); for (String key : keyList) { Tag tag = new Tag(); tag.setName(key); for (Question question : questionImmutableMap.get(key)) { tag.addQuestion(question.getQuestionId()); } difficultyList.add(tag); } return difficultyList; } public static List<Tag> getStatus() { List<String> keyList = Lists.newArrayList(Constant.STATUS_TODO, Constant.STATUS_SOLVED, Constant.STATUS_ATTEMPTED); List<Question> questionList = getQuestionCache(); ImmutableListMultimap<String, Question> questionImmutableMap = Multimaps.index(questionList.iterator(), new Function<Question, String>() { @Override public String apply(Question question) { String status; if ("ac".equals(question.getStatus())) { status = Constant.STATUS_SOLVED; } else if ("notac".equals(question.getStatus())) { status = Constant.STATUS_ATTEMPTED; } else { status = Constant.STATUS_TODO; } return status; } }); List<Tag> statusList = Lists.newArrayList(); for (String key : keyList) { Tag tag = new Tag(); tag.setName(key); for (Question question : questionImmutableMap.get(key)) { tag.addQuestion(question.getQuestionId()); } statusList.add(tag); } return statusList; } public static List<Tag> getTags() { List<Tag> tags = new ArrayList<>(); HttpRequest httpRequest = HttpRequest.get(URLUtils.getLeetcodeTags()); HttpResponse response = HttpRequestUtils.executeGet(httpRequest); if (response != null && response.getStatusCode() == 200) { try { String body = response.getBody(); tags = parseTag(body); } catch (Exception e1) { LogUtils.LOG.error("Request tags exception", e1); } } else { LogUtils.LOG.error("Request tags failed, status:" + response.getStatusCode() + "body:" + response.getBody()); } return tags; } public static List<Tag> getLists() { List<Tag> tags = new ArrayList<>(); HttpRequest httpRequest = HttpRequest.get(URLUtils.getLeetcodeFavorites()); HttpResponse response = HttpRequestUtils.executeGet(httpRequest); if (response != null && response.getStatusCode() == 200) { try { String body = response.getBody(); tags = parseList(body); } catch (Exception e1) { LogUtils.LOG.error("Request Lists exception", e1); } } else { LogUtils.LOG.error("Request Lists failed, status:" + response.getStatusCode() + "body:" + response.getBody()); } return tags; } public static List<Tag> getCategory(String url) { List<Tag> tags = new ArrayList<>(); HttpRequest httpRequest = HttpRequest.get(URLUtils.getLeetcodeCardInfo()); HttpResponse response = HttpRequestUtils.executeGet(httpRequest); if (response != null && response.getStatusCode() == 200) { try { String body = response.getBody(); tags = parseCategory(body, url); } catch (Exception e1) { LogUtils.LOG.error("Request CardInfo exception", e1); } } else { LogUtils.LOG.error("Request CardInfo failed, status:" + response.getStatusCode() + "body:" + response.getBody()); } return tags; } private static List<Question> parseQuestion(String str) { List<Question> questionList = new ArrayList<Question>(); if (StringUtils.isNotBlank(str)) { JSONObject jsonObject = JSONObject.parseObject(str); Boolean isPremium = new Integer("0").equals(jsonObject.getInteger("frequency_high")); //Premium users display frequency JSONArray jsonArray = jsonObject.getJSONArray("stat_status_pairs"); for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); Question question = new Question(object.getJSONObject("stat").getString("question__title")); question.setLeaf(Boolean.TRUE); question.setQuestionId(object.getJSONObject("stat").getString("question_id")); question.setFrontendQuestionId(object.getJSONObject("stat").getString("frontend_question_id")); try { if (object.getBoolean("paid_only") && isPremium) { question.setStatus(object.getBoolean("paid_only") ? "lock" : null); } else { question.setStatus(object.get("status") == null ? "" : object.getString("status")); } } catch (Exception ee) { question.setStatus(""); } question.setTitleSlug(object.getJSONObject("stat").getString("question__title_slug")); question.setLevel(object.getJSONObject("difficulty").getInteger("level")); try { if (object.getJSONObject("stat").containsKey("question__article__live")) { if (object.getJSONObject("stat").get("question__article__live") == null || !object.getJSONObject("stat").getBoolean("question__article__live")) { question.setArticleLive(Constant.ARTICLE_LIVE_NONE); } else { question.setArticleLive(Constant.ARTICLE_LIVE_ONE); question.setArticleSlug(object.getJSONObject("stat").getString("question__title_slug")); } } else { question.setArticleLive(Constant.ARTICLE_LIVE_LIST); } } catch (Exception e) { LogUtils.LOG.error("Identify abnormal article", e); question.setArticleLive(Constant.ARTICLE_LIVE_NONE); } questionList.add(question); } translation(questionList); Collections.sort(questionList, new Comparator<Question>() { @Override public int compare(Question arg0, Question arg1) { String frontendId0 = arg0.getFrontendQuestionId(); String frontendId1 = arg1.getFrontendQuestionId(); if (StringUtils.isNumeric(frontendId0) && StringUtils.isNumeric(frontendId1)) { return Integer.valueOf(frontendId0).compareTo(Integer.valueOf(frontendId1)); } else if (StringUtils.isNumeric(frontendId0)) { return -1; } else if (StringUtils.isNumeric(frontendId1)) { return 1; } else { return frontendId0.compareTo(frontendId1); } } }); } return questionList; } private static void translation(List<Question> questions) { if (URLUtils.isCn() && !PersistentConfig.getInstance().getConfig().getEnglishContent()) { String filePathTranslation = PersistentConfig.getInstance().getTempFilePath() + TRANSLATIONNAME; try { HttpRequest httpRequest = HttpRequest.post(URLUtils.getLeetcodeGraphql(), "application/json"); httpRequest.setBody("{\"operationName\":\"getQuestionTranslation\",\"variables\":{},\"query\":\"query getQuestionTranslation($lang: String) {\\n translations: allAppliedQuestionTranslations(lang: $lang) {\\n title\\n questionId\\n __typename\\n }\\n}\\n\"}"); httpRequest.addHeader("Accept", "application/json"); HttpResponse response = HttpRequestUtils.executePost(httpRequest); String body; if (response != null && response.getStatusCode() == 200) { body = response.getBody(); FileUtils.saveFile(filePathTranslation, body); } else { body = FileUtils.getFileBody(filePathTranslation); } if (StringUtils.isNotBlank(body)) { Map<String, String> translationMap = new HashMap<String, String>(); JSONArray jsonArray = JSONObject.parseObject(body).getJSONObject("data").getJSONArray("translations"); for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); translationMap.put(object.getString("questionId"), object.getString("title")); } for (Question question : questions) { if (translationMap.containsKey(question.getQuestionId())) { question.setTitle(translationMap.get(question.getQuestionId())); } } } else { LogUtils.LOG.error("读取翻译内容为空"); } } catch (Exception e1) { LogUtils.LOG.error("获取题目翻译错误", e1); } } } private static List<Tag> parseTag(String str) { List<Tag> tags = new ArrayList<Tag>(); if (StringUtils.isNotBlank(str)) { JSONArray jsonArray = JSONObject.parseObject(str).getJSONArray("topics"); for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); Tag tag = new Tag(); tag.setSlug(object.getString("slug")); String name = object.getString(URLUtils.getTagName()); if (StringUtils.isBlank(name)) { name = object.getString("name"); } tag.setName(name); JSONArray questionArray = object.getJSONArray("questions"); for (int j = 0; j < questionArray.size(); j++) { tag.addQuestion(questionArray.getInteger(j).toString()); } tags.add(tag); } } return tags; } private static List<Tag> parseCategory(String str, String url) { List<Tag> tags = new ArrayList<Tag>(); if (StringUtils.isNotBlank(str)) { JSONArray jsonArray = JSONArray.parseObject(str).getJSONObject("categories").getJSONArray("0"); for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); Tag tag = new Tag(); tag.setSlug(object.getString("slug")); tag.setType(URLUtils.getLeetcodeUrl() + "/api" + object.getString("url").replace("problemset","problems")); tag.setName(object.getString("title")); if(url.contains(tag.getType())){ tag.setSelect(true); } tags.add(tag); } } return tags; } private static List<Tag> parseList(String str) { List<Tag> tags = new ArrayList<Tag>(); if (StringUtils.isNotBlank(str)) { JSONArray jsonArray = JSONArray.parseArray(str); for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); Tag tag = new Tag(); tag.setSlug(object.getString("id")); tag.setType(object.getString("type")); String name = object.getString("name"); if (StringUtils.isBlank(name)) { name = object.getString("name"); } tag.setName(name); JSONArray questionArray = object.getJSONArray("questions"); for (int j = 0; j < questionArray.size(); j++) { tag.addQuestion(questionArray.getInteger(j).toString()); } tags.add(tag); } } return tags; } }