User:MilHistBot/AutoCheck.cs
Appearance
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]);
}
}