RYM: Auto count average tracks rating with modifiers

.

La data de 30-09-2018. Vezi ultima versiune.

// ==UserScript==
// @name         RYM: Auto count average tracks rating with modifiers
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  .
// @author       You
// @match        https://rateyourmusic.com/release/*
// @match        https://rateyourmusic.com/collection/*
// @match        https://rateyourmusic.com/collection_t/*
// @grant        none
// ==/UserScript==

(() => {
    'use strict';

    //Fix collection_t page table
    if (document.getElementById('mass_tag_form')) {
        const tracksHeader = document.createElement('th');
        tracksHeader.textContent = 'Track ratings';
        const ratingsHeader = document.querySelector('.or_q_header:nth-child(4)');
        ratingsHeader.parentNode.insertBefore(tracksHeader, ratingsHeader.nextSibling);

        const ratingCol = document.querySelectorAll('.or_q_rating');
        [...ratingCol].forEach(item => {
            const reviewCol = document.createElement('td');
            reviewCol.classList.add('or_q_review_td');
            item.parentNode.insertBefore(reviewCol, item.nextSibling);
        });

        const tracksCol = document.querySelectorAll('.or_q_review_td[colspan="5"]');
        [...tracksCol].forEach(item => {
            const parentRow = item.parentNode;
            const previousRow = parentRow.previousSibling;
            const reviewInner = item.querySelector('.or_q_review');

            const reviewsCol = previousRow.querySelector('.or_q_review_td');
            console.log(reviewsCol);
            reviewsCol.appendChild(reviewInner);

            const tagsCol = item.nextSibling;
            previousRow.appendChild(tagsCol);

            parentRow.remove();
        });
    }

    const pagetype = document.querySelector('.release_page') ? 'release' : 'collection';

    const highestPercentCount = (averageRating, ratingsArray) => {
        let highestRatingCount = 0;

        ratingsArray.forEach(rating => {
            if (rating >= averageRating) highestRatingCount++;
        });

        return [parseFloat((highestRatingCount / ratingsArray.length * 100).toFixed(2)), highestRatingCount];
    };

    const ratingsModifiers = {
        2: .7,
        3: .75,
        4: .8,
        5: .85,
        6: 1.1,
        7: 1.2,
        8: 1.3,
        9: 1.5,
        10: 1.9
    };
    const suggestedRatingValues = {
        2: 0,
        3: 1.9,
        4: 2.7,
        5: 3.75,
        6: 5,
        7: 6.75,
        8: 9,
        9: 11.25,
        10: 15
    };
    const bonusRatings = {
        6: .075,
        7: .1,
        8: .15,
        9: .175,
        10: .2
    };

    window.recountRating = ratingBlock => {
        const ratingIsElement = ratingBlock instanceof Element;

        let trackRatings;
        let ratingsAverage;
        let suggestedRating;
        if (ratingIsElement) {
            ratingsAverage = ratingBlock.querySelectorAll('.track_rating_average');
            suggestedRating = ratingBlock.querySelector('.release_rating_suggestion');
            if (pagetype === 'release') {
                trackRatings = ratingBlock.querySelectorAll('.tracklisting .rating_num');
            }

            else if (pagetype === 'collection') {
                trackRatings = ratingBlock.querySelectorAll('.trackratings td:last-child');
            }
        }

        const ratingsArray = ratingIsElement ? [] : ratingBlock;
        let countedTracks = ratingIsElement ? trackRatings.length : ratingsArray.length;
        let totalRating = 0;
        let averageRating;
        let ratingPercent;
        let suggestedTotalRating = 0;
        let suggestedAverageRating = 0;
        let suggestedAverageRatingValue = 0;
        let highestRating = 0;
        let bonusRating = 0.00;
        let highestPercent;
        let averageRatingModifier;

        if (ratingIsElement) {
            [...trackRatings].forEach(element => {
                let ratingValue;
                let ratingText = '';

                if (pagetype === 'release') {
                    ratingText = element.textContent;
                    if (ratingText === '---') {
                        countedTracks--;
                        return;
                    }
                }

                else if (pagetype === 'collection') {
                    ratingText = element.querySelector('img') && parseFloat(element.querySelector('img').getAttribute('title'));
                    if (!ratingText) {
                        countedTracks--;
                        return;
                    }
                }

                ratingValue = parseFloat(ratingText) * 2;
                ratingsArray.push(ratingValue);
            });
        }

        ratingsArray.forEach(ratingValue => {
            let albumRatingTrackValue;
            if (ratingValue > highestRating) highestRating = ratingValue;
            totalRating += ratingValue;
            albumRatingTrackValue = ratingValue * ratingsModifiers[ratingValue];
            suggestedTotalRating += albumRatingTrackValue;
        });

        if (ratingIsElement && countedTracks === 0) {
            suggestedRating.style.display = 'none';
            return [...ratingsAverage].forEach(item => {
                item.style.display = 'none';
            });
        }

        averageRating = parseFloat((totalRating / countedTracks).toFixed(2));
        suggestedAverageRatingValue = parseFloat((suggestedTotalRating / countedTracks).toFixed(2));

        if (ratingIsElement) {
            [...ratingsAverage].forEach(item => {
                item.style.display = 'inline';
                item.querySelector('span').innerHTML = `<b>${averageRating.toFixed(2)}</b> from ${countedTracks}/${trackRatings.length}`;
            });
        }

        if (ratingsArray.length > 4) {
            ratingsArray.forEach(rating => {
                if (bonusRatings[rating] && suggestedAverageRatingValue <= suggestedRatingValues[rating]) {
                    bonusRating += bonusRatings[rating];
                }
            });
            bonusRating = parseFloat(bonusRating.toFixed(2));
            suggestedAverageRatingValue = parseFloat((suggestedAverageRatingValue + bonusRating).toFixed(2));
        }

        suggestedAverageRating += (() => {
            switch(true) {
                case (suggestedAverageRatingValue >= suggestedRatingValues[10] && highestRating === 10):
                    return 10;
                case (suggestedAverageRatingValue >= suggestedRatingValues[9] && highestRating === 10 || suggestedAverageRatingValue >= suggestedRatingValues[9] + .5 && highestRating === 9):
                    return 9;
                case (suggestedAverageRatingValue >= suggestedRatingValues[8] && highestRating >= 9 || suggestedAverageRatingValue >= suggestedRatingValues[8] + .25 && highestRating === 8):
                    return 8;
                case (suggestedAverageRatingValue >= suggestedRatingValues[7] && highestRating >= 8 || suggestedAverageRatingValue >= suggestedRatingValues[7] + .5 && highestRating === 7):
                    return 7;
                case (suggestedAverageRatingValue >= suggestedRatingValues[6]):
                    return 6;
                case (suggestedAverageRatingValue >= suggestedRatingValues[5]):
                    return 5;
                case (suggestedAverageRatingValue >= suggestedRatingValues[4]):
                    return 4;
                case (suggestedAverageRatingValue >= suggestedRatingValues[3]):
                    return 3;
                default:
                    return 2;
            }
        })();

        highestPercent = highestPercentCount(suggestedAverageRating, ratingsArray);
        if ((highestPercent[0] < 33.33 && suggestedAverageRatingValue < suggestedRatingValues[suggestedAverageRating] + .5) || (ratingsArray.length > 6 && highestPercent[1] < 3) || (ratingsArray.length === 3 && highestPercent[1] < 2)) {
            suggestedAverageRating--;
        }

        if (ratingIsElement) {
            suggestedRating.style.display = 'inline-block';
            suggestedRating.innerHTML = `Suggested rating: <b>${(suggestedAverageRating / 2).toFixed(1)}</b> <small>(<span class="release_rating_suggestion_value">${suggestedAverageRatingValue.toFixed(2)}</span>, +${bonusRating}, ${highestPercent[0]}%)</small>`;
            ratingPercent = parseInt(countedTracks / trackRatings.length * 100);
            suggestedRating.style.opacity = ratingPercent === 100 ? 1 : (ratingPercent >= 50 ? .66 : .33);
        }

        return {
            ratingsArray: ratingsArray.join(', '),
            averageRating,
            suggestedAverageRating,
            suggestedAverageRatingValue: suggestedAverageRatingValue.toFixed(2),
            bonusRating,
            highestPercent
        };
    };

    (() => {
        if (pagetype === 'release') {
            const trackRatingsButton = document.getElementById('track_rating_btn');
            const trackRatingsSaveButton = document.getElementById('track_ratings_save_btn');
            const trackRatingsSuccess = document.getElementById('track_rating_success');
            let ratingsSaveInterval;
            let ratingsSaveIntervalIndex = 0;

            const ratingsAverage = [];
            ratingsAverage.push(document.createElement('span'));
            ratingsAverage[0].classList.add('track_rating_average');
            ratingsAverage[0].style.display = 'none';
            ratingsAverage[0].innerHTML = ': <span></span>';

            ratingsAverage.push(ratingsAverage[0].cloneNode(true));
            ratingsAverage[1].innerHTML = `Average${ratingsAverage[1].innerHTML}`;
            ratingsAverage[1].style.fontSize = '11px';
            ratingsAverage[1].style.marginLeft = '5px';

            trackRatingsButton.appendChild(ratingsAverage[0]);
            trackRatingsSuccess.parentNode.insertBefore(ratingsAverage[1], trackRatingsSuccess.nextSibling);

            const suggestedRating = document.createElement('span');
            const catalogTopDiv = document.querySelector('.release_my_catalog');
            suggestedRating.classList.add('release_rating_suggestion');
            suggestedRating.style.fontSize = '11px';
            suggestedRating.style.marginTop = '2px';
            suggestedRating.style.opacity = .3;
            catalogTopDiv.parentNode.insertBefore(suggestedRating, catalogTopDiv.nextSibling);
            //document.getElementById('release_touch_catalog_guidance').style.display = 'none';

            trackRatingsSaveButton.addEventListener('click', () => {
                window.recountRating(document.getElementById('my_catalog'));

                ratingsSaveInterval = setInterval(() => {
                    ratingsSaveIntervalIndex++;
                    if (trackRatingsSaveButton.getAttribute('disabled') || ratingsSaveIntervalIndex >= 15) {
                        console.log(window.recountRating(document.getElementById('my_catalog')));
                        clearInterval(ratingsSaveInterval);
                        ratingsSaveIntervalIndex = 0;
                    }
                }, 300);
            });

            document.getElementById('add_to_list_btn').addEventListener('click', event => {
                let ratingSelectionInput = catalogTopDiv.querySelector('.selection_textarea');
                if (!ratingSelectionInput) {
                    ratingSelectionInput = document.createElement('textarea');
                    ratingSelectionInput.classList.add('selection_textarea');
                    ratingSelectionInput.style.position = 'absolute';
                    ratingSelectionInput.style.top = '-9999px';
                    ratingSelectionInput.style.left = '-9999px';
                    catalogTopDiv.appendChild(ratingSelectionInput);
                }

                let inputValueString = `${document.querySelector('.release_pri_genres').textContent}\n\n[b]${parseFloat(document.querySelector('.release_my_catalog .rating_num').textContent) * 2}/10[/b]`;
                if (suggestedRating.style.display === 'inline-block') inputValueString += ` (${document.querySelector('.release_rating_suggestion_value').textContent})`;
                ratingSelectionInput.value = inputValueString;

                ratingSelectionInput.select();
                document.execCommand('copy');

                Array.from(document.querySelectorAll('#add_to_list_lists a')).forEach(link => {
                    const currentDate = document.querySelector('.album_info td[colspan="2"] b').textContent;
                    if (link.textContent === currentDate) {
                        link.setAttribute('target', '_blank');
                        link.click();
                    }
                });
            });

            console.log(window.recountRating(document.getElementById('my_catalog')));
        }

        else if (pagetype === 'collection') {
            const resultsArray = [];
            const trackRatingsButton = document.querySelectorAll('.or_q_review');

            trackRatingsButton.forEach(item => {
                const trackRatingsHeader = item.querySelector('.track_rating_header');
                if (!trackRatingsHeader) return;
                const titleDiv = trackRatingsHeader.querySelector('div[style="float:left;"]');

                const suggestedRating = document.createElement('span');
                suggestedRating.classList.add('release_rating_suggestion');
                suggestedRating.style.marginLeft = '25px';
                suggestedRating.style.color = '#000';
                suggestedRating.style.opacity = .3;
                titleDiv.parentNode.insertBefore(suggestedRating, titleDiv.nextSibling);

                const ratingsAverage = document.createElement('span');
                ratingsAverage.classList.add('track_rating_average');
                ratingsAverage.style.marginLeft = '25px';
                ratingsAverage.style.fontSize = '11px';
                ratingsAverage.style.color = '#000';
                ratingsAverage.style.display = 'none';
                ratingsAverage.innerHTML = 'Average: <span></span>';
                titleDiv.parentNode.insertBefore(ratingsAverage, titleDiv.nextSibling);

                resultsArray.push(window.recountRating(item));
            });

            console.table(resultsArray);
        }
    })();
})();