User:PearBOT/Aircraft specs/source

import pywikibot
import re
from pywikibot import pagegenerators
import unicodedata
regexbase = "(sq\. ft\.|{{[Nn]owrap\|)?([0-9\.\,]+)([½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑])?(\+)?(}})?([\s\.\,]|( ))*( )?"
regexlist = {
    "m":regexbase+"(m)",
    "ft":regexbase+"(ft)",
    "in":regexbase+"(in)",
    "sqm":regexbase+"(sqm|m2|m<sup>2<\/sup>|m²|sq m)",
    "sqft":regexbase+"(sq. ft.|sq ft|{{nowrap\|sq ft}}|sqft|ft2|ft<sup>2<\/sup>|ft²)",
    "kg":regexbase+"(kg)",
    "lb":regexbase+"(lb|\[\[pound \(mass\)\|lb]])",
    "kw":regexbase+"(kw|kW)",
    "hp":regexbase+"(hp|\[\[horsepower\|hp]])",
    "shp":regexbase+"(shp|\[\[horsepower\|shp]])",
    "kn":regexbase+"(kn|kN|\[\[kilonewton\|kN]])",
    "lbf":regexbase+"(\[\[lbf]]|\[\[pound-force\|lb<sub>f<\/sub>]]|lbf|\[\[pound-force\|lbf]]|lb|lbs)",
    "kmh":regexbase+"(kmh|km\/h)",
    "mph":regexbase+"(mph)",
    "kts":regexbase+"(\[\[knot \(unit\)\|kn]]|kts|kt|knots|\[\[knot \(unit\)\|knots]]|kn)",
    "mach":regexbase+"(mach|\[\[Mach speed\|Mach]])",
    "km":regexbase+"(km)",
    "miles":regexbase+"(miles|mi)",
    "nmi":regexbase+"(nmi|\[\[nautical mile\|nmi]]|\[\[nautical mile\|nm]]|nm|\[\[nautical mile\|NM]]|NM)",
    "ms":regexbase+"(ms|m\/s)",
    "ftmin":regexbase+"(ftmin|ft\/min)",
    "kg/m2":regexbase+"(kg\/m²|kg\/m2|kg\/m<sup>2<\/sup>)",
    "lb/sqft":regexbase+"(lb\/\(sq ft\)|lb\/sqft|lb\/ft²|lb\/ft<sup>2<\/sup>)"  
}
fractionvalues = {
    "½":0.5,
    "⅓":0.3,
    "⅔":0.7,
    "¼":0.3,
    "¾":0.8,
    "⅕":0.2,
    "⅖":0.4,
    "⅗":0.6,
    "⅘":0.8,
    "⅙":0.2,
    "⅚":0.8,
    "⅐":0.1,
    "⅛":0.1,
    "⅜":0.4,
    "⅝":0.6,
    "⅞":0.9,
    "⅑":0.1
}
extratextregex ="^(({{[Nn]owrap\|)|(}})|\+|(&nbsp;)|\,|\.|[½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑]|\s|\d|sqm|m2|m<sup>2<\/sup>|m²|sq m|m|ft|in|sq ft|{{nowrap\|sq ft}}|sqft|ft2|ft<sup>2<\/sup>|ft²|lb|\[\[pound \(mass\)\|lb]]|kg|kw|kW|hp|\[\[horsepower\|hp]]|shp|\[\[horsepower\|shp]]|kn|kN|\[\[kilonewton\|kN]]|\[\[lbf]]|\[\[pound-force\|lb<sub>f<\/sub>]]|lbf|\[\[pound-force\|lbf]]|lb|lbs|(kmh|km\/h)|mph|\[\[knot \(unit\)\|kn]]|kts|kt|knots|\[\[knot \(unit\)\|knots]]|kn|mach|\[\[Mach speed\|Mach]]|km|lb\/\(sq ft\)|lb\/sqft|lb\/ft²|lb\/ft<sup>2<\/sup>|kg\/m²|kg\/m2|kg\/m<sup>2<\/sup>|ftmin|ft\/min|ms|m\/s|nmi|\[\[nautical mile\|nmi]]|nm|\[\[nautical mile\|NM]]|NM|miles|mi)*$"
def extratext(main):
    if not re.search(extratextregex,x[1].get(main)):
        errorpage.text += "\n*Extra text at " 
        errorpage.text += page.full_url()
        errorpage.text += " " 
        errorpage.text += x[1].get(main)
        global abort 
        abort = True
        return False
    else:
        return True
