Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Sandbox/Chao: Difference between revisions

From BlazBlue Wiki
m (fix bug where BBRadio section displays incorrect header)
m (insert subheader only when there are images to include below it)
 
(37 intermediate revisions by the same user not shown)
Line 2: Line 2:
{{#invoke:Sandbox/Chao|GallerySection|character=Noel Vermillion|section=Portraits}}
{{#invoke:Sandbox/Chao|GallerySection|character=Noel Vermillion|section=Portraits}}
simulate passing a frame to the function in the console with:
simulate passing a frame to the function in the console with:
myFrame = { args = { character='Noel Vermillion', section='Portraits' } }
myFrame = { args = { character='Noel Vermillion' } }
=p.main(myFrame)
=p.GallerySection ( myFrame )
=p.GallerySection ( myFrame )
=p.testExpandTemplate( myFrame )
=p.testExpandTemplate( myFrame )
=p.render(myFrame)


--]]
--]]


local p = {}
local cargo = mw.ext.cargo
local cargo = mw.ext.cargo


local galleryData = mw.loadData('Module:Sandbox/Chao/data')
-------------------------------------
local ordering = galleryData.ordering
-- Gallery Section Class
local sections = galleryData.sections
-------------------------------------
 
local GalleryTemplate = {}
GalleryTemplate.__index = GalleryTemplate
 
GalleryTemplate.fields = {
character = true,
source = true,
section = true,
limit = true,
widths = true,
header = true,
title = true,
sort = true,
see_all = true,
see_cameos = true,
--Gallery Section (BBRadio)
season = true,
episode = true,
widths = true,
--Gallery Section
cat = true,
cat2 = true,
--Misc/Shared
count_all = true,
count_cameos = true,
images_in_section = true,
}
 
GalleryTemplate.templateMethods = {
['Gallery Section (Cargo)'] = 'makeGallerySectionCargo',
['Gallery Section (BBRadio)'] = 'makeGallerySectionBBRadio',
['Gallery Section'] = 'makeGallerySection',
}
 
function GalleryTemplate.new(frame, templateType, params)
local self = setmetatable({}, GalleryTemplate)
self.templateType= templateType
self.frame = frame
for field in pairs(GalleryTemplate.fields) do
self[field] = params[field] or ''
end


function p.render(frame)
self.images_in_section = 0
text = {}
self.cat = params.category or ''
_char = frame.args['character'] or ''
if (params.character == nil)
then self.character = frame.args.character or ''
if _char == '' then
else self.character = params.character or ''
else
end
_char = cargo_escape(_char)
return self
end
 
function GalleryTemplate:__tostring()
local method = GalleryTemplate.templateMethods[self.templateType]
if method then
return self[method](self)
end
end
return ''
for i,v in ipairs (ordering) do
end
category = v
 
params = sections[v] or ''
function GalleryTemplate.makeGallerySectionCargo(self)
local expanded_template = nil
 
self.character = cargo_escape(self.character)


if params == '' then
self.count_all = GalleryTemplate._countImages_GallerySectionCargo(self,false) or 0
else
self.count_cameos = GalleryTemplate._countImages_GallerySectionCargo(self,true) or 0
t = {}
local total_images = self.count_all + self.count_cameos
class = params.class or ''
if class == '' then
else
table.insert(t, '<div class="' .. class .. '">')
end
-- v is a table of templates in this section
if self.count_all > 0 then
for k2,v2 in pairs (params) do
self.see_all = 'y'
end
template = v2.template or ''
params = {}
--fill in any missing template arguments
--Gallery Section (Cargo)
params.character = _char
params.source = v2.source or ''
params.section = v2.section or ''
params.limit = v2.limit or ''
params.widths = v2.widths or ''
params.header = v2.header or ''
params.title = v2.title or ''
params.sort = v2.sort or ''
params.see_all = v2.see_all or ''
params.see_cameos = v2.see_cameos or ''
--Gallery Section (BBRadio)
params.season = v2.season or ''
params.episode = v2.episode or ''
params.widths = v2.widths or ''
if template == 'Gallery Section (Cargo)' then
if self.count_cameos > 0 then
params.count_all = p._countImages_GallerySectionCargo(params, false) or 0
self.see_cameos = 'y'
params.count_cameos = p._countImages_GallerySectionCargo(params, true) or 0
end
total_images = params.count_all + params.count_cameos
if params.count_all > 0 then
params.see_all = 'y'
end
if params.count_cameos > 0 then
params.see_cameos = 'y'
end
if total_images > 0 then
expanded_template = p._expandTemplate_GallerySectionCargo(frame, params)
table.insert(t, expanded_template)
end
elseif template == 'Gallery Section (BBRadio)' then
params.count_all = p._countImages_GallerySectionBBRadio(params) or 0
expanded_template = p._expandTemplate_GallerySectionBBRadio(frame, params)
table.insert(t, expanded_template)
elseif template == 'Gallery Section' then
end
end
if class == '' then
if total_images > 0 then
else
expanded_template = GalleryTemplate._expandTemplate_GallerySectionCargo(self, self.frame)
table.insert(t, '</div>')
--table.insert(t_galleries, expanded_template)
end
self.images_in_section = self.images_in_section + total_images
--templates = concatvalues(t,"")
templates = table.concat(t)
if templates == "" then
else
-- insert the section, prepended by its header, to the final text
table.insert(text, '<h2>' .. category .. '</h2>\n' .. templates)
end
end
end
end
 
