Difference between revisions of "Module:User:Mr. Stradivarius/sandbox3"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(error message tweaks)
blackwiki>Mr. Stradivarius
(add the importanceScale class, fixes for qualityScale class methods, better makeCheckSelfFunction code, better error messages in checkForDuplicateTriggers, fix indentation)
Line 18: Line 18:
 
-- Makes a simple function that raises an error if the dot syntax is used with methods.
 
-- Makes a simple function that raises an error if the dot syntax is used with methods.
 
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
 
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc )
+
-- The uniqueMethod variable should be the name of a method unique to the class.
 +
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc, uniqueMethod )
 
     return function( self, method )
 
     return function( self, method )
         if type( self ) ~= 'table' or type( self.new ) ~= 'function' then
+
         if type( self ) ~= 'table' or type( self.new ) ~= 'function' or type( self[ uniqueMethod ] ) ~= 'function' then
 
             error( mw.ustring.format(
 
             error( mw.ustring.format(
 
                 '%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
 
                 '%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
Line 55: Line 56:
 
     s = checkString( s )
 
     s = checkString( s )
 
     if s then
 
     if s then
if type( array ) == 'table' then
+
        if type( array ) == 'table' then
table.insert( array, s )
+
            table.insert( array, s )
 
         elseif type( array ) == 'nil' then
 
         elseif type( array ) == 'nil' then
 
             array = {}
 
             array = {}
 
             table.insert( array, s )
 
             table.insert( array, s )
else
+
        else
error( mw.ustring.format(
+
            error( mw.ustring.format(
'Error in argument #1 to addStringToArray: expected type "table" or "nil", got type "%s"',
+
                'Error in argument #1 to addStringToArray: expected type "table" or "nil", got type "%s"',
type( array )
+
                type( array )
), 2 )
+
            ), 2 )
    end
+
        end
end
+
    end
 
     return array or {}
 
     return array or {}
 
end
 
end
Line 76: Line 77:
 
local banner = {}
 
local banner = {}
 
banner.__index = banner
 
banner.__index = banner
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object' )
+
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object', 'exportCategories' )
  
 
function banner:new( init )
 
function banner:new( init )
 
     init = type( init ) == 'table' and init or {}
 
     init = type( init ) == 'table' and init or {}
 
     local obj = {}
 
     local obj = {}
   
+
 
 
     obj.objectName = init.objectName
 
     obj.objectName = init.objectName
 
     if not obj.objectName then
 
     if not obj.objectName then
 
         error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
 
         error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
 
     end
 
     end
   
+
 
 
     -- Set the project name and exit if its value is absent or invalid.
 
     -- Set the project name and exit if its value is absent or invalid.
 
     obj.project = init.project
 
     obj.project = init.project
 
     if type( obj.project ) ~= 'string' or obj.project == '' then return end
 
     if type( obj.project ) ~= 'string' or obj.project == '' then return end
   
+
 
 
     -- Set the index metamethod and the metatable.
 
     -- Set the index metamethod and the metatable.
 
     self.__index = self
 
     self.__index = self
Line 99: Line 100:
 
function banner:setImage( s )
 
function banner:setImage( s )
 
     checkSelfBanner( self, 'setImage' )
 
     checkSelfBanner( self, 'setImage' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
self.image = s
+
        self.image = s
end
+
    end
 
end
 
end
  
 
-- Gets the banner's main image.
 
-- Gets the banner's main image.
 
function banner:getImage()
 
function banner:getImage()
checkSelfBanner( self, 'getImage' )
+
    checkSelfBanner( self, 'getImage' )
return self.image
+
    return self.image
 
end
 
end
  
Line 114: Line 115:
 
function banner:addCategory( s )
 
function banner:addCategory( s )
 
     checkSelfBanner( self, 'addCategory' )
 
     checkSelfBanner( self, 'addCategory' )
self.categories = addStringToArray( self.categories, s )
+
    self.categories = addStringToArray( self.categories, s )
 
end
 
end
  
Line 169: Line 170:
 
-- Adds an array of row objects to the banner object.
 
-- Adds an array of row objects to the banner object.
 
function banner:addRows( t )
 
function banner:addRows( t )
checkSelfBanner( self, 'addRows' )
+
    checkSelfBanner( self, 'addRows' )
if type( t ) == 'table' then
+
    if type( t ) == 'table' then
for i, rowObject in ipairs( t ) do
+
        for i, rowObject in ipairs( t ) do
self:addRow( rowObject )
+
            self:addRow( rowObject )
end
+
        end
end
+
    end
 
end
 
end
  
Line 187: Line 188:
 
local row = {}
 
local row = {}
 
row.__index = row
 
row.__index = row
local checkSelfRow = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'row', 'row object' )
+
local checkSelfRow = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'row', 'row object', 'getCategories' ) -- TODO: replace getCategories with a less generic function.
  
 
function row:new( init )
 
function row:new( init )
Line 201: Line 202:
 
function row:addCategory( s )
 
function row:addCategory( s )
 
     checkSelfRow( self, 'addCategory' )
 
     checkSelfRow( self, 'addCategory' )
self.categories = addStringToArray( self.categories, s )
+
    self.categories = addStringToArray( self.categories, s )
 
end
 
end
  
Line 222: Line 223:
 
function row:export()
 
function row:export()
 
     checkSelfRow( self, 'export' )
 
     checkSelfRow( self, 'export' )
   
+
 
 
     -- Get the result of the icon and content export functions, and check the results.
 
     -- Get the result of the icon and content export functions, and check the results.
 
     local rowIconOutput = type( self.exportRowIcon ) == 'function' and self:exportRowIcon()
 
     local rowIconOutput = type( self.exportRowIcon ) == 'function' and self:exportRowIcon()
Line 228: Line 229:
 
     local rowContentOutput = type( self.exportRowContent ) == 'function' and self:exportRowContent()
 
     local rowContentOutput = type( self.exportRowContent ) == 'function' and self:exportRowContent()
 
     rowContentOutput = checkString( rowContentOutput )
 
     rowContentOutput = checkString( rowContentOutput )
   
+
 
 
     -- Export the row html.
 
     -- Export the row html.
 
     local ret = htmlBuilder.create()
 
     local ret = htmlBuilder.create()
 
     if rowIconOutput and rowContentOutput then
 
     if rowIconOutput and rowContentOutput then
 
         ret
 
         ret
            .tag( 'tr' )
+
        .tag( 'tr' )
                .tag( 'td' )
+
        .tag( 'td' )
                    .wikitext( rowIconOutput )
+
        .wikitext( rowIconOutput )
                    .done()
+
        .done()
                .tag( 'td' )
+
        .tag( 'td' )
                    .attr( 'colspan', '2' )
+
        .attr( 'colspan', '2' )
                    .wikitext( rowContentOutput )
+
        .wikitext( rowContentOutput )
 
     elseif rowContentOutput and not rowIconOutput then
 
     elseif rowContentOutput and not rowIconOutput then
 
         ret
 
         ret
            .tag( 'tr' )
+
        .tag( 'tr' )
                .tag( 'td' )
+
        .tag( 'td' )
                    .attr( 'colspan', '3' )
+
        .attr( 'colspan', '3' )
                    .wikitext( rowContentOutput )
+
        .wikitext( rowContentOutput )
 
     end
 
     end
 
     return tostring( ret )
 
     return tostring( ret )
Line 260: Line 261:
 
local assessmentGrade = {}
 
local assessmentGrade = {}
 
assessmentGrade.__index = assessmentGrade
 
assessmentGrade.__index = assessmentGrade
local checkSelfAssessmentGrade = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentGrade', 'assessmentGrade object' )
+
local checkSelfAssessmentGrade = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentGrade', 'assessmentGrade object', 'getGradeName' )
  
 
function assessmentGrade:new( init )
 
function assessmentGrade:new( init )
Line 274: Line 275:
 
-- the grade name would be "c".
 
-- the grade name would be "c".
 
function assessmentGrade:setGradeName( s )
 
function assessmentGrade:setGradeName( s )
checkSelfAssessmentGrade( self, 'setGradeName' )
+
    checkSelfAssessmentGrade( self, 'setGradeName' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
self.gradeName = mw.ustring.lower( s )
+
        self.gradeName = mw.ustring.lower( s )
end
+
    end
 
end
 
end
  
 
-- Gets the grade name.
 
-- Gets the grade name.
 
function assessmentGrade:getGradeName()
 
function assessmentGrade:getGradeName()
checkSelfAssessmentGrade( self, 'getGradeName' )
+
    checkSelfAssessmentGrade( self, 'getGradeName' )
return self.gradeName
+
    return self.gradeName
 
end
 
end
  
Line 291: Line 292:
 
-- would be "foo".
 
-- would be "foo".
 
function assessmentGrade:addTrigger( s )
 
function assessmentGrade:addTrigger( s )
checkSelfAssessmentGrade( self, 'addTrigger' )
+
    checkSelfAssessmentGrade( self, 'addTrigger' )
self.triggers = addStringToArray( self.triggers, s )
+
    self.triggers = addStringToArray( self.triggers, s )
 
end
 
end
  
 
-- Adds an array of triggers to the assessment grade object.
 
-- Adds an array of triggers to the assessment grade object.
 
function assessmentGrade:addTriggers( t )
 
function assessmentGrade:addTriggers( t )
checkSelfAssessmentGrade( self, 'addTriggers' )
+
    checkSelfAssessmentGrade( self, 'addTriggers' )
if type( t ) ~= 'table' then return end
+
    if type( t ) ~= 'table' then return end
for i, trigger in ipairs( t ) do
+
    for i, trigger in ipairs( t ) do
self:addTrigger( trigger )
+
        self:addTrigger( trigger )
end
+
    end
 
end
 
end
  
 
-- Returns an array containing the trigger values for the assessment grade object.
 
-- Returns an array containing the trigger values for the assessment grade object.
 
function assessmentGrade:getTriggers()
 
function assessmentGrade:getTriggers()
checkSelfAssessmentGrade( self, 'getTriggers' )
+
    checkSelfAssessmentGrade( self, 'getTriggers' )
return self.triggers or {}
+
    return self.triggers or {}
 
end
 
end
  
Line 314: Line 315:
 
-- by the qualityScale and importanceScale objects or banner objects.
 
-- by the qualityScale and importanceScale objects or banner objects.
 
function assessmentGrade:setCategory( s )
 
function assessmentGrade:setCategory( s )
checkSelfAssessmentGrade( self, 'setCategory' )
+
    checkSelfAssessmentGrade( self, 'setCategory' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
self.category = s
+
        self.category = s
end
+
    end
 
end
 
end
  
 
-- Gets the assessment grade's category.
 
-- Gets the assessment grade's category.
 
function assessmentGrade:getCategory()
 
function assessmentGrade:getCategory()
checkSelfAssessmentGrade( self, 'getCategory' )
+
    checkSelfAssessmentGrade( self, 'getCategory' )
return self.category
+
    return self.category
 
end
 
end
  
 
-- Sets the color of the icon box when the assessment grade is used.
 
-- Sets the color of the icon box when the assessment grade is used.
 
function assessmentGrade:setColor( s )
 
function assessmentGrade:setColor( s )
checkSelfAssessmentGrade( self, 'setColor' )
+
    checkSelfAssessmentGrade( self, 'setColor' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
self.color = s
+
        self.color = s
end
+
    end
 
end
 
end
  
 
-- Gets the color used for the assessment grade.
 
-- Gets the color used for the assessment grade.
 
function assessmentGrade:getColor()
 
function assessmentGrade:getColor()
checkSelfAssessmentGrade( self, 'getColor' )
+
    checkSelfAssessmentGrade( self, 'getColor' )
return self.color
+
    return self.color
 
end
 
end
  
 
-- Sets an icon for the assessment grade.
 
-- Sets an icon for the assessment grade.
 
function assessmentGrade:setIcon( s )
 
function assessmentGrade:setIcon( s )
checkSelfAssessmentGrade( self, 'setIcon' )
+
    checkSelfAssessmentGrade( self, 'setIcon' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
self.icon = s
+
        self.icon = s
end
+
    end
 
end
 
end
  
 
-- Gets the assessment grade icon.
 
-- Gets the assessment grade icon.
 
function assessmentGrade:getIcon()
 
function assessmentGrade:getIcon()
checkSelfAssessmentGrade( self, 'getIcon' )
+
    checkSelfAssessmentGrade( self, 'getIcon' )
return self.icon
+
    return self.icon
 
end
 
end
  
Line 380: Line 381:
 
local assessmentScale = {}
 
local assessmentScale = {}
 
assessmentScale.__index = assessmentScale
 
assessmentScale.__index = assessmentScale
local checkSelfAssessmentScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentScale', 'assessmentScale object' )
+
local checkSelfAssessmentScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentScale', 'assessmentScale object', 'addGrade' )
  
 
function assessmentScale:new( init )
 
function assessmentScale:new( init )
Line 389: Line 390:
 
     self.__index = self
 
     self.__index = self
 
     return setmetatable( obj, self )
 
     return setmetatable( obj, self )
 +
end
 +
 +
-- Sets the name of the parameter that accepts trigger values from assessmentGrade objects.
 +
-- For example, if an article was rated as |class=start, the parameter name would be "class".
 +
function assessmentScale:setParamName( s )
 +
    checkSelfAssessmentScale( self, 'setParamName' )
 +
    s = checkString( s )
 +
    if s then
 +
        self.param = s
 +
    end
 +
end
 +
 +
-- Gets the parameter name.
 +
function assessmentScale:getParamName()
 +
    checkSelfAssessmentScale( self, 'getParamName' )
 +
    return self.param
 
end
 
end
  
Line 396: Line 413:
 
function assessmentScale:setCategoryFamily( s )
 
function assessmentScale:setCategoryFamily( s )
 
     checkSelfAssessmentScale( self, 'setCategoryFamily' )
 
     checkSelfAssessmentScale( self, 'setCategoryFamily' )
s = checkString( s )
+
    s = checkString( s )
if s then
+
    if s then
 
         self.categoryFamily = s
 
         self.categoryFamily = s
end
+
    end  
 
end
 
end
  
Line 410: Line 427:
 
-- Adds an assessment grade object.
 
-- Adds an assessment grade object.
 
function assessmentScale:addGrade( gradeObject )
 
function assessmentScale:addGrade( gradeObject )
checkSelfAssessmentScale( self, 'addGrade' )
+
    checkSelfAssessmentScale( self, 'addGrade' )
gradeObject = checkObject( gradeObject )
+
    gradeObject = checkObject( gradeObject )
if gradeObject then
+
    if gradeObject then
local gradeName = gradeObject:getGradeName()
+
        local gradeName = gradeObject:getGradeName()
if not checkString( gradeName ) then
+
        if not checkString( gradeName ) then
 
             error( mw.ustring.format( 'Grade name not found (was type "%s"). Please set a grade name with the "setGradeName" method of the assessment grade object' , type( gradeName ) ), 2 )
 
             error( mw.ustring.format( 'Grade name not found (was type "%s"). Please set a grade name with the "setGradeName" method of the assessment grade object' , type( gradeName ) ), 2 )
 
         else
 
         else
self.grades = self.grades or {}
+
            self.grades = self.grades or {}
if self.grades[ gradeName ] then
+
            if self.grades[ gradeName ] then
error( mw.ustring.format( 'Attempted to add assessment grade %s, but assessment grade %s was already defined. Assessment grades can only be defined once', gradeName, gradeName ), 2 )
+
                error( mw.ustring.format( 'Attempted to add assessment grade %s, but assessment grade %s was already defined. Assessment grades can only be defined once', gradeName, gradeName ), 2 )
else
+
            else
self.grades[ gradeName ] = gradeObject
+
                self.grades[ gradeName ] = gradeObject
end
+
            end
end
+
        end
end
+
    end
 
end
 
end
  
 
-- Adds an array of grade objects.
 
-- Adds an array of grade objects.
 
function assessmentScale:addGrades( t )
 
function assessmentScale:addGrades( t )
checkSelfAssessmentScale( self, 'addGrades' )
+
    checkSelfAssessmentScale( self, 'addGrades' )
if type( t ) ~= 'table' then return end
+
    if type( t ) ~= 'table' then return end
for i, gradeObject in ipairs( t ) do
+
    for i, gradeObject in ipairs( t ) do
self:addGrade( gradeObject )
+
        self:addGrade( gradeObject )
end
+
    end
 
end
 
end
  
 
-- Removes an assessment grade object from the assessment scale.
 
-- Removes an assessment grade object from the assessment scale.
 
function assessmentScale:removeGrade( s )
 
function assessmentScale:removeGrade( s )
checkSelfAssessmentScale( self, 'removeGrade' )
+
    checkSelfAssessmentScale( self, 'removeGrade' )
s = checkString( s )
+
    s = checkString( s )
if s and type( self.grades ) == 'table' and self.grades[ s ] then
+
    if s and type( self.grades ) == 'table' and self.grades[ s ] then
self.grades[ s ] = nil
+
        self.grades[ s ] = nil
end
+
    end
 
end
 
end
  
 
-- Removes multiple assessment grade objects from the assessment scale.
 
-- Removes multiple assessment grade objects from the assessment scale.
 
function assessmentScale:removeGrades( t )
 
function assessmentScale:removeGrades( t )
checkSelfAssessmentScale( self, 'removeGrades' )
+
    checkSelfAssessmentScale( self, 'removeGrades' )
if type( t ) == 'table' then
+
    if type( t ) == 'table' then
for i, grade in ipairs( t ) do
+
        for i, grade in ipairs( t ) do
self:removeGrade( grade )
+
            self:removeGrade( grade )
end
+
        end
end
+
    end
 
end
 
end
  
 
-- Gets the object's grade table.
 
-- Gets the object's grade table.
 
function assessmentScale:getGrades()
 
function assessmentScale:getGrades()
checkSelfAssessmentScale( self, 'getGrades' )
+
    checkSelfAssessmentScale( self, 'getGrades' )
return self.grades or {}
+
    return self.grades or {}
 
end
 
end
  
function assessmentScale:editGrade()
+
-- Gets the specified grade object.
 +
function assessmentScale:getGrade( gradeName )
 +
    checkSelfAssessmentScale( self, 'getGrade' )
 +
    self.grades = self.grades or {}
 +
    gradeName = checkString( gradeName )
 +
    if gradeName then
 +
        return self.grades[ gradeName ]
 +
    end
 +
end
 +
 
 +
-- Edits a grade object in the grades table by calling one of its methods.
 +
function assessmentScale:editGrade( gradeName, method, ... )
 +
    checkSelfAssessmentScale( self, 'editGrade' )
 +
    self.grades = self.grades or {}
 +
    gradeName = checkString( gradeName )
 +
    method = checkString( method )
 +
    if not ( gradeName and method ) then return end
 +
    local gradeObject = self.grades[ gradeName ]
 +
    if not checkObject( gradeObject ) then
 +
        error( mw.ustring.format( 'editGrade: no object found with grade name "%s"', gradeName ), 2 )
 +
    end
 +
    if type( gradeObject[ method ] ) ~= 'function' then
 +
        error( mw.ustring.format( 'editGrade: method "%s" was not found in the "%s" grade object', method, gradeName ), 2 )
 +
    end
 +
    self.grades[ gradeName ][ method ]( self, ... )
 
end
 
end
  
Line 468: Line 509:
 
function assessmentScale:checkForDuplicateTriggers()
 
function assessmentScale:checkForDuplicateTriggers()
 
     checkSelfAssessmentScale( self, 'checkForDuplicateTriggers' )
 
     checkSelfAssessmentScale( self, 'checkForDuplicateTriggers' )
     local grades = self:getGrades()
+
     local grades = self.grades or {}
    mw.log( dts( grades ) )
 
 
     if type( grades ) ~= 'table' then return end
 
     if type( grades ) ~= 'table' then return end
 
     local exists = {}
 
     local exists = {}
Line 481: Line 521:
 
                     if trigger then
 
                     if trigger then
 
                         if exists[ trigger ] then
 
                         if exists[ trigger ] then
                             error( mw.ustring.format( 'Duplicate trigger values "%s" detected in the assessment scale object', trigger ), 2 )
+
                             error( mw.ustring.format(
 +
                                'Duplicate trigger values "%s" detected in the assessment grade objects "%s" and "%s"',
 +
                                trigger, exists[ trigger ], name
 +
                            ), 2 )
 
                         else
 
                         else
                             exists[ trigger ] = true
+
                             exists[ trigger ] = name
 
                         end
 
                         end
 
                     end
 
                     end
Line 497: Line 540:
  
 
local qualityScale = assessmentScale:new()
 
local qualityScale = assessmentScale:new()
 +
local checkSelfQualityScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'qualityScale', 'qualityScale object', 'setFaGrade' )
  
 
-- Sets the FA (Featured Article) grade with default settings.
 
-- Sets the FA (Featured Article) grade with default settings.
 
function qualityScale:setFaGrade()
 
function qualityScale:setFaGrade()
 +
    checkSelfQualityScale( self, 'setFaGrade' )
 
     local faGrade = qualityGrade:new()
 
     local faGrade = qualityGrade:new()
faGrade:setGradeName( 'fa' )
+
    faGrade:setGradeName( 'fa' )
faGrade:addTrigger( 'fa' )
+
    faGrade:addTrigger( 'fa' )
faGrade:setColor( '#6699ff' )
+
    faGrade:setColor( '#6699ff' )
faGrade:setIcon( 'Featured article star.svg' )
+
    faGrade:setIcon( 'Featured article star.svg' )
qualityScale:addGrade( faGrade )
+
    self:addGrade( faGrade )
 
end
 
end
  
 
-- Sets the A grade with default settings.
 
-- Sets the A grade with default settings.
 
function qualityScale:setAGrade()
 
function qualityScale:setAGrade()
local aGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setAGrade' )
aGrade:setGradeName( 'a' )
+
    local aGrade = qualityGrade:new()
aGrade:addTrigger( 'a' )
+
    aGrade:setGradeName( 'a' )
aGrade:setColor( '#66ffff' )
+
    aGrade:addTrigger( 'a' )
 +
    aGrade:setColor( '#66ffff' )
 
     aGrade:setIcon( 'Symbol a class.svg' )
 
     aGrade:setIcon( 'Symbol a class.svg' )
qualityScale:addGrade( aGrade )
+
    self:addGrade( aGrade )
 
end
 
end
  
 
-- Sets the GA (Good Article) grade with default settings.
 
-- Sets the GA (Good Article) grade with default settings.
 
function qualityScale:setGaGrade()
 
function qualityScale:setGaGrade()
local gaGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setGaGrade' )
gaGrade:setGradeName( 'ga' )
+
    local gaGrade = qualityGrade:new()
gaGrade:addTrigger( 'ga' )
+
    gaGrade:setGradeName( 'ga' )
gaGrade:setColor( '#66ff66' )
+
    gaGrade:addTrigger( 'ga' )
gaGrade:setIcon( 'Symbol support vote.svg' )
+
    gaGrade:setColor( '#66ff66' )
qualityScale:addGrade( gaGrade )
+
    gaGrade:setIcon( 'Symbol support vote.svg' )
 +
    self:addGrade( gaGrade )
 
end
 
end
  
 
-- Sets the B grade with default settings.
 
-- Sets the B grade with default settings.
 
function qualityScale:setBGrade()
 
function qualityScale:setBGrade()
local bGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setBGrade' )
bGrade:setGradeName( 'b' )
+
    local bGrade = qualityGrade:new()
bGrade:addTrigger( 'b' )
+
    bGrade:setGradeName( 'b' )
bGrade:setColor( '#b2ff66' )
+
    bGrade:addTrigger( 'b' )
qualityScale:addGrade( bGrade )
+
    bGrade:setColor( '#b2ff66' )
 +
    self:addGrade( bGrade )
 
end
 
end
  
 
-- Sets the C grade with default settings.
 
-- Sets the C grade with default settings.
 
function qualityScale:setCGrade()
 
function qualityScale:setCGrade()
local cGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setCGrade' )
cGrade:setGradeName( 'c' )
+
    local cGrade = qualityGrade:new()
cGrade:addTrigger( 'c' )
+
    cGrade:setGradeName( 'c' )
cGrade:setColor( '#ffff66' )
+
    cGrade:addTrigger( 'c' )
qualityScale:addGrade( cGrade )
+
    cGrade:setColor( '#ffff66' )
 +
    self:addGrade( cGrade )
 
end
 
end
  
 
-- Sets the Start grade with default settings.
 
-- Sets the Start grade with default settings.
 
function qualityScale:setStartGrade()
 
function qualityScale:setStartGrade()
local startGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setStartGrade' )
startGrade:setGradeName( 'start' )
+
    local startGrade = qualityGrade:new()
startGrade:addTrigger( 'start' )
+
    startGrade:setGradeName( 'start' )
startGrade:setColor( '#ffaa66' )
+
    startGrade:addTrigger( 'start' )
qualityScale:addGrade( startGrade )
+
    startGrade:setColor( '#ffaa66' )
 +
    self:addGrade( startGrade )
 
end
 
end
  
 
-- Sets the Stub grade with default settings.
 
-- Sets the Stub grade with default settings.
 
function qualityScale:setStubGrade()
 
function qualityScale:setStubGrade()
local stubGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setStubGrade' )
stubGrade:setGradeName( 'stub' )
+
    local stubGrade = qualityGrade:new()
stubGrade:addTrigger( 'stub' )
+
    stubGrade:setGradeName( 'stub' )
stubGrade:setColor( '#ff6666' )
+
    stubGrade:addTrigger( 'stub' )
qualityScale:addGrade( stubGrade )
+
    stubGrade:setColor( '#ff6666' )
 +
    self:addGrade( stubGrade )
 
end
 
end
  
 
-- Sets the FL (Featured List) grade with default settings.
 
-- Sets the FL (Featured List) grade with default settings.
 
function qualityScale:setFlGrade()
 
function qualityScale:setFlGrade()
local flGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setFlGrade' )
flGrade:setGradeName( 'fl' )
+
    local flGrade = qualityGrade:new()
flGrade:addTrigger( 'fl' )
+
    flGrade:setGradeName( 'fl' )
flGrade:setColor( '#6699ff' )
+
    flGrade:addTrigger( 'fl' )
flGrade:setIcon( 'Featured article star.svg' )
+
    flGrade:setColor( '#6699ff' )
qualityScale:addGrade( flGrade )
+
    flGrade:setIcon( 'Featured article star.svg' )
 +
    self:addGrade( flGrade )
 
end
 
end
  
 
-- Sets the List grade with default settings.
 
-- Sets the List grade with default settings.
 
function qualityScale:setListGrade()
 
function qualityScale:setListGrade()
local listGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setListGrade' )
listGrade:setGradeName( 'list' )
+
    local listGrade = qualityGrade:new()
listGrade:addTrigger( 'list' )
+
    listGrade:setGradeName( 'list' )
listGrade:setColor( '#aa88ff' )
+
    listGrade:addTrigger( 'list' )
qualityScale:addGrade( listGrade )
+
    listGrade:setColor( '#aa88ff' )
 +
    self:addGrade( listGrade )
 
end
 
end
  
 
-- Sets the NA (not applicable) grade with default settings.
 
-- Sets the NA (not applicable) grade with default settings.
 
function qualityScale:setNaGrade()
 
function qualityScale:setNaGrade()
local naGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setNaGrade' )
naGrade:setGradeName( 'na' )
+
    local naGrade = qualityGrade:new()
naGrade:addTriggers{ 'na', 'n/a' }
+
    naGrade:setGradeName( 'na' )
naGrade:setColor( '#f5f5f5' )
+
    naGrade:addTriggers{ 'na', 'n/a' }
qualityScale:addGrade( naGrade )
+
    naGrade:setColor( '#f5f5f5' )
 +
    self:addGrade( naGrade )
 
end
 
end
  
 
-- Sets the Category grade with default settings.
 
-- Sets the Category grade with default settings.
 
function qualityScale:setCategoryGrade()
 
function qualityScale:setCategoryGrade()
local categoryGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setCategoryGrade' )
categoryGrade:setGradeName( 'category' )
+
    local categoryGrade = qualityGrade:new()
categoryGrade:addTriggers{ 'category', 'cat', 'categ' }
+
    categoryGrade:setGradeName( 'category' )
categoryGrade:setColor( '#ffdb58' )
+
    categoryGrade:addTriggers{ 'category', 'cat', 'categ' }
qualityScale:addGrade( categoryGrade )
+
    categoryGrade:setColor( '#ffdb58' )
 +
    self:addGrade( categoryGrade )
 
end
 
end
  
 
-- Sets the Disambig (disambiguation) grade with default settings.
 
-- Sets the Disambig (disambiguation) grade with default settings.
 
function qualityScale:setDisambigGrade()
 
function qualityScale:setDisambigGrade()
local disambigGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setDisambigGrade' )
disambigGrade:setGradeName( 'disambig' )
+
    local disambigGrade = qualityGrade:new()
disambigGrade:addTriggers{ 'disambiguation', 'disambig', 'disamb', 'dab' }
+
    disambigGrade:setGradeName( 'disambig' )
disambigGrade:setColor( '#00fa9a' )
+
    disambigGrade:addTriggers{ 'disambiguation', 'disambig', 'disamb', 'dab' }
qualityScale:addGrade( disambigGrade )
+
    disambigGrade:setColor( '#00fa9a' )
 +
    self:addGrade( disambigGrade )
 
end
 
end
  
 
-- Sets the File grade with default settings.
 
-- Sets the File grade with default settings.
 
function qualityScale:setFileGrade()
 
function qualityScale:setFileGrade()
local fileGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setFileGrade' )
fileGrade:setGradeName( 'file' )
+
    local fileGrade = qualityGrade:new()
fileGrade:addTriggers{ 'file', 'img', 'image' }
+
    fileGrade:setGradeName( 'file' )
fileGrade:setColor( '#ddccff' )
+
    fileGrade:addTriggers{ 'file', 'img', 'image' }
qualityScale:addGrade( fileGrade )
+
    fileGrade:setColor( '#ddccff' )
 +
    self:addGrade( fileGrade )
 
end
 
end
  
 
-- Sets the Portal grade with default settings.
 
-- Sets the Portal grade with default settings.
 
function qualityScale:setPortalGrade()
 
function qualityScale:setPortalGrade()
local portalGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setPortalGrade' )
portalGrade:setGradeName( 'portal' )
+
    local portalGrade = qualityGrade:new()
portalGrade:addTrigger( 'portal' )
+
    portalGrade:setGradeName( 'portal' )
portalGrade:setColor( '#cc8899' )
+
    portalGrade:addTrigger( 'portal' )
qualityScale:addGrade( portalGrade )
+
    portalGrade:setColor( '#cc8899' )
 +
    self:addGrade( portalGrade )
 
end
 
end
  
 
-- Sets the Project grade with default settings.
 
-- Sets the Project grade with default settings.
 
function qualityScale:setProjectGrade()
 
function qualityScale:setProjectGrade()
local projectGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setProjectGrade' )
projectGrade:setGradeName( 'project' )
+
    local projectGrade = qualityGrade:new()
projectGrade:addTriggers{ 'project', 'proj', 'prj' }
+
    projectGrade:setGradeName( 'project' )
projectGrade:setColor( '#c0c090' )
+
    projectGrade:addTriggers{ 'project', 'proj', 'prj' }
qualityScale:addGrade( projectGrade )
+
    projectGrade:setColor( '#c0c090' )
 +
    self:addGrade( projectGrade )
 
end
 
end
  
 
-- Sets the Template grade with default settings.
 
-- Sets the Template grade with default settings.
 
function qualityScale:setTemplateGrade()
 
function qualityScale:setTemplateGrade()
local templateGrade = qualityGrade:new()
+
    checkSelfQualityScale( self, 'setTemplateGrade' )
templateGrade:setGradeName( 'template' )
+
    local templateGrade = qualityGrade:new()
templateGrade:addTriggers{ 'template', 'temp', 'tpl', 'tmp', 'templ' }
+
    templateGrade:setGradeName( 'template' )
templateGrade:setColor( '#fbceb1' )
+
    templateGrade:addTriggers{ 'template', 'temp', 'tpl', 'tmp', 'templ' }
qualityScale:addGrade( templateGrade )
+
    templateGrade:setColor( '#fbceb1' )
 +
    self:addGrade( templateGrade )
 
end
 
end
  
 
-- Sets the Redirect grade with default settings.
 
-- Sets the Redirect grade with default settings.
 
function qualityScale:setRedirectGrade()
 
function qualityScale:setRedirectGrade()
 +
    checkSelfQualityScale( self, 'setRedirectGrade' )
 
     local redirectGrade = qualityGrade:new()
 
     local redirectGrade = qualityGrade:new()
redirectGrade:setGradeName( 'redirect' )
+
    redirectGrade:setGradeName( 'redirect' )
redirectGrade:addTriggers{ 'redirect', 'red', 'redir' }
+
    redirectGrade:addTriggers{ 'redirect', 'red', 'redir' }
redirectGrade:setColor( '#c0c0c0' )
+
    redirectGrade:setColor( '#c0c0c0' )
qualityScale:addGrade( redirectGrade )
+
    self:addGrade( redirectGrade )
 
end
 
end
  
 
-- Sets the Book grade with default settings.
 
-- Sets the Book grade with default settings.
 
function qualityScale:setBookGrade()
 
function qualityScale:setBookGrade()
 +
    checkSelfQualityScale( self, 'setBookGrade' )
 
     local bookGrade = qualityGrade:new()
 
     local bookGrade = qualityGrade:new()
 
     bookGrade:setGradeName( 'book' )
 
     bookGrade:setGradeName( 'book' )
bookGrade:addTriggers{ 'book', 'bk' }
+
    bookGrade:addTriggers{ 'book', 'bk' }
bookGrade:setColor( '#98ff98' )
+
    bookGrade:setColor( '#98ff98' )
qualityScale:addGrade( bookGrade )
+
    self:addGrade( bookGrade )
 
end
 
end
  
 
-- Sets the FM (Featured media) grade with default settings.
 
-- Sets the FM (Featured media) grade with default settings.
 
function qualityScale:setFmGrade()
 
function qualityScale:setFmGrade()
 +
    checkSelfQualityScale( self, 'setFmGrade' )
 
     local fmGrade = qualityGrade:new()
 
     local fmGrade = qualityGrade:new()
 
     fmGrade:setGradeName( 'fm' )
 
     fmGrade:setGradeName( 'fm' )
 
     fmGrade:addTrigger( 'fm' )
 
     fmGrade:addTrigger( 'fm' )
fmGrade:setColor( '#6699ff' )
+
    fmGrade:setColor( '#6699ff' )
 
     fmGrade:setIcon( 'Featured article star.svg' )
 
     fmGrade:setIcon( 'Featured article star.svg' )
qualityScale:addGrade( fmGrade )
+
    self:addGrade( fmGrade )
 
end
 
end
  
 
-- Set the standard quality scale with default values.
 
-- Set the standard quality scale with default values.
 
function qualityScale:setStandardQualityScale()
 
function qualityScale:setStandardQualityScale()
self:setFaGrade()
+
    checkSelfQualityScale( self, 'setStandardQualityScale' )
self:setAGrade()
+
    self:setFaGrade()
self:setGaGrade()
+
    self:setAGrade()
self:setBGrade()
+
    self:setGaGrade()
self:setCGrade()
+
    self:setBGrade()
self:setStartGrade()
+
    self:setCGrade()
self:setStubGrade()
+
    self:setStartGrade()
self:setFlGrade()
+
    self:setStubGrade()
self:setListGrade()
+
    self:setFlGrade()
self:setNaGrade()
+
    self:setListGrade()
 +
    self:setNaGrade()
 
end
 
end
  
 
-- Set the extended quality scale with default values.
 
-- Set the extended quality scale with default values.
 
function qualityScale:setExtendedQualityScale()
 
function qualityScale:setExtendedQualityScale()
self:setStandardQualityScale()
+
    checkSelfQualityScale( self, 'setExtendedQualityScale' )
self:setCategoryGrade()
+
    self:setStandardQualityScale()
self:setDisambigGrade()
+
    self:setCategoryGrade()
self:setFileGrade()
+
    self:setDisambigGrade()
self:setPortalGrade()
+
    self:setFileGrade()
self:setProjectGrade()
+
    self:setPortalGrade()
self:setTemplateGrade()
+
    self:setProjectGrade()
 +
    self:setTemplateGrade()
 
end
 
end
  
 
----------------------------------------------------------
 
----------------------------------------------------------
-- Define the importanceGrade class
+
-- Define the importanceScale class
 
----------------------------------------------------------
 
----------------------------------------------------------
  
local importanceGrade = assessmentGrade:new()
+
local importanceScale = assessmentScale:new()
      
+
local checkSelfImportanceScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'importanceScale', 'importanceScale object', 'setTopGrade' )
 +
 
 +
-- Sets the Top grade with default settings.
 +
function importanceScale:setTopGrade()
 +
    checkSelfImportanceScale( self, 'setTopGrade' )
 +
    local topGrade = importanceGrade:new()
 +
    topGrade:setGradeName( 'top' )
 +
    topGrade:addTrigger( 'top' )
 +
    topGrade:setColor( '#ff00ff' )
 +
    self:addGrade( topGrade )
 +
end
 +
 
 +
-- Sets the High grade with default settings.
 +
function importanceScale:setHighGrade()
 +
    checkSelfImportanceScale( self, 'setHighGrade' )
 +
    local highGrade = importanceGrade:new()
 +
     highGrade:setGradeName( 'high' )
 +
    highGrade:addTrigger( 'high' )
 +
    highGrade:setColor( '#ff88ff' )
 +
    self:addGrade( highGrade )
 +
end
 +
 
 +
-- Sets the Mid grade with default settings.
 +
function importanceScale:setMidGrade()
 +
    checkSelfImportanceScale( self, 'setMidGrade' )
 +
    local midGrade = importanceGrade:new()
 +
    midGrade:setGradeName( 'mid' )
 +
    midGrade:addTrigger( 'mid' )
 +
    midGrade:setColor( '#ffbbff' )
 +
    self:addGrade( midGrade )
 +
end
 +
 
 +
-- Sets the Low grade with default settings.
 +
function importanceScale:setLowGrade()
 +
    checkSelfImportanceScale( self, 'setLowGrade' )
 +
    local lowGrade = importanceGrade:new()
 +
    lowGrade:setGradeName( 'low' )
 +
    lowGrade:addTrigger( 'low' )
 +
    lowGrade:setColor( '#ffddff' )
 +
    self:addGrade( lowGrade )
 +
end
 +
 
 +
-- Sets the Bottom grade with default settings.
 +
function importanceScale:setBottomGrade()
 +
    checkSelfImportanceScale( self, 'setBottomGrade' )
 +
    local bottomGrade = importanceGrade:new()
 +
    bottomGrade:setGradeName( 'bottom' )
 +
    bottomGrade:addTrigger( 'bottom' )
 +
    bottomGrade:setColor( '#ffeeff' )
 +
    self:addGrade( bottomGrade )
 +
end
 +
 
 +
-- Sets the No grade with default settings.
 +
function importanceScale:setNoGrade()
 +
    checkSelfImportanceScale( self, 'setNoGrade' )
 +
    local noGrade = importanceGrade:new()
 +
    noGrade:setGradeName( 'no' )
 +
    noGrade:addTrigger( 'no' )
 +
    noGrade:setColor( '#ffffff' )
 +
    self:addGrade( noGrade )
 +
end
 +
 
 +
-- Sets the NA grade with default settings.
 +
function importanceScale:setNaGrade()
 +
    checkSelfImportanceScale( self, 'setNaGrade' )
 +
    local naGrade = importanceGrade:new()
 +
    naGrade:setGradeName( 'na' )
 +
    naGrade:addTriggers{ 'na', 'n/a' }
 +
    naGrade:setColor( '#f5f5f5' )
 +
    self:addGrade( naGrade )
 +
end
 +
 
 +
-- Sets the Core grade with default settings.
 +
function importanceScale:setCoreGrade()
 +
    checkSelfImportanceScale( self, 'setCoreGrade' )
 +
    local coreGrade = importanceGrade:new()
 +
    coreGrade:setGradeName( 'core' )
 +
    coreGrade:addTrigger( 'core' )
 +
    coreGrade:setColor( '#ff00ff' )
 +
    self:addGrade( coreGrade )
 +
end
 +
 
 +
-- Sets the standard importance scale with default settings.
 +
function importanceScale:setStandardImportanceScale()
 +
    checkSelfImportanceScale( self, 'setStandardImportanceScale' )
 +
    self:setTopGrade()
 +
    self:setHighGrade()
 +
    self:setMidGrade()
 +
    self:setLowGrade()
 +
    self:setNaGrade()
 +
end
 +
 
 
----------------------------------------------------------
 
----------------------------------------------------------
 
-- Define the taskForce class
 
-- Define the taskForce class

Revision as of 14:52, 5 September 2013

Usage

Template:Missing documentation {{#invoke:User:Mr. Stradivarius|function_name}}



local dts = require( 'Module:User:Anomie/deepToString' ).deepToString -- for debugging

-- TODO:
-- define self.page

local htmlBuilder = require( 'Module:HtmlBuilder' )

----------------------------------------------------------
-- Define constants
----------------------------------------------------------

local currentTitleObject = mw.title.getCurrentTitle()

----------------------------------------------------------
-- Helper functions
----------------------------------------------------------

-- Makes a simple function that raises an error if the dot syntax is used with methods.
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
-- The uniqueMethod variable should be the name of a method unique to the class.
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc, uniqueMethod )
    return function( self, method )
        if type( self ) ~= 'table' or type( self.new ) ~= 'function' or type( self[ uniqueMethod ] ) ~= 'function' then
            error( mw.ustring.format(
                '%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
                libraryName, selfObjDesc, method, varName, method, varName, method
            ), 3 )
        end
    end
end

-- Checks to see if a given variable is a non-blank string. Returns the string if true,
-- and returns false if not.
local function checkString( s )
    if type( s ) == 'string' and s ~= '' then
        return s
    else
        return false
    end
end

-- Checks to see if a given variable is an object of some kind. Returns the object if true,
-- and returns false if not. 
local function checkObject( obj )
    if type( obj ) == 'table' and type( obj.new ) == 'function' then
        return obj
    else
        return false
    end
end

-- Adds a string to an array. Returns nil on an attempt to add a non-string value, and returns
-- an error on an attempt to add a string to a non-table value. Checks that the string is not
-- the empty string, and if the array is not present, the function creates it.
local function addStringToArray( array, s )
    s = checkString( s )
    if s then
        if type( array ) == 'table' then
            table.insert( array, s )
        elseif type( array ) == 'nil' then
            array = {}
            table.insert( array, s )
        else
            error( mw.ustring.format(
                'Error in argument #1 to addStringToArray: expected type "table" or "nil", got type "%s"',
                type( array )
            ), 2 )
        end
    end
    return array or {}
end

----------------------------------------------------------
-- Define the banner class
----------------------------------------------------------

local banner = {}
banner.__index = banner
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object', 'exportCategories' )

function banner:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}

    obj.objectName = init.objectName
    if not obj.objectName then
        error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
    end

    -- Set the project name and exit if its value is absent or invalid.
    obj.project = init.project
    if type( obj.project ) ~= 'string' or obj.project == '' then return end

    -- Set the index metamethod and the metatable.
    self.__index = self
    return setmetatable( obj, self )
end

-- Sets the banner's main image.
function banner:setImage( s )
    checkSelfBanner( self, 'setImage' )
    s = checkString( s )
    if s then
        self.image = s
    end
end

-- Gets the banner's main image.
function banner:getImage()
    checkSelfBanner( self, 'getImage' )
    return self.image
end

-- Adds one category to the banner's "categories" table.
function banner:addCategory( s )
    checkSelfBanner( self, 'addCategory' )
    self.categories = addStringToArray( self.categories, s )
end

-- Adds all categories in a "categories" array to the banner's "categories" table.
function banner:addCategories( categoryTable )
    checkSelfBanner( self, 'addCategories' )
    if type( categoryTable ) == 'table' then
        for i, category in ipairs( rowObject.categories ) do
            self:addCategory( category )
        end
    end
end

-- Returns the banner object's category table.
function banner:getCategories()
    checkSelfBanner( self, 'getCategories' )
    return self.categories or {}
end

-- Returns a string of category links for the categories in obj.categories.
function banner:exportCategories()
    checkSelfBanner( self, 'exportCategories' )
    if type( self.categories ) == 'table' then
        local ret = {}
        for i, category in ipairs( self.categories ) do
            category = checkString( category )
            if category then
                table.insert( ret, mw.ustring.format(
                    '[[Category:%s|%s]]',
                    category,
                    type( self.page ) == 'string' and self.page or currentTitleObject.text
                ) )
            end
        end
        return table.concat( ret )
    end
    return ''
end        

-- Adds a row object to the banners "rows" table, and adds the row object's categories
-- to the banners "categories" table. Categories are deleted from the row object after
-- they have been transferred.
function banner:addRow( rowObject )
    checkSelfBanner( self, 'addRow' )
    self.rows = self.rows or {}
    rowObject = checkObject( rowObject )
    if rowObject then
        self:addCategories( rowObject.categories )
        rowObject.categories = nil -- Erase the categories from the row object to make sure we don't add the same categories twice.
        table.insert( self.rows, rowObject )
    end
end

-- Adds an array of row objects to the banner object.
function banner:addRows( t )
    checkSelfBanner( self, 'addRows' )
    if type( t ) == 'table' then
        for i, rowObject in ipairs( t ) do
            self:addRow( rowObject )
        end
    end
end

function banner:export()
    checkSelfBanner( self, 'export' )
end

----------------------------------------------------------
-- Define the row class
----------------------------------------------------------

local row = {}
row.__index = row
local checkSelfRow = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'row', 'row object', 'getCategories' ) -- TODO: replace getCategories with a less generic function.

function row:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}

    -- Set the index metamethod and the metatable.
    self.__index = self
    return setmetatable( obj, self )
end

-- Adds a category to the "categories" table of the row object. Creates the categories table if it doesn't exist.
function row:addCategory( s )
    checkSelfRow( self, 'addCategory' )
    self.categories = addStringToArray( self.categories, s )
end

-- Adds all categories in an array to the row's "categories" table.
function row:addCategories( t )
    checkSelfRow( self, 'addCategories' )
    if type( t ) == 'table' then
        for i, category in ipairs( t ) do
            self:addCategory( category )
        end
    end
end

-- Returns the row object's category table.
function row:getCategories()
    checkSelfRow( self, 'getCategories' )
    return self.categories or {}
end

function row:export()
    checkSelfRow( self, 'export' )

    -- Get the result of the icon and content export functions, and check the results.
    local rowIconOutput = type( self.exportRowIcon ) == 'function' and self:exportRowIcon()
    rowIconOutput = checkString( rowIconOutput )
    local rowContentOutput = type( self.exportRowContent ) == 'function' and self:exportRowContent()
    rowContentOutput = checkString( rowContentOutput )

    -- Export the row html.
    local ret = htmlBuilder.create()
    if rowIconOutput and rowContentOutput then
        ret
        .tag( 'tr' )
        .tag( 'td' )
        .wikitext( rowIconOutput )
        .done()
        .tag( 'td' )
        .attr( 'colspan', '2' )
        .wikitext( rowContentOutput )
    elseif rowContentOutput and not rowIconOutput then
        ret
        .tag( 'tr' )
        .tag( 'td' )
        .attr( 'colspan', '3' )
        .wikitext( rowContentOutput )
    end
    return tostring( ret )
end

----------------------------------------------------------
-- Define the assessmentGrade class
--
-- The assessmentGrade class sets the categories and
-- aliases for one importance scale grade or quality scale
-- grade.
----------------------------------------------------------

local assessmentGrade = {}
assessmentGrade.__index = assessmentGrade
local checkSelfAssessmentGrade = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentGrade', 'assessmentGrade object', 'getGradeName' )

function assessmentGrade:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}

    -- Set the index metamethod and the metatable.
    self.__index = self
    return setmetatable( obj, self )
end

-- Sets the name of the assessment grade. For example, for a C-class quality grade,
-- the grade name would be "c".
function assessmentGrade:setGradeName( s )
    checkSelfAssessmentGrade( self, 'setGradeName' )
    s = checkString( s )
    if s then
        self.gradeName = mw.ustring.lower( s )
    end
end

-- Gets the grade name.
function assessmentGrade:getGradeName()
    checkSelfAssessmentGrade( self, 'getGradeName' )
    return self.gradeName
end

-- Adds a trigger for the assessment grade. For example, if you want
-- the grade to be triggered by the code "|class=foo", then the trigger
-- would be "foo".
function assessmentGrade:addTrigger( s )
    checkSelfAssessmentGrade( self, 'addTrigger' )
    self.triggers = addStringToArray( self.triggers, s )
end

-- Adds an array of triggers to the assessment grade object.
function assessmentGrade:addTriggers( t )
    checkSelfAssessmentGrade( self, 'addTriggers' )
    if type( t ) ~= 'table' then return end
    for i, trigger in ipairs( t ) do
        self:addTrigger( trigger )
    end
end

-- Returns an array containing the trigger values for the assessment grade object.
function assessmentGrade:getTriggers()
    checkSelfAssessmentGrade( self, 'getTriggers' )
    return self.triggers or {}
end

-- Sets the category used by the assessment grade. This should only be used if the
-- category does not follow the default naming system. Normally categories are set
-- by the qualityScale and importanceScale objects or banner objects.
function assessmentGrade:setCategory( s )
    checkSelfAssessmentGrade( self, 'setCategory' )
    s = checkString( s )
    if s then
        self.category = s
    end
end

-- Gets the assessment grade's category.
function assessmentGrade:getCategory()
    checkSelfAssessmentGrade( self, 'getCategory' )
    return self.category
end

-- Sets the color of the icon box when the assessment grade is used.
function assessmentGrade:setColor( s )
    checkSelfAssessmentGrade( self, 'setColor' )
    s = checkString( s )
    if s then
        self.color = s
    end
end

-- Gets the color used for the assessment grade.
function assessmentGrade:getColor()
    checkSelfAssessmentGrade( self, 'getColor' )
    return self.color
end

-- Sets an icon for the assessment grade.
function assessmentGrade:setIcon( s )
    checkSelfAssessmentGrade( self, 'setIcon' )
    s = checkString( s )
    if s then
        self.icon = s
    end
end

-- Gets the assessment grade icon.
function assessmentGrade:getIcon()
    checkSelfAssessmentGrade( self, 'getIcon' )
    return self.icon
end

----------------------------------------------------------
-- Define the qualityGrade class
----------------------------------------------------------

local qualityGrade = assessmentGrade:new()

----------------------------------------------------------
-- Define the importanceGrade class
----------------------------------------------------------

local importanceGrade = assessmentGrade:new()

----------------------------------------------------------
-- Define the assessmentScale class
--
-- The assessmentScale class provides the infrastructure
-- for importance scales and quality scales. It uses
-- assessmentGrade objects to define each grade
-- on the assessment scale.
----------------------------------------------------------

local assessmentScale = {}
assessmentScale.__index = assessmentScale
local checkSelfAssessmentScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentScale', 'assessmentScale object', 'addGrade' )

function assessmentScale:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}

    -- Set the index metamethod and the metatable.
    self.__index = self
    return setmetatable( obj, self )
end

-- Sets the name of the parameter that accepts trigger values from assessmentGrade objects.
-- For example, if an article was rated as |class=start, the parameter name would be "class".
function assessmentScale:setParamName( s )
    checkSelfAssessmentScale( self, 'setParamName' )
    s = checkString( s )
    if s then
        self.param = s
    end
end

-- Gets the parameter name.
function assessmentScale:getParamName()
    checkSelfAssessmentScale( self, 'getParamName' )
    return self.param
end

-- Sets the name of the category family. For example, for a quality scale with categories
-- such as [[Category:C-class tulips articles]] and [[Category:List-class tulips articles]]
-- the category family name would be "tulips articles".
function assessmentScale:setCategoryFamily( s )
    checkSelfAssessmentScale( self, 'setCategoryFamily' )
    s = checkString( s )
    if s then
        self.categoryFamily = s
    end    
end

-- Gets the category family name for the assessment object.
function assessmentScale:getCategoryFamily()
    checkSelfAssessment( self, 'getCategoryFamily' )
    return self.categoryFamily
end

-- Adds an assessment grade object.
function assessmentScale:addGrade( gradeObject )
    checkSelfAssessmentScale( self, 'addGrade' )
    gradeObject = checkObject( gradeObject )
    if gradeObject then
        local gradeName = gradeObject:getGradeName()
        if not checkString( gradeName ) then
            error( mw.ustring.format( 'Grade name not found (was type "%s"). Please set a grade name with the "setGradeName" method of the assessment grade object' , type( gradeName ) ), 2 )
        else
            self.grades = self.grades or {}
            if self.grades[ gradeName ] then
                error( mw.ustring.format( 'Attempted to add assessment grade %s, but assessment grade %s was already defined. Assessment grades can only be defined once', gradeName, gradeName ), 2 )
            else
                self.grades[ gradeName ] = gradeObject
            end
        end
    end
end

-- Adds an array of grade objects.
function assessmentScale:addGrades( t )
    checkSelfAssessmentScale( self, 'addGrades' )
    if type( t ) ~= 'table' then return end
    for i, gradeObject in ipairs( t ) do
        self:addGrade( gradeObject )
    end
end

-- Removes an assessment grade object from the assessment scale.
function assessmentScale:removeGrade( s )
    checkSelfAssessmentScale( self, 'removeGrade' )
    s = checkString( s )
    if s and type( self.grades ) == 'table' and self.grades[ s ] then
        self.grades[ s ] = nil
    end
end

-- Removes multiple assessment grade objects from the assessment scale.
function assessmentScale:removeGrades( t )
    checkSelfAssessmentScale( self, 'removeGrades' )
    if type( t ) == 'table' then
        for i, grade in ipairs( t ) do
            self:removeGrade( grade )
        end
    end
end

-- Gets the object's grade table.
function assessmentScale:getGrades()
    checkSelfAssessmentScale( self, 'getGrades' )
    return self.grades or {}
end

-- Gets the specified grade object.
function assessmentScale:getGrade( gradeName )
    checkSelfAssessmentScale( self, 'getGrade' )
    self.grades = self.grades or {}
    gradeName = checkString( gradeName )
    if gradeName then
        return self.grades[ gradeName ]
    end
end

-- Edits a grade object in the grades table by calling one of its methods.
function assessmentScale:editGrade( gradeName, method, ... )
    checkSelfAssessmentScale( self, 'editGrade' )
    self.grades = self.grades or {}
    gradeName = checkString( gradeName )
    method = checkString( method )
    if not ( gradeName and method ) then return end
    local gradeObject = self.grades[ gradeName ]
    if not checkObject( gradeObject ) then
        error( mw.ustring.format( 'editGrade: no object found with grade name "%s"', gradeName ), 2 )
    end
    if type( gradeObject[ method ] ) ~= 'function' then
        error( mw.ustring.format( 'editGrade: method "%s" was not found in the "%s" grade object', method, gradeName ), 2 )
    end
    self.grades[ gradeName ][ method ]( self, ... )
end

-- Checks for duplicate triggers for the grade objects added to the assessment scale.
-- If any are found, displays an error.
function assessmentScale:checkForDuplicateTriggers()
    checkSelfAssessmentScale( self, 'checkForDuplicateTriggers' )
    local grades = self.grades or {}
    if type( grades ) ~= 'table' then return end
    local exists = {}
    for name, gradeObj in pairs( grades ) do
        gradeObj = checkObject( gradeObj )
        if gradeObj then
            local triggers = type( gradeObj.getTriggers ) == 'function' and gradeObj:getTriggers()
            if type( triggers ) == 'table' then
                for i, trigger in ipairs( triggers ) do
                    trigger = checkString( trigger )
                    if trigger then
                        if exists[ trigger ] then
                            error( mw.ustring.format(
                                'Duplicate trigger values "%s" detected in the assessment grade objects "%s" and "%s"',
                                trigger, exists[ trigger ],	name
                            ), 2 )
                        else
                            exists[ trigger ] = name
                        end
                    end
                end
            end
        end
    end
end

----------------------------------------------------------
-- Define the qualityScale class
----------------------------------------------------------

local qualityScale = assessmentScale:new()
local checkSelfQualityScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'qualityScale', 'qualityScale object', 'setFaGrade' )