def unitparam(unit,main): 
    global abort
    if ((x[1].get(main+" main") is not "") and (main+" main" in x[1].keys())) or ((x[1].get(main+" alt") is not "") and (main + " alt" in x[1].keys())):
        if re.search(regexlist.get(unit),x[1].get(main+" main")):
            if extratext(main+" main"):
                fraction = 0
                if re.search(regexlist.get(unit),x[1].get(main+" main")).group(3) is not None:
                    fraction = fractionvalues[re.search(regexlist.get(unit),x[1].get(main+" main")).group(3)]
                    return str(float(re.search(regexlist.get(unit),x[1].get(main+" main")).group(2).replace(",",""))+fraction)
                return str(re.search(regexlist.get(unit),x[1].get(main+" main")).group(2).replace(",",""))
        elif re.search(regexlist.get(unit),x[1].get(main+" alt")):
            if extratext(main+" alt"):
                fraction = 0
                if re.search(regexlist.get(unit),x[1].get(main+" alt")).group(3) is not None:
                    fraction = fractionvalues[re.search(regexlist.get(unit),x[1].get(main+" alt")).group(3)]
                    return str(float(re.search(regexlist.get(unit),x[1].get(main+" alt")).group(2).replace(",",""))+fraction)
                return re.search(regexlist.get(unit),x[1].get(main+" alt")).group(2).replace(",","")
        elif unit == "in" and (re.search(regexlist.get("ft"),x[1].get(main+" main")) or re.search(regexlist.get("ft"),x[1].get(main+" alt"))):
            return "0"
        elif unit == "mach" or unit == "shp" or unit == "hp" or unit == "nmi" or unit == "kts":
            return ""
        elif not re.search("\d",x[1].get(main+" main")) and not re.search("\d",x[1].get(main+" alt")):
            return ""
        else:
            errorpage.text += "\n*Unidentified unit at " 
            errorpage.text += page.full_url()
            errorpage.text += " " 
            errorpage.text += x[1].get(main+" main")
            errorpage.text += ", " 
            errorpage.text += x[1].get(main+" alt")
            errorpage.text += " Looking for:"
            errorpage.text += unit
            abort = True
            return ""
    return ""
def unitif(what, unit, main):
    if what:
        return unitparam(unit, main)
    else:
        return ""
def findtype(what,x):
    if x.get("plane or copter?") == "plane" and what == "plane":
        return True
    if x.get("plane or copter?") == "copter" and what == "copter":
        return True
    if not (x.get("plane or copter?") == "copter" or x.get("plane or copter?") == "plane"):
        errorpage.text += "*Unknown type at " 
        errorpage.text += page.full_url()
        global abort
        abort = True
    if (x.get("plane or copter?") == "copter" and what == "plane") or (x.get("plane or copter?") == "plane" and what == "copter"):
        return False
def findprimeunit(x):
    if re.search(regexlist["m"],x.get("length main")) and re.search(regexlist["ft"],x.get("length alt")):
        return "met"
    elif re.search(regexlist["ft"],x.get("length main")) and re.search(regexlist["m"],x.get("length alt")):
        if re.search(regexlist["kts"],x.get("max speed main")):
            return "kts"
        else:
            return "imp"
    else:
        errorpage.text += "*Unknown prime unit at " 
        errorpage.text += page.full_url()
        global abort
        abort = True
def get(x,index,note=False):
    if (x.get(index) is not "") and (index in x.keys()):
        if note:
            return "*" + x.get(index)
        return x.get(index)
    else: 
        return ""
def armaments():
    if(x[1].get("armament") is "") or ("armament" not in x[1].keys()):
        return("")
    elif (x[1].get("armament") is not "") and ("armament" in x[1].keys()):
        return """|armament = """ + get(x[1],"armament") + """<!-- add bulletted list here or if you want to use the following 
        specific parameters, remove this parameter--> """
    else:
        global abort
        abort = True
        errorpage.text += "*Armaments error at " 
        errorpage.text += page.full_url()
        return ""
