Jump to content

User:MilHistBot/AutoCheck.cs

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Hawkeye7 (talk | contribs) at 05:07, 21 November 2019 (Created). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

public class AutoCheck
{
    private Page article;
    private Page talk;
    private Bot bot;

    private int unchanged;
    private int upgrade;
    private int newgrade;
    private int downgrade;

    private const string milHistTemplates = "MILHIST|WPMH|WPMIL|Military *history|WikiProject *Military|WikiProject *War";
    private const string alliedTemplates  = "WPSHIPS|WikiProject *Ships|WPAVIATION|WikiProject *Aviation";
    private const string allTemplates = milHistTemplates + "|" + alliedTemplates;

    private bool debugFlag = false;
   
    private void debug (string message)
    {
        if (debugFlag)
        {
            bot.Cred.Showtime (message);      
        }
    }
           
    private void compareRatings (string oldRating, string botRating)
    {
        if (oldRating.Equals (botRating))
        {
            unchanged++;
        } else
        {
            switch (oldRating)
            {
                case "":
                    newgrade++;
                    break;
                case "List":
                case "Start":
                case "Stub":
                    upgrade++;
                    break;
                case "C":
                case "Cl":
                    if (botRating.Equals ("Start"))
                        downgrade++;
                    else
                        upgrade++;
                    break;
                case "B":
                case "Bl":
                    downgrade++;
                    break;
                default:
                    throw new ApplicationException ("unknown rating: '" + oldRating + "'");
            }
        }                       
    }

    private string listRating (string rating)
    {
        switch (rating)
        {
            case "Start":
                rating = "List";
                break;
            case "C":
               rating = "CL";
                break;
            case "B":
               rating = "BL";
                break;
            default:
                throw new ApplicationException ("unknown rating: '" + rating + "'");
        }
        return rating;
    }

    private bool list ()
    {
        return talk.FindAll (allTemplates).Exists (ind => ind.Exists ("class", "List"));           
    }
     
    private void report ()
    {
        bot.Cred.Showtime (String.Format("{0} articles newly rated, {1} downgraded, {2} upgraded, {3} unchanged - total {4}",
                            newgrade, downgrade, upgrade, unchanged, newgrade + downgrade + upgrade + unchanged));  
    }

    private bool unsourced ()
    {
        return article.InCategory ("Category:All articles with unsourced statements");
    }

    private List<IToken> getLineTokens ()
    {
        int firstIndex = 0;
        int lastIndex = article.FindLastIndex ();          
       
        var firstSection = article.FindSection (".");
        if (null != firstSection)
        {         
//              debug ("First section = " + firstSection.Text);
            firstIndex = article.FindIndex (firstSection);           
        }   
       
        var lastSection  = article.FindSection ("Notes|References|External links|Further reading|See Also");
        if (null != lastSection)
        {
//              debug ("Last section  = " + lastSection.Text);
            lastIndex  = article.FindIndex (lastSection);
        }          
           
        var lineTokens = article.GetRange (firstIndex + 1, lastIndex - firstIndex);
               
        return lineTokens;   
    }

    private bool inlineCitations ()
    {
        bool isReferenced = true;
        if (unsourced ())
        {
            isReferenced = false;
        }
        else
        {
            var lineTokens = getLineTokens ();
            var lines      = lineTokens.FindAll (ind=>(ind.Type == TokenType.Text && Regex.IsMatch (ind.Text, "\n")));

            foreach (var line in lines)
            {
                IToken last;
                int index = article.FindIndex (line);
                do
                {
                    last  = article.GetToken (--index);
                } while (last.Type == TokenType.Text && last.Text.Equals ("\n"));             

//              debug ("last = '" + last.Text + "' type = " + last.Type);
//              debug ("line = '" + line.Text + "'");             
               
                if (last.Type != TokenType.Section && last.Type != TokenType.Reference && last.Type != TokenType.Template && last.Type != TokenType.Link)
                {
                    isReferenced = false;
                    break;
                }
            }
        }       

        return isReferenced;
    }
   
    private bool coverage ()
    {
        return !article.Prediction ().Equals ("Start");
    }