-- Sets the FA (Featured Article) grade with default settings.
function qualityScale:setFaGrade()
    checkSelfQualityScale( self, 'setFaGrade' )
    local faGrade = qualityGrade:new()
    faGrade:setGradeName( 'fa' )
    faGrade:addTrigger( 'fa' )
    faGrade:setColor( '#6699ff' )
    faGrade:setIcon( 'Featured article star.svg' )
    self:addGrade( faGrade )
end

-- Sets the A grade with default settings.
function qualityScale:setAGrade()
    checkSelfQualityScale( self, 'setAGrade' )
    local aGrade = qualityGrade:new()
    aGrade:setGradeName( 'a' )
    aGrade:addTrigger( 'a' )
    aGrade:setColor( '#66ffff' )
    aGrade:setIcon( 'Symbol a class.svg' )
    self:addGrade( aGrade )
end

-- Sets the GA (Good Article) grade with default settings.
function qualityScale:setGaGrade()
    checkSelfQualityScale( self, 'setGaGrade' )
    local gaGrade = qualityGrade:new()
    gaGrade:setGradeName( 'ga' )
    gaGrade:addTrigger( 'ga' )
    gaGrade:setColor( '#66ff66' )
    gaGrade:setIcon( 'Symbol support vote.svg' )
    self:addGrade( gaGrade )
