User:Aaron Schulz/history.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//[[Category:Wikipedia administrators who use VoA script|{{PAGENAME}}]]<nowiki>
//Helper tools

// History line parsing
importScript('User:Voice of All/Dates.js');

wiki_bot_list = {};
wiki_sysop_list = {};

function fillMapOfUsersInGroup(group, id_by_name) {
    var api = new mw.Api();

    return api.get({
        action: 'query',
        list: 'allusers',
        augroup: group,
        aulimit: 5000,
        format: 'json'

    }).done(function (res) {
        if (res && res.query && res.query.allusers != undefined) {
            for (var i = 0; i < res.query.allusers.length; i++) {
                id_by_name[res.query.allusers[i].name] = res.query.allusers[i].userid;
            }
        } else if (res && res.error) {
            alert('Error: API returned error code "' + res.error.code + '": ' + res.error.info);
        } else {
            alert('Error: Unknown result from API.');
        }
    });
}

function addTab(href, text, id, tooltip) {
    mw.util.addPortletLink("p-cactions", href, text, id, tooltip);
}

//History stats tabs
$(addhiststats);

function addhiststats() {
    if (location.href.indexOf('&action=history') != -1 && location.href.indexOf('&jsaction=validate') == -1) {
        addTab("javascript:histstats()", "%", "ca-stats", "History statistics", "");
    } else if (location.href.search(/=(Special:Log|Special%3ALog).*&user=[^&]+/) != -1 && location.href.search(/=Special:Log\/|&type=\w/) == -1) {
        addTab("javascript:logstats()", "%", "ca-stats", "User's log statistics", "");
        addTab("javascript:masterview(5000)", "5k", "ca-v5k", "view last 5000 actions", "");
    } else if (document.title.indexOf('User contributions') == 0) {
        addTab("javascript:sumperentcuse()", "%", "ca-sumuse", "User's edit statistics", "");
    } else if (document.title.search(/User:|User talk:/) == 0 && document.title.indexOf('/') == -1 && location.href.search(/Special:/) == -1) {
        addTab("javascript:get_userlist_xml()", "$", "ca-stats6", "Shows user groups", "");
    }
}

//END

function logstats() {
    var body = document.getElementById('bodyContent');
    if (document.getElementById('contentSub').innerHTML.indexOf('Viewing log statistics ') != -1) {
        alert("Results already shown.");
        return;
    }
    var protects = 0;
    var unprotects = 0;
    var deletes = 0;
    var patrols = 0;
    var reviews = 0;
    var undeletes = 0;
    var blocks = 0;
    var range_blocks = 0;
    var unblocks = 0;
    var moves = 0;
    var rights = 0;
    var botsf = 0;
    var botsd = 0;
    var renames = 0;
    var uploads = 0;
    var other = 0;
    if (!body.getElementsByTagName('ul')[0]) {
        alert('No log events found!');
        return;
    }
    var l = body.getElementsByTagName('ul')[0].getElementsByTagName('li');
    for (var i = 0; i < l.length; i++) {
        var html = l[i].innerHTML;
        if (html.indexOf('</a>) moved <a href=') != -1) {
            moves += 1;
        } else if (html.indexOf('</a>) uploaded "<a href=') != -1) {
            uploads += 1;
        }
        //sysops
        else if (html.indexOf('</a>) blocked "<a href=') != -1) {
            blocks += 1;
            if (l[i].getElementsByTagName('a')[3].innerHTML.search(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d\d/) != -1) {
                range_blocks += 1;
            } else if (l[i].getElementsByTagName('a')[4].innerHTML.search(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d\d/) != -1) {
                range_blocks += 1;
            }
        } else if (html.indexOf('</a>) unblocked <a href=') != -1) {
            unblocks += 1;
        } else if (html.indexOf('</a>) protected <a href=') != -1) {
            protects += 1;
        } else if (html.indexOf('</a>) unprotected <a href=') != -1) {
            unprotects += 1;
        } else if (html.indexOf('</a>) deleted "<a href=') != -1) {
            deletes += 1;
        } else if (html.indexOf('</a>) restored "<a href=') != -1) {
            undeletes += 1;
        } else if (html.indexOf('</a>) marked <a href=') != -1) {
            patrols += 1;
        } else if (html.indexOf('</a>) reviewed "<a href=') != -1) {
            reviews += 1;
        }
        //bcrats
        else if (html.search(/<\/a>\) changed <a href=.+<\/a>'s rights from/) != -1) {
            rights += 1;
        } else if (html.indexOf('<span class="comment">\(Renamed the user') != -1) {
            renames += 1;
        } else if (html.indexOf('/a>) granted bot status to <a href=') != -1) {
            botsf += 1;
        } else if (html.indexOf('</a>) removed bot status from <a href=') != -1) {
            botsd += 1;
        }
    }
    //Timing
    var first_date = l[0].innerHTML.split(' <a href=')[0].split('<A HREF=')[0];
    var last_date = l[i - 1].innerHTML.split(' <a href=')[0].split('<A HREF=')[0];
    var current_date = new Date();
    current_date = current_date.toUTCString().replace(/GMT/, "UTC");
    var E = l.length;
    var totdays = getElapsedTime(current_date, last_date);
    var RoundedFrameDays = Math.round((1) * totdays) / 1;
    if (RoundedFrameDays == 0) RoundedFrameDays = 1;
    //
    var average = E / totdays;
    document.getElementById('contentSub').innerHTML = '<br><span style="color:darkblue;"><strong>Viewing log statistics data for this user for the </span>' + E + ' <span style="color:darkblue;">events shown on this page</span></strong>';
    //
    var TimeDATE = '<span style="color:blue;"><strong>Time range:</span> ' + RoundedFrameDays + ' approximate day(s) of log items on this page</strong></span><br> ' + 'Current time: ' + current_date + ' <strong>||</strong> Oldest action on: ' + last_date + ' (UTC)<br>';
    //
    document.getElementById('bodyContent').innerHTML = '<div id="contentSub">' + document.getElementById('contentSub').innerHTML + '</div>' + TimeDATE + '<span style="color:black;"><strong>Average actions per day:</span> ' + Math.round((100) * average) / 100 + '</strong> (for last ' + E + ' actions(s))<br>' + '<strong><span style="color:blue;">User actions:</strong></span><br>' + '<span style="color:darkgreen;"><strong>Page moves:</span> ' + Math.round((100) * (100 * (moves) / E)) / 100 + '</strong>% (' + moves + ' actions(s))<br>' + '<span style="color:darkblue;"><strong>Uploads:</span> ' + Math.round((100) * (100 * (uploads) / E)) / 100 + '</strong>% (' + uploads + ' actions(s))<br>' + '<strong><span style="color:blue;">Sysop actions:</strong></span><br>' + '<span style="color:black;"><strong>Page protects:</span> ' + Math.round((100) * (100 * (protects) / E)) / 100 + '</strong>% (' + protects + ' actions(s))<br>' + '<span style="color:grey;"><strong>Page unprotects:</span> ' + Math.round((100) * (100 * (unprotects) / E)) / 100 + '</strong>% (' + unprotects + ' actions(s))<br>' + '<span style="color:darkred;"><strong>Patrols:</span> ' + Math.round((100) * (100 * (patrols) / E)) / 100 + '</strong>% (' + patrols + ' actions(s))<br>' + '<span style="color:darkred;"><strong>Deletes:</span> ' + Math.round((100) * (100 * (deletes) / E)) / 100 + '</strong>% (' + deletes + ' actions(s))<br>' + '<span style="color:black;"><strong>Undeletes:</span> ' + Math.round((100) * (100 * (undeletes) / E)) / 100 + '</strong>% (' + undeletes + ' actions(s))<br>' + '<span style="color:red;"><strong>Blocks:</span> ' + Math.round((100) * (100 * (blocks) / E)) / 100 + '</strong>% (' + blocks + ' actions(s)) <i>(' + range_blocks + ' range block(s))</i><br>' + '<span style="color:black;"><strong>Unblocks:</span> ' + Math.round((100) * (100 * (unblocks) / E)) / 100 + '</strong>% (' + unblocks + ' actions(s))<br>' + '<strong><span style="color:blue;">Bureaucrat actions:</strong></span><br>' + '<span style="color:darkblue;"><strong>Promotions:</span> ' + Math.round((100) * (100 * (rights) / E)) / 100 + '</strong>% (' + rights + ' actions(s))<br>' + '<span style="color:#FF6600;"><strong>Bot flaggings:</span> ' + Math.round((100) * (100 * (botsf) / E)) / 100 + '</strong>% (' + botsf + ' actions(s))<br>' + '<span style="color:darkred;"><strong>Bot de-flaggings:</span> ' + Math.round((100) * (100 * (botsd) / E)) / 100 + '</strong>% (' + botsd + ' actions(s))<br>' + '<span style="color:black;"><strong>Renames:</span> ' + Math.round((100) * (100 * (renames) / E)) / 100 + '</strong>% (' + renames + ' actions(s))<br>' + body.innerHTML.split('<!-- start content -->')[1];
}

