ParcourSimple

Simplification de l'affichage des voeux en attente sur ParcourSup!

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         ParcourSimple
// @namespace    https://ypetit.net/
// @version      0.8.2
// @description  Simplification de l'affichage des voeux en attente sur ParcourSup!
// @author       ypetit
// @license      GNU GPLv3
// @match        https://dossierappel.parcoursup.fr/Candidat/admissions?ACTION=0
// @match        https://dossier.parcoursup.fr/Candidat/admissions?ACTION=0
// @icon         https://www.google.com/s2/favicons?sz=64&domain=parcoursup.fr
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';

    GM_addStyle(`
        #psimple{
            position: absolute;
            top: 0;
            left: 0;
            display: block;
            z-index: 99999;
            height: 40px;
            padding: 4px 10px;
            background-color: var(--background-active-blue-france);
            color: #FFF;
        }
        #psimple img{
            margin: 0 10px;
        }
        #psimple .key{
            font-family: Courrier;
            background-color: lightgrey;
            color: #000;
            font-weight: bold;
            border: 1px solid black;
            border-radius: 3px;
            display: inline-block;
            padding: 0 8px 2px;
        }
        #psimple .help{
            display: inline-block;
            padding: 0 10px;
        }
        #parcoursimple {
            position:fixed;
            z-index: 9999;
            top:40px;
            max-height: 98%;
            overflow-y: auto;
            overflow-x: hidden;
            background-color: whitesmoke;
            margin: 10px;
            border: dotted dimgray 1px;
            box-shadow: 10px 8px 5px gray;
        }
        #parcoursimple table{
            background-color: #FFF;
            overflow-x: hidden;
        }
        #parcoursimple thead{
            position: sticky;
            top: 0;
            z-index:99;
        }
        #parcoursimple tr{
             line-height: 20px;
        }
        #parcoursimple tr:nth-child(even) {background: #DDF}
        #parcoursimple tr:nth-child(odd) {background: #EEE}
        #parcoursimple th{
            color: #FFF;
            background-color: var(--background-active-blue-france);
            font-weight: bold;
        }
        #parcoursimple th, #parcoursimple td{
            padding: 2px 4px;
        }
        #parcoursimple .right{
            text-align: right;
        }
        #parcoursimple .bold{
            font-weight: bold;
        }
        #parcoursimple .light{
            color: lightgrey;
        }
        #parcoursimple .ok{
            background-color: lightgreen;
            font-weight: bold;
        }
        #parcoursimple .nan{
            background-color: #CCC;
        }
        #parcoursimple .ko{
            background-color: lightpink;
            font-style: italic;
        }
        #parcoursimple .diff{
            display: inline;
            font-size: x-small;
            min-width: 30px;
        }
        #parcoursimple .indicB{
            font-size: xx-small;
        }
        #parcoursimple .indicB{
            position: relative;
            top: 0;
            height: 20px;
            z-index: 0;
        }
        #parcoursimple .indicB .bar{
            display:inline-block;
        }
        #parcoursimple .indicB .base{
            background-color: lightblue;
            border: 1px solid black;
            text-align: left;
            padding-left: 1px;
        }
        #parcoursimple .indicB .propal{
            background-color: lightgreen;
            border: 1px dashed black;
            text-align: center;
        }
        #parcoursimple .indicB .place{
            background-color: gold;
            border: 1px dashed gray;
            border-right: solid black;
            border-width: 1px 1px 1px 0;
            text-align: center;
        }
        #parcoursimple .indicB .total{
            background-color: coral;
            border: 1px dotted gray;
            text-align: right;
            padding-right: 1px;
        }
        #parcoursimple .blur{
            color: transparent;
            text-shadow: 0 0 20px #002;
        }
        #parcoursimple .arrow {
            border: solid black;
            border-width: 0 2px 2px 0;
            display: inline-block;
            padding: 3px;
        }
        #parcoursimple .arrow.up {
            position: relative;
            top: 3px;
            left: 0px;
            transform: rotate(-135deg);
        }
        #parcoursimple .arrow.down {
            top: -24px;
            position: relative;
            left: -8px;
            transform: rotate(45deg);
        }
        #parcoursimple .marker{
            position: relative;
            top: -10px;
            margin-left: -4px;
        }
        /* add other CSS here */
    `);

    document.addEventListener('keyup', function (e) {
        // if click on a
        if (65 === e.which) {
            const x = document.getElementById('parcoursimple');
            x.style.display = (x.style.display === "none") ? "block" : "none";
        } else if (66 === e.which) {
            document.querySelectorAll("#parcoursimple tbody td:first-child").forEach(x => x.classList.add('blur'));
            document.querySelectorAll("#parcoursimple tbody td:nth-child(2)").forEach(x => x.classList.add('blur'));
        }
    });

    $("body").prepend('<div id="psimple"><img src="/favicon.ico"> ' +
        'Clavier : ' +
        '<div class="help"><div class="key">a</div> affiche/cache le tableau</div>' +
        '|<div class="help"><div class="key">b</div> floute les noms des écoles et formations</div>' +
        '</div>');
    $("body").append(
        '<div id="parcoursimple" name="parcoursimple">' +
        '<table id="parcoursimple_table">' +
        '<thead><tr>' +
        ' <th>Ecole</th>' +
        ' <th>Cursus</th>' +
        ' <th>Places<br/>Dispo.</th>' +
        ' <th>Dernier<br/>2022</th>' +
        ' <th>Position au<br/>Classement</th>' +
        ' <th>Dernière<br/>Proposition</th>' +
        ' <th>Place en<br/>Liste</th>' +
        ' <th width="300px">Visualisation</th>' +
        ' <th>Total<br/>Attente</th>' +
        '</tr></thead>' +
        '<tbody id="parcoursimple_table_body"></tbody></table></div>'
    );

    // get all wishes
    const cards = Array.from(document.querySelectorAll(".psup-wish-card--info"));
    const wishes = [];

    class Wish {
        constructor(school, course, id, waiting_position, waiting_total, places, ranking, last, lastLastYear) {
            this.school = school;
            this.course = course;
            this.id = id;
            this.waiting_position = Number(waiting_position);
            this.waiting_total = Number(waiting_total);
            this.places = Number(places);
            this.ranking = Number(ranking);
            this.last = Number(last);
            this.lastLastYear = Number(lastLastYear);
            this.error = false;
        }

        setError() {
            this.error = true;
            return this;
        };

        show() {
            let ligne = "<tr>";
            ligne += "<td>" + this.school + "</td>";
            ligne += "<td>" + this.course + "</td>";
            if (this.error) {
                ligne += "<td colspan='7'>Une erreur est survenue, classement indisponible dans ParcourSimple :(</td>";
            } else {
                ligne += "<td class='right'>" + this.places + "</td>";
                ligne += "<td class='right'>" + (Number.isNaN(this.lastLastYear) ? "???" : this.lastLastYear) + "</td>";
                ligne += "<td class='right " + this.rankColor() + "'>" + this.ranking + this.rankDiff() + "</td>";
                ligne += "<td class='right'>" + this.last + "</td>";
                ligne += "<td class='right bold'>" + this.waiting_position + "</td>";
                ligne += "<td>"
                    + "<div class='indicB'>"
                    + "<div class='bar base' style='width:" + (this.places / (this.last + this.waiting_total) * 100) + "%'>" + this.places + "</div>"
                    + "<div class='bar propal' style='width:" + ((this.last - this.places) / (this.last + this.waiting_total) * 100) + "%'>" + (this.last - this.places) + "</div>"
                    + "<div class='bar place' style='width:" + (this.waiting_position / (this.last + this.waiting_total) * 100) + "%'>" + this.waiting_position + "</div>"
                    + "<div class='bar total' style='width:" + ((this.waiting_total - this.waiting_position) / (this.last + this.waiting_total) * 100) + "%'>" + (this.waiting_total - this.waiting_position) + "</div>"
                    + "<div class='marker' style='left:" + ((this.last + this.waiting_position) / (this.last + this.waiting_total) * 100) + "%'>"
                    + "<span class='arrow up'></span>"
                    + "<span class='arrow down'></span>"
                    + "</div>"
                    + "</div>"
                    + "</td>";
                ligne += "<td class='right light'>" + this.waiting_total + "</td>";
            }
            ligne += "</tr>";
            return ligne;
        }

        rankColor() {
            return isNaN(this.lastLastYear) ? "nan" : this.lastLastYear > this.ranking ? "ok" : "ko";
        }

        rankDiff() {
            return (Number.isNaN(this.lastLastYear) ? "" : " <div class='diff'>(" + (this.ranking - this.lastLastYear) + ")</div>");
        }
    }

    const promises = [];
    cards.forEach(card => {
        const school = card.querySelectorAll('.psup-wish-card__school')[0].innerHTML;
        const course = card.querySelectorAll('.psup-wish-card__course')[0].innerHTML;
        try {
            const onclick = card.querySelectorAll('button')[0].getAttribute('onclick');
            const id = onclick.substring(onclick.indexOf("&") + 1, onclick.lastIndexOf("'"));
            const URL = "admissions?ACTION=2&" + id + "&frOpened=false&frJsModalButton=true";
            promises.push($.ajax({
                url: URL,
                type: "GET",
                dataType: "html",
                success: function (h) {
                    const template = document.createElement('div');
                    template.innerHTML = h.trim();
                    const waiting_position = template.querySelector("div ul li:nth-child(1) b").innerHTML;
                    const waiting_total = template.querySelector("div ul li:nth-child(2) b").innerHTML;
                    // --------------
                    const places = template.querySelector(".fr-alert ul li:nth-child(1) b").innerHTML;
                    const ranking = template.querySelector(".fr-alert ul li:nth-child(2) p b").innerHTML;
                    const last = template.querySelector(".fr-alert ul li:nth-child(3) b").innerHTML;
                    const lastYear = template.querySelector(".fr-alert ul li:nth-child(4) b");
                    const lastLastYear = (lastYear) ? lastYear.innerHTML : "?";
                    wishes.push(new Wish(school,
                        course,
                        id,
                        waiting_position,
                        waiting_total,
                        places,
                        ranking,
                        last,
                        lastLastYear
                    ));
                },
                error: function (h) {
                    console.err(h);
                },
                complete: function () {
                }
            }));
        } catch (error) {
            // log the error in the console
            console.log(error);
            // send feedback
            console.info(card);
            // add placeholder
            wishes.push(new Wish(school, course).setError());
        }
    });
    $.when.apply($, promises).then(function () {
        wishes.sort((a, b) => a.waiting_position - b.waiting_position);
        let r = document.getElementById("parcoursimple_table_body");
        for (let w in wishes) {
            r.innerHTML += wishes[w].show().trim();
        }
    });

})();