end

-- Sets the B grade with default settings.
function qualityScale:setBGrade()
    checkSelfQualityScale( self, 'setBGrade' )
    local bGrade = qualityGrade:new()
    bGrade:setGradeName( 'b' )
    bGrade:addTrigger( 'b' )
    bGrade:setColor( '#b2ff66' )
    self:addGrade( bGrade )
end

-- Sets the C grade with default settings.
function qualityScale:setCGrade()
    checkSelfQualityScale( self, 'setCGrade' )
    local cGrade = qualityGrade:new()
    cGrade:setGradeName( 'c' )
    cGrade:addTrigger( 'c' )
    cGrade:setColor( '#ffff66' )
    self:addGrade( cGrade )
end

-- Sets the Start grade with default settings.
function qualityScale:setStartGrade()
    checkSelfQualityScale( self, 'setStartGrade' )
    local startGrade = qualityGrade:new()
    startGrade:setGradeName( 'start' )
    startGrade:addTrigger( 'start' )
    startGrade:setColor( '#ffaa66' )
    self:addGrade( startGrade )
end

-- Sets the Stub grade with default settings.
function qualityScale:setStubGrade()
    checkSelfQualityScale( self, 'setStubGrade' )
    local stubGrade = qualityGrade:new()
    stubGrade:setGradeName( 'stub' )
    stubGrade:addTrigger( 'stub' )
    stubGrade:setColor( '#ff6666' )
    self:addGrade( stubGrade )