function masterview(number) {

    if (location.href.search(/&limit=\d+/) != -1) {
        var limit = location.href.match(/&limit=\d+/g)[0];
        var url = location.href.replace(limit, '&limit=' + number);
    } else if (location.href.indexOf('Special:Contributions/') != -1) {
        var name = location.href.split('Special:Contributions/')[1];
        var url = mw.config.get('wgScript') + '?title=Special:Contributions&limit=' + number + '&target=' + name;
    } else {
        var url = location.href + '&limit=' + number;
    }
    location.href = url;
}

function get_userlist_xml() {
    document.getElementById('contentSub').innerHTML += '<br><strong>Searching for current usergroup information.' + '\n' + 'Please wait...</strong>';
    gml_xmlhttp = HTTPClient();
    if (!gml_xmlhttp) return;
    if (mw.config.get('wgNamespaceNumber') == 2 || mw.config.get('wgNamespaceNumber') == 3) {
        user_name = mw.config.get('wgTitle');
    } else // invalid?
    {
        return;
    }
    var pageurl = mw.config.get('wgScriptPath') + '/api.php?action=query&list=users&usprop=groups|registration|editcount|blockinfo&format=xml&ususers=' + encodeURIComponent(user_name);
    gml_xmlhttp.open("GET", pageurl, true);
    gml_xmlhttp.onreadystatechange = alertget;
    gml_xmlhttp.send(null);
}

function alertget() {
    if (gml_xmlhttp.readyState != 4)
        return;
    xml = gml_xmlhttp.responseText;
    doc = gml_XMLParse(xml);
    var user = doc.getElementsByTagName('user');
    var info;
    var blocked = null;
    if (user[0].attributes.getNamedItem("missing") == null && user[0].attributes.getNamedItem("invalid") == null) {
        gset = doc.getElementsByTagName('groups');
        if (gset[0]) {
            var groups = gset[0].getElementsByTagName("g");
            info = groups[0].textContent;
            for (var i = 1; i < groups.length; i++) {
                info += ", " + groups[i].textContent;
            }
        } else {
            info = "(None)"
        }
        info += "; ";
        info += user[0].attributes.getNamedItem("editcount").value + " edits; ";
        info += "Registered " + user[0].attributes.getNamedItem("registration").value;
        if (user[0].attributes.getNamedItem("blockedby") != null)
            blocked = "Blocked by " + user[0].attributes.getNamedItem("blockedby").value + ": " + user[0].attributes.getNamedItem("blockreason").value;
    } else info = '(username invalid)';
    document.getElementById('contentSub').innerHTML += '<br><b><span style="color:blue;">' + info + '</span>' + (blocked == null ? '' : '<br><span style="color:red;">' + blocked + '</span>') + '</b>';
}

function userget() {
    if (gml_xmlhttp.readyState != 4)
        return;
    alert("Usergroup list obtained. Seaching for " + user_name + ".");
    xml = gml_xmlhttp.responseText.replace(/<body.*"ns-4">/, '<body class="ns-4">');
    doc = gml_XMLParse(xml);
    var l = doc.getElementsByTagName('li');
    var user_name = document.getElementById('bodyContent').getElementsByTagName('a')[0].innerHTML;
    var user_sysop = 'no';
    for (i = 0; i < l.length; i++) {
        var name = l[i].getElementsByTagName('a')[0].innerHTML;
        if (user_name == name) {
            user_sysop = 'yes';
            break;
        }
    }
    return user_sysop;
}

// ********************************
// User edit statistics
// ********************************
contribs_first = true;
STATS_ALL_JS_RAN = false;

function sumperentcuse() {
    if (document.getElementById('contentSub').innerHTML.indexOf('Viewing contribution data for') != -1) {
        alert("Results already shown.");
        return;
    }
//check name
    rights_status = '';
    Username = 'this user';
    if (location.href.indexOf('username=') != -1) {
        Username = location.href.split('username=')[1].split('&')[0].replace(/\+/g, ' ');
    } else {
        Username = document.getElementById('bodyContent').getElementsByTagName('a')[0].innerHTML;
    }
    theusername = 'user </span><span style="color:purple;">' + Username + '</span>';
    document.getElementById('contentSub').innerHTML += "<br><strong>Analyzing contributions...please wait</strong>";
    gml_xmlhttp = HTTPClient();
    var pageurl = mw.config.get('wgScript') + '?title=Special:Log&type=upload&user=' + Username + '&page=&limit=5000&useskin=standard';
    gml_xmlhttp.open("GET", pageurl, true);
    gml_xmlhttp.onreadystatechange = sumperentcuse2;
    gml_xmlhttp.send(null);
}

// Get number of non-revert uploads
edits_page_compared_js = 0;

function sumperentcuse2() {
    if (gml_xmlhttp.readyState != 4) return;
    xml = gml_xmlhttp.responseText;
    document.getElementById('contentSub').innerHTML += "<br><strong>Analyzing uploads...</strong>";
    Uploads = 0;
    Uploads_length = 0;
    var up_list_unique = '|';
    if (xml.indexOf('<ul>') != -1) {
        xml = xml.split('<ul>')[1].split('</ul>')[0];
        Uploads_length = xml.split('<li>').length - 1;
        var l = xml.split('<li>');
        for (z = 0; z < l.length; z++) {
            var litxt = l[z].split('</li>')[0];
            var name = l[z].split('</li>')[0];
            if (name.indexOf(') uploaded "<a href="') != -1) {
                name = name.split(') uploaded "<a href="')[1];
            } else if (name.indexOf(') uploaded "<A href="') != -1) {
                name = name.split(') uploaded "<A href="')[1];
            } else {
                name = '';
            }
            name = name.split('" title="')[0];
            if (up_list_unique.indexOf('|' + name + '|') == -1 && name.indexOf('action=edit') == -1 && name != '' && litxt.indexOf('(Reverted to ') == -1) {
                up_list_unique += name + '|';
            }
        }
    }
    Uploads = up_list_unique.split('|').length - 2;
    sumperentcuse3();
}

//initializing
EC_tot = 0;
ave_tot = 0;
//
Pagelist = '';
TE = 0;
sum_edits = 0;
sumart_edits = 0;
Art_minor = 0;
Artm_to_minor = 0;
Sum_value = -1;
NS = 0;
M = 0;
R = 0;
EX = 0;
UM = 0;
MAM = 0;
//minor/major flagging
All_markedMaj = 0;
All_markedMin = 0;
Minor_withsum = 0;
Major_withsum = 0;
Major_edit_sum = 0;
Major_article_sum = 0;
Minor_article_sum = 0;
Article_minor_edits = 0;
Article_major_edits = 0;
Is_minor = 0;
Not_minor = 0;
//namespaces
Talk = 0;
User = 0;
Usertalk = 0;
MediawikiE = 0;
Wikipediatalk = 0;
WikipediaE = 0;
Images = 0;
Template = 0;
Category = 0;
Portal = 0;
Help = 0;
TTalk = 0;
ITalk = 0;
HTalk = 0;
PTalk = 0;
CTalk = 0;
MTalk = 0;
ArticleE = 0;
//unique pages
Unique_pages = 0;
//degree of contribution
ArtSig = 0;
ArtSf = 0;
ArtRv = 0;
ArtM = 0;
ArtUM = 0;
//type of non-article contribs
PR_tot = 0;
BOT_tot = 0;
RAfC_tot = 0;
CP_tot = 0;
FAC_tot = 0;
AN_tot = 0;
RfA_tot = 0;
AfC_tot = 0;
RfA_votes_S = 0;
RfA_votes_O = 0;
XfD_tot = 0;
AWB_edits = 0;
Protections = 0;
Moves = 0;
Dummy_Moves = 0;
Redirects = 0;
User_warnings = 0;
User_welcomes = 0;
//block list (for "compare" compatibility)
blk_num = 0;