    private bool structure ()
    {
        return article.FindAllSections (".").Count > 0;
    }

    private bool grammar ()
    {
        return true;
    }

    private bool infobox ()
    {
        return article.Exists ("Infobox") || article.ExistsNs ("File");
    }   

    public static string FirstCharToUpper (string input)
    {
        return String.IsNullOrEmpty (input) ? "" : input.Substring(0,1).ToUpper() + input.Substring(1).ToLower ();
    }

    void autoCheck (string articlePage, string talkPage)
    {      
        try
        {        
            article = new Page (bot, articlePage);
            article.Load ();
            talk = new Page (bot, talkPage);
            talk.Load ();
           
            bool isList        = list ();         
            bool hasReferences = inlineCitations ();
            bool hasCoverage   = coverage ();
            bool hasStructure  = structure ();
            bool hasGrammar    = grammar ();
            bool hasInfobox    = infobox ();
           
            string botRating = ((hasReferences && hasCoverage) && hasStructure && hasGrammar && hasInfobox) ? "B" :
                               ((hasReferences || hasCoverage) && hasStructure && hasGrammar && hasInfobox) ? "C" :
                               "Start";                     
            if (isList)
            {
                botRating = listRating (botRating);
            }
 
            var templates = talk.FindAll (allTemplates);                   
            foreach (var template in templates)
            {
                debug ("\tOriginal: <code>" + template.Text + "</code>");                        
               
                string oldRating = "";
                var classParameter = template.Find ("^class$");
                if (null != classParameter)
                {
                    oldRating = FirstCharToUpper (classParameter.Value);
                }

                var oldParameters = template.FindAll ("^class$|^importance$|^b\\d$|^B-Class-\\d$");
                foreach (var parameter in oldParameters)
                {
                    template.Remove (parameter);
                }
    
                if (isList && Regex.IsMatch (template.Name, milHistTemplates))
                {
                    template.Add ("list", "yes");
                }                                
   
                template.Insert (0, "class", botRating);
                template.Insert (1, "b1", hasReferences ? "yes" : "no");
                template.Insert (2, "b2", hasCoverage   ? "yes" : "no");
                template.Insert (3, "b3", hasStructure  ? "yes" : "no");
                template.Insert (4, "b4", hasStructure  ? "yes" : "no");
                template.Insert (5, "b5", hasInfobox    ? "yes" : "no");
   
                debug ("\told rating = " + oldRating);
                debug ("\tprediction = " + article.Prediction ());
                debug ("\tbot rating = " + botRating);
           
                debug ("\tModified: <code>" + template.Text + "</code>");
                compareRatings (oldRating, botRating);
   
                talk.Save ("Automatic MILHIST checklist assessment");
            }
        }
        catch (Exception ex)
        {
            string message = "Error in " + articlePage + ":\n" + ex.Message + "\n" + ex.StackTrace;
            if (debugFlag)
            {
                bot.Cred.Showtime (message);
            }
            else
            {
                bot.Cred.Warning (message);
            }
        }
    }
   
    private AutoCheck (string articlePage)
    {
        bot = new Bot ();
        bot.Cred.Showtime ("started");
        string talkPage = "Talk:" + articlePage;
        bot.Cred.Showtime ("1: " + articlePage);
        autoCheck (articlePage, talkPage);
        bot.Cred.Showtime ("done");
    }
   
    private AutoCheck (int max)
    {
        int count = 1;
        bot = new Bot ();
        bot.Cred.Showtime ("started");
        var talkPages = bot.Category ("Military history articles with missing B-Class checklists");
        foreach (var talk in talkPages)
        {
            string talkPage = talk.Title;
            string articlePage = talkPage.Substring (5);
            bot.Cred.Showtime (count + ": " + articlePage);
            autoCheck (articlePage, talkPage);
            if (++count > max)
            {
                break;
            }
        }
        report ();
        bot.Cred.Showtime ("done");
    }

    static public void Main (string [] args)
    {
        int max = 5;
        var autoCheck = (0 == args.Length || Int32.TryParse (args[0], out max)) ? new AutoCheck (max) : new AutoCheck (args[0]);
    }
}