end

-- Sets the FL (Featured List) grade with default settings.
function qualityScale:setFlGrade()
    checkSelfQualityScale( self, 'setFlGrade' )
    local flGrade = qualityGrade:new()
    flGrade:setGradeName( 'fl' )
    flGrade:addTrigger( 'fl' )
    flGrade:setColor( '#6699ff' )
    flGrade:setIcon( 'Featured article star.svg' )
    self:addGrade( flGrade )
end

-- Sets the List grade with default settings.
function qualityScale:setListGrade()
    checkSelfQualityScale( self, 'setListGrade' )
    local listGrade = qualityGrade:new()
    listGrade:setGradeName( 'list' )
    listGrade:addTrigger( 'list' )
    listGrade:setColor( '#aa88ff' )
    self:addGrade( listGrade )
end

-- Sets the NA (not applicable) grade with default settings.
function qualityScale:setNaGrade()
    checkSelfQualityScale( self, 'setNaGrade' )
    local naGrade = qualityGrade:new()
    naGrade:setGradeName( 'na' )
    naGrade:addTriggers{ 'na', 'n/a' }
    naGrade:setColor( '#f5f5f5' )
    self:addGrade( naGrade )
end

-- Sets the Category grade with default settings.
function qualityScale:setCategoryGrade()
    checkSelfQualityScale( self, 'setCategoryGrade' )
    local categoryGrade = qualityGrade:new()
    categoryGrade:setGradeName( 'category' )
    categoryGrade:addTriggers{ 'category', 'cat', 'categ' }
    categoryGrade:setColor( '#ffdb58' )
    self:addGrade( categoryGrade )
