From cf91bfa2d4fd022bb5bd075579761e17952f081a Mon Sep 17 00:00:00 2001 From: Suhyun Park Date: Fri, 19 Jun 2020 02:10:30 +0900 Subject: [PATCH] Release 1.3 --- README.md | 4 - manifest.json | 4 +- src/content/main.js | 296 +++++---------------------- src/content/utils.js | 17 +- src/injected/tagify.2.31.3.min.js | 7 - src/injected/voting.js | 57 ------ src/options/options_logged_info.html | 59 ------ src/options/options_logged_info.js | 27 --- src/options/options_login.html | 21 -- src/options/options_login.js | 37 ---- svg/ka1.svg | 1 - svg/ka2.svg | 1 - svg/ka3.svg | 1 - svg/ka4.svg | 1 - svg/ka5.svg | 1 - svg/ka6.svg | 1 - svg/ka7.svg | 1 - svg/nr.svg | 1 + 18 files changed, 60 insertions(+), 477 deletions(-) delete mode 100644 src/injected/tagify.2.31.3.min.js delete mode 100644 src/injected/voting.js delete mode 100644 src/options/options_logged_info.html delete mode 100644 src/options/options_logged_info.js delete mode 100644 src/options/options_login.js delete mode 100644 svg/ka1.svg delete mode 100644 svg/ka2.svg delete mode 100644 svg/ka3.svg delete mode 100644 svg/ka4.svg delete mode 100644 svg/ka5.svg delete mode 100644 svg/ka6.svg delete mode 100644 svg/ka7.svg create mode 100644 svg/nr.svg diff --git a/README.md b/README.md index 6a43666..9ff59da 100755 --- a/README.md +++ b/README.md @@ -25,10 +25,6 @@ solved.ac는 계속 커뮤니티 프로젝트로 남을 것입니다. 지금까 ### 문제 난이도 표시 개별 문제에 난이도 표시 -### 문제 난이도 의견 제출 -문제 난이도 의견 제출 -문제 난이도 의견 제출 - ## 소스로부터 설치 ### Chrome diff --git a/manifest.json b/manifest.json index d2eb4b9..adf548d 100755 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "solved.ac", - "version": "1.2.4.1", - "description": "Problem difficulty informations for BOJ", + "version": "1.3", + "description": "우리 모두가 만들어가는 알고리즘 문제해결 학습의 이정표 🚩 Problem difficulty informations for BOJ", "manifest_version": 2, "author": "shiftpsh", "icons": { diff --git a/src/content/main.js b/src/content/main.js index 2f833af..783e556 100644 --- a/src/content/main.js +++ b/src/content/main.js @@ -1,143 +1,27 @@ -loadScript('/src/injected/tagify.2.31.3.min.js') -loadScript('/src/injected/voting.js') - -async function initializeVoting(problemId, defaultLevel, myVote) { - const token = await getPrefs('token') - - var params = { - "token": token - } - - const currentUser = await (await fetch("https://api.solved.ac/validate_token.php", - { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify(params) - }) - ).json() - - var user = currentUser.user - if (user.level < 16 && user.user_id !== "solvedac") return - if (!document.querySelector(".label-success") && user.user_id !== "solvedac") return - - const algorithms = await (await fetch("https://api.solved.ac/algorithms.php")).json() - const showTagsInEnglish = JSON.parse(await getPrefs('show_tags_in_english', 'false')) - - const bottom = document.querySelector(".col-md-12:nth-child(4)") - var visibleState = "poll_shown" - if (myVote) visibleState = "poll_hidden" - bottom.outerHTML += "

난이도 투표 펼치기/접기