//
function sumperentcuse3() {
    var compare = 0;
    document.getElementById('contentSub').innerHTML += "<br><strong>Analyzing edits...</strong>";
    if (document.getElementById('contentSub').innerHTML.indexOf('edit comparison between') != -1) {
        compare = 1;
    }
    if (Username == 'Talk' && compare == 0) {
        theusername = '</span><span style="color:purple;">this IP address</span>';
    } else if (compare == 1) {
        theusername = '</span><span style="color:purple;">these users</span>';
    } else if (Username == 'navigation') {
        theusername = '</span><span style="color:purple;">these IP addresses</span>';
    }
    if (Username in wiki_sysop_list) {
        rights_status = ' </span><span style="color:blue;">(sysop)</span><span style="color:purple;">';
    }
    var cnt = 0;
//tagging edits
    var rvlink = '<span style="color:darkred;"><strong>rv</strong></span>';
    var nslink = '<strong><span style="color:darkgrey;">no summary</span></strong>';
    var mslink = '<strong>minor</strong>';
    var tplink = '<strong>most recent</strong>';
    var c = document.getElementById('contentSub');
    var a = c.getElementsByTagName('a');
    l = document.getElementById('pagehistory').getElementsByTagName('li');
    if (l[0] == undefined) {
        alert("Nothing to analyze!");
        return;
    }
    var link_offset = 0; // for old revdelete links (show/hide)
//For loop START
    for (i = 0; i < l.length; i++) {
        // check if this is a block even -- hacky
        // there to make this work with compare contribs, where these events are listed...
        if (l[i].innerHTML.search(/ (unblocked|blocked)( "| )<[Aa] href="/) == -1) {
            var tpnt = '';
//find pagename, and split li text after it to get summary text, the k loop fixes this for autosums
            if (l[i].getElementsByTagName('a')[2]) {
                tpnt = l[i].getElementsByTagName('a')[2].innerHTML;
            }
            var Careful = 'no';
            var Revert = 'no';
            var Minor = 'no';
            var Superfic = 'no';
            var Notable = 'no';
            var Minor_nonrv = -1;
            var Minor_or_sum = -1;
            var Marked_as_minor = 'no';
            var Namespace_type = 'non-article';
            var Namespace = '';
            var Sum_value = -1;
//get the edit summary
            var autoc = 'no';
            var the_sum = '';
            for (k = 0; k < l[i].getElementsByTagName('span').length; k++) {
                if (l[i].getElementsByTagName('span')[k].className == 'minor') {
                    Minor_nonrv = 1;
                    Minor_or_sum = 1;
                    Minor = 'yes';
                    Marked_as_minor = 'yes';
                } else if (l[i].getElementsByTagName('span')[k].className == 'comment') {
                    Sum_value = 1;
                    Minor_or_sum = 1;
                    var Careful = 'no';
                    the_sum = l[i].getElementsByTagName('span')[k].innerHTML;
                    // remove any tag cruft
                    the_sum = the_sum.replace(/(<span class="autocomment">.+<\/span>|→)/gi, '');
                    // remove parens
                    //the_sum = the_sum.replace(/^\(|\)$/i,'');
                    break;
                } else {
                    Sum_value = -1;
                    if (Minor == 'no') {
                        Minor_or_sum = -1;
                    }
                }
            }
            //End of k loop
            //get pagename (var "Namespace" is really just the page name here)
            //edit type passes included here
            if (l[i].getElementsByTagName('a')[3 + link_offset]) {
                var Namespace = l[i].getElementsByTagName('a')[3 + link_offset].innerHTML;
            }
            if (Pagelist.indexOf('|' + Namespace + '|') == -1) {
                Pagelist += '|' + Namespace + '|';
                Unique_pages += 1;
            }
            //get protections
            if (the_sum.search(/\((Protected|Unprotected) .+: .+/) == 0) {
                Protections += 1;
            }
            //get moves
            else if (the_sum.search(/\(moved <a href=.+<.a> to <a href=.+<.a>/i) == 0 && Marked_as_minor == 'yes') {
                Moves += 1;
            }
            //get moves
            else if (the_sum.search(/\(moved <a href=.+<.a> to <a href=.+<.a>:/i) == 0 && Marked_as_minor == 'no') {
                Dummy_Moves += 1;
            }
            //get redirects
            else if (the_sum.search(/(redirect |redirected |redir|red\.|#redirect|#redir|#red\.|page redir|redirection to|r\)|rd\)|rd\.\))|(fix|make|create|double|repair|db|dbl|bypass|skip) redir/i) != -1) {
                Redirects += 1;
            }
            //get AWB edits
            if (the_sum.search(/using <a href="\/wiki\/Wikipedia:AutoWikiBrowser"| using <a href="\/wiki\/(WP|[Ww]iki|[Ww]ikipedia):AWB"/i) != -1) {
                AWB_edits += 1;
                Careful = 'yes';
                Superfic = 'yes';
            }
            //remove links from summary
            the_sum = the_sum.replace(/<a href=([^>\]])+>([^<]+)<\/a>/ig, '$2');
            //sort namespaces
            if (Namespace.indexOf('Talk:') == 0) {
                Namespace_type = 'talk';
                Talk = Talk + 1;
            } else if (Namespace.indexOf('User:') == 0) {
                Namespace_type = 'talk';
                User = User + 1;
            } else if (Namespace.indexOf('User talk:') == 0) {
                Namespace_type = 'talk';
                Usertalk = Usertalk + 1;
                if (the_sum.search(/\(test|\(warn|test\d|test[-: ]|warn (user|vandal)|user notice:|warning[ :\)]|vandism|vandaliz|please stop|your (recent|edits)|regarding (changes|edits)|changes to/i) != -1) {
                    User_warnings += 1;
                } else if (the_sum.search(/welcome[ :\)!]|welc[ :\)!]|welc.[ :\)!]|(create|make) an account/i) != -1) {
                    User_welcomes += 1;
                }
            } else if (Namespace.indexOf('MediaWiki:') == 0) {
                MediawikiE = MediawikiE + 1;
            } else if (Namespace.search(/(Commons|Wikipedia) talk:/) == 0) {
                Namespace_type = 'talk';
                Wikipediatalk = Wikipediatalk + 1;
            } else if (Namespace.search(/(Commons|Wikipedia):/) == 0) {
                WikipediaE = WikipediaE + 1;
                if (Namespace.search(/Wikipedia:Peer review\//) == 0) {
                    PR_tot += 1;
                } else if (Namespace.search(/Wikipedia:Articles for creation\//) == 0) {
                    AfC_tot += 1;
                } else if (Namespace.search(/Wikipedia:[Rr]equests for ([Cc]omment|[Aa]rbitration)/) == 0) {
                    RAfC_tot += 1;
                } else if (Namespace.search(/for [Dd]eletion|Deletion [Rr]eview|(Redirects|Categories) for [Dd]iscussion/) != -1) {
                    XfD_tot += 1;
                } else if (Namespace.search(/Wikipedia:Copyright/) != -1) {
                    CP_tot += 1;
                } else if (Namespace.search(/Wikipedia:Featured (article|picture|list) candidates/) != -1) {
                    FAC_tot += 1;
                } else if (Namespace.search(/Wikipedia:(Administrators' noticeboard|Administrator intervention against vandalism|Requests for investigation|WikiProject on open proxies|Long term abuse|Suspected sock puppets|Abuse reports|Personal attack intervention noticeboard|Requests for checkuser)/) != -1) {
                    AN_tot += 1;
                } else if (Namespace.search(/Wikipedia:Requests for (adminship|bureaucratship)/) == 0) {
                    RfA_tot += 1;
                    if (the_sum.search(/\((support|supp\.|sup\.|supp|endorse|(e|s|ss|ws)[\.\)]|nominate\)|new )|(endorse|support|supp|sup\.|absolutely|definitely|[\.\(][es])[\);:]/i) != -1) {
                        RfA_votes_S += 1;
                    } else if (the_sum.search(/\((oppose|op\.|opp|reject|no[\.\)]|(o|wo|so)[\.\)])|(oppose|opp|op\.|absolutely not|definitely not|[\.\(]o)[\);:]/i) != -1) {
                        RfA_votes_O += 1;
                    }
                } else if (Namespace.indexOf('Wikipedia:Bots/Requests for approval') == 0) {
                    BOT_tot += 1;
                }
            } else if (Namespace.indexOf('Image:') == 0) {
                Images = Images + 1;
            } else if (Namespace.indexOf('Template:') == 0) {
                Template = Template + 1;
            } else if (Namespace.indexOf('Category:') == 0) {
                Category = Category + 1;
            } else if (Namespace.search(/(Portal|Creator):/) == 0) {
                Portal = Portal + 1;
            } else if (Namespace.indexOf('Help:') == 0) {
                Help = Help + 1;
            } else if (Namespace.search(/Template talk:/) == 0) {
                Namespace_type = 'talk';
                TTalk = TTalk + 1;
            } else if (Namespace.search(/Image talk:/) == 0) {
                Namespace_type = 'talk';
                ITalk = ITalk + 1;
            } else if (Namespace.search(/Category talk:/) == 0) {
                Namespace_type = 'talk';
                CTalk = CTalk + 1;
            } else if (Namespace.search(/(Portal|Creator) talk:/) == 0) {
                Namespace_type = 'talk';
                PTalk = PTalk + 1;
            } else if (Namespace.search(/Help talk:/) == 0) {
                Namespace_type = 'talk';
                HTalk = HTalk + 1;
            } else if (Namespace.search(/MediaWiki talk:/) == 0) {
                Namespace_type = 'talk';
                MTalk = MTalk + 1;
            } else {
                Namespace_type = 'article';
            }
//begin passes
//basic flagging
            if (Sum_value == -1) {
                NS = NS + 1;
                if (STATS_ALL_JS_RAN == false) l[i].innerHTML += ' (' + nslink + ') #' + NS;
            }
            if (l[i].innerHTML.indexOf('(top)') != -1) {
                TE = TE + 1;
            }
//article reverts
            if (Namespace_type == 'article' && Sum_value == 1 && the_sum.search('(P|p)rotect(ed| )') == -1) {
                if (the_sum.search(/(RV|Rv|rV)[Vv]|-[ -]rv|[Rr](V|v)|\(rv|\(R[Vv]|RV[ :;\)]|Rv[ :;\)]|rv[ :;\)]|[Rr]m |[Rr]mv/) != -1 || the_sum.search(/[ \(]stop |[ \(]rever(t|ted|ting)|rever(t|ted|ting)[ :;\)]|reversion|graffitti| nonsense|vandal ed| vandal|rollback[ :\.\)]| irrelevant| unverified/i) != -1 || the_sum.search(/dele(t|ed|e) vandal|linkspam|remov(ed|ing)|delet(ed|ing) |reinsta(t|ted)[ :\.\)]|restor(e|ed|ing)[ :\.\)]| previous[ :\.\)]| version /i) != -1 || the_sum.search(/re-added|re-inserted|added back /i) != -1 || the_sum.search(/back again|POINT|no such |speculation\)| such thing| agree with[ :\.\)]| don't[ :\.\)]| do not[ :\.\)]|\(surely[ :\.\)]|\?[ :\.\)]|\?\.|\?\)/i) != -1 || the_sum.search(/linkspam[ :\.\)]|nonsense[ :\.\)]|vandal ed|ollback[ :\.\)]| vandal| vandals | vandal[ \.\)]|trolling|delete[:\.\)]| revision \d+ by /i) != -1) {
                    Superfic = 'no';
                    Notable = 'no';
                    Significant = 'no';
                    Minor_nonrv = -1;
                    Revert = 'yes';
                    R = R + 1;
                    if (STATS_ALL_JS_RAN == false) l[i].innerHTML += ' (' + rvlink + ') #' + R;
                }
            }
//long summary article reverts
            else if (Namespace_type == 'article' && Sum_value == 1 && the_sum.search('(P|p)rotect(ed| )') == -1 && the_sum.length > 25) {
                if (is_long_revert(the_sum)) {
                    Superfic = 'no';
                    Notable = 'no';
                    Significant = 'no';
                    Minor_nonrv = -1;
                    Revert = 'yes';
                    R = R + 1;
                    if (STATS_ALL_JS_RAN == false) l[i].innerHTML += ' (' + rvlink + ') #' + R;
                }
            }
//non-article reverts
            else if (Namespace_type != 'article' && Sum_value == 1 && the_sum.search('rotect(ed| )') == -1) {
                if (the_sum.search(/\((RVv|Rvv|rVv|-[ -]rv|rv|R[Vv]|RV|rev|rest|restore|Rv|rv|RrV|Rrv)[ :;\)]|BOT - Revert|BOT - [Rr]v\. |BOT - [Rr]v |reverted edits by /) != -1 || the_sum.search(/[ \(]rever(t|ted|ting)[ :;\)](comment|note|reply|resp|rude|incivil|personal|edits by|changes by)|reversion|graffitti| nonsense|vandal edit|rollback[ :\.\)]| irrelevant|(t|ed|e) vandal|linkspam|remov(ed|ing)|delet(ed|ing) |reinsta(t|ted)|restore(d) |(un|n)ecessary /i) != -1) {
                    Minor_nonrv = -1;
                    Revert = 'yes';
                    R = R + 1;
                    if (STATS_ALL_JS_RAN == false) l[i].innerHTML += ' (' + rvlink + ') #' + R;
                }
            }
//
//analysis
            if (Marked_as_minor == 'yes' && Revert == 'no' && Sum_value == 1) {
                All_markedMin = All_markedMin + 1;
            }
            if (Marked_as_minor == 'no' && Revert == 'no' && Sum_value == 1) {
                All_markedMaj = All_markedMaj + 1;
            }
            if (Namespace_type == 'article') {
                ArticleE = ArticleE + 1;
                if (Minor_or_sum == -1) {
                    Minor = 'no'
                }
//article edit summary use percent stuff
                if (Marked_as_minor == 'no' && i < 1000 && contribs_first == true) {
                    sumart_edits += 1;
                    Article_major_edits = Article_major_edits + 1;
                    if (Sum_value == 1) {
                        Major_article_sum = Major_article_sum + 1;
                    }
                } else if (Marked_as_minor == 'yes' && i < 1000 && contribs_first == true) {
                    sumart_edits += 1;
                    Article_minor_edits = Article_minor_edits + 1;
                    if (Sum_value == 1) {
                        Minor_article_sum = Minor_article_sum + 1;
                    }
                }
            }
//overall for edit percent usage (up 1000 only)
            if (Marked_as_minor == 'yes' && i < 1000 && contribs_first == true) {
                sum_edits += 1;
                Is_minor = Is_minor + 1;
                if (Sum_value == 1) {
                    Minor_withsum = Minor_withsum + 1;
                }
            } else if (Marked_as_minor == 'no' && i < 1000 && contribs_first == true) {
                sum_edits += 1;
                Not_minor = Not_minor + 1;
                if (Sum_value == 1) {
                    Major_withsum = Major_withsum + 1;
                }
            }
//done
            if (Minor_nonrv == 1) {
                M = M + 1;
                if (Marked_as_minor == 'yes' && Superfic == 'no') {
                    if (STATS_ALL_JS_RAN == false) l[i].innerHTML += ' (' + mslink + ') #' + M;
                }
            }
        } else {
            blk_num += 1;
        }
    }