def badparam():
    print(x[1].get("number of propellers per engine") is not "")
    print("number of propellers per engine" in x[1].keys())
    if ((x[1].get("number of propellers per engine") is not "") and ("number of propellers per engine" in x[1].keys())):
        global abort
        abort = True
        errorpage.text += "\n*Bad parameter at " 
        errorpage.text += page.full_url()
def payload():
    payloadtext = ""
    if (x[1].get("Payload main") is not "" and "Payload main" in x[1].keys()) and (x[1].get("Payload alt") is not "" and "Payload alt" in x[1].keys()):
        extratext("Payload main")
        extratext("Payload alt")
        payloadtext =  "\n**" + "Useful load:" + get(x[1],"Useful load main") + " (" + get(x[1],"Useful load alt") + ")"
    elif (x[1].get("Payload main") is "" or "Payload main" not in x[1].keys()) and (x[1].get("Payload alt") is "" or "Payload alt" not in x[1].keys()):
        return ""
    else:
        global abort
        abort = True
        errorpage.text += "\n*Payload problem at " 
        errorpage.text += page.full_url()
        return payloadtext
    if(((x[1].get("payload more") is not "") and ("payload more" in x[1].keys()))):
        payloadtext = payloadtext + "\n" + get(x[1],"payload more")
    return payloadtext
def usefulload():
    payloadtext = ""
    if (x[1].get("Useful load main") is not "" and "Useful load main" in x[1].keys()) and (x[1].get("Useful load alt") is not "" and "Useful load alt" in x[1].keys()):
        extratext("Useful load main")
        extratext("Useful load alt")
        payloadtext =  "\n**" + "Useful load:" + get(x[1],"Useful load main") + " (" + get(x[1],"Useful load alt") + ")"
        return payloadtext
    elif (x[1].get("Useful load main") is "" or "Useful load main" not in x[1].keys()) and (x[1].get("Useful load alt") is "" or "Useful load alt" not in x[1].keys()):
        return ""
    else:
        global abort
        abort = True
        errorpage.text += "\n*Useful load problem at " 
        errorpage.text += page.full_url()
        return payloadtext
def powermass():
    powermasstext = ""
    if(((x[1].get("power/mass main") is not "") and ("power/mass main" in x[1].keys()))):
        powermasstext = powermasstext + get(x[1],"power/mass main")
        if(((x[1].get("power/mass alt") is not "") and ("power/mass alt" in x[1].keys()))):
            powermasstext = powermasstext + " (" + get(x[1],"power/mass alt")+ ")"
    return powermasstext
def getarmaments(x, index):
    if re.search("^\*\*",get(x,index)):
        errorpage.text += "\n*Indentation problem at " 
        errorpage.text += page.full_url()
        errorpage.text += " " 
        errorpage.text += get(x,index)
        global abort
        abort = True  
        return ""
    else:
        return get(x,index)
def subtemplatenum():
    templatenum=0
    for parameter in x[1].values():
        if re.search("[^{]*\{\{"*7,parameter):
            templatenum += 7
        elif re.search("[^{]*\{\{"*6,parameter):
            templatenum += 6
        elif re.search("[^{]*\{\{"*5,parameter):
            templatenum += 5
        elif re.search("[^{]*\{\{"*4,parameter):
            templatenum += 4
        elif re.search("[^{]*\{\{"*3,parameter):
            templatenum += 3
        elif re.search("[^{]*\{\{"*2,parameter):
            templatenum += 2
        elif re.search("[^{]*\{\{",parameter):
            templatenum += 1
    return templatenum