gallery = table.concat(text)
return expanded_template
mw.log(dump(gallery))
end
return gallery
 
function GalleryTemplate.makeGallerySectionBBRadio(self)
self.character = cargo_escape(self.character)
self.count_all = GalleryTemplate._countImages_GallerySectionBBRadio(self) or 0
local expanded_template = GalleryTemplate._expandTemplate_GallerySectionBBRadio(self,self.frame)
--table.insert(t_galleries, expanded_template)
self.images_in_section = self.images_in_section + self.count_all
return expanded_template
end
 
function GalleryTemplate.makeGallerySection(self)
self.count_all = GalleryTemplate._countImages_GallerySection(self) or 0
local expanded_template = GalleryTemplate._expandTemplate_GallerySection(self,self.frame)
--table.insert(t_galleries, expanded_template)
self.images_in_section = self.images_in_section + self.count_all
return expanded_template
end
end


-- counts the number of images with this character (or cameo) for sections using Template:Gallery Section (Cargo)
-- counts the number of images with this character (or cameo) for sections using Template:Gallery Section (Cargo)
-- countCameos: boolean
-- countCameos: boolean
function p._countImages_GallerySectionCargo(params, countCameos)
function GalleryTemplate._countImages_GallerySectionCargo(self, countCameos)
tables = 'Files'
tables = 'Files'
fields = 'COUNT(Files._pageName)'
fields = 'COUNT(Files._pageName)'


character = params.character or ''
character = self.character or ''
source = params.source or ''
source = self.source or ''
section = params.section or ''
section = self.section or ''


where_clause_parts = {}
where_clause_parts = {}
Line 125: Line 133:
end
end
if source == '' then
if source == '' then else table.insert(where_clause_parts, "Files.Source HOLDS '" .. source .. "'") end
else
if section == '' then else table.insert(where_clause_parts, "Files.Gallery_Sections HOLDS '" .. section .. "'") end
table.insert(where_clause_parts, "Files.Source HOLDS '" .. source .. "'")
end
if section == '' then
else
table.insert(where_clause_parts, "Files.Gallery_Sections HOLDS '" .. section .. "'")
end
where_clause = concatvalues(where_clause_parts, " AND ")
where_clause = concatvalues(where_clause_parts, " AND ")


Line 146: Line 147:
end
end


function p._countImages_GallerySectionBBRadio(params)
function GalleryTemplate._countImages_GallerySectionBBRadio(self)
tables = 'Files,BBRadio_Cuts'
tables = 'Files,BBRadio_Cuts'
fields = 'COUNT(Files._pageName)'
fields = 'COUNT(Files._pageName)'
join_on = 'Files._pageName=BBRadio_Cuts._pageName'
join_on = 'Files._pageName=BBRadio_Cuts._pageName'
_character = params.character or ''
_season = params.season or ''
mw.log(_character)
mw.log("Count images for " .. self.character .. ' season ' .. self.season)
mw.log(_season)


where_clause = 'Files.Characters HOLDS "' .. _character .. '" AND BBRadio_Cuts.Season="' .. _season .. '"'
where_clause = 'Files.Characters HOLDS "' .. self.character .. '" AND BBRadio_Cuts.Season="' .. self.season .. '"'