//END of FOR loop
    if (i == 1) {
        document.getElementById('contentSub').innerHTML = '<span style="color:blue;"><strong>There are no contribution statistics to show since there is only one edit.</span></strong><br>';
        return;
    }
    EC_tot += i;
//NOTE: the max edits per iteration MUST be higher than Max_Eforsum for this method to hold
    if (contribs_first == true) {
        ave_tot = i;
        current_date = new Date();
        current_date = current_date.toUTCString().replace(/GMT/, "UTC");
// skip show/hide link
        if (mw.config.get('wgUserGroups').indexOf('sysop') == -1) {
            first_date = l[0].getElementsByTagName('a')[0].innerHTML;
            last_date_f = l[i - 1].getElementsByTagName('a')[0].innerHTML;
        } else {
            first_date = l[0].getElementsByTagName('a')[1].innerHTML;
            last_date_f = l[i - 1].getElementsByTagName('a')[1].innerHTML;
        }
        totdays_first = getElapsedTime(current_date, last_date_f);
        totdays_frame = getElapsedTime(first_date, last_date_f);
        average = ave_tot / totdays_first;
        faverage = ave_tot / totdays_frame;
//Check up to 1000 edits, may redefine average edits/day
        var Max_Eforsum = 1000;
        if (ave_tot > Max_Eforsum && contribs_first == true) {
            ave_tot = Max_Eforsum;
            yearloc = l[Max_Eforsum - 1].innerHTML.split(' <a href=')[0].split('<A HREF=')[0];
            totdays_first = getElapsedTime(current_date, yearloc);
            totdays_frame = getElapsedTime(first_date, yearloc);
            average = ave_tot / totdays_first;
            faverage = ave_tot / totdays_frame;
        }
    }