def draw(x):
    longtext = ("""{{Aircraft specs/sandbox
    |ref                        = <!-- reference --> """ + get(x,"ref") + """
    |prime units?               = """ + primeunit + """
    <!-- imp or kts first for US aircraft, and UK aircraft pre-metrification, 
    met(ric) first for all others. You MUST choose a format, or no specifications will show -->
    <!--General characteristics-->
    |crew                   = """ + get(x,"crew") + """
    |capacity               = """ + get(x,"capacity") + payload() + """
    |length m               = """ + unitparam("m","length") + """
    |length ft              = """ + unitparam("ft","length") + """
    |length in              = """ + unitparam("in","length") + """
    |span m                 = """ + unitif(plane,"m","span") + """
    |span ft                = """ + unitif(plane,"ft","span") + """
    |span in                = """ + unitif(plane,"in","span") + """
    |height m               = """ + unitparam("m","height") + """
    |height ft              = """ + unitparam("ft","height") + """
    |height in              = """ + unitparam("in","height") + """
    |wing area sqm          = """ + unitif(plane,"sqm","area") + """
    |wing area sqft         = """ + unitif(plane,"sqft","area") + """
    |aspect ratio           = """ + get(x,"aspect ratio") + """
    |airfoil                = """ + get(x,"airfoil") + """
    |empty weight kg        = """ + unitparam("kg","empty weight") + """
    |empty weight lb        = """ + unitparam("lb","empty weight") + """
    |gross weight kg        = """ + unitparam("kg","loaded weight") + """
    |gross weight lb        = """ + unitparam("lb","loaded weight") + """
    |max takeoff weight kg  = """ + unitparam("kg","max takeoff weight") + """
    |max takeoff weight lb  = """ + unitparam("lb","max takeoff weight") + """
    |more general           = """ + get(x,"more general", True) + """
    <!--Powerplant-->
    |eng1 number            = """ + get(x,"number of props") + get(x,"number of jets") + """
    |eng1 name              = """ + get(x,"engine (prop)") + get(x,"engine (jet)") + """
    |eng1 type              = """ + get(x,"type of prop") + get(x,"type of jet") + """
    |eng1 kw                = <!-- prop engines --> """ + unitparam("kw","power") + """
    |eng1 hp                = <!-- prop engines --> """ + unitparam("hp","power") + """
    |eng1 shp               = <!-- prop engines --> """ + unitparam("shp","power") + """
    |eng1 kn                = <!-- jet/rocket engines --> """ + unitparam("kn","thrust") + """
    |eng1 lbf               = <!-- jet/rocket engines --> """ + unitparam("lbf","thrust") + """
    |power original         = """ + get(x,"power original") + """
    |thrust original        = """ + get(x,"thrust original") + """
    |eng1 kn-ab             = """ + unitparam("kn","afterburning thrust") + """
    |eng1 lbf-ab            = """ + unitparam("lbf","afterburning thrust") + """
    |more power             = """ + get(x,"more general powerplant", True) + """
    |prop name              = """ + get(x,"propellers") + """
    |prop dia m             = <!-- propeller aircraft --> """ + unitparam("m","propeller diameter") + """
    |prop dia ft            = <!-- propeller aircraft --> """ + unitparam("ft","propeller diameter") + """
    |prop dia in            = <!-- propeller aircraft --> """ + unitparam("in","propeller diameter") + """
    |rot dia m              = <!-- helicopters --> """ + unitif(copter,"m","span main") + """
    |rot dia ft             = <!-- helicopters --> """ + unitif(copter,"ft","span main") + """
    |rot dia in             = <!-- helicopters --> """ + unitif(copter,"in","span main")  + """
    |rot area sqm           = <!-- helicopters --> """ + unitif(copter,"sqm","area")  + """
    |rot area sqft          = <!-- helicopters --> """ + unitif(copter,"sqft","area") + """
    <!--Performance-->
    |max speed kmh          = """ + unitparam("kmh","max speed") + """
    |max speed mph          = """ + unitparam("mph","max speed") + """
    |max speed kts          = """ + unitparam("kts","max speed") + """
    |max speed note         = """ + get(x,"max speed more") + """
    |max speed mach         = """ + unitparam("mach","max speed") + """
    |cruise speed kmh       = """ + unitparam("kmh","cruise speed") + """
    |cruise speed mph       = """ + unitparam("mph","cruise speed") + """
    |cruise speed kts       = """ + unitparam("kts","cruise speed") + """
    |cruise speed note      = """ + get(x,"cruise speed more") + """
    |stall speed kmh        = """ + unitparam("kmh","stall speed") + """
    |stall speed mph        = """ + unitparam("mph","stall speed") + """
    |stall speed kts        = """ + unitparam("kts","stall speed") + """
    |stall speed note       = """ + get(x,"stall speed more") + """
    |never exceed speed kmh = """ + unitparam("kmh","never exceed speed") + """
    |never exceed speed mph = """ + unitparam("mph","never exceed speed") + """
    |never exceed speed kts = """ + unitparam("kts","never exceed speed") + """
    |range km               = """ + unitparam("km","range") + """
    |range miles            = """ + unitparam("miles","range") + """
    |range nmi              = """ + unitparam("nmi","range") + """
    |range note             = """ + get(x,"range more") + """
    |combat range km        = """ + unitparam("km","combat radius") + """
    |combat range miles     = """ + unitparam("miles","combat radius") + """
    |combat range nmi       = """ + unitparam("nmi","combat radius") + """
    |combat range note      = """ + get(x,"combat radius more") + """
    |ferry range km         = """ + unitparam("km","ferry range") + """
    |ferry range miles      = """ + unitparam("miles","ferry range") + """
    |ferry range nmi        = """ + unitparam("nmi","ferry range") + """
    |ferry range note       = """ + get(x,"ferry range more") + """
    |endurance              = <!-- if range unknown --> """ + get(x,"endurance") + """
    |ceiling m              = """ + unitparam("m","ceiling") + """
    |ceiling ft             = """ + unitparam("ft","ceiling") + """
    |ceiling note           = """ + get(x,"ceiling more") + """
    |climb rate ms          = """ + unitparam("ms","climb rate") + """
    |climb rate ftmin       = """ + unitparam("ftmin","climb rate") + """
    |climb rate note        = """ + get(x,"climb rate more") + """
    |sink rate ms           = <!-- sailplanes --> """ + unitparam("ms","sink rate") + """
    |sink rate ftmin        = <!-- sailplanes --> """ + unitparam("ftmin","sink rate") + """
    |sink rate note         = """ + get(x,"sink rate more") + """
    |wing loading kg/m2     = """ + unitif(plane,"kg/m2","loading") + """
    |wing loading lb/sqft   = """ + unitif(plane,"lb/sqft","loading") + """
    |disk loading kg/m2     = """ + unitif(copter,"kg/m2","loading") + """
    |disk loading lb/sqft   = """ + unitif(copter,"lb/sqft","loading") + """
    |power/mass             = """ + powermass() + """
    |thrust/weight          = """ + get(x,"thrust/weight") + """
    |more performance       = """ + get(x,"more performance") + """
    <!--Armament-->
    """ + armaments() + """
    |guns                   = """ + getarmaments(x,"guns") + """
    |bombs                  = """ + getarmaments(x,"bombs") + """
    |rockets                = """ + getarmaments(x,"rockets") + """
    |missiles               = """ + getarmaments(x,"missiles") + """
    |hardpoints             = """ + getarmaments(x,"hardpoints")+ """
    |hardpoint capacity     = """ + getarmaments(x,"hardpoint capacity") + """
    |hardpoint rockets      = """ + getarmaments(x,"hardpoint rockets") + """
    |hardpoint missiles     = """ + getarmaments(x,"hardpoint missiles") + """
    |hardpoint bombs        = """ + getarmaments(x,"hardpoint bombs") + """
    |hardpoint other        = """ + getarmaments(x,"hardpoint other") + """
    |avionics               = """ + getarmaments(x,"avionics") + "}}")
    return longtext
