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

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(add alias-matching function)
blackwiki>Mr. Stradivarius on tour
(add quality assessment classes and methods)
Line 47: Line 47:
 
end
 
end
  
-- Checks an array of aliases or an alias string against a table of arguments.
+
-- Adds a string to an array. Returns nil on an attempt to add a non-string value, and returns
-- If a match is found, returns the argument value, and if not returns nil.
+
-- an error on an attempt to add a string to a non-table value. Checks that the string is not
-- All non-nil values are matched. If there is more than one match, returns the
+
-- the empty string, and if the array is not present, the function creates it.
-- match for the first matching alias in the list.
+
local function addStringToArray( array, s )
local function matchParam( args, aliases )
+
     s = checkString( s )
     if type( args ) ~= 'table' then return end
+
if s then
    if type( aliases ) == 'table' then
+
if type( array ) == 'table' then
        for i, alias in ipairs( aliases ) do
+
table.insert( array, s )
            alias = checkString( alias )
+
else
            if alias then
+
error( mw.ustring.format(
                local argMatch = args[ alias ]
+
'error in argument #1 to addStringToArray: expected type "table", got type "%s"',
                if argMatch ~= nil then
+
type( array )
                    return argMatch
+
) )
                end
+
end
            end
+
end
        end
 
    elseif checkString( aliases ) then
 
        local alias = aliases
 
        local argMatch = args[ alias ]
 
        if argMatch then
 
            return argMatch
 
        end
 
    end
 
 
end
 
end
  
Line 98: Line 90:
 
end
 
end
  
function banner:setImage()
+
-- Sets the banner's main image.
 +
function banner:setImage( s )
 
     checkSelfBanner( self, 'setImage' )
 
     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
 
end
  
 
-- Adds one category to the banner's "categories" table.
 
-- Adds one category to the banner's "categories" table.
 
function banner:addCategory( category )
 
function banner:addCategory( category )
     category = checkString( category )
+
     checkSelfBanner( self, 'addCategory' )
    if category then
+
addStringToArray( self.categories, category )
        self.categories = self.categories or {}
 
        table.insert( self.categories, category )
 
    end
 
 
end
 
end
  
 
-- Adds all categories in a "categories" array to the banner's "categories" table.
 
-- Adds all categories in a "categories" array to the banner's "categories" table.
 
function banner:addCategories( categoryTable )
 
function banner:addCategories( categoryTable )
 +
    checkSelfBanner( self, 'addCategories' )
 
     if type( categoryTable ) == 'table' then
 
     if type( categoryTable ) == 'table' then
 
         for i, category in ipairs( rowObject.categories ) do
 
         for i, category in ipairs( rowObject.categories ) do
Line 118: Line 119:
 
         end
 
         end
 
     end
 
     end
 +
end
 +
 +
-- Returns the banner object's category table.
 +
function banner:getCategories()
 +
    checkSelfBanner( self, 'getCategories' )
 +
    return self.categories or {}
 
end
 
end
  
 
-- Returns a string of category links for the categories in obj.categories.
 
-- Returns a string of category links for the categories in obj.categories.
 
function banner:exportCategories()
 
function banner:exportCategories()
 +
    checkSelfBanner( self, 'exportCategories' )
 
     if type( self.categories ) == 'table' then
 
     if type( self.categories ) == 'table' then
 
         local ret = {}
 
         local ret = {}
Line 153: Line 161:
 
end
 
end
  
function banner:exportRows()
+
-- Adds an array of row objects to the banner object.
    local ret = {}
+
function banner:addRows( t )
    if type( self.rows ) == 'table' then
+
checkSelfBanner( self, 'addRows' )
        for i, rowObject in ipairs( self.rows ) do
+
if type( t ) == 'table' then
            rowObject = checkObject( rowObject )
+
for i, rowObject in ipairs( t ) do
            if rowObject then
+
self:addRow( rowObject )
                table.insert( ret, rowObject:export() )
+
end
            end
+
end
        end
 
    end
 
    return table.concat( ret )
 
 
end
 
end
  
function banner:export( templateArgs )
+
function banner:export()
 
     checkSelfBanner( self, 'export' )
 
     checkSelfBanner( self, 'export' )
 
end
 
end
Line 187: Line 192:
 
end
 
end
  
 +
-- Adds a category to the "categories" table of the row object. Creates the categories table if it doesn't exist.
 
function row:addCategory( category )
 
function row:addCategory( category )
 
     checkSelfRow( self, 'addCategory' )
 
     checkSelfRow( self, 'addCategory' )
     if type( category ) == 'string' and category ~= '' then
+
addStringToArray( self.categories, category )
         self.categories = self.categories or {}
+
end
        table.insert( self.categories, category )
+
 
 +
-- 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
 +
end
 +
 +
-- Returns the row object's category table.
 +