//
    if (STATS_ALL_JS_RAN == true) {
        contribs_first = false;
        if (contribs_done == false) get_contribs_chain();
    }
    if (STATS_ALL_JS_RAN == false || contribs_done == true) {
        E = EC_tot;
        framedays = getElapsedTime(first_date, last_date_f);
        totdays = getElapsedTime(current_date, last_date_f);
        var RoundedFrameDays = Math.round((1) * framedays) / 1;
        if (RoundedFrameDays == 0) RoundedFrameDays = 1;
        var RoundedWallDays = Math.round((1) * totdays) / 1;
        if (RoundedWallDays == 0) RoundedWallDays = 1;
        average = Math.round((100) * average) / 100;
        faverage = Math.round((100) * faverage) / 100;
        var avenotice = '';
//wow..statistics people
        var caverage = Math.round((1000) * caverage) / 1000;
//
        var TimeDATE = '<span style="color:blue;"><strong>Time range:</span> ' + RoundedFrameDays + ' approximate day(s) of edits on this page (' + RoundedWallDays + ' day(s) passed since first edit) </strong></span><br> ' + 'Current time: ' + current_date + ' <strong>||</strong> ' + 'Last edit: ' + first_date + ' <strong>||</strong> ' + 'Oldest edit: ' + last_date_f + '<br>';
//
        if (location.href.split("&offset=")[1] != undefined) {
            if (location.href.split("&offset=0")[1] != undefined) {
                var offset = 'no';
            } else {
                Uploads = '<strong>[Value unknown]*</strong>';
                average = '<strong>[Value unknown]*</strong>';
                avenotice = '<strong><span style="color:darkblue;">*Average edits per day (and uploads) not shown because the most recent edit is not visible</strong></span><br>';
                TimeDATE = '';
                var offset = 'yes';
            }
        }
        if (edits_page_compared_js == 1) {
            rights_status = '';
            Uploads = '<strong>[Value unknown]*</strong>';
            average = '<strong>[Value unknown]*</strong>';
            faverage = '<strong>[Value unknown]*</strong>';
            avenotice = '<strong><span style="color:darkblue;">*Average edits per day (and uploads) not shown because their are multiple users</strong></span><br>';
            TimeDATE = '';
        }
        var tot_moves = Moves + Dummy_Moves;
        var U_edits = UM;
        var FAQ = '<a href="' + mw.config.get('wgServer') + '/wiki/User:Voice_of_All/History_analysis_JS_Definitions_and_FAQ" title="HistoryFAQ"> <span style="color:blue;">(FAQ)</span></a>';
        oldbody = document.getElementById('bodyContent').innerHTML;
//
        document.getElementById('contentSub').innerHTML += '<br><span style="color:darkblue;"><strong>Viewing contribution data for ' + theusername + rights_status + ' <span style="color:darkblue;">(over the </span>' + E + ' <span style="color:darkblue;">edit(s) shown on this page)</span></strong>' + FAQ;
//
        MAIN_NS = 'Article';
        PORTAL_NS = 'Portal';
        WIKIPEDIA_NS = 'Wikipedia';
        if (mw.config.get('wgServer') == "http://commons.wikimedia.org") {
            PORTAL_NS = 'Creator';
            WIKIPEDIA_NS = 'Commons';
            MAIN_NS = 'Gallery';
        }
        document.getElementById('bodyContent').innerHTML = '<div id="contentSub">' + document.getElementById('contentSub').innerHTML + '</div>' + TimeDATE + '<span style="color:darkblue;"><strong>Overall edit summary use (last</span> ' + sum_edits + ' <span style="color:darkblue;">edits): </span>' + ' Major edits: ' + Math.round((100) * (100 * (Major_withsum / Not_minor))) / 100 + '</strong>% ' + ' <strong>Minor edits: </span>' + Math.round((100) * (100 * (Minor_withsum / Is_minor))) / 100 + '</strong>%<br>' + '<strong>Average edits per day: ' + average + ' </strong>(currently, for last ' + ave_tot + ' edit(s))<br>' + '<strong>Average edits per day: ' + faverage + ' </strong>(since last active, for last ' + ave_tot + ' edit(s))<br>' + '<strong><span style="color:darkblue;">Article edit summary use (last</span> ' + sumart_edits + ' <span style="color:darkblue;">edits): </span>' + ' Major article edits: ' + Math.round((100) * (100 * (Major_article_sum / Article_major_edits))) / 100 + '</strong>% ' + ' <strong>Minor article edits: </span>' + Math.round((100) * (100 * (Minor_article_sum / Article_minor_edits))) / 100 + '</strong>%<br>' + '<span style="color:blue;"><strong>Encyclopedia contributions (out of all</span> ' + E + ' <span style="color:blue;">edits shown on this page and last</span> ' + Uploads_length + ' <span style="color:blue;">image uploads):</strong></span><br>' + '<strong><span style="color:#3366CC;">Unique image uploads (non-deleted/reverts/updates):</span> ' + Uploads + '</strong> (checks last 5000)<br>' + '<strong><span style="color:darkgreen;">Superficial article edits marked as minor:</span> ' + Math.round((100) * (100 * (Art_minor - Artm_to_minor) / Art_minor)) / 100 + '</strong>%<br>' + '<span style="color:blue;"><strong>Project contributions (as marked):</strong></span><br>' + '<strong><span style="color:darkgreen;">Articles for Creation:</span> ' + Math.round((100) * (100 * (AfC_tot) / E)) / 100 + '</strong>% (' + AfC_tot + ' edit(s))<br>' + '<strong><span style="color:darkgreen;">Peer Review:</span> ' + Math.round((100) * (100 * (PR_tot) / E)) / 100 + '</strong>% (' + PR_tot + ' edit(s))<br>' + '<strong><span style="color:darkred;">Pages for Deletion:</span> ' + Math.round((100) * (100 * (XfD_tot) / E)) / 100 + '</strong>% (' + XfD_tot + ' edit(s))<br>' + '<strong>Copyright problems pages: ' + Math.round((100) * (100 * (CP_tot) / E)) / 100 + '</strong>% (' + CP_tot + ' edit(s))<br>' + '<span style="color:red;"><strong>WP:AN/related noticeboards:</span> ' + Math.round((100) * (100 * (AN_tot) / E)) / 100 + '</strong>% (' + AN_tot + ' edit(s))<br>' + '<strong>Bot approvals pages: ' + Math.round((100) * (100 * (BOT_tot) / E)) / 100 + '</strong>% (' + BOT_tot + ' edit(s))<br>' + '<strong><span style="color:#3366CC;">FA/FP/FL candidate pages:</span> ' + Math.round((100) * (100 * (FAC_tot) / E)) / 100 + '</strong>% (' + FAC_tot + ' edit(s))<br>' + '<strong><span style="color:#FF6600;">RfC/RfAr pages:</span> ' + Math.round((100) * (100 * (RAfC_tot) / E)) / 100 + '</strong>% (' + RAfC_tot + ' edit(s))<br>' + '<strong><span style="color:darkblue;">Requests for adminship:</span> ' + Math.round((100) * (100 * (RfA_tot) / E)) / 100 + '</strong>% (' + RfA_tot + ' edit(s))<br>' + '<strong><span style="color:grey;">Identified RfA votes:</span> ' + Math.round((100) * (100 * (1 * RfA_votes_S + 1 * RfA_votes_O) / E)) / 100 + '</strong>% (' + RfA_votes_S + ' support vote(s)) ' + ' <strong>||</strong> ' + ' (' + RfA_votes_O + ' oppose vote(s))<br>' + '<strong><span style="color:#FF6600;">User warnings:</span> ' + Math.round((100) * (100 * (User_warnings) / E)) / 100 + '</strong>% (' + User_warnings + ' edit(s))<br>' + '<strong><span style="color:darkblue;">User welcomes:</span> ' + Math.round((100) * (100 * (User_welcomes) / E)) / 100 + '</strong>% (' + User_welcomes + ' edit(s))<br>' + '<span style="color:blue;"><strong>Special edit type statistics (as marked):</strong></span><br>' + '<strong><span style="color:darkgreen;">Page moves:</span> ' + Math.round((100) * (100 * (tot_moves) / E)) / 100 + '</strong>% (' + tot_moves + ' edit(s)) (' + Moves + ' moves(s))<br>' + '<strong><span style="color:purple;">Page redirections:</span> ' + Math.round((100) * (100 * (Redirects) / E)) / 100 + '</strong>% (' + Redirects + ' edit(s))<br>' + '<strong><span style="color:grey;">Page (un)protections:</span> ' + Math.round((100) * (100 * (Protections) / E)) / 100 + '</strong>% (' + Protections + ' edit(s))<br>' + '<strong><span style="color:darkred;">AutoWikiBrowser edits:</span> ' + Math.round((100) * (100 * (AWB_edits) / E)) / 100 + '</strong>% (' + AWB_edits + ' edit(s))<br>' + '<span style="color:blue;"><strong>Breakdown of all edits:</strong></span><br>' + '<strong>Unique pages edited: ' + Unique_pages + ' <span style="color:darkblue;">|</span> ' + 'Average edits per page: ' + Math.round(100 * E / Unique_pages) / 100 + ' <span style="color:darkblue;">|</span> ' + 'Edits on top: ' + Math.round((100) * (100 * (TE) / E)) / 100 + '</strong>%<br>' + '<strong>Edits marked as major (non-minor/reverts): ' + Math.round((100) * (100 * (All_markedMaj) / E)) / 100 + '</strong>% (' + All_markedMaj + ' edit(s))<br>' + '<strong>Edits marked as minor (non-reverts): ' + Math.round((100) * (100 * (All_markedMin) / E)) / 100 + '</strong>% (' + All_markedMin + ' edit(s))<br>' + '<span style="color:darkred;"><strong>Marked reverts (reversions/text removal):</span> ' + Math.round((100) * (100 * (R) / E)) / 100 + '</strong>% (' + R + ' edit(s))<br>' + '<span style="color:blue;"><strong>Edit count by namespace:</span><br>' + MAIN_NS + ': ' + Math.round((100) * (100 * (ArticleE) / E)) / 100 + '</strong>% (' + ArticleE + ') <strong><span style="color:darkblue;">|</span> ' + MAIN_NS + ' talk: ' + Math.round((100) * (100 * (Talk) / E)) / 100 + '</strong>% (' + Talk + ')<br>' + '<strong>User: ' + Math.round((100) * (100 * (User) / E)) / 100 + '</strong>% (' + User + ') <strong><span style="color:darkblue;">|</span> User talk: ' + Math.round((100) * (100 * (Usertalk) / E)) / 100 + '</strong>% (' + Usertalk + ') <br>' + '<strong>' + WIKIPEDIA_NS + ': ' + Math.round((100) * (100 * (WikipediaE) / E)) / 100 + '</strong>% (' + WikipediaE + ') <strong><span style="color:darkblue;">|</span> ' + WIKIPEDIA_NS + ' talk: ' + Math.round((100) * (100 * (Wikipediatalk) / E)) / 100 + '</strong>% (' + Wikipediatalk + ')<br>' + '<strong>Image: ' + Math.round((100) * (100 * (Images) / E)) / 100 + '</strong>% (' + Images + ') <strong><span style="color:darkblue;">|</span> Image talk: ' + Math.round((100) * (100 * (ITalk) / E)) / 100 + '</strong>% (' + ITalk + ')<br>' + '<strong>Template: ' + Math.round((100) * (100 * (Template) / E)) / 100 + '</strong>% (' + Template + ') <strong><span style="color:darkblue;">|</span> Template talk: ' + Math.round((100) * (100 * (TTalk) / E)) / 100 + '</strong>% (' + TTalk + ')<br>' + '<strong>Category: ' + Math.round((100) * (100 * (Category) / E)) / 100 + '</strong>% (' + Category + ') <strong><span style="color:darkblue;">|</span> Category talk: ' + Math.round((100) * (100 * (CTalk) / E)) / 100 + '</strong>% (' + CTalk + ')<br>' + '<strong>' + PORTAL_NS + ': ' + Math.round((100) * (100 * (Portal) / E)) / 100 + '</strong>% (' + Portal + ') <strong><span style="color:darkblue;">|</span> ' + PORTAL_NS + ' talk: ' + Math.round((100) * (100 * (PTalk) / E)) / 100 + '</strong>% (' + PTalk + ')<br>' + '<strong>Help: ' + Math.round((100) * (100 * (Help) / E)) / 100 + '</strong>% (' + Help + ') <strong><span style="color:darkblue;">|</span> Help talk: ' + Math.round((100) * (100 * (HTalk) / E)) / 100 + '</strong>% (' + HTalk + ')<br>' + '<strong>MediaWiki: ' + Math.round((100) * (100 * (MediawikiE) / E)) / 100 + '</strong>% (' + MediawikiE + ') <strong><span style="color:darkblue;">|</span> MediaWiki talk: ' + Math.round((100) * (100 * (MTalk) / E)) / 100 + '</strong>% (' + MTalk + ')<br>' + avenotice + oldbody.split(/<!-- start content -->|<!-- bodycontent -->/)[1];
        var body = document.getElementById('bodyContent');
        if (STATS_ALL_JS_RAN == false) {
            if (typeof (setupTooltips) != 'undefined') {
                body.ranSetupTooltipsAlready = false;
                setupTooltips(body);
            }
        } else {
            body.getElementsByTagName('ul')[0].innerHTML = '';
        }
    }
}