site = pywikibot.Site('en', 'wikipedia')
errorpage = pywikibot.Page(site, u"User:PearBOT/Aircraft specs problems")
linkpage = pywikibot.Page(site, u"User:PearBOT/test")
for page in pywikibot.pagegenerators.LinkedPageGenerator(linkpage):
    text = page.text
    templates=pywikibot.textlib.extract_templates_and_params(text,remove_disabled_parts="yes",strip ="yes")
    for x in templates:
        if x[0] == "Aircraft specifications" or x[0] =="Aircraft specification" or x[0] == "Airtemp-test" or x[0] == "Airtemp-test" or x[0] == "aircraft specifications" or x[0] =="aircraft specification" or x[0] == "airtemp-test" or x[0] == "airtemp-test":       
            print(page.full_url())
            longtext=""
            plane = False
            copter = False
            copter=findtype("copter", x[1])
            plane=findtype("plane", x[1])
            primeunit=findprimeunit(x[1])
            badparam()
            finalregex = ""
            i=0
            while i < (1+subtemplatenum()):
                finalregex += "[^}]*}}"
                i+=1
            templatetext=draw(x[1]);
            if abort:
                abort = False
                errorpage.text += "\n*Page skipped at: " 
                errorpage.text += page.full_url()
                errorpage.save("Page skipped")
            else:
                page.text = re.sub("{{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)"+finalregex,templatetext,page.text)
                page.save(u"Bot test")