function row:getCategories()
 +
    checkSelfRow( self, 'getCategories' )
 +
    return self.categories or {}
 
end
 
end
  
Line 225: Line 244:
 
end
 
end
  
 +
----------------------------------------------------------
 +
-- 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' )
 +
 +
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 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 = checkString( gradeObject:getGradeName() )
 +
if gradeName then
 +
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
 +
 +
----------------------------------------------------------
 +
-- Define the qualityScale class
 +
----------------------------------------------------------
 +
 +
local qualityScale = assessmentScale:new()
 +
 +
-- Sets the FA grade with default settings.
 +
function qualityScale:setFaGrade()
 +
local faGrade = qualityGrade:new()
 +
faGrade:setGradeName( 'fa' )
 +
faGrade:addTrigger( 'fa' )
 +
faGrade:setColor( '#6699ff' )
 +
faGrade:setIcon( 'Featured article star.svg' )
 +
qualityScale:addGrade( faGrade )
 +
end
 +
 +
-- Sets the A grade with default settings.
 +
function qualityScale:setAGrade()
 +
local aGrade = qualityGrade:new()
 +
aGrade:setGradeName( 'a' )
 +
aGrade:addTrigger( 'a' )
 +
aGrade:setColor( '#66ffff' )
 +
qualityScale:addGrade( aGrade )
 +
end
 +
 +
-- Sets the GA grade with default settings.
 +
function qualityScale:setGaGrade()
 +
local flGrade = qualityGrade:new()
 +
gaGrade:setGradeName( 'ga' )
 +
gaGrade:addTrigger( 'ga' )
 +
gaGrade:setColor( '#66ff66' )
 +
gaGrade:setIcon( 'Symbol support vote.svg' )
 +
qualityScale:addGrade( gaGrade )
 +
end
 +
 +
-- Sets the B grade with default settings.
 +
function qualityScale:setBGrade()
 +
local bGrade = qualityGrade:new()
 +
bGrade:setGradeName( 'b' )
 +
bGrade:addTrigger( 'b' )
 +
bGrade:setColor( '#b2ff66' )
 +
qualityScale:addGrade( bGrade )
 +
end
 +
 +
-- Sets the C grade with default settings.
 +
function qualityScale:setCGrade()
 +
local cGrade = qualityGrade:new()
 +
cGrade:setGradeName( 'c' )
 +
cGrade:addTrigger( 'c' )
 +
cGrade:setColor( '#ffff66' )
 +
qualityScale:addGrade( cGrade )
 +
end
 +
 +
-- Sets the Start grade with default settings.
 +
function qualityScale:setStartGrade()
 +
local startGrade = qualityGrade:new()
 +
startGrade:setGradeName( 'start' )
 +
startGrade:addTrigger( 'start' )
 +
startGrade:setColor( '#ffaa66' )
 +
qualityScale:addGrade( startGrade )
 +
end
 +
 +
-- Sets the Stub grade with default settings.
 +
function qualityScale:setStubGrade()
 +
local stubGrade = qualityGrade:new()
 +
stubGrade:setGradeName( 'stub' )
 +
stubGrade:addTrigger( 'stub' )
 +
stubGrade:setColor( '#ff6666' )
 +
qualityScale:addGrade( stubGrade )
 +
end
 +
 +
-- Sets the FL grade with default settings.
 +
function qualityScale:setFlGrade()
 +
local flGrade = qualityGrade:new()
 +
flGrade:setGradeName( 'fl' )
 +
flGrade:addTrigger( 'fl' )
 +
flGrade:setColor( '#6699ff' )
 +
flGrade:setIcon( 'Featured article star.svg' )
 +
qualityScale:addGrade( flGrade )
 +
end
 +
 +
-- Sets the List grade with default settings.
 +
function qualityScale:setListGrade()
 +
local listGrade = qualityGrade:new()
 +
listGrade:setGradeName( 'list' )
 +
listGrade:addTrigger( 'list' )
 +
listGrade:setColor( '#aa88ff' )
 +
qualityScale:addGrade( listGrade )
 +
end
 +
 +
-- Sets the NA grade with default settings.
 +
function qualityScale:setNaGrade()
 +
local naGrade = qualityGrade:new()
 +
naGrade:setGradeName( 'na' )
 +
naGrade:addTrigger( 'na' )
 +
naGrade:setColor( '#f5f5f5' )
 +
qualityScale:addGrade( naGrade )
 +
end
 +
 +
-- Sets the Category grade with default settings.
 +
function qualityScale:setCategoryGrade()
 +
local categoryGrade = qualityGrade:new()
 +
categoryGrade:setGradeName( 'category' )
 +
categoryGrade:addTriggers{ 'category', 'cat' }
 +
categoryGrade:setColor( '#ffdb58' )
 +
qualityScale:addGrade( categoryGrade )
 +
end
 +
 +
-- Sets the Disambig grade with default settings.
 +