//END

function histstats() {
    fillMapOfUsersInGroup('sysop', wiki_sysop_list).done( function () {
        histstats_internal();
    });
}

//Vandal and IP stats
function histstats_internal() {
    if (document.getElementById('contentSub').innerHTML.search(/Viewing page modification statistics |There are no page modification statistics |Analyzing history...please wait/) != -1) {
        alert("Results already shown.");
        return;
    }
//
    var Namespace_type = 'non-article';
    var Namespace = document.title.split(' - ')[0];
    if (Namespace.search('(Image:|Template:| talk:|Category:|Portal:|Wikipedia:|MediaWiki:|Help:|Talk:|User:|View and restore deleted pages)') == -1) {
        Namespace_type = 'article';
    }
//tagging edits
    var rvlink = '<span style="color:darkred;"><strong>rv</strong></span>';
    var vanlink = '<span style="color:red;"><strong>likely rvv</strong></span>';
    // grrr
    var browser = navigator.appName;
    if (browser == "Microsoft Internet Explorer") {
        var revlink = '<STRONG><I>reverted</I></STRONG>';
    } else {
        var revlink = '<strong><i>reverted</i></strong>';
    }
    var mslink = '<strong>minor</strong>';
    var tplink = '<strong>most recent</strong>'
    var botlink = '<span style="color:purple;"><strong>bot</strong></span>';
    var syslink = '<span style="color:blue;"><strong>sysop</strong></span>';
    var nutlink = '<strong><i>no user pages</i></strong>';
    var ntlink = '<strong><i>blank talk page</i></strong>';
    var nulink = '<strong><i>blank userpage</i></strong>';
    var iplink = '<strong><i>IP edit</i></strong>';
    var iplink = '<strong>IP edit</strong>';
    var nslink = '<strong><span style="color:darkgrey;">no summary</span></strong>';
//
    var firstbody = document.getElementById('bodyContent').innerHTML;
    var oldloc = location.href;
//
    var IP_nonreverts = 0;
    var OU_nonreverts = 0;
    var Reverted = 0;
    var time_damaged = 0; // days
    var R = 0;
    var V = 0;
    var IP = 0;
    var UM = 0;
    var NS = 0;
    var SYS = 0;
    var BOT = 0;
    var OU = 0;
    var username = '';
    var Users = 0;
    var ArtSig = 0;
    var ArtSf = 0;
    var ArtRv = 0;
    var ArtM = 0;
    var ArtUM = 0;
    var c = document.getElementById('contentSub');
    var a = c.getElementsByTagName('a');
    l = document.getElementById('pagehistory').getElementsByTagName('li');
    document.getElementById('contentSub').innerHTML += "<br><strong>Analyzing history...please wait</strong>";
//
// alert(wiki_sysop_list["Voice of All"]);
    var now = new Date();
    var current_time = now.toUTCString().replace(/GMT/, "UTC");
    var User_list = '';
    for (i = 0; i < l.length; i++) {
        var UserType = null;
        var IP_edits = 0;
        var Careful = 'no';
        var Revert = 'no';
        var DRevert = 'no'; // damage revert
        var RollbackE = 'no';
        var Minor = 'no';
        var Superfic = 'no';
        var Notable = 'no';
        var Significant = 'no';
        var Minor_nonrv = -1;
        var Sum_value = -1;
        var Minor_or_sum = -1;
        var Marked_as_minor = 'no';
        var protection = 0;
        var link_offset = 0; // revdelete
        t = l[i].innerHTML;
        if (i == 0) {
            username = l[i].getElementsByTagName('a')[2 + link_offset].innerText;
        } else if (l[i].innerHTML.indexOf(') (prev)') != -1) // ugh
        {
            username = l[i].getElementsByTagName('a')[2 + link_offset].innerText;
        } else {
            username = l[i].getElementsByTagName('a')[3 + link_offset].innerText;
        }

        if (User_list.indexOf('|' + username + '|') == -1) {
            Users += 1;
            User_list += '|' + username + '|';
        }
        var autoc = 'no';
        var the_sum = '';
        for (k = 0; k < l[i].getElementsByTagName('span').length; k++) {
            ls = l[i].getElementsByTagName('span');
            if (ls[k].className == 'minor') {
                Minor_nonrv = 1;
                Minor_or_sum = 1;
                Minor = 'yes';
                Marked_as_minor = 'yes';
            } else if (ls[k].classList.contains('comment')) {
                Sum_value = 1;
                Minor_or_sum = 1;
                var Careful = 'no';
                the_sum = ls[k].innerHTML;
                // remove parens
                //the_sum = the_sum.replace(/^\(|\)$/i,'');
                break;
            } else if (ls[k].classList.contains('autocomment')) {
                Sum_value = 1;
                Minor_or_sum = 1;
                var Careful = 'no';
                the_sum = ls[k].innerHTML;
                // remove any tag cruft
                the_sum = the_sum.replace(/(<span class="[^"]*autocomment[^"]*">.+<\/span>|→)/gi, '');
                // remove parens
                //the_sum = the_sum.replace(/^\(|\)$/i,'');
                break;
            } else {
                Sum_value = -1;
                if (Minor == 'no') {
                    Minor_or_sum = -1;
                }
            }
        }
        //End of k loop
        raw_sum = the_sum;
//remove links
        the_sum = the_sum.replace(/<a href=([^>\]])+>([^<]+)<\/a>/ig, '$2');
/////
        if (Sum_value == -1) {
            NS = NS + 1;
            l[i].innerHTML += ' (' + nslink + ') #' + NS;
        }
        if (username in wiki_sysop_list) {
            SYS = SYS + 1;
            UserType = 'sysop';
            l[i].innerHTML += ' (' + syslink + ') #' + SYS;
        } else if (username.search(/(\b[Ss]cript\b|\b[Bb]ot\b|\w+Bot\b)/) != -1 || username in wiki_bot_list) {
            BOT = BOT + 1;
            UserType = 'bot';
            l[i].innerHTML += ' (' + botlink + ') #' + BOT;
        }
        if (l[i].innerHTML.search(/\[([Ee]dit|[Mm]ove)=[a-zA-Z0-9 ] +|class="comment">\(Unprotected /) != -1) {
            // Protection level change
            protection = 1;
            Minor_nonrv = 1;
            Minor = 'yes';
            Careful = 'yes';
            Superfic = 'yes';
            Notable = 'no';
            Significant = 'no';
            l[i].innerHTML = '<span style="background-color: #FFFFCC">' + l[i].innerHTML + '</span>';
        } else if (
            the_sum.search(/\((rvv|Rvv|RVV|RvV|RV V|rv v)/) != -1 ||
            the_sum.search(/reverted edits|Popups assisted reversion|reverted vandalism|revert to revision|to last version by|to last revision by|compromise the integrity|troll(s|ing)\)/i) != -1 ||
            the_sum.search(/BOT - rv|BOT - Reverted|vandal edit/i) != -1 ||
            the_sum.search(/rv vandalism|\(rv\/v\)/i) != -1
        ) {
            // Vandalism rollback
            V += 1;
            l[i].innerHTML += ' (' + vanlink + ') #' + V;
            R += 1;
            l[i].innerHTML += ' (' + rvlink + ') #' + R;
            Superfic = 'no';
            Notable = 'no';
            Significant = 'no';
            Minor_nonrv = -1;
            Revert = 'yes';
            DRevert = 'yes';
            RollbackE = 'yes';
        } else if (
            the_sum.search(/[\( ]([Ss]top |[Rr]everted edit|[Rr]everted \d+ edit|rv|Rv|RV|[Rr]evert|[Rr]ollback|[Rr]olling )/) != -1 ||
            the_sum.search(/revert[ |:|\.|\;)]|reverting[ |:|\.|\);]|reverted[ |:|\.|\);]|rollback[ |:|\.|\);]/i) != -1 ||
            l[i].classList.contains('mw-tag-mw-rollback')
        ) {
            // Other rollback
            R += 1;
            l[i].innerHTML += ' (' + rvlink + ') #' + R;
            Superfic = 'no';
            Notable = 'no';
            Significant = 'no';
            Minor_nonrv = -1;
            Revert = 'yes';
            DRevert = 'yes';
            RollbackE = 'yes';
        } else if (
            the_sum.search(/(Rm|rm|Remove|remove) (vandalism|test|nonsense)|remove vandalism|removed vandalism|rmv graffitti|rm graffitti|rv graffitti|reverting vandal|compromise the integrity/i) != -1 ||
            the_sum.search(/fixed vandalism|Revert vandal|revert vandal|delete vandal|linkspam| vandalism|vandals | vandal/i) != -1 ||
            the_sum.search(/(Rev|rev) vandal|\(vandal|\(trolling/) != -1 ||
            raw_sum.search(/ revision \d+ by |title="WP:UNDO"|\((Revert|trolls|trolling)\)/) != -1
        ) {
            // Vandalism revert
            V += 1;
            l[i].innerHTML += ' (' + vanlink + ') #' + V;
            R += 1;
            l[i].innerHTML += ' (' + rvlink + ') #' + R;
            Superfic = 'no';
            Notable = 'no';
            Significant = 'no';
            Minor_nonrv = -1;
            Revert = 'yes';
            DRevert = 'yes';
        } else if (
            the_sum.search(/Restoring |[Rr]evert|[Rr]estore[ :\.\)]|[Rr]estoring[ :\.\)]|[Rr]estored[ :\.\)]|Rm[ :\.\)]|rm[ :\.\)]|einstated[ :\.\)]|rmv[ :\.\)]|[Rr]einstate[ :\.\)]|rv\.|POINT/) != -1 ||
            the_sum.search(/delete[ |:|\.|]|deleted[ |:|\.]|remove[ :\)]|removing[ :\)]|reinstated|reinstate/i) != -1 ||
            the_sum.search(/restore[ :\.\)]|estored[ :\.\)]/i) != -1 ||
            the_sum.search(/re-added|re-inserted|added \w{5,20} again |added back |last time /i) != -1 ||
            the_sum.search(/back again|no such | such thing| agree with[ :\.\)]| don't[ :\.\)]| do not[ :\.\)]|\(surely[ :\.\)]|no need[ :\.\)]|\?\)/i) != -1 ||
            the_sum.search('(P|p)rotect(ed| )') == -1 && the_sum.length > 25 && is_long_revert(the_sum) ||
            l[i].classList.contains( 'mw-tag-mw-manual-revert' ) ||
            l[i].classList.contains( 'mw-tag-mw-undo' )
        ) {
            // Other revert
            R += 1;
            l[i].innerHTML += ' (' + rvlink + ') #' + R;
            Superfic = 'no';
            Notable = 'no';
            Significant = 'no';
            Minor_nonrv = -1;
            Revert = 'yes';
        }

        // Reverted edit flagging
        if (l[i].classList.contains( 'mw-tag-mw-reverted' ) && l[i].innerHTML.indexOf(revlink) == -1) {
            Reverted += 1;
            l[i].innerHTML += revlink;
        }

        // Do NOT count edits as reverted more than once
        if (Revert == 'yes' && l[i].innerHTML.indexOf(revlink) != -1) {
            Reverted = Reverted - 1;
            l[i].innerHTML = l[i].innerHTML.replace(revlink, '');
        } else {
            l[i].innerHTML = l[i].innerHTML.replace(revlink, ' (<span style="color:darkorange;">' + revlink + '</span>) ');
        }

        if (RollbackE == 'yes' && l[i + 1] && raw_sum.search(/ \d{6,10}( dated .+ | )by .+ using <[Aa] href/) == -1) {
            // Standard rollbacks
            var badname = l[i + 1].getElementsByTagName('a')[3].innerHTML;
            var uname = '';
            for (var h = i + 1; h < l.length; h++) {
                uname = l[h].getElementsByTagName('a')[3].innerHTML;
                if (l[h].innerHTML.indexOf(') (prev)') == -1 && l[h].innerHTML.indexOf(revlink) == -1 && uname == badname) {
                    Reverted += 1;
                    l[h].innerHTML += revlink;
                } else {
                    if (DRevert == 'yes') {
                        time2 = getTimeOfHistLI(i);
                        time1 = getTimeOfHistLI(h - 1);
                        duration = getElapsedTime(time2, time1);
                        time_damaged += duration;
                        l[i].innerHTML += ' <b>[' + Math.round((100) * 24 * 60 * duration) / 100 + ' min]</b>';
                    }
                    break;
                }
            }
        } else if (Revert == 'yes' && l[i + 1] && the_sum.search(/ \d{6,10}( dated [^ ]+ | )by [^ ]+ using /i) != -1) {
            // JS rollbacks (Lupin's popups, VP, VS)
            var goodname = the_sum.match(/ \d{6,10}( dated [^ ]+ | )by [^ ]+ using /i)[0].split(' by ')[1].split('. using ')[0].split(' using ')[0];
            var uname = '';
            var z = 0;
            // User renames or deleted revs or other flukes can skrew this up, set a 20 edit revert limit
            for (var h = i + 1; h < l.length; h++) {
                uname = l[h].getElementsByTagName('a')[3].innerHTML;
                // See if this makes sense. We don't want to start marking if it goes nowhere...
                if (l[h].innerHTML.indexOf(') (prev)') == -1 && uname != goodname) {
                    z += 1;
                    if (z == 21) {
                        l[i].innerHTML += ' [invalid revert to "' + goodname + '"]';
                        z = 1;
                        break;
                    }
                } else {
                    break;
                }
            }
            for (var h = i + 1; h < i + 1 + z; h++) {
                if (l[h].innerHTML.indexOf(revlink) == -1) {
                    Reverted += 1;
                    l[h].innerHTML += revlink;
                }
                // last one
                if (DRevert == 'yes' && h == (i + z)) {
                    time2 = getTimeOfHistLI(i);
                    time1 = getTimeOfHistLI(h);
                    duration = getElapsedTime(time2, time1);
                    time_damaged += duration;
                    l[i].innerHTML += ' <b>[' + Math.round((100) * 24 * 60 * duration) / 100 + ' min]</b>';
                }
            }
        } else if (Revert == 'yes' && l[i + 1] && the_sum.search(/Undid revision \d+ by /i) != -1) {
            // Revert using (undo) links
            var badID = the_sum.match(/Undid revision \d+ by /i)[0].split(' revision ')[1].split(' by ')[0];
            var z = 0;
            // check up to next 20 edits
            for (var h = i + 1; h < l.length; h++) {
                z++;
                if (z >= 20) {
                    if (DRevert == 'yes') {
                        time2 = getTimeOfHistLI(i);
                        time1 = getTimeOfHistLI(h);
                        duration = getElapsedTime(time2, time1);
                        time_damaged += duration;
                        l[i].innerHTML += ' <b>[' + Math.round((100) * 24 * 60 * duration) / 100 + ' min]</b>';
                    }
                    l[i].innerHTML += ' [invalid revert of rev "' + badID + '"]';
                    break;
                }
                if (l[h].getElementsByTagName('a')[0].href.indexOf('oldid=' + badID) != -1) {
                    // already marked as reverted?
                    if (l[h].innerHTML.indexOf(revlink) == -1) {
                        Reverted += 1;
                        l[h].innerHTML += revlink;
                    }
                    if (DRevert == 'yes') {
                        time2 = getTimeOfHistLI(i);
                        time1 = getTimeOfHistLI(h);
                        duration = getElapsedTime(time2, time1);
                        time_damaged += duration;
                        l[i].innerHTML += ' <b>[' + Math.round((100) * 24 * 60 * duration) / 100 + ' min]</b>';
                    }
                    break;
                }
            }
        } else if (DRevert == 'yes' && l[i + 1]) {
            time2 = getTimeOfHistLI(i);
            time1 = getTimeOfHistLI(i + 1);
            duration = getElapsedTime(time2, time1);
            time_damaged += duration;
            l[i].innerHTML += ' <b>[' + Math.round((100) * 24 * 60 * duration) / 100 + ' min]</b>';
        }