end

-- Sets the Disambig (disambiguation) grade with default settings.
function qualityScale:setDisambigGrade()
    checkSelfQualityScale( self, 'setDisambigGrade' )
    local disambigGrade = qualityGrade:new()
    disambigGrade:setGradeName( 'disambig' )
    disambigGrade:addTriggers{ 'disambiguation', 'disambig', 'disamb', 'dab' }
    disambigGrade:setColor( '#00fa9a' )
    self:addGrade( disambigGrade )
end

-- Sets the File grade with default settings.
function qualityScale:setFileGrade()
    checkSelfQualityScale( self, 'setFileGrade' )
    local fileGrade = qualityGrade:new()
    fileGrade:setGradeName( 'file' )
    fileGrade:addTriggers{ 'file', 'img', 'image' }
    fileGrade:setColor( '#ddccff' )
    self:addGrade( fileGrade )
end

-- Sets the Portal grade with default settings.
function qualityScale:setPortalGrade()
    checkSelfQualityScale( self, 'setPortalGrade' )
    local portalGrade = qualityGrade:new()
    portalGrade:setGradeName( 'portal' )
    portalGrade:addTrigger( 'portal' )
    portalGrade:setColor( '#cc8899' )
    self:addGrade( portalGrade )
end

-- Sets the Project grade with default settings.
function qualityScale:setProjectGrade()
    checkSelfQualityScale( self, 'setProjectGrade' )
    local projectGrade = qualityGrade:new()
    projectGrade:setGradeName( 'project' )
    projectGrade:addTriggers{ 'project', 'proj', 'prj' }
    projectGrade:setColor( '#c0c090' )
    self:addGrade( projectGrade )