function qualityScale:setDisambigGrade()
 +
local disambigGrade = qualityGrade:new()
 +
disambigGrade:setGradeName( 'disambig' )
 +
disambigGrade:addTriggers{ 'disambig', 'dab', 'disambiguation' }
 +
disambigGrade:setColor( '#00fa9a' )
 +
qualityScale:addGrade( disambigGrade )
 +
end
 +
 +
-- Sets the File grade with default settings.
 +
function qualityScale:setFileGrade()
 +
local fileGrade = qualityGrade:new()
 +
fileGrade:setGradeName( 'file' )
 +
fileGrade:addTriggers{ 'file', 'image' }
 +
fileGrade:setColor( '#ddccff' )
 +
qualityScale:addGrade( fileGrade )
 +
end
 +
 +
-- Sets the Portal grade with default settings.
 +
function qualityScale:setPortalGrade()
 +
local portalGrade = qualityGrade:new()
 +
portalGrade:setGradeName( 'portal' )
 +
portalGrade:addTrigger( 'portal' )
 +
portalGrade:setColor( '#cc8899' )
 +
qualityScale:addGrade( portalGrade )
 +
end
 +
 +
-- Sets the Project grade with default settings.
 +
function qualityScale:setProjectGrade()
 +
local projectGrade = qualityGrade:new()
 +
projectGrade:setGradeName( 'project' )
 +
projectGrade:addTriggers{ 'project', 'wikiproject' }
 +
projectGrade:setColor( '#c0c090' )
 +
qualityScale:addGrade( projectGrade )
 +
end
 +
 +
-- Sets the Template grade with default settings.
 +
function qualityScale:setTemplateGrade()
 +
local templateGrade = qualityGrade:new()
 +
templateGrade:setGradeName( 'template' )
 +
templateGrade:addTrigger( 'template' )
 +
templateGrade:setColor( '#fbceb1' )
 +
qualityScale:addGrade( templateGrade )
 +
end
 +
 +
-- Set the standard quality scale with default values.
 +
function qualityScale: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()
 +
self:setStandardQualityScale()
 +
self:setCategoryGrade()
 +
self:setDisambigGrade()
 +
self:setFileGrade()
 +
self:setPortalGrade()
 +
self:setProjectGrade()
 +
self:setTemplateGrade()
 +
end
 +
 +
----------------------------------------------------------
 +
-- Define the assessmentGrade class
 +
--
 +
-- The assessmentGrade class sets the categories and
 +
-- aliases for one importance scale grade or quality scale
 +
-- grade.
 +
----------------------------------------------------------
 +
 +
local assessmentGrade = {}
 +
assessmenteGrade.__index = assessmentGrade
 +
local checkSelfAssessmentGrade = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'assessmentGrade', 'assessmentGrade object' )
 +
 +
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' )
 +
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 taskForce class
 
-- Define the taskForce class
Line 246: Line 646:
  
 
function p.test( frame )
 
function p.test( frame )
      
+
     local myRow = row:new()
 +
    return row:export()
 
end
 
end
 +
  
 
return p
 
return p

Revision as of 06:14, 4 September 2013

Usage

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



-- 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.
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc )
    return function( self, method )
        if type( self ) ~= 'table' or type( self.new ) ~= '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 )
		else
			error( mw.ustring.format(
				'error in argument #1 to addStringToArray: expected type "table", got type "%s"',
				type( array )
			) )
		end
	end
end

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

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

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( category )
    checkSelfBanner( self, 'addCategory' )
	addStringToArray( self.categories, category )
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' )

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( category )
    checkSelfRow( self, 'addCategory' )
	addStringToArray( self.categories, category )
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 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' )

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 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 = checkString( gradeObject:getGradeName() )
		if gradeName then
			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

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

local qualityScale = assessmentScale:new()

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

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

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

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

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

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

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

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

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

-- Sets the NA grade with default settings.
function qualityScale:setNaGrade()
	local naGrade = qualityGrade:new()
	naGrade:setGradeName( 'na' )
	naGrade:addTrigger( 'na' )
	naGrade:setColor( '#f5f5f5' )
	qualityScale:addGrade( naGrade )
end

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

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

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

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

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

-- Sets the Template grade with default settings.
function qualityScale:setTemplateGrade()
	local templateGrade = qualityGrade:new()
	templateGrade:setGradeName( 'template' )
	templateGrade:addTrigger( 'template' )
	templateGrade:setColor( '#fbceb1' )
	qualityScale:addGrade( templateGrade )
end

-- Set the standard quality scale with default values.
function qualityScale: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()
	self:setStandardQualityScale()
	self:setCategoryGrade()
	self:setDisambigGrade()
	self:setFileGrade()
	self:setPortalGrade()
	self:setProjectGrade()
	self:setTemplateGrade()
end

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

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

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' )
	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 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 myRow = row:new()
    return row:export()
end


return p