//end article stats
// User flagging
        if (l[i].innerHTML.indexOf('(cur) (') == -1 && l[i].innerHTML.indexOf(') (prev)') == -1) {
            if (l[i].getElementsByTagName('a')[3].href.indexOf('Special:Contributions') != -1) {
                IP = IP + 1;
                l[i].innerHTML += ' (' + iplink + ') #' + IP;
                UserType = 'ip';
            }
        } else if (l[i].innerHTML.indexOf('(cur) (') != -1 && l[i].innerHTML.indexOf(') (prev)') != -1) {
            if (l[i].getElementsByTagName('a')[1].href.indexOf('Special:Contributions') != -1) {
                IP = IP + 1;
                l[i].innerHTML += ' (' + iplink + ') #' + IP;
                UserType = 'ip';
            }
        } else if (l[i].innerHTML.indexOf('(cur) (') != -1 || l[i].innerHTML.indexOf(') (prev)') != -1) {
            if (l[i].getElementsByTagName('a')[2].href.indexOf('Special:Contributions') != -1) {
                IP = IP + 1;
                l[i].innerHTML += ' (' + iplink + ') #' + IP;
                IP_edits += 1;
                UserType = 'ip';
            }
        }

        if ( UserType == null ) {
            OU += 1;
            UserType = 'regular';
        }

        if ( UserType == 'regular' && l[i].innerHTML.indexOf(revlink) == -1 && Revert == 'no') {
            OU_nonreverts += 1;
        } else if ( UserType == 'ip' && l[i].innerHTML.indexOf(revlink) == -1 && Revert == 'no') {
            IP_nonreverts += 1;
        }
    }