end

-- Sets the Template grade with default settings.
function qualityScale:setTemplateGrade()
    checkSelfQualityScale( self, 'setTemplateGrade' )
    local templateGrade = qualityGrade:new()
    templateGrade:setGradeName( 'template' )
    templateGrade:addTriggers{ 'template', 'temp', 'tpl', 'tmp', 'templ' }
    templateGrade:setColor( '#fbceb1' )
    self:addGrade( templateGrade )
end

-- Sets the Redirect grade with default settings.
function qualityScale:setRedirectGrade()
    checkSelfQualityScale( self, 'setRedirectGrade' )
    local redirectGrade = qualityGrade:new()
    redirectGrade:setGradeName( 'redirect' )
    redirectGrade:addTriggers{ 'redirect', 'red', 'redir' }
    redirectGrade:setColor( '#c0c0c0' )
    self:addGrade( redirectGrade )
end

-- Sets the Book grade with default settings.
function qualityScale:setBookGrade()
    checkSelfQualityScale( self, 'setBookGrade' )
    local bookGrade = qualityGrade:new()
    bookGrade:setGradeName( 'book' )
    bookGrade:addTriggers{ 'book', 'bk' }
    bookGrade:setColor( '#98ff98' )
    self:addGrade( bookGrade )
end

-- Sets the FM (Featured media) grade with default settings.
function qualityScale:setFmGrade()
    checkSelfQualityScale( self, 'setFmGrade' )
    local fmGrade = qualityGrade:new()
    fmGrade:setGradeName( 'fm' )
    fmGrade:addTrigger( 'fm' )
    fmGrade:setColor( '#6699ff' )
    fmGrade:setIcon( 'Featured article star.svg' )
    self:addGrade( fmGrade )