local args = {
local args = {
Line 166: Line 163:
result = cargo.query( tables, fields, args )
result = cargo.query( tables, fields, args )
count = result[1][fields] or '0'
count = result[1][fields] or '0'
mw.log(dump(args))
mw.log(dump(result))
mw.log(count)


return tonumber(count)
return tonumber(count)
end
end


function p._expandTemplate_GallerySectionCargo(frame, params)
function GalleryTemplate._countImages_GallerySection(self)
_character = params.character or ''
cat1 = self.character or ''
_source = params.source or ''
cat2 = self.cat or ''
_section = params.section or ''
cat3 = self.cat2 or ''
_limit = tonumber(params.limit) or 4
 
_title = params.title or ''
local query = {}
_header = params.header or ''
if cat1 ~= '' then table.insert(query, '[[Category:' .. cat1 .. ']]') end
_see_all = params.see_all or ''
if cat2 ~= '' then table.insert(query, '[[Category:' .. cat2 .. ']]') end
_see_cameos = params.see_cameos or ''
if cat3 ~= '' then table.insert(query, '[[Category:' .. cat3 .. ']]') end
_count_all = params.count_all or ''
_count_cameos = params.count_cameos or ''
gallery = frame:expandTemplate{ title = 'Gallery Section (Cargo)', args = {  
local result = mw.smw.getQueryResult( query )
character = _character,
count = result.meta.count or 0
source = _source,
 
section = _section,
return count
end
 
function GalleryTemplate._expandTemplate_GallerySectionCargo(self)
_limit = tonumber(self.limit) or 4
 
if self.frame.expandTemplate == nil then return '' end
gallery = self.frame:expandTemplate{ title = 'Gallery Section (Cargo)', args = {  
character = self.character,
source = self.source,
section = self.section,
limit = _limit,
title = self.title,
header = self.header,
see_all = self.see_all,
see_cameos = self.see_cameos,
count_all = self.count_all,
count_cameos = self.count_cameos
}}
 
return gallery
end
 
function GalleryTemplate._expandTemplate_GallerySectionBBRadio(self)
_limit = tonumber(self.limit) or 4
_widths = tonumber(self.widths) or 250
 
if self.frame.expandTemplate == nil then return '' end
gallery = self.frame:expandTemplate { title = 'Gallery Section (BBRadio)', args = {
self.character,
self.season,
self.episode,
self.header,
self.title,
widths = _widths,
limit = _limit,
limit = _limit,
title = _title,
count_all = self.count_all
header = _header,
see_all = _see_all,
see_cameos = _see_cameos,
count_all = _count_all,
count_cameos = _count_cameos
}}
}}


Line 202: Line 222:
end
end


function p._expandTemplate_GallerySectionBBRadio(frame, params)
function GalleryTemplate._expandTemplate_GallerySection(self)
_character = params.character or ''
_limit = tonumber(self.limit) or 4
_season = params.season or ''
_widths = tonumber(self.widths) or 250
_episode = params.episode or ''
_count_all = self.count_all or 0
_header = params.header or ''
_title = self.title or ''
_title = params.title or ''
_limit = tonumber(params.limit) or 4
_widths = tonumber(params.widths) or 250
_count_all = params.count_all or ''


gallery = frame:expandTemplate { title = 'Gallery Section (BBRadio)', args = {
if self.frame.expandTemplate == nil then return '' end
_character,
gallery = self.frame:expandTemplate { title = 'Gallery Section', args = {
_season,
self.character,
_episode,
self.cat,
_header,
self.cat2,
_title,
self.header,
self.title,
widths = _widths,
widths = _widths,
limit = _limit,
limit = _limit,
count_all = _count_all
count_all = _count_all,
}}
}}


return gallery
return gallery
end
end
function GalleryTemplate:getNumberOfImages(self)
return self.images_in_section
end
-------------------------------------
-- Gallery Class
-------------------------------------
local Gallery = {}
Gallery.__index = Gallery
function Gallery.new(data, frame)
local self = setmetatable({}, Gallery)
self.galleryData = mw.loadData(data)
self.ordering = self.galleryData.ordering
self.sections = self.galleryData.sections
self.frame = frame
return self
end
function Gallery:__tostring()
local frame = self.frame
text = {}
_char = frame.args['character'] or ''
for i,v in ipairs (self.ordering) do
category = v
local params = self.sections[v] or ''
if params == '' then
else
local t_section = {}
local t_galleries = {}
local images_in_section = 0
local images_in_subsection = 0
local current_subheader = ''
-- add a wrapper div if there's a class to apply to the section
class = params.class or ''
if class ~= '' then
table.insert(t_section, '<div class="' .. class .. '">')
end
-- each v2 represents one template call
for k2,v2 in pairs(params) do
template = v2.template or ''
local title = v2.title or ''
mw.log(template .. ": " .. title)
if not (template == 'Header') and template ~= '' then
local g = nil
local expanded_g = nil
g = GalleryTemplate.new(frame, template, v2)
if g ~= nil then
expanded_g = tostring(g)
mw.log("imgs: " .. g:getNumberOfImages(g) or 0 )
if expanded_g ~= nil and expanded_g ~= '' then
table.insert(t_galleries, expanded_g)
num_images = tonumber(g:getNumberOfImages(g)) or 0
images_in_subsection = images_in_subsection  + num_images
images_in_section = images_in_section + num_images
mw.log("expanded_g: " .. expanded_g)
end
mw.log("t_galleries: " .. table.concat(t_galleries))
end
elseif template == 'Header' then
-- if this is not the first subheader in this section
if current_subheader ~= '' then
-- check if the previous subheader's galleries had images in them
if images_in_subsection > 0 then
table.insert(t_section, current_subheader)
g = table.concat(t_galleries)
if g ~= "" then
table.insert(t_section, g)
end
-- reset galleries and images for the next subsection
clear_table(t_galleries)
images_in_subsection = 0
end
end
local header = v2.header or ''
-- save the new subheader and wait to see if the following galleries have any images in them
current_subheader = '<' .. header .. '>' .. title .. '</' .. header .. ">\n"
end
end
-- check the number of images in the section
mw.log("---\n" .. category .. " images_in_section = " .. images_in_section)
mw.log("t_galleries: " .. table.concat(t_galleries))
if images_in_section > 0 then
-- if there is a subheader to insert, then insert it
if current_subheader ~= "" and images_in_subsection > 0 then
table.insert(t_section, current_subheader)
end
-- if there are galleries to insert, then insert them
g = table.concat(t_galleries)
table.insert(t_section, g)
-- close the wrapping div if one was added
if class ~= "" then
table.insert(t_section, "</div>")
end
-- insert the section, prepended by the section header, to the final text
s = concatvaluesonly(t_section, '')
mw.log('t_section ' .. category .. ' ' .. s)
if s ~= "" then
table.insert(text, '<h2>' .. category .. '</h2>\n' .. s)
end
end
mw.log("\n")
clear_table(t_galleries)
clear_table(t_section)
end
end
gallery = table.concat(text)
return gallery
end
-------------------------------------
-- Main
-------------------------------------
local p = {}
function p.main(frame)
data = frame.args.data or 'Module:Character Gallery/data'
gallery = Gallery.new(data, frame)
--mw.log(dump(tostring(gallery)))
return tostring(gallery)
end
-------------------------------------
-- Tests
-------------------------------------


function p.testExpandTemplate_1(frame)
function p.testExpandTemplate_1(frame)
Line 269: Line 428:
mw.log('no parameters found')
mw.log('no parameters found')
else
else
mw.log(dump(k))
mw.log(k.class)
mw.log(k.class)
for k2,v2 in pairs (k) do
for k2,v2 in pairs (k) do
mw.log(k2)
mw.log(k2)
mw.log(dump(v2))
end
end
end
end
end
end
-------------------------------------
-- Utility Functions
-------------------------------------
-- clear a table
function clear_table(t)
for k in pairs (t) do
    t [k] = nil
end
end
end
end

Latest revision as of 01:26, 29 April 2020

Main Visuals

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Main Artwork]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Main Artwork
|sources=
}}
Load 3 more...

