Moduli:CS1 charts
Pamja
--[[--------------------------< G R A P H E X P E R I M E N T >----------------------------------------------
TODO: when a category is empty, is there any need to graph it?
TODO: provide a switch between miant cat charting and error cat charting
]]
require('Module:No globals');
local getArgs = require ('Module:Arguments').getArgs;
local cfg = mw.loadData ('Moduli:Citation/CS1/Configuration');
--[[--------------------------< M A I N T _ C A T S _ T >------------------------------------------------------
sequence table of maint cats. Each value is the maint cat's key in Module:Citation/CS1/Configuration <error_conditions>
k/v table.
some cats have subcategories so those categories aren't listed in <error_conditions>. For those categories not listed
in <error_conditions>, provide the category name without namespace prefix, and include a matching entry in subcats_t
that holds a sequence table of the category's subcats.
]]
local maint_cats_t = { -- categories are listed here in the order in which they are displayed
'maint_unfit', -- Mirëmbajtja CS1: Adresë e papërshtatshme
'maint_archived_copy', -- Mirëmbajtja CS1: Archived copy si titull
'maint_bot_unknown', -- Mirëmbajtja CS1: BOT: gjendja e adresës origjinale është e panjohur
'maint_untitled', -- Mirëmbajtja CS1: Botim periodik i patitulluar
'maint_ref_duplicates_default', -- Mirëmbajtja CS1: Citimi referon vetveten
'maint_date_year', -- Mirëmbajtja CS1: Data dhe viti
'maint_doi_inactive', -- Mirëmbajtja CS1: DOI joaktive
'maint_pmc_embargo', -- Mirëmbajtja CS1: Embargo PMC ka skaduar
-- 'Mirëmbajtja CS1: Emra shifrorë', -- has these subcats with assembled names so this cat not in cfg.error_conditions
'Mirëmbajtja CS1: Emra shifrorë: lista e autorëve', -- these cats displayed directly
'Mirëmbajtja CS1: Emra shifrorë: lista e intervistuesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e kontribuesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e përkthyesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e redaktorëve',
-- 'Mirëmbajtja CS1: Emra të shumëfishtë', -- has these subcats with assembled names so this cat not in cfg.error_conditions
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e autorëve', -- these cats displayed directly
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e intervistuesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e kontribuesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e përkthyesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e redaktorëve',
'maint_others', -- Mirëmbajtja CS1: Është përdorur gabimisht parametri i të tjerëve
'maint_others_avm', -- Mirëmbajtja CS1: Është përdorur gabimisht parametri i të tjerëve te citimet audiovizuale
'maint_authors', -- Mirëmbajtja CS1: Është përdorur parametri i autorëve
'maint_ref_harv', -- Mirëmbajtja CS1: Është përdorur ref=harv
'maint_date_format', -- Mirëmbajtja CS1: Formati i datës
'maint_jfm_format', -- Mirëmbajtja CS1: Formati JFM
'maint_mr_format', -- Mirëmbajtja CS1: Formati MR
'maint_pmc_format', -- Mirëmbajtja CS1: Formati PMC
'maint_doi_ignore', -- Mirëmbajtja CS1: Gabime DOI të injoruara
'maint_isbn_ignore', -- Mirëmbajtja CS1: Gabime ISBN të injoruara
'maint_issn_ignore', -- Mirëmbajtja CS1: Gabime ISSN të injoruara
'maint_unknown_lang', -- Mirëmbajtja CS1: Gjuhë e panjohur
'maint_postscript', -- Mirëmbajtja CS1: Passhkrimi
'maint_extra_punct', -- Mirëmbajtja CS1: Pikësim shtesë
-- 'Mirëmbajtja CS1: Tekst shtesë', -- has these subcats with assembled names so this cat not in cfg.error_conditions
'Mirëmbajtja CS1: Tekst shtesë: lista e autorëve', -- these cats displayed directly
'Mirëmbajtja CS1: Tekst shtesë: lista e intervistuesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e kontribuesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e përkthyesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e redaktorëve',
'maint_location', -- Mirëmbajtja CS1: Vendodhja
'maint_zbl', -- Mirëmbajtja CS1: ZBL
}
--[[--------------------------< E R R O R _ C A T S _ T >------------------------------------------------------
sequence table of error cats. Each value is the error cat's key in Module:Citation/CS1/Configuration <error_conditions>
k/v table.
Kategoria:Gabime_CS1--Gabime CS1: Mungon parametri i gjuhës
]]
local error_cats_t = { -- categories are listed here in the order in which they are displayed
'err_bad_url', -- Gabime CS1: Adresa
'err_archive_url', -- Gabime CS1: Adresa e arkivimit
'err_bare_url_missing_title', -- Gabime CS1: Adresë e zhveshur
'err_bad_arxiv', -- Gabime CS1: arXiv
'err_bad_asin', -- Gabime CS1: ASIN
'err_bad_asin_tld', -- Gabime CS1: ASIN TLD
'err_bad_bibcode', -- Gabime CS1: bibcode
'err_bad_biorxiv', -- Gabime CS1: bioRxiv
'err_empty_citation', -- Gabime CS1: Burim bosh
'err_bad_citeseerx', -- Gabime CS1: citeseerx
'err_bad_date', -- Gabime CS1: Datat
'err_accessdate_missing_url', -- Gabime CS1: Datë aksesimi pa adresë
'err_bad_doi', -- Gabime CS1: DOI
'err_embargo_missing_pmc', -- Gabime CS1: Embargo PMC
'err_format_missing_url', -- Gabime CS1: Format pa adresë
'err_apostrophe_markup', -- Gabime CS1: Formatimi
'err_bad_hdl', -- Gabime CS1: HDL
'err_bad_isbn', -- Gabime CS1: ISBN
'err_bad_ismn', -- Gabime CS1: ISMN
'err_bad_issn', -- Gabime CS1: ISSN
'err_chapter_ignored', -- Gabime CS1: Janë injoruar kapitujt
'err_bad_jfm', -- Gabime CS1: JFM
'err_bad_jstor', -- Gabime CS1: JSTOR
'err_class_ignored', -- Gabime CS1: klasa
'err_wikilink_in_url', -- Gabime CS1: Konflikt URL-wikilink
'err_contributor_ignored', -- Gabime CS1: kontribuesi
'err_bad_lccn', -- Gabime CS1: LCCN
'err_param_has_ext_link', -- Gabime CS1: Lidhjet e jashtme
'err_bad_usenet_id', -- Gabime CS1: message-id
'err_bad_mr', -- Gabime CS1: MR
'err_cite_web_url', -- Gabime CS1: Mungon adresa
'err_missing_periodical', -- Gabime CS1: Mungon botimi periodik
'err_missing_name', -- Gabime CS1: Mungon emri
-- 'err_language_missing', -- Gabime CS1: Mungon parametri i gjuhës
'err_citation_missing_title', -- Gabime CS1: Mungon titulli
'err_missing_pipe', -- Gabime CS1: Mungon vija ndarëse
'err_bad_oclc', -- Gabime CS1: OCLC
'err_bad_ol', -- Gabime CS1: OL
'err_bad_osti', -- Gabime CS1: OSTI
'err_text_ignored', -- Gabime CS1: Parametra të pa emëruar
'err_parameter_ignored', -- Gabime CS1: Parametra të palejuar
'err_param_unknown_empty', -- Gabime CS1: Parametra të panjohur bosh
'err_redundant_parameters', -- Gabime CS1: Parametra të tepërt
'err_deprecated_params', -- Gabime CS1: Parametra të vjetëruar
'err_script_parameter', -- Gabime CS1: Parametrat script
'err_disp_name', -- Gabime CS1: Parametri display
'err_param_access_requires_param', -- Gabime CS1: parametri i aksesimit
'err_bad_paramlink', -- Gabime CS1: parametri i lidhjes
'err_etal', -- Gabime CS1: Përdorim i gabuar i et al.
'err_bad_pmc', -- Gabime CS1: PMC
'err_bad_pmid', -- Gabime CS1: PMID
'err_bad_rfc', -- Gabime CS1: RFC
'err_bad_s2cid', -- Gabime CS1: S2CID
'err_bad_sbn', -- Gabime CS1: SBN
'err_invisible_char', -- Gabime CS1: simbol i padukshëm
'err_ssrn_missing', -- Gabime CS1: SSRN
'err_vancouver', -- Gabime CS1: Stili Vankuver
'err_extra_text_edition', -- Gabime CS1: Tekst shtesë: Botimi
'err_extra_text_pages', -- Gabime CS1: Tekst shtesë: Faqet
'err_extra_text_issue', -- Gabime CS1: Tekst shtesë: Numri
'err_extra_text_volume', -- Gabime CS1: Tekst shtesë: Vëllimi
'err_generic_title', -- Gabime CS1: Titull i përgjithshëm
'err_trans_missing_title', -- Gabime CS1: titull i përkthyer
'err_invalid_param_val', -- Gabime CS1: Vlerë e palejuar parametri
'err_bad_zbl', -- Gabime CS1: ZBL
}
--[[--------------------------< L A N U A G E _ C A T S >------------------------------------------------------
]]
local language_cats_t = {
'Gabime CS1: Mungon parametri i gjuhës',
'Mirëmbajtje CS1: Gjuhë e panjohur',
'Vetitë CS1: Burime në gjuhë me kod ISO 3 shkronjor',
}
local cat_base_name = 'Vetitë CS1: Burime në ';
local lang_tag_this_wiki = mw.language.getContentLanguage().code;
local lang_names_t = mw.language.fetchLanguageNames (lang_tag_this_wiki, 'all');
for tag, lang in pairs (lang_names_t) do -- loop through a k/v table of language tag (k) / language name (v) pairs
if 2 == #tag then -- ISO 639-1 codes only
table.insert (language_cats_t, table.concat ({cat_base_name, lang, ' (', tag, ')'})); -- create category name from base name, languange name, and tag
end
end
--[[--------------------------< S C R I P T _ L A N G _ C A T S _ T >------------------------------------------
]]
local script_lang_cats_t = {};
cat_base_name = 'Vetitë CS1: Vlera në ';
for _, tag in ipairs (cfg.script_lang_codes) do
table.insert (script_lang_cats_t, table.concat ({cat_base_name, lang_names_t[tag], ' (', tag, ')'})); -- create category name from base name, languange name, and tag
end
--[[--------------------------< S U B C A T S _ T >------------------------------------------------------------
some maint and error cats have subcategories. The subcat names are often dynamically created so the parent categories
don't have entries in Module:Citation/CS1/Configuration <error_conditions>.
<subcats_t> is a k/v table where k is the parent category name and v is a sequence table of the parent's subcategory
names (all without namespace prefix)
]]
local subcats_t = {
['Mirëmbajtja CS1: Emra shifrorë'] = { -- subcats of Mirëmbajtja CS1: Emra shifrorë
'Mirëmbajtja CS1: Emra shifrorë: lista e autorëve',
'Mirëmbajtja CS1: Emra shifrorë: lista e intervistuesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e kontribuesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e përkthyesve',
'Mirëmbajtja CS1: Emra shifrorë: lista e redaktorëve',
},
['Mirëmbajtja CS1: Emra të shumëfishtë'] = { -- subcats of Mirëmbajtja CS1: Emra të shumëfishtë
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e autorëve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e intervistuesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e kontribuesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e përkthyesve',
'Mirëmbajtja CS1: Emra të shumëfishtë: lista e redaktorëve',
},
['Mirëmbajtja CS1: Tekst shtesë'] = { -- subcats of Mirëmbajtja CS1: Tekst shtesë
'Mirëmbajtja CS1: Tekst shtesë: lista e autorëve',
'Mirëmbajtja CS1: Tekst shtesë: lista e intervistuesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e kontribuesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e përkthyesve',
'Mirëmbajtja CS1: Tekst shtesë: lista e redaktorëve',
},
['Gabime CS1: Tekst shtesë'] = { -- subcats of Gabime CS1: Tekst shtesë; these are charted separately
'Gabime CS1: Tekst shtesë: Botimi',
'Gabime CS1: Tekst shtesë: Faqet',
'Gabime CS1: Tekst shtesë: Numri',
'Gabime CS1: Tekst shtesë: Vëllimi',
}
}
local bar_chart_delimiter = ';'; -- for |delimiter=
local bar_chart_units_suffix = '_faqe'; -- for |units suffix=
local page_title = mw.title.getCurrentTitle().prefixedText; -- namespace and name
local bar_chart_maint_cat_title = 'Mirëmbajtja CS1'; -- name without namespace
local bar_chart_error_cat_title = 'Gabime CS1'; -- name without namespace
--[[--------------------------< B A R _ C H A R T _ C O L O R S >----------------------------------------------
these colors from Stampa:Grafiku i kategorive të gabimeve CS1 (64 colors)
]]
local bar_chart_colors_t = {
'Red',
'GreenYellow',
'SlateBlue',
'Silver',
'Maroon',
'Yellow',
'Olive',
'Lime',
'Green',
'Brown',
'Teal',
'Blue',
'Navy',
'Fuchsia',
'Purple',
'ForestGreen',
'Tomato',
'LightSeaGreen',
'RosyBrown',
'DarkOliveGreen',
'MediumVioletRed',
'Olivedrab',
'Hotpink',
'Indigo',
'Gold',
'LawnGreen',
'Peru',
'BlueViolet',
'OrangeRed',
'RoyalBlue',
'DimGrey',
'Chartreuse',
'Chocolate',
'Orange',
'Plum',
'IndianRed',
'MediumAquamarine',
'Tan',
'LightSalmon',
'LightSlategrey',
'Magenta',
'Firebrick',
'DarkGoldenRod',
'SpringGreen',
'Khaki',
'YellowGreen',
'DarkOrange',
'LightCoral',
'DarkSlateGray',
'Crimson',
'SteelBlue',
'MediumSeaGreen',
'DeepPink',
'LightSkyBlue',
'Thistle',
'BlanchedAlmond',
'Burlywood',
'DarkViolet',
'LimeGreen',
'OldLace',
'Black',
'Palevioletred',
'Lightsteelblue',
'Moccasin',
}
--[[--------------------------< S U B C A T _ D A T A _ F E T C H >--------------------------------------------
return the total number of pages, files, and subcats in a named category's (<cat>) subcategories; when no subcats
listed in <subcats_t>, returns 0
]]
local function subcat_data_fetch (cat)
local page_count = 0;
if subcats_t[cat] then -- if this category has listed subcats
local pages_in_cat_t = {};
for i, subcat in ipairs (subcats_t[cat]) do -- for each subcat
pages_in_cat_t = mw.site.stats.pagesInCategory (subcat, '*'); -- get the various counts and
page_count = page_count + pages_in_cat_t.files + pages_in_cat_t.pages + pages_in_cat_t.subcats; -- tally
end
end
return page_count;
end
--[[--------------------------< B A R _ C H A R T _ C R E A T E >----------------------------------------------
]]
local function bar_chart_create (frame)
local page_counts_t = {};
local subcat_counts_t = {};
local cat_names_t = {};
local cats_t = {}; --(('maint' == frame.args[1]) and maint_cats_t) or (('error' == frame.args[1]) and error_cats_t) or maint_cats_t;
local bar_chart_x_legends;
if 'error' == frame.args[1] then
cats_t = error_cats_t;
bar_chart_x_legends = (page_title == ('Kategoria:' .. bar_chart_error_cat_title)) and bar_chart_error_cat_title or table.concat ({'[[:Kategoria:', bar_chart_error_cat_title, '|', bar_chart_error_cat_title, ']]'});
else
cats_t = maint_cats_t;
bar_chart_x_legends = (page_title == ('Kategoria:' .. bar_chart_maint_cat_title)) and bar_chart_maint_cat_title or table.concat ({'[[:Kategoria:', bar_chart_maint_cat_title, '|', bar_chart_maint_cat_title, ']]'});
end
for i, cat in ipairs (cats_t) do
local pages_in_cat_t = {};
if cfg.error_conditions[cat] then
cat = cfg.error_conditions[cat].category; -- fetch the category name from Module:Citation/CS1/Configuration; use plaintext cat else
end
cat_names_t[i] = cat; -- save a copy of the category name
pages_in_cat_t = mw.site.stats.pagesInCategory (cat, '*'); -- get the table of counts
if 0 ~= subcat_data_fetch (cat) then
page_counts_t[i] = pages_in_cat_t.files + pages_in_cat_t.pages + subcat_data_fetch (cat); -- don't include pages_in_cat_t.subcats in tally
subcat_counts_t[i] = pages_in_cat_t.subcats; -- but remember for later annotation
else
page_counts_t[i] = pages_in_cat_t.files + pages_in_cat_t.pages; -- there are no subcats so don't bother
end
end
local out = {'chart', 'bar chart'}; -- init for #invoke parser function call with Module:Chart and function barChart()
out.delimiter = bar_chart_delimiter; -- |delimiter=
out['units suffix'] = bar_chart_units_suffix; -- |units suffix=
local tail;
local group_names_t = {};
local colors_t = {};
local j = 0; -- indexer for cats that that are not empty
for i, v in ipairs (cats_t) do
if 0 ~= page_counts_t[i] then
j = j + 1; -- bump the indexer
out['group ' .. j] = page_counts_t[i]; -- add |group 1= to |group n= pararameters
if subcat_counts_t[i] then -- if this cat has subcats
tail = table.concat ({' faqe nga ', subcat_counts_t[i], ' nënkategori'}) -- modify the group name tail
else -- here when no subcats
tail = ' faqe'; -- standard group name tail
end
out['tooltip ' .. j] = table.concat ({cat_names_t[i], ' ', page_counts_t[i], tail}); -- add |tooltip 1= to |tooltip n= pararameters
table.insert (group_names_t, table.concat ({'[[:Kategoria:', cat_names_t[i], '|', cat_names_t[i], ']] ', page_counts_t[i], tail}));
if 64 == j then
break;
end
end
end
out['group names'] = table.concat (group_names_t, bar_chart_delimiter); -- add |group names= parameter
out['colors'] = table.concat (bar_chart_colors_t, bar_chart_delimiter, 1, j); -- add |colors= parameter
out['x legends'] = table.concat ({bar_chart_x_legends, ' (', #page_counts_t-j, ' nga ', #cats_t, ' kategori bosh janë fshehur)'}); -- add |x legends=
return frame:callParserFunction ('#invoke', out); -- {{#invoke:chart|bar chart|args...}}
end
--[[--------------------------< P I E _ C H A R T _ C R E A T E >----------------------------------------------
]]
local function pie_chart_create (frame)
local args_t = getArgs (frame);
local raw = {}; -- count, legend, and category extracted from category
local slices = {}; -- formatted output suitable for [[Module:Chart]]
local link = true; --'yes' == frame.args_t.link:lower(); -- make a boolean
local delimiter = ';'; --args_t.delimiter or ':';
local selector = args_t.selector and args_t.selector:lower() or 'pages';
selector = ({all='all', pages='pages', subcats='subcats', files='files'})[selector] or 'pages';
local cats_t = {};
if 'lang' == args_t[1] then
cats_t = language_cats_t;
elseif 'script' == args_t[1] then
cats_t = script_lang_cats_t;
else
cats_t = language_cats_t;
end
for _, cat in ipairs (cats_t) do -- spin category names and construct raw data for chart
local t = {}
table.insert (t, mw.site.stats.pagesInCategory (cat, 'pages'));
table.insert (t, cat and cat:match (args_t.pattern or '.*') or cat); -- extract legend; use cat name if pattern not provided
if link then
table.insert (t, cat); -- add cat name for linking
end
table.insert (raw, t); -- save this
end
if 0==#raw then
return string.format ('(%s%s%s%s%s)', -1, delimiter, 'Gabim: Grafiku nuk ka asnjë pjesë të përcaktuar', delimiter, '#d33');
end
for i, v in ipairs (raw) do -- look for duplicate names
for j=i+1, #raw do
if raw[i][2] == raw[j][2] then
return string.format ('(%s%s%s %s%s%s)', -1, delimiter, 'Gabim: Grafiku ka disa pjesë me emra të njëjta', raw[i][2], delimiter, '#d33');
end
end
end
local function comp (a, b) -- used in following table.sort()
if a[1] == b[1] then -- when same do
return a[2] < b[2]; -- ascending alpha sort on name
end
return tonumber (a[1]) > tonumber(b[1]); -- descending sort
end
table.sort (raw, comp); -- descending sort
local non_empty_count = 0; -- count of categories with at least one page
local empty_count = 0;
local other_pages_tally = 0; -- tally of pages not included in the first 25 slices
for i, t in ipairs (raw) do
if 26 > i and 0 ~= t[1] then -- slices 1 - 25 separately in the chart (as long as they have something in them)
if link and t[3] then -- build a linked slice; t[3] may be nil if cat doesn't match |pattern=
table.insert (slices, string.format ('(%s%s%s%s%s[[:Category:%s]])', t[1], delimiter, t[2], delimiter, delimiter, t[3]));
else -- build an unlinked slice
table.insert (slices, string.format ('(%s%s%s)', t[1], delimiter, t[2]));
end
elseif 0 ~= t[1] then -- would-be slices 26+
non_empty_count = non_empty_count + 1; -- count the number of non-empty cats
if t[1] then -- in case t[1] is nil for whatever reason; shouldn't be; TODO: do we need this?
other_pages_tally = other_pages_tally + t[1]; -- sum the number of pages in these non-empty cats
end
else
empty_count = empty_count + 1; -- count the number of empty cats
end
end
if 0 == #slices then -- nothing in slices{}
return string.format ('(%s%s%s%s%s)', -1, delimiter, 'Gabim: Vlera e të gjitha pjesëve të përcaktuara është 0', delimiter, '#d33');
end
if 0 ~= non_empty_count or 0 ~= empty_count then -- 26th slice
table.insert (slices, string.format ('(%s%s%s kategori të tjera + %s kategori bosh)', other_pages_tally, delimiter, non_empty_count, empty_count));
end
local out = {'chart', 'pie chart'}; -- init for #invoke parser function call with Module:Chart and function pieChart()
out['delimiter'] = ';';
out['units suffix'] = '_faqe';
out['percent'] = 'true';
out['slices'] = table.concat (slices, '\n');
return frame:callParserFunction ('#invoke', out); -- {{#invoke:chart|bar chart|args...}}
end
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
bar_chart_create = bar_chart_create,
pie_chart_create = pie_chart_create,
}