end

-- Set the standard quality scale with default values.
function qualityScale:setStandardQualityScale()
    checkSelfQualityScale( self, 'setStandardQualityScale' )
    self:setFaGrade()
    self:setAGrade()
    self:setGaGrade()
    self:setBGrade()
    self:setCGrade()
    self:setStartGrade()
    self:setStubGrade()
    self:setFlGrade()
    self:setListGrade()
    self:setNaGrade()
end

-- Set the extended quality scale with default values.
function qualityScale:setExtendedQualityScale()
    checkSelfQualityScale( self, 'setExtendedQualityScale' )
    self:setStandardQualityScale()
    self:setCategoryGrade()
    self:setDisambigGrade()
    self:setFileGrade()
    self:setPortalGrade()
    self:setProjectGrade()
    self:setTemplateGrade()
end

----------------------------------------------------------
-- Define the importanceScale class
----------------------------------------------------------

local importanceScale = assessmentScale:new()
local checkSelfImportanceScale = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'importanceScale', 'importanceScale object', 'setTopGrade' )

-- Sets the Top grade with default settings.
function importanceScale:setTopGrade()
    checkSelfImportanceScale( self, 'setTopGrade' )
    local topGrade = importanceGrade:new()
    topGrade:setGradeName( 'top' )
    topGrade:addTrigger( 'top' )
    topGrade:setColor( '#ff00ff' )
    self:addGrade( topGrade )