Gallery Section (Cargo)/Q3 4 7 50 Noel Vermillion Main Artwork _pageName

Character Crest

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Crests]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Crests
|sources=
}}

Chibi

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Chibi]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Chibi
|sources=
}}

Gameplay

Arcade

BlazBlue: Calamity Trigger

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Arcade Mode]][[Category:BlazBlue: Calamity Trigger]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Arcade Mode
|sources=BlazBlue: Calamity Trigger
}}
Load 2 more...

Gallery Section (Cargo)/Q3 4 6 50 Noel Vermillion BlazBlue: Calamity Trigger Arcade Mode _pageName

BlazBlue: Continuum Shift

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Arcade Mode]][[Category:BlazBlue: Continuum Shift]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Arcade Mode
|sources=BlazBlue: Continuum Shift
}}

BlazBlue: Chrono Phantasma

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Arcade Mode]][[Category:BlazBlue: Chrono Phantasma]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Arcade Mode
|sources=BlazBlue: Chrono Phantasma
}}
Load 6 more...

Gallery Section (Cargo)/Q3 4 10 50 Noel Vermillion BlazBlue: Chrono Phantasma Arcade Mode _pageName

BlazBlue: Central Fiction

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Arcade Mode]][[Category:BlazBlue: Central Fiction]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Arcade Mode
|sources=BlazBlue: Central Fiction
}}
Load 3 more...

Gallery Section (Cargo)/Q3 4 7 50 Noel Vermillion BlazBlue: Central Fiction Arcade Mode _pageName

Load 9 more...

Gallery Section (Cargo)/Q3 4 13 50 Noel Vermillion BlazBlue: Central Fiction Arcade Mode _pageName

Story

Portraits

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Portraits]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Portraits
|sources=
}}
Load 7 more...

Gallery Section (Cargo)/Q3 4 11 50 Noel Vermillion Portraits _pageName

Short Stories

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Short Story Illustrations]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Short Story Illustrations
|sources=
}}

BlazBlue: Calamity Trigger

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Calamity Trigger]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Calamity Trigger
}}
Load 11 more...

Gallery Section (Cargo)/Q3 4 15 50 Noel Vermillion BlazBlue: Calamity Trigger Story _pageName

Load 1 more...

Gallery Section (Cargo)/Q3 4 5 50 Noel Vermillion BlazBlue: Calamity Trigger Story _pageName

BlazBlue: Continuum Shift

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Continuum Shift]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Continuum Shift
}}
Load 8 more...

Gallery Section (Cargo)/Q3 4 12 50 Noel Vermillion BlazBlue: Continuum Shift Story _pageName

BlazBlue: Chrono Phantasma

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Chrono Phantasma]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Chrono Phantasma
}}
Load 9 more...

Gallery Section (Cargo)/Q3 4 13 50 Noel Vermillion BlazBlue: Chrono Phantasma Story _pageName

BlazBlue: Central Fiction

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Central Fiction]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Central Fiction
}}
Load 7 more...

Gallery Section (Cargo)/Q3 4 11 50 Noel Vermillion BlazBlue: Central Fiction Story _pageName

