atcoder-problems-api

library for API provided by AtCoder Problems

Verze ze dne 31. 12. 2021. Zobrazit nejnovější verzi.

Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greasyfork.org/scripts/437862/1004089/atcoder-problems-api.js

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function fetchJson(url) {
    return __awaiter(this, void 0, void 0, function* () {
        const res = yield fetch(url);
        if (res.ok)
            return res.json();
        console.error("response is not ok", res);
        throw new Error(`requests to ${url} failed`);
    });
}

const ATCODER_PROBLEMS_URL = 'https://kenkoooo.com/atcoder';
const V3_API_URL = `${ATCODER_PROBLEMS_URL}/atcoder-api/v3`;

function getApiUrl(name) {
    return `${ATCODER_PROBLEMS_URL}/resources/${name}.json`;
}
// Information API
const CONTESTS_INFORMATION_URL = getApiUrl("contests");
const getContests = () => fetchJson(CONTESTS_INFORMATION_URL);
const PROBLEMS_INFORMATION_URL = getApiUrl("problems");
const getProblems = () => fetchJson(PROBLEMS_INFORMATION_URL);
const DETAILED_PROBLEMS_INFORMATION_URL = getApiUrl("merged-problems");
const getDetailedProblems = () => fetchJson(DETAILED_PROBLEMS_INFORMATION_URL);
const CONTESTS_AND_PROBLEMS_URL = getApiUrl("contest-problem");
const getContestsAndProblems = () => fetchJson(CONTESTS_AND_PROBLEMS_URL);
// Resources
const ESTIMATED_DIFFICULTIES_URL = getApiUrl("problem-models");
const getEstimatedDifficulties = () => fetchJson(ESTIMATED_DIFFICULTIES_URL);

var information = /*#__PURE__*/Object.freeze({
    __proto__: null,
    getContests: getContests,
    getProblems: getProblems,
    getDetailedProblems: getDetailedProblems,
    getContestsAndProblems: getContestsAndProblems,
    getEstimatedDifficulties: getEstimatedDifficulties
});

function getStatisticsFunctions(name) {
    const ranking = (from, to) => fetchJson(`${V3_API_URL}/${name}_ranking?from=${from}&to=${to}`);
    const userRank = (user) => fetchJson(`${V3_API_URL}/user/${name}_rank?user=${user}`);
    return { ranking, userRank };
}
const { ranking: getAcceptedCountRanking, userRank: getUserAcceptedCountRank } = getStatisticsFunctions("ac");
const { ranking: getRatedPointSumRanking, userRank: getUserRatedPointSumRank } = getStatisticsFunctions("rated_point_sum");
const { ranking: getLongestStreakRanking, userRank: getUserLongestStreakRank } = getStatisticsFunctions("streak");
const getLanguageAcceptedCountRanking = (from, to, language) => fetchJson(`${V3_API_URL}/language_ranking?from=${from}&to=${to}&language=${language}`);
const getUserLanguageAcceptedCountRank = (user) => fetchJson(`${V3_API_URL}/user/language_rank?user=${user}`);
const getLanguageList = () => fetchJson(`${V3_API_URL}/language_list`);

var statistics = /*#__PURE__*/Object.freeze({
    __proto__: null,
    getAcceptedCountRanking: getAcceptedCountRanking,
    getUserAcceptedCountRank: getUserAcceptedCountRank,
    getRatedPointSumRanking: getRatedPointSumRanking,
    getUserRatedPointSumRank: getUserRatedPointSumRank,
    getLongestStreakRanking: getLongestStreakRanking,
    getUserLongestStreakRank: getUserLongestStreakRank,
    getLanguageAcceptedCountRanking: getLanguageAcceptedCountRanking,
    getUserLanguageAcceptedCountRank: getUserLanguageAcceptedCountRank,
    getLanguageList: getLanguageList
});

const SUBMISSION_DB_NAME = "ATCODER-PROBLEMS-API";
const VERSION = 1;
function getSubmissionsCount(user, from, to) {
    return __awaiter(this, void 0, void 0, function* () {
        const { count } = yield fetchJson(`${V3_API_URL}/user/submission_count?user=${user}&from_second=${from}&to_second=${to}`);
        return count;
    });
}
const getSubmissionsFromAPI = (user, from) => fetchJson(`${V3_API_URL}/user/submissions?user=${user}&from_second=${from}`);
const INF = Math.pow(10, 10);
function openUserDb(user) {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open(`${SUBMISSION_DB_NAME}-${user}`, VERSION);
        request.onupgradeneeded = (event) => {
            const db = request.result;
            if (event.oldVersion < 1) {
                const store = db.createObjectStore("submissions", { keyPath: "id" });
                store.createIndex("by_epoch_second", "epoch_second");
                store.createIndex("by_problem_id", "problem_id");
                store.createIndex("by_contest_id", "contest_id");
            }
        };
        request.onsuccess = (ev) => resolve(request.result);
        request.onerror = reject;
    });
}
function waitUntilSuccess(request) {
    return new Promise((resolve, reject) => {
        request.onsuccess = _ => resolve(request.result);
    });
}
function getLastEntry(db, storeName) {
    const transaction = db.transaction(storeName, "readonly");
    const submissionsStore = transaction.objectStore(storeName);
    const request = submissionsStore.openCursor(null, "prev");
    return new Promise((resolve, reject) => {
        request.onsuccess = (event) => {
            const cursor = request.result;
            if (!cursor)
                resolve(undefined);
            else
                resolve(cursor.value);
        };
        request.onerror = reject;
    });
}
function getCount(db, storeName) {
    const transaction = db.transaction(storeName, "readonly");
    const submissionsStore = transaction.objectStore(storeName);
    return waitUntilSuccess(submissionsStore.count());
}
function add(db, storeName, entry) {
    const transaction = db.transaction(storeName, "readwrite");
    const submissionsStore = transaction.objectStore(storeName);
    return waitUntilSuccess(submissionsStore.add(entry));
}
function getAll(db, storeName) {
    const transaction = db.transaction(storeName, "readonly");
    const submissionsStore = transaction.objectStore(storeName);
    return waitUntilSuccess(submissionsStore.getAll());
}
function getSubmissions(user) {
    var _a, _b;
    return __awaiter(this, void 0, void 0, function* () {
        const count = yield getSubmissionsCount(user, -1, INF);
        if (count === 0)
            return [];
        let db = yield openUserDb(user);
        let lastEpoch = (_b = (_a = (yield getLastEntry(db, "submissions"))) === null || _a === void 0 ? void 0 : _a.epoch_second) !== null && _b !== void 0 ? _b : -1;
        while ((yield getCount(db, "submissions")) < count) {
            const latestSubmissions = yield getSubmissionsFromAPI(user, lastEpoch + 1);
            if (latestSubmissions.length == 0)
                break;
            for (const submission of latestSubmissions) {
                yield add(db, "submissions", submission);
                lastEpoch = submission.epoch_second;
            }
        }
        return yield getAll(db, "submissions");
    });
}

var submission = /*#__PURE__*/Object.freeze({
    __proto__: null,
    getSubmissions: getSubmissions
});

Object.assign(window, Object.assign(Object.assign(Object.assign({}, information), statistics), submission));