" - - const difficultySectionConainer = document.getElementById("problem_difficulty") - const difficultySection = document.createElement("div") - difficultySection.className = "poll" - difficultySectionConainer.appendChild(difficultySection) - - const commentCaption = document.createElement("span") - commentCaption.className = "vote_caption" - commentCaption.innerText = "난이도 의견" - difficultySection.appendChild(commentCaption) - - const difficultySelector = document.createElement("select") - difficultySelector.name = "difficulty_selector" - difficultySelector.className = "difficulty_selector" - - var difficultyValueMin = 1 - if (user.user_id === "solvedac") { - difficultyValueMin = 0 - } - for (var i = difficultyValueMin; i <= 30; i++) { - const difficultyItem = document.createElement("option") - difficultyItem.value = i - difficultyItem.innerText = levelName(i) - difficultyItem.className = levelCssClass(i) - difficultySelector.appendChild(difficultyItem) - } - - difficultySelector.selectedIndex = (defaultLevel - 1); - difficultySection.appendChild(difficultySelector); - difficultySection.appendChild(document.createElement("br")) - - const commentSection = document.createElement("textarea") - commentSection.id = "problem_comment" - commentSection.setAttribute("onkeydown", "onPollKeyDown(event)") - if (myVote) commentSection.value = myVote.comment - difficultySection.appendChild(commentSection) - difficultySection.appendChild(document.createElement("br")) - - const whitelist = algorithms.map((algo) => algorithmToTag(algo, showTagsInEnglish)) - var selectedAlgorithms = [] - if (myVote) selectedAlgorithms = myVote.algorithms.map((algo) => algorithmToTag(algo, showTagsInEnglish)) - - const algorithmCaption = document.createElement("span") - algorithmCaption.className = "vote_caption" - algorithmCaption.innerText = "알고리즘 분류 의견" - difficultySection.appendChild(algorithmCaption) - - const algorithmSection = document.createElement("input") - algorithmSection.id = "algorithm_input" - algorithmSection.name = "basic" - algorithmSection.setAttribute("onkeydown", "onPollKeyDown(event)") - difficultySection.appendChild(algorithmSection) - - const whitelistScript = document.createElement("script") - whitelistScript.innerHTML = "var whitelist = JSON.parse(" + JSON.stringify(JSON.stringify(whitelist)) + ");" - difficultySection.appendChild(whitelistScript) - - const algorithmInputScript = document.createElement("script") - algorithmInputScript.innerHTML = "var algorithmSuggestionInput=new Tagify(document.querySelector('#algorithm_input')," - + "{enforceWhitelist: true, whitelist: whitelist, autocomplete: false, dropdown: {enabled: 1, classname: 'algorithm_dropdown', maxItems: Infinity, highlightFirst: true}});" - + "algorithmSuggestionInput.addTags(JSON.parse(" + JSON.stringify(JSON.stringify(selectedAlgorithms)) + "))" - difficultySection.appendChild(algorithmInputScript) - - const sendButton = document.createElement("button") - sendButton.className = "btn btn-primary" - sendButton.id = "poll_submit" - sendButton.type = "submit" - sendButton.innerText = "이렇게 제출하기" - sendButton.style.marginTop = "16px" - sendButton.setAttribute("onclick", "sendVote('" + token + "'," + problemId + ")") - difficultySection.appendChild(sendButton) -} - async function addLevelIndicators() { if (isProblemPage()) { - const token = await getPrefs('token') - const problemIdContainer = document.querySelector("ul.problem-menu li a") const problemId = problemIdContainer.innerText.replace(/[^0-9.]/g, "") const problemInfo = document.querySelector("div.page-header") - const levelData = await (await fetch("https://api.solved.ac/problem_level.php?id=" + problemId)).json() - const difficultyVotes = await (await fetch("https://api.solved.ac/question_level_votes.php?id=" + problemId)).json() - - if (levelData.level == null) { + const levelData = await (await fetch("https://api.solved.ac/v2/problems/show.json?id=" + problemId)).json() + + if (!levelData.success || !levelData.result.problems.length) { var description = document.createElement("span") - description.innerText = "아직 solved.ac 데이터베이스에 등록되지 않은 문제입니다. 내일 오전 6시부터 난이도 의견 제출이 가능합니다." + description.innerText = "아직 solved.ac 데이터베이스에 등록되지 않은 문제입니다." problemInfo.appendChild(description) return } + const problem = levelData.result.problems[0] const nick = document.querySelector("ul.loginbar li:first-child a").innerText.trim() - var votedFlag = false - var myVote var titleBadge = document.createElement("span") titleBadge.className = "title_badge" - titleBadge.innerHTML = levelLabel(levelData.level) + " " + levelText(levelData.level) + titleBadge.innerHTML = levelLabel(problem.level, problem.level_locked) + " " + levelText(problem.level, problem.level_locked) problemInfo.appendChild(titleBadge) - if (levelData.kudeki_level) { - var titleBadge = document.createElement("span") - titleBadge.className = "title_badge" - titleBadge.innerHTML = " / " + kudekiLevelLabel(levelData.kudeki_level) + " " + kudekiLevelText(levelData.kudeki_level) - problemInfo.appendChild(titleBadge) - } - - var standard = (difficultyVotes.length > 0 && difficultyVotes[0].user_id == "solvedac") + var standard = (problem.level_locked) if (standard) { var standardIndicator = document.createElement("img") @@ -149,29 +33,18 @@ async function addLevelIndicators() { standardIndicator.alt = "solved.ac 표준" standardIndicator.title = "solved.ac 표준" problemInfo.appendChild(standardIndicator) - - if (nick === "solvedac") { - for (var i = 0; i < difficultyVotes.length; i++) { - var vote = difficultyVotes[i] - if (vote.user_id === nick) { - votedFlag = true - myVote = vote - } - } - } } - const hideOtherVotes = JSON.parse(await getPrefs('hide_other_votes', 'false')) const showTagsInEnglish = JSON.parse(await getPrefs('show_tags_in_english', 'false')) if (document.querySelector(".label-success") || nick === "solvedac") { - if (levelData.algorithms) { + if (problem.tags) { problemInfo.appendChild(document.createElement("br")) } - for (var j = 0; j < levelData.algorithms.length; j++) { - var algo = levelData.algorithms[j] + for (var j = 0; j < problem.tags.length; j++) { + var algo = problem.tags[j] var algorithmTag = document.createElement("a") - algorithmTag.setAttribute("href", "https://solved.ac/problems/algorithms/" + algo.algorithm_id) + algorithmTag.setAttribute("href", "https://solved.ac/problems/tags/" + algo.tag_name) if (showTagsInEnglish) { algorithmTag.innerText = algo.full_name_en } else { @@ -180,139 +53,74 @@ async function addLevelIndicators() { algorithmTag.className = "algorithm_tag" problemInfo.appendChild(algorithmTag) } + } - if (levelData.level != 0 && !standard) { - var difficultyVotesContainer = document.createElement("div"); - difficultyVotesContainer.className = "difficulty_vote_container" - - for (var i = 0; i < difficultyVotes.length; i++) { - var vote = difficultyVotes[i] - if (vote.user_id === nick) { - votedFlag = true - myVote = vote - } - if (hideOtherVotes) continue - - var difficultyVote = document.createElement("div") - difficultyVote.className = "difficulty_vote" - difficultyVote.innerHTML = "" - + "" - + levelLabel(vote.user_level) + vote.user_id - + "" - + " ➔ " + levelLabel(vote.voted_level) - difficultyVote.appendChild(document.createElement("br")) - - var voteCommentContainer = document.createElement("div") - var voteComment = document.createElement("span") - voteComment.className = "comment" - voteComment.innerText = vote.comment - if (!vote.comment) { - voteCommentContainer.classList.add("comment_none") - voteComment.innerText = "난이도 의견을 입력하지 않았습니다" - } - difficultyVote.appendChild(voteCommentContainer) - voteCommentContainer.appendChild(voteComment) - if (vote.algorithms) { - for (var j = 0; j < vote.algorithms.length; j++) { - var algo = vote.algorithms[j] - var algorithmTag = document.createElement("a") - algorithmTag.setAttribute("href", "https://solved.ac/problems/algorithms/" + algo.algorithm_id) - if (showTagsInEnglish) { - algorithmTag.innerText = algo.full_name_en - } else { - algorithmTag.innerText = algo.full_name_ko - } - algorithmTag.className = "algorithm_tag" - voteCommentContainer.appendChild(algorithmTag) - } - } - difficultyVotesContainer.appendChild(difficultyVote) - } - problemInfo.appendChild(difficultyVotesContainer) - } + problemInfo.appendChild(document.createElement("br")) + var solvedAcIndicator = document.createElement("span") + solvedAcIndicator.innerText = "난이도 제공: solved.ac" + problemInfo.appendChild(solvedAcIndicator) - if (token && (!standard || nick === "solvedac")) { - var defaultLevel = 1 - if (levelData.level) defaultLevel = levelData.level - if (votedFlag) defaultLevel = myVote.voted_level - initializeVoting(problemId, defaultLevel, myVote) - } + if (document.querySelector(".label-success") || nick === "solvedac") { + var solvedAcIndicator2 = document.createElement("span") + solvedAcIndicator2.innerText = " — " + problemInfo.appendChild(solvedAcIndicator2) + var contributeIndicator = document.createElement("a") + contributeIndicator.href = "https://solved.ac/contribute/" + problemId + contributeIndicator.innerText = "난이도 투표하러 가기" + problemInfo.appendChild(contributeIndicator) } } if (isNotUserOrVsPage()) { pattern = /^(https?:\/\/(www\.)?acmicpc\.net)?\/problem\/([0-9]+)$/i + var problemIds = [] var problemLinks = document.getElementsByTagName("a") problemLinks = [].slice.call(problemLinks, 0) problemLinks - .filter(function (item) { + .filter((item) => { return item.getAttribute("href") && pattern.test(item.getAttribute("href")) }) - .forEach(async function (item, index) { + .forEach((item, index) => { const problemId = item.getAttribute("href").match(pattern)[3] - - const levelData = await (await fetch("https://api.solved.ac/problem_level.php?id=" + problemId)).json() - if (levelData.kudeki_level) { - item.insertAdjacentHTML('afterbegin', kudekiLevelLabel(levelData.kudeki_level)) - } - item.insertAdjacentHTML('afterbegin', levelLabel(levelData.level)) + problemIds.push(problemId) }) + + const levelData = await (await fetch("https://api.solved.ac/v2/problems/lookup.json?ids=" + problemIds.join(","))).json() + var problemData = [] + if (levelData.success) { + levelData.result.problems.forEach((problem) => { + problemData[problem.id] = problem + }) + problemLinks + .filter((item) => { + return item.getAttribute("href") && pattern.test(item.getAttribute("href")) + }) + .forEach((item, index) => { + const problemId = item.getAttribute("href").match(pattern)[3] + item.insertAdjacentHTML('afterbegin', levelLabel(problemData[problemId].level, problemData[problemId].level_locked)) + }) + } } if (isUserPage()) { var userId = document.querySelector(".page-header h1").innerText.trim() var userStaticsTable = document.querySelector("#statics tbody") const isShowUserTempTier = JSON.parse(await getPrefs('show_userpage_temp_tier', 'false')) - const userData = await (await fetch("https://api.solved.ac/user_information.php?id=" + userId)).json() + const userData = await (await fetch("https://api.solved.ac/v2/users/show.json?id=" + userId)).json() + + if ((!userData.success || !userData.result.user.length) && !isShowUserTempTier) return + const user = userData.result.user[0] - if (!userData && !isShowUserTempTier) return - var newRow = document.createElement("tr") var newRowHeader = document.createElement("th") var newRowDescription = document.createElement("td") - if(!userData && isShowUserTempTier) { - var acceptPanel = document.querySelector(".panel.panel-default") - var acceptProblems = acceptPanel.querySelectorAll(".problem_number>a") - var totalExpPoint = 0 - var promises = []; - var levelData = [] - - const levelDataResponses = await (await fetch("https://api.solved.ac/exp_table.php")).text() - levelDataResponses.split(',').forEach(level => levelData.push(parseInt(level))) - - for(i = 0; i < acceptProblems.length; i++) { - var problemId = acceptProblems[i].textContent; - promises[i] = fetch("https://api.solved.ac/problem_level.php?id=" + problemId) - } - - responses = await Promise.all(promises) - for(i = 0; i < responses.length; i++) { - data = await responses[i].json() - if(data.level != 0) - totalExpPoint += levelData[data.level] - } - - var expTable = [] - const expTableData = await (await fetch("https://api.solved.ac/exp_cap.php")).text() - expTableData.split(',').forEach(level => expTable.push(parseInt(level))) - var expectLevel = getExpectLevelFromExpPoint(totalExpPoint, expTable) - - newRowHeader.innerText = "solved.ac 임시티어" - newRowDescription.innerHTML = "" - + "" - + levelLabel(expectLevel) + "" +userId + "" + newRowHeader.innerText = "solved.ac" + newRowDescription.innerHTML = "" + + "" + + levelLabel(user.level) + "" + user.user_id + "" + "" + "" - } - else { - newRowHeader.innerText = "solved.ac" - newRowDescription.innerHTML = "" - + "" - + levelLabel(userData.level) + "" + userData.user_id + "" - + "" - + "" - } newRow.appendChild(newRowHeader) newRow.appendChild(newRowDescription) diff --git a/src/content/utils.js b/src/content/utils.js index 04c0d94..1434c95 100644 --- a/src/content/utils.js +++ b/src/content/utils.js @@ -43,32 +43,25 @@ function levelCssClass(level) { return prefix[Math.floor((level - 1) / 5)] } -function levelText(level) { - if (level == 0) return "Unranked" +function levelText(level, level_locked) { + if (!level && level_locked) return "Not ratable" + if (!level) return "Unrated" return "" + levelName(level) + "" } -function kudekiLevelText(level) { - const roman = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] - return "Ghudegy " + roman[level - 1] + "" -} - function levelLabelUnlisted() { return "00" + "" } -function levelLabel(level) { +function levelLabel(level, level_locked) { if (level === null) return levelLabelUnlisted() if (level == -1) level = 0 + if (!level && level_locked) return "00" + "" return "" + ('0' + level).slice(-2) + "" } -function kudekiLevelLabel(level) { - return "" -} - function matchCurrentURL(regex) { return regex.test(window.location.toString()) } diff --git a/src/injected/tagify.2.31.3.min.js b/src/injected/tagify.2.31.3.min.js deleted file mode 100644 index 6d241e1..0000000 --- a/src/injected/tagify.2.31.3.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Tagify (v 2.31.2)- tags input component - * By Yair Even-Or - * Don't sell this code. (c) - * https://github.com/yairEO/tagify - */ -!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.Tagify=e()}(this,function(){"use strict";function c(t){return function(t){if(Array.isArray(t)){for(var e=0,i=new Array(t.length);e