end

-- Sets the High grade with default settings.
function importanceScale:setHighGrade()
    checkSelfImportanceScale( self, 'setHighGrade' )
    local highGrade = importanceGrade:new()
    highGrade:setGradeName( 'high' )
    highGrade:addTrigger( 'high' )
    highGrade:setColor( '#ff88ff' )
    self:addGrade( highGrade )
end

-- Sets the Mid grade with default settings.
function importanceScale:setMidGrade()
    checkSelfImportanceScale( self, 'setMidGrade' )
    local midGrade = importanceGrade:new()
    midGrade:setGradeName( 'mid' )
    midGrade:addTrigger( 'mid' )
    midGrade:setColor( '#ffbbff' )
    self:addGrade( midGrade )
end

-- Sets the Low grade with default settings.
function importanceScale:setLowGrade()
    checkSelfImportanceScale( self, 'setLowGrade' )
    local lowGrade = importanceGrade:new()
    lowGrade:setGradeName( 'low' )
    lowGrade:addTrigger( 'low' )
    lowGrade:setColor( '#ffddff' )
    self:addGrade( lowGrade )
end

-- Sets the Bottom grade with default settings.
function importanceScale:setBottomGrade()
    checkSelfImportanceScale( self, 'setBottomGrade' )
    local bottomGrade = importanceGrade:new()
    bottomGrade:setGradeName( 'bottom' )
    bottomGrade:addTrigger( 'bottom' )
    bottomGrade:setColor( '#ffeeff' )
    self:addGrade( bottomGrade )
end

-- Sets the No grade with default settings.
function importanceScale:setNoGrade()
    checkSelfImportanceScale( self, 'setNoGrade' )
    local noGrade = importanceGrade:new()
    noGrade:setGradeName( 'no' )
    noGrade:addTrigger( 'no' )
    noGrade:setColor( '#ffffff' )
    self:addGrade( noGrade )
end

-- Sets the NA grade with default settings.
function importanceScale:setNaGrade()
    checkSelfImportanceScale( self, 'setNaGrade' )
    local naGrade = importanceGrade:new()
    naGrade:setGradeName( 'na' )
    naGrade:addTriggers{ 'na', 'n/a' }
    naGrade:setColor( '#f5f5f5' )
    self:addGrade( naGrade )
end

-- Sets the Core grade with default settings.
function importanceScale:setCoreGrade()
    checkSelfImportanceScale( self, 'setCoreGrade' )
    local coreGrade = importanceGrade:new()
    coreGrade:setGradeName( 'core' )
    coreGrade:addTrigger( 'core' )
    coreGrade:setColor( '#ff00ff' )
    self:addGrade( coreGrade )
end

-- Sets the standard importance scale with default settings.
function importanceScale:setStandardImportanceScale()
    checkSelfImportanceScale( self, 'setStandardImportanceScale' )
    self:setTopGrade()
    self:setHighGrade()
    self:setMidGrade()
    self:setLowGrade()
    self:setNaGrade()
end

----------------------------------------------------------
-- Define the taskForce class
----------------------------------------------------------

local taskForce = row:new()

-----------------------------------------------------------------
-- Export objects and functions to be used from other modules
-----------------------------------------------------------------

local p = {}

p.banner = banner
p.row = row
p.makeCheckSelfFunction = makeCheckSelfFunction

-----------------------------------------------------------------
-- Testing area
-----------------------------------------------------------------

function p.test( frame )
    local myqs = qualityScale:new()
    myqs:setStandardQualityScale()
    local fooGrade = qualityGrade:new()
    fooGrade:addTrigger( 'fa' )
    fooGrade:setGradeName( 'foo' )
    myqs:addGrade( fooGrade )
    myqs:checkForDuplicateTriggers()
    return myqs.grades.a.icon
end

return p