//end of FOR LOOP
    if (i == 1) {
        document.getElementById('contentSub').innerHTML = '<span style="color:blue;"><strong>There are no page modification statistics to show since there is only one edit.</span></strong><br>';
        return;
    }
    if (document.title.indexOf('View and restore deleted pages') != -1) {
        var first_time = l[0].getElementsByTagName('a')[0].innerHTML;
        var last_time = l[i - 1].getElementsByTagName('a')[0].innerHTML;
    } else {
        var first_time = getTimeOfHistLI(0);
        var last_time = getTimeOfHistLI(i - 1);
    }
    var E = i;
    var SE = E - Reverted - R;
    var RU = E - IP;
    var ESUM = E - NS;
    var totdays = getElapsedTime(current_time, last_time);
    var framedays = getElapsedTime(first_time, last_time);
    var caverage = E / totdays;
    var average = E / framedays;
    var rvaverage = R / framedays;
    var nonrvave = average - rvaverage;
    var RoundedFrameDays = Math.round((1) * framedays) / 1;
    if (framedays < 1) RoundedFrameDays = 1;
    var RoundedWallDays = Math.round((1) * totdays) / 1;
    if (totdays < 1) RoundedWallDays = 1;
    var avenotice = '';
//wow..statistics people
    var caverage = Math.round((1000) * caverage) / 1000;
    if (location.href.split("&offset=")[1] != undefined) {
        if (location.href.split("&offset=0")[1] != undefined) {
            var offset = 'no';
        } else {
            caverage = '<strong>[Value unknown]*</strong>';
            RoundedWallDays = '<strong>[Value unknown]*</strong>';
            avenotice = '<strong>*Average edits per day not shown because the most recent edit to this page is not visible</strong><br>';
            var offset = 'yes';
        }
    }
//
    document.getElementById('contentSub').innerHTML += '<br>' +
        '<strong>Breakdown of edits (' + E + ' total) by user (' + Users + ' total):</strong><br>' +
        Math.round((100) * BOT / E * 100) / 100 + '% <span style="color:purple;">bots</span> (' + BOT + ' edit(s))<br>' +
        Math.round((100) * SYS / E * 100) / 100 + '% <span style="color:blue;">administrators</span> (' + SYS + ' edit(s))<br>' +
        Math.round((100) * OU / E * 100) / 100 + '% <span style="color:grey;">basic accounts</span> (' + OU + ' edit(s))<br>' +
        Math.round((100) * IP / E * 100) / 100 + '% <span style="color:darkred;">non-accounts</span> (' + IP + ' edit(s))<br>' +
        Math.round((100) * E / Users) / 100 + ' edit(s) per user<br>' +
        '<strong>Time frame of edits:</strong><br>' +
        'Newest shown edit date: ' + first_time + '<br>' +
        'Oldest shown edit date: ' + last_time + '<br>' +
        'Current time: ' + current_time + '<br>' +
        'Day(s) between oldest and newest shown edits: ' + RoundedFrameDays + '<br>' +
        'Day(s) since oldest shown edit: ' + RoundedWallDays + '<br>' +
        '<strong>Rates:</strong><br> ' +
        caverage + ' edit(s) per day (as of the current time)<br>' +
        Math.round((1000) * average) / 1000 + ' edit(s) per day (as of newest shown edit)<br>' +
        Math.round((1000) * rvaverage) / 1000 + ' <span style="color:darkred;">marked revert(s) per day (as of newest shown edit)</span><br>' +
        '<strong>Percentages and ratios:</strong><br> ' +
        Math.round((100) * ESUM / E * 100) / 100 + '% edits with a summary<br>' +
        Math.round((100) * R / E * 100) / 100 + '% <span style="color:darkred;">marked reverts</span> (' + R + ')<br>' +
        Math.round((100) * V / E * 100) / 100 + '% <span style="color:red;">marked reverts likely removing vandalism</span> (' + V + ')<br>' +
        Math.round((100) * 100 * SE / E) / 100 + '% <span style="color:darkblue;">of edits are non-reverts and non-reverted (as of newest shown edit)</span> (' + SE + ' out of ' + E + ' edit(s))<br>' +
        Math.round((100) * 100 * OU_nonreverts / OU) / 100 + '% <span style="color:grey;">of edits by basic accounts are non-reverts and non-reverted (as of newest shown edit)</span> (' + OU_nonreverts + ' out of ' + OU + ' edit(s))<br>' +
        Math.round((100) * 100 * IP_nonreverts / IP) / 100 + '% <span style="color:darkgreen;">of edits by non-accounts are non-reverts and non-reverted (as of newest shown edit)</span> (' + IP_nonreverts + ' out of ' + IP + ' edit(s))<br>' +
        '1:<span style="color:darkred;">' + Math.round((100) * R / (E - R)) / 100 + '</span> lasting edits to marked reverts<br>' +
        Math.round((100) * 100 * time_damaged / framedays) / 100 + '% <span style="color:darkorange;"><strong>of time page showed a reverted edit (as of newest shown edit)</strong></span> (' + Math.round((100) * time_damaged * 24 * 60) / 100 + '/' + Math.round((100) * framedays * 24 * 60) / 100 + ' min)<br/>' +
        avenotice;

//popups
    var body = document.getElementById('bodyContent');
    if (typeof (setupTooltips) == 'undefined') return;
    body.ranSetupTooltipsAlready = false;
    setupTooltips(body);
}

//END

function is_long_revert(the_sum) {
    if (the_sum.search(/remove[ :\.\)]|removed[ :\.\)]|[ :\)]remove|[ :\)]removed|seriously[ :\.\)]|WTF[ :\.\)]|\?\?|!!|restore[ :\.\)]|restored[ :\.\)]|restoring[ :\.\)]/i) != -1 || the_sum.search(/(Should|should|Is|is) not |should(nt|n't) |c(an't|annot) |(un|n)ecessary |no need[ :\.\)]|Abuse of |admin powers | violat(e|es|ed) | policy| standards| doesn't| your | you're| yours| you are | aren't| isn't|\(stop |(?! to) stop[ :\.\)]| not|please[ :\.\)]|[ :\.\)]please|just stop|please stop|can't|cant|why[ :\.\)]| the talk page| (see|to) (talk|discussion)/i) != -1)
        return true;
    else
        return false;
}


//***********************
//standard XML Support
function HTTPClient() {
    var gml_http;
    if (window.XMLHttpRequest) {
        gml_http = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
            gml_http = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                gml_http = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                gml_http = false;
            }
        }
    }
    return gml_http;
}

function gml_XMLParse(string) {
    if (document.implementation.createDocument) {
        var gml_xmlparser = new DOMParser()
        return gml_xmlparser.parseFromString(string, "text/xml");
    } else if (window.ActiveXObject) {
        var gml_xmldoc = new ActiveXObject("Microsoft.XMLDOM");
        gml_xmldoc.async = "false";
        ret = gml_xmldoc.loadXML(string);
        if (!ret)
            return null;
        return gml_xmldoc.documentElement;
    }
    return null;
}

// Some functions for parsing raw HTML.
// Need to be maintained...
window.getSumOfHistLI = function (index) {
    var the_sum = '';
    var l = document.getElementById('pagehistory').getElementsByTagName('li')[index];
    var ls = l.getElementsByTagName('span');

    for (k = 0; k < ls.length; k++) {
        if (ls[k].className == 'autocomment') {
            if (ls[k - 1].innerHTML.indexOf("-</span> ") != -1) {
                the_sum = ls[k - 1].innerHTML.split("-</span> ")[1].split("</span>")[0];
            } else if (ls[k - 1].innerHTML.indexOf("-</span>") != -1) {
                the_sum = ls[k - 1].innerHTML.split("-</span>")[1].split("</span>")[0];
            } else if (ls[k - 1].innerHTML.indexOf("</span>") != -1) {
                the_sum = ls[k - 1].innerHTML.split("</span>")[1].split("</span>")[0];
            } else {
                the_sum = '';
            }
            break;
        } else if (ls[k].className == 'comment') {
            the_sum = ls[k].innerHTML;
        }
    }
    the_sum = the_sum.replace(/(-<\/span>|→)/gi, '');
    return the_sum;
}

window.getTimeOfHistLI = function (index) {
    var the_time = '';
    var l = document.getElementById('pagehistory').getElementsByTagName('li')[index];
    var la = l.getElementsByTagName('a');

    for (var k = 0; k < la.length; k++) {
        if (la[k].href.indexOf('&oldid=') != -1 && la[k].href.indexOf('&diff=') == -1) {
            the_time = la[k].innerHTML;
            break;
        }
    }
    return the_time;
}

//END
//**********

//</nowiki>