BlazBlue: Cross Tag Battle

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Cross Tag Battle]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Cross Tag Battle
}}
Load 1 more...

Gallery Section (Cargo)/Q3 4 5 50 Noel Vermillion BlazBlue: Cross Tag Battle Story _pageName

BlazBlue: Clone Phantasma

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Story]][[Category:BlazBlue: Clone Phantasma]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Story
|sources=BlazBlue: Clone Phantasma
}}

Novels

BlazBlue: Calamity Trigger - Part 1

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:BlazBlue: Calamity Trigger - Part 1]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=
|sources=BlazBlue: Calamity Trigger - Part 1
}}

BlazBlue: Calamity Trigger - Part 2

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:BlazBlue: Calamity Trigger - Part 2]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=
|sources=BlazBlue: Calamity Trigger - Part 2
}}
Load 2 more...

Gallery Section (Cargo)/Q3 4 6 50 Noel Vermillion BlazBlue: Calamity Trigger - Part 2 _pageName

BlazBlue: Continuum Shift - Part 1

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:BlazBlue: Continuum Shift - Part 1]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=
|sources=BlazBlue: Continuum Shift - Part 1
}}

BlazBlue: Continuum Shift - Part 2

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:BlazBlue: Continuum Shift - Part 2]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=
|sources=BlazBlue: Continuum Shift - Part 2
}}

Radio Show

Chibi Portraits

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Chibi Portraits]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Chibi Portraits
|sources=
}}
Load 47 more...

Gallery Section (Cargo)/Q3 4 51 50 Noel Vermillion Chibi Portraits _pageName

Blazblue Radio

Load 50 more...

Gallery_Section_(BBRadio)/Q1 4 117 50 Noel Vermillion 1 _pageName 150

Blazblue Radio Continued

Load 50 more...

Gallery_Section_(BBRadio)/Q1 4 151 50 Noel Vermillion 2 _pageName 150

Blazblue Radio Wide

Load 50 more...

Gallery_Section_(BBRadio)/Q1 4 130 50 Noel Vermillion W _pageName 150

Blazblue Radio Hyper

Load 50 more...

Gallery_Section_(BBRadio)/Q1 4 70 50 Noel Vermillion H _pageName 150

Blazblue Radio Ace

Load 50 more...

Gallery_Section_(BBRadio)/Q1 4 57 50 Noel Vermillion A _pageName 150

Blazblue Radio Quick

Load 47 more...

Gallery_Section_(BBRadio)/Q1 4 51 50 Noel Vermillion Q _pageName 150

Blazblue Radio Dynamic

Load 38 more...

Gallery_Section_(BBRadio)/Q1 4 42 50 Noel Vermillion D _pageName 150

Blazblue Radio NEO

Load 33 more...

Gallery_Section_(BBRadio)/Q1 4 37 50 Noel Vermillion NEO _pageName 150

Blazblue Radio Repeat

Load 1 more...

Gallery_Section_(BBRadio)/Q1 4 5 50 Noel Vermillion R _pageName 150

Blazblue Radio Repeat 2

BlazBlue Alternative: Dark War

All Related Files

... further results

Artwork

Promotional

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Promotional Artwork]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Promotional Artwork
|sources=
}}
Load 46 more...

Gallery Section (Cargo)/Q3 4 50 50 Noel Vermillion Promotional Artwork _pageName

Birthday Art

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Birthday Art]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Birthday Art
|sources=
}}
Load 7 more...

Gallery Section (Cargo)/Q3 4 11 50 Noel Vermillion Birthday Art _pageName

Load 1 more...

Gallery Section (Cargo)/Q3 4 5 50 Noel Vermillion Birthday Art _pageName

Staff Extras

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Staff Extras]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Staff Extras
|sources=
}}
Load 27 more...

Gallery Section (Cargo)/Q3 4 31 50 Noel Vermillion Staff Extras _pageName

Special Artwork

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Special Artwork]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Special Artwork
|sources=
}}
Load 10 more...

Gallery Section (Cargo)/Q3 4 14 50 Noel Vermillion Special Artwork _pageName

Pre-order Bonuses

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Pre-order Bonuses]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Pre-order Bonuses
|sources=
}}
Load 44 more...

Gallery Section (Cargo)/Q3 4 48 50 Noel Vermillion Pre-order Bonuses _pageName

Wallpapers

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Wallpapers]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Wallpapers
|sources=
}}
Load 17 more...

Gallery Section (Cargo)/Q3 4 21 50 Noel Vermillion Wallpapers _pageName

Stickers

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Stickers]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Stickers
|sources=
}}
Load 42 more...

Gallery Section (Cargo)/Q3 4 46 50 Noel Vermillion Stickers _pageName

Icons

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Icons]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion OR
|cameos=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Icons
|sources=
}}
Load 25 more...

Gallery Section (Cargo)/Q3 4 29 50 Noel Vermillion Icons _pageName

Production Art

Model Sheets

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Model Sheets]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Model Sheets
|sources=
}}
Load 11 more...

Gallery Section (Cargo)/Q3 4 15 50 Noel Vermillion Model Sheets _pageName

Early Designs

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Early Designs]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Early Designs
|sources=
}}

Storyboards

ⓘ How to add an image hereTo add an image to this section, upload it with all of the following categories:
[[Category:Noel Vermillion]][[Category:Storyboards]]
OR make sure the file has the following filled out on its page:
{{Gallery Metadata
|characters=Noel Vermillion
|locations=
|weapons=
|artists=
|section=Storyboards
|sources=
}}
Load 10 more...

Gallery Section (Cargo)/Q3 4 14 50 Noel Vermillion Storyboards _pageName

Collaborations

Destiny Child

... further results

Girls' Frontline

... further results

Lord of Vermilion Re:2

... further results

Mabinogi Duel

Unlimited VS

... further results

Fantasy War Tactics


--[[
{{#invoke:Sandbox/Chao|GallerySection|character=Noel Vermillion|section=Portraits}}
simulate passing a frame to the function in the console with:
myFrame = { args = { character='Noel Vermillion' } }
=p.main(myFrame)
=p.GallerySection ( myFrame )
=p.testExpandTemplate( myFrame )

--]]

local cargo = mw.ext.cargo

-------------------------------------
-- Gallery Section Class
-------------------------------------

local GalleryTemplate = {}
GalleryTemplate.__index = GalleryTemplate

GalleryTemplate.fields = {
	character = true,
	source = true,
	section = true,
	limit = true,
	widths = true,
	header = true,
	title = true,
	sort = true,
	see_all = true,
	see_cameos = true,
	--Gallery Section (BBRadio)
	season = true,
	episode = true,
	widths = true,
	--Gallery Section
	cat = true,
	cat2 = true,
	--Misc/Shared
	count_all = true,
	count_cameos = true,
	images_in_section = true,
}

GalleryTemplate.templateMethods = {
	['Gallery Section (Cargo)'] = 'makeGallerySectionCargo',
	['Gallery Section (BBRadio)'] = 'makeGallerySectionBBRadio',
	['Gallery Section'] = 'makeGallerySection',
}

function GalleryTemplate.new(frame, templateType, params)
	local self = setmetatable({}, GalleryTemplate)
	self.templateType= templateType
	self.frame = frame
	for field in pairs(GalleryTemplate.fields) do
		self[field] = params[field] or ''
	end

	self.images_in_section = 0
	self.cat = params.category or ''
	if (params.character == nil)
		then self.character = frame.args.character or ''
		else self.character = params.character or ''
	end
	return self
end

function GalleryTemplate:__tostring()
	local method = GalleryTemplate.templateMethods[self.templateType]
	if method then
		return self[method](self)
	end
	return ''
end

function GalleryTemplate.makeGallerySectionCargo(self)
	local expanded_template = nil

	self.character = cargo_escape(self.character)

	self.count_all = GalleryTemplate._countImages_GallerySectionCargo(self,false) or 0
	self.count_cameos = GalleryTemplate._countImages_GallerySectionCargo(self,true) or 0
	local total_images = self.count_all + self.count_cameos
	
	if self.count_all > 0 then
		self.see_all = 'y'
	end
	
	if self.count_cameos > 0 then
		self.see_cameos = 'y'
	end
	
	if total_images > 0 then
		expanded_template = GalleryTemplate._expandTemplate_GallerySectionCargo(self, self.frame)
		--table.insert(t_galleries, expanded_template)
		self.images_in_section = self.images_in_section + total_images
	end

	return expanded_template
end

function GalleryTemplate.makeGallerySectionBBRadio(self)
	self.character = cargo_escape(self.character)
	self.count_all = GalleryTemplate._countImages_GallerySectionBBRadio(self) or 0
	local expanded_template = GalleryTemplate._expandTemplate_GallerySectionBBRadio(self,self.frame)
	--table.insert(t_galleries, expanded_template)
	self.images_in_section = self.images_in_section + self.count_all
	return expanded_template
end

function GalleryTemplate.makeGallerySection(self)
	self.count_all = GalleryTemplate._countImages_GallerySection(self) or 0
	local expanded_template = GalleryTemplate._expandTemplate_GallerySection(self,self.frame)
	--table.insert(t_galleries, expanded_template)
	self.images_in_section = self.images_in_section + self.count_all
	return expanded_template
end

-- counts the number of images with this character (or cameo) for sections using Template:Gallery Section (Cargo)
-- countCameos: boolean
function GalleryTemplate._countImages_GallerySectionCargo(self, countCameos)
	tables = 'Files'
	fields = 'COUNT(Files._pageName)'

	character = self.character or ''
	source = self.source or ''
	section = self.section or ''

	where_clause_parts = {}
	if countCameos then
		table.insert(where_clause_parts, "Files.Cameos HOLDS '" .. character .. "'")
	else
		table.insert(where_clause_parts, "Files.Characters HOLDS '" .. character .. "'")
	end
	
	if source == '' then else table.insert(where_clause_parts, "Files.Source HOLDS '" .. source .. "'")	end
	if section == '' then else table.insert(where_clause_parts, "Files.Gallery_Sections HOLDS '" .. section .. "'")	end
	where_clause = concatvalues(where_clause_parts, " AND ")

	local args = {
		where = where_clause
	}

	result = cargo.query( tables, fields, args )
	count = result[1][fields] or '0'

	return tonumber(count)
end

function GalleryTemplate._countImages_GallerySectionBBRadio(self)
	tables = 'Files,BBRadio_Cuts'
	fields = 'COUNT(Files._pageName)'
	join_on = 'Files._pageName=BBRadio_Cuts._pageName'
	
	mw.log("Count images for " .. self.character .. ' season ' .. self.season)

	where_clause = 'Files.Characters HOLDS "' .. self.character .. '" AND BBRadio_Cuts.Season="' .. self.season .. '"'

	local args = {
		where = where_clause,
		join = join_on
	}

	result = cargo.query( tables, fields, args )
	count = result[1][fields] or '0'

	return tonumber(count)
end

function GalleryTemplate._countImages_GallerySection(self)
	cat1 = self.character or ''
	cat2 = self.cat or ''
	cat3 = self.cat2 or ''

	local query = {}
	if cat1 ~= '' then table.insert(query, '[[Category:' .. cat1 .. ']]') end
	if cat2 ~= '' then table.insert(query, '[[Category:' .. cat2 .. ']]') end
	if cat3 ~= '' then table.insert(query, '[[Category:' .. cat3 .. ']]') end
	
	local result = mw.smw.getQueryResult( query )
	count = result.meta.count or 0

	return count
end

function GalleryTemplate._expandTemplate_GallerySectionCargo(self)
	_limit = tonumber(self.limit) or 4

	if self.frame.expandTemplate == nil then return '' end
	gallery = self.frame:expandTemplate{ title = 'Gallery Section (Cargo)', args = { 
		character = self.character,
		source = self.source,
		section = self.section,
		limit = _limit,
		title = self.title,
		header = self.header,
		see_all = self.see_all,
		see_cameos = self.see_cameos,
		count_all = self.count_all,
		count_cameos = self.count_cameos
	}}

	return gallery
end

function GalleryTemplate._expandTemplate_GallerySectionBBRadio(self)
	_limit = tonumber(self.limit) or 4
	_widths = tonumber(self.widths) or 250

	if self.frame.expandTemplate == nil then return '' end
	gallery = self.frame:expandTemplate { title = 'Gallery Section (BBRadio)', args = {
		self.character,
		self.season,
		self.episode,
		self.header,
		self.title,
		widths = _widths,
		limit = _limit,
		count_all = self.count_all
	}}

	return gallery
end

function GalleryTemplate._expandTemplate_GallerySection(self)
	_limit = tonumber(self.limit) or 4
	_widths = tonumber(self.widths) or 250
	_count_all = self.count_all or 0
	_title = self.title or ''

	if self.frame.expandTemplate == nil then return '' end
	gallery = self.frame:expandTemplate { title = 'Gallery Section', args = {
		self.character,
		self.cat,
		self.cat2,
		self.header,
		self.title,
		widths = _widths,
		limit = _limit,
		count_all = _count_all,
	}}

	return gallery
end

function GalleryTemplate:getNumberOfImages(self)
	return self.images_in_section
end

-------------------------------------
-- Gallery Class
-------------------------------------

local Gallery = {}
Gallery.__index = Gallery

function Gallery.new(data, frame)
	local self = setmetatable({}, Gallery)
	self.galleryData = mw.loadData(data)
	self.ordering = self.galleryData.ordering
	self.sections = self.galleryData.sections
	self.frame = frame
	return self
end

function Gallery:__tostring()
	local frame = self.frame
	text = {}
	_char = frame.args['character'] or ''
	
	for i,v in ipairs (self.ordering) do
		category = v
		local params = self.sections[v] or ''
		
		if params == '' then
		else
			local t_section = {}
			local t_galleries = {}
			local images_in_section = 0
			local images_in_subsection = 0
			local current_subheader = ''
			
			-- add a wrapper div if there's a class to apply to the section
			class = params.class or ''
			if class ~= '' then
				table.insert(t_section, '<div class="' .. class .. '">')
			end

			-- each v2 represents one template call
			for k2,v2 in pairs(params) do
				template = v2.template or ''

				local title = v2.title or ''
				mw.log(template .. ": " .. title)

				if not (template == 'Header') and template ~= '' then
					local g = nil
					local expanded_g = nil

					g = GalleryTemplate.new(frame, template, v2)
					if g ~= nil then
						expanded_g = tostring(g)
						mw.log("imgs: " .. g:getNumberOfImages(g) or 0 )
						if expanded_g ~= nil and expanded_g ~= '' then
							table.insert(t_galleries, expanded_g)
							num_images = tonumber(g:getNumberOfImages(g)) or 0
							images_in_subsection = images_in_subsection  + num_images
							images_in_section = images_in_section + num_images
							mw.log("expanded_g: " .. expanded_g)
						end
						mw.log("t_galleries: " .. table.concat(t_galleries))
					end
				elseif template == 'Header' then
					-- if this is not the first subheader in this section
					if current_subheader ~= '' then
						-- check if the previous subheader's galleries had images in them
						if images_in_subsection > 0 then
							table.insert(t_section, current_subheader)
							g = table.concat(t_galleries)
							if g ~= "" then
								table.insert(t_section, g)
							end
							-- reset galleries and images for the next subsection
							clear_table(t_galleries)
							images_in_subsection = 0
						end
					end
					local header = v2.header or ''
					-- save the new subheader and wait to see if the following galleries have any images in them
					current_subheader = '<' .. header .. '>' .. title .. '</' .. header .. ">\n"
				end
			end

			-- check the number of images in the section
			mw.log("---\n" .. category .. " images_in_section = " .. images_in_section)
			mw.log("t_galleries: " .. table.concat(t_galleries))

			if images_in_section > 0 then
				-- if there is a subheader to insert, then insert it
				if current_subheader ~= "" and images_in_subsection > 0 then
					table.insert(t_section, current_subheader)
				end
			
				-- if there are galleries to insert, then insert them
				g = table.concat(t_galleries)
				table.insert(t_section, g)

				-- close the wrapping div if one was added
				if class ~= "" then
					table.insert(t_section, "</div>")
				end

				-- insert the section, prepended by the section header, to the final text
				s = concatvaluesonly(t_section, '')
				mw.log('t_section ' .. category .. ' ' .. s)
				if s ~= "" then
					table.insert(text, '<h2>' .. category .. '</h2>\n' .. s)
				end
			end

			mw.log("\n")
			clear_table(t_galleries)
			clear_table(t_section)
		end
	end
	
	gallery = table.concat(text)
	return gallery
end

-------------------------------------
-- Main
-------------------------------------
local p = {}

function p.main(frame)
	data = frame.args.data or 'Module:Character Gallery/data'
	gallery = Gallery.new(data, frame)

	--mw.log(dump(tostring(gallery)))
	return tostring(gallery)
end

-------------------------------------
-- Tests
-------------------------------------

function p.testExpandTemplate_1(frame)
	
	v = {
		character = 'Noel Vermillion',
		source = 'BlazBlue: Central Fiction', 
		section = '', 
		limit = 8, 
		title = 'title', 
		header = 'h3', 
		see_all = 'y', 
		see_cameos = 'y', 
		count_all = '7'
	}
	text = p._expandTemplate_GallerySectionCargo(frame, v)
	
	return text
end

function p.testExpandTemplate_2(frame)
	
	v = {
		character = 'Noel Vermillion',
		season = 'NEO', 
		limit = 8, 
		title = 'title', 
		header = 'h3', 
		see_all = 'y', 
		count_all = '7',
	}
	text = p._expandTemplate_GallerySectionBBRadio(frame, v)
	
	return text
end

function p.testOrdering()
	for i,v in ipairs (ordering) do
		section = v
		k = sections[v] or ''

		mw.log('\n' .. i .. ': ' .. section)
		if k == '' then
			mw.log('no parameters found')
		else
			mw.log(k.class)
			for k2,v2 in pairs (k) do
				mw.log(k2)
			end
		end
		
	end
end

-------------------------------------
-- Utility Functions
-------------------------------------

-- clear a table
function clear_table(t)
	for k in pairs (t) do
    	t [k] = nil
	end
end

-- concat all the strings in table s together with the given delimiter
function concatvalues(s,delimiter)
    local t = { }
    for k,v in ipairs(s) do
        t[#t+1] = tostring(v)
    end
    return table.concat(t,delimiter)
end

-- concat all the strings in table s together with the given delimiter
-- skips blank entries (where value v = "")
function concatvaluesonly(s,delimiter)
    local t = { }
    for k,v in ipairs(s) do
    	if not (v == '') then
    		t[#t+1] = tostring(v)
    	end
    end
    return table.concat(t,delimiter)
end

function cargo_escape(s)
	return (string.gsub(s, "[']", {
		["'"] = "",
		['"'] = "",
	}))
end

function quote_escape(s)
	return (string.gsub(s, "[\"']", {
		["\'"] = "\\'",
		['\"'] = '\\"'
	}))
end

function html_escape(s)
    return (string.gsub(s, "[<>\"'/ ,]", {
        ["<"] = "%3C",
        [">"] = "%3E",
        ['"'] = "%22",
        ["'"] = "%27",
        ["/"] = "%2F",
        [" "] = "+",
        [","] = "%2C"
    }))
end

-- helpful for printing tables
function dump(o)
   if type(o) == 'table' then
      local s = '{ '
      for k,v in pairs(o) do
         if type(k) ~= 'number' then k = '"'..k..'"' end
         s = s .. '['..k..'] = ' .. dump(v) .. ','
      end
      return s .. '} '
   else
      return tostring(o)
   end
end

return p