Module:Sandbox/trappist the monk/taxonomy
Appearance
require('Module:No globals');
--[[--------------------------< T A X O M A P >----------------------------------------------------------------
this is a table of sequence tables that each list the first and last taxon name in a particular module. module_select()
uses these tables to determine which data module 'should' have the data for the taxon name.
[1] first taxon name in the data module
[2] last taxon name in the module
[3] suffix appended to the base module name to create: 'Module:Sandbox/trappist the monk/taxonomy <suffix>'
These tables are created by an awb script when it splits much larger raw data file before the splits are uploaded
to en.wiki.
]]
local taxomap_t = {
A = {
{'ADA clade', 'Acremoniella', 'A1'},
{'Acrepidopterum', 'Afripupa', 'A2'},
{'Afristreptaxis', 'Alienochelys', 'A3'},
{'Alienoptera', 'Ammotrophus', 'A4'},
{'Ammoxenidae', 'Anerastia', 'A5'},
{'Anerastiini', 'Aotus', 'A6'},
{'Aoupinieta', 'Archemitra', 'A7'},
{'Archencyrtus', 'Asfuvirales', 'A8'},
{'Asgard', 'Auriculariaceae', 'A9'},
{'Auriculariales', 'Azygopus', 'A10'},
},
B = {
{'BOP clade', 'Baurusuchus', 'B1'},
{'Baurutitan', 'Blotiella', 'B2'},
{'Blubervirales', 'Brasilidia', 'B3'},
{'Brasiliguana', 'Byturus', 'B4'},
},
C = {
{'CRuMs', 'Camirus', 'C1'},
{'Camisiidae', 'Cassidae', 'C2'},
{'Cassidinae', 'Cerianthula', 'C3'},
{'Cerianthus', 'Chersodromus', 'C4'},
{'Chersomanes', 'Chrysoritis', 'C5'},
{'Chrysoscota', 'Cnephalocotes', 'C6'},
{'Cnephalodes', 'Conosperminae', 'C7'},
{'Conospermum', 'Craterispermeae', 'C8'},
{'Craterispermum', 'Cuprella', 'C9'},
{'Cupressaceae', 'Czekanowskiales', 'C10'},
},
D = {
{'Daanosaurus', 'Denteilema', 'D1'},
{'Dentella', 'Digitalideae', 'D2'},
{'Digitalis', 'Dodonaeoideae', 'D3'},
{'Dodonidia', 'Dzharatitanis', 'D4'},
{'Dzhungarocosa', 'Dzungariotherium', 'D5'},
},
E = {
{'Eacles', 'Empidinae', 'E1'},
{'Empidoidea', 'Epiprininae', 'E2'},
{'Epiprinus', 'Eucrada', 'E3'},
{'Eucradinae', 'Eutrichopidia', 'E4'},
{'Eutrichopoda', 'Ezosciadium', 'E5'},
},
G = {
{'Gabara', 'Gibbacousteau', 'G1'},
{'Gibbafroneta', 'Gonypetidae', 'G2'},
{'Gonypetinae', 'Gyroweisia', 'G3'},
},
H = {
{'HTVC010P', 'Hecastocleis', 'H1'},
{'Hecatera', 'Hesperoptenus', 'H2'},
{'Hesperorhipis', 'Homalocephale', 'H3'},
{'Homaloceras', 'Hymenocardia', 'H4'},
{'Hymenocardiinae', 'Hytrosaviridae', 'H5'},
},
L = {
{'La', 'Lechriopini', 'L1'},
{'Lechriops', 'Lethrinidae', 'L2'},
{'Lethrinops', 'Lithophyllum', 'L3'},
{'Lithopoma', 'Lycosidae', 'L4'},
{'Lycosinae', 'Lyttoniidina', 'L5'},
},
M = {
{'Maaqwi', 'Manjala', 'M1'},
{'Manjekia', 'Meganeurinae', 'M2'},
{'Meganeuropsis', 'Messageriella', 'M3'},
{'Messapicetus', 'Mideopsis', 'M4'},
{'Midgee', 'Mopalia', 'M5'},
{'Mopaliidae', 'Myxococcaceae', 'M6'},
{'Myxococcales', 'minke whale species complex', 'M7'},
},
N = {
{'Naashoibitosaurus', 'Neocoleoidea', 'N1'},
{'Neocollyris', 'Nicolepeira', 'N2'},
{'Nicoletia', 'Nystalea', 'N3'},
{'Nystaleinae', 'Nyungwea', 'N4'},
},
O = {
{'OSLEUM', 'Ondigus', 'O1'},
{'Ondina', 'Orthonevra', 'O2'},
{'Orthonopias', 'Ozyptila', 'O3'},
},
P = {
{'P2virus', 'Papasula', 'P1'},
{'Papaver', 'Paratachardina', 'P2'},
{'Paratachina', 'Peltigeraceae', 'P3'},
{'Peltigerales', 'Phalacrus (beetle)', 'P4'},
{'Phalaenoides', 'Phyllodiscus', 'P5'},
{'Phyllodistomum', 'Plantae', 'P6'},
{'Plantae/?', 'Poecilognathus', 'P7'},
{'Poecilographa', 'Praya', 'P8'},
{'Praydidae', 'Protodictya', 'P9'},
{'Protodiplatyidae', 'Pseudonigrita', 'P10'},
{'Pseudoniscidae', 'Ptyoiulus', 'P11'},
{'Ptyomaxia', 'Pyxis', 'P12'},
},
S = {
{'SAR', 'Scaptochirus', 'S1'},
{'Scaptocoris', 'Segestes', 'S2'},
{'Segestria', 'Sinapriculus', 'S3'},
{'Sinarachna', 'Sphaerobambos', 'S4'},
{'Sphaerobothria', 'Stenolicmus', 'S5'},
{'Stenoloba', 'Stylotermes', 'S6'},
{'Stylotermitidae', 'Szovitsia', 'S7'},
},
T = {
{'TG3', 'Tentyriini', 'T1'},
{'Tenualosa', 'Thermodesulfobacteriaceae', 'T2'},
{'Thermodesulfobacteriales', 'Torreyochloinae', 'T3'},
{'Torricellia', 'Trihecaton', 'T4'},
{'Trihecatontidae', 'Typhlosyrinx', 'T5'},
{'Typhlotanaidae', 'Tzvelevopyrethrum', 'T6'},
},
}
local modules_loaded = {}; -- a list of the modules loaded while crawling the tree; viewable in the lua log
local is_not_italic_virus_taxon_t = {
['unranked domain'] = true, -- taxon names assigned these ranks are *not* to be italicized
['unranked'] = true,
['virus group'] = true,
['virus'] = true,
['strain'] = true,
['serotype'] = true,
}
local is_italic_taxon_t = { -- taxon names assigned these ranks are to be italicized
['genus'] = true,
['ichnogenus'] = true,
['oogenus'] = true,
['subgenus'] = true,
['ichnosubgenus'] = true,
['oosubgenus'] = true,
['supersectio'] = true,
['sectio'] = true,
['subsectio'] = true,
['series'] = true,
['subseries'] = true,
['species complex'] = true,
['species group'] = true,
['species subgroup'] = true,
['species'] = true,
['ichnospecies'] = true,
['oospecies'] = true,
['subspecies'] = true,
['ichnosubspecies'] = true,
['oosubspecies'] = true,
}
local anglicize_rank_t = { -- this table adapted from {{anglicise rank}}
['alliance'] = '\'\'Alliance\'\'', -- Special cases, alphabetic order
['basic shell type'] = '\'\'Basic shell type\'\'',
['branch'] = '\'\'Branch\'\'',
['clade'] = '\'\'Clade\'\'',
['cladus'] = '\'\'Clade\'\'',
['form taxon'] = '\'\'Form taxon\'\'',
['grade'] = '\'\'Grade\'\'',
['gradus'] = '\'\'Grade\'\'',
['informal'] = '\'\'Informal group\'\'',
['informal group'] = '\'\'Informal group\'\'',
['morphotype'] = '\'\'Morphotype\'\'',
['node'] = '\'\'Node\'\'',
['plesion'] = '\'\'Plesion\'\'',
['plesion-group'] = '\'\'Plesion-group\'\'',
['possible clade'] = '\'\'Clade?\'\'',
['realm'] = '\'\'Realm\'\'',
['species complex'] = '\'\'Species complex\'\'',
['species group'] = '\'\'Species group\'\'',
['species subgroup'] = '\'\'Species subgroup\'\'',
['stem group'] = '\'\'Stem group\'\'',
['total group'] = '\'\'Total group\'\'',
['unranked'] = '(unranked)', -- not a special case in {{anglicise rank}} but included here for convenience
['serotype'] = 'Serotype', -- Virus ranks below species
['strain'] = 'Strain',
['virus'] = 'Virus',
['virus group'] = 'Group',
['classis'] = 'Class', -- Linnaean taxonomy, alphabetic order
['cohort'] = 'Cohort',
['divisio'] = 'Division',
['domain'] = 'Domain',
['epifamilia'] = 'Epifamily',
['familia'] = 'Family',
['forma'] = 'Form',
['genus'] = 'Genus',
['grandordo'] = 'Grandorder',
['grandordo-mb'] = 'Grandorder', -- McKenna & Bell version
['hyperfamilia'] = 'Hyperfamily',
['infraclassis'] = 'Infraclass',
['infralegio'] = 'Infralegion',
['infralegion'] = 'Infralegion',
['infraordo'] = 'Infraorder',
['infraphylum'] = 'Infraphylum',
['infraregnum'] = 'Infrakingdom',
['infratribus'] = 'Infratribe',
['legio'] = 'Legion',
['legion'] = 'Legion',
['magnordo'] = 'Magnorder',
['micrordo'] = 'Microrder',
['microphylum'] = 'Microphylum',
['mirordo-Mirorder'] = 'Mirorder',
['mirordo-mb'] = 'Mirorder', -- McKenna & Bell version
['nanordo'] = 'Nanorder',
['nanophylum'] = 'Nanophylum',
['ordo'] = 'Order',
['parafamilia'] = 'Parafamily',
['parvclassis'] = 'Parvclass',
['parvordo'] = 'Parvorder',
['phylum'] = 'Phylum',
['regnum'] = 'Kingdom',
['sectio'] = 'Section',
['series'] = 'Series',
['species'] = 'Species',
['subclassis'] = 'Subclass',
['subcohort'] = 'Subcohort',
['subdivisio'] = 'Subdivision',
['subfamilia'] = 'Subfamily',
['subgenus'] = 'Subgenus',
['sublegio'] = 'Sublegion',
['sublegion'] = 'Sublegion',
['subordo'] = 'Suborder',
['subphylum'] = 'Subphylum',
['subregnum'] = 'Subkingdom',
['subsectio'] = 'Subsection',
['subseries'] = 'Subseries',
['subspecies'] = 'Subspecies',
['subterclassis'] = 'Subterclass', -- used in WoRMS
['subtribus'] = 'Subtribe',
['superclassis'] = 'Superclass',
['supercohort'] = 'Supercohort',
['superdivisio'] = 'Superdivision',
['superdomain'] = 'Superdomain',
['superfamilia'] = 'Superfamily',
['superlegio'] = 'Superlegion',
['superlegion'] = 'Superlegion',
['superordo'] = 'Superorder',
['superphylum'] = 'Superphylum',
['superregnum'] = 'Superkingdom',
['supersectio'] = 'Supersection',
['supertribus'] = 'Supertribe',
['tribus'] = 'Tribe',
['varietas'] = 'Variety',
['zoodivisio'] = 'Division',
['zoosectio'] = 'Section',
['zoosubdivisio'] = 'Subdivision',
['zoosubsectio'] = 'Subsection',
['ichnoclassis'] = 'Ichnoclass', --trace fossil taxonomy, alphabetic order
['ichnocohort'] = 'Ichnocohort',
['ichnodivisio'] = 'Ichnodivision',
['ichnofamilia'] = 'Ichnofamily',
['ichnogenus'] = 'Ichnogenus',
['ichnograndordo'] = 'Ichnograndorder',
['ichnograndordo-mb'] = 'Ichnograndorder', --McKenna & Bell version-->
['ichnoinfraclassis'] = 'Ichnoinfraclass',
['ichnoinfradivisio'] = 'Ichnoinfradivision',
['ichnoinfraordo'] = 'Ichnoinfraorder',
['ichnolegio'] = 'Ichnolegion',
['ichnolegion'] = 'Ichnolegion',
['ichnomagnordo'] = 'Ichnomagnorder',
['ichnomicrordo'] = 'Ichnomicrorder',
['ichnoordo'] = 'Ichnoorder',
['ichnoparvordo'] = 'Ichnoparvorder',
['ichnospecies'] = 'Ichnospecies',
['ichnostem-group'] = 'Ichnostem-Group',
['ichnosubclassis'] = 'Ichnosubclass',
['ichnosubdivisio'] = 'Ichnosubdivision',
['ichnosubfamilia'] = 'Ichnosubfamily',
['ichnosublegio'] = 'Ichnosublegion',
['ichnosublegion'] = 'Ichnosublegion',
['ichnosubordo'] = 'Ichnosuborder',
['ichnosuperclassis'] = 'Ichnosuperclass',
['ichnosupercohort'] = 'Ichnosupercohort',
['ichnosuperfamilia'] = 'Ichnosuperfamily',
['ichnosuperordo'] = 'Ichnosuperorder',
['ooclassis'] = 'Ooclass', --fossilized egg taxonomy, alphabetic order
['oocohort'] = 'Oocohort',
['oofamilia'] = 'Oofamily',
['oogenus'] = 'Oogenus',
['oomagnordo'] = 'Oomagnorder',
['oordo'] = 'Oorder',
['oospecies'] = 'Oospecies',
['oosubclassis'] = 'Oosubclass',
['oosubgenus'] = 'Oosubgenus',
['oosubspecies'] = 'Oosubspecies',
['oosupercohort'] = 'Oosupercohort',
['oosuperordo'] = 'Oosuperorder',
}
local is_always_displayed_t = {
['virus_group'] = true,
['regnum'] = true,
['phylum'] = true,
['divisio'] = true,
['classis'] = true,
['ordo'] = true,
['familia'] = true,
['genus'] = true,
['species'] = true,
}
--[[--------------------------< M O D U L E _ S E L E C T >----------------------------------------------------
Select one data module to load that 'should' hold data for <taxon>. Returns an enumerated letter suffix that
will be appended to the base module name to make: Module:Sandbox/trappist the monk/taxonomy <suffix>
]]
local function module_select (taxon)
local letter = taxon:match ('^%a'); -- get the first character of the taxon name
letter = (letter and letter:upper()) or 'symbols'; -- if a letter force uppercase; 'symbols' else
if not taxomap_t[letter] then -- if no table in <taxomap_t> for <letter>
return letter;
end
for _, map_t in ipairs (taxomap_t[letter]) do -- loop through the <letter> map table looking for the table that should hold <taxon>
if (map_t[1] <= taxon) and (taxon <= map_t[2]) then -- compare <taxon> against table's first and last entries
return map_t[3]; -- should be here, return the enumerated letter
end
end
end
--[[--------------------------< T A X O N _ G E T >------------------------------------------------------------
fetch a taxon table from the appropriate Module:Sandbox/trappist the monk/taxonomy <letter> date module where
<letter> is the uppercase first letter of <taxon> or 'symbols' when the first catacter is not a letter.
follow one 'same_as' if that parameter is present
]]
local function taxon_get (taxon, no_follow)
local suffix = module_select (taxon); -- get the suffix to append to the base data module name
local taxon_t = {}; -- the return table
local same_as_t = {}; -- table used to hold data when <taxon> data has a same_as value
local same_as; -- holds the <same_as> value from <taxon> data; nil else
local taxon_module_name = 'Module:Sandbox/trappist the monk/taxonomy ' .. suffix;
local ok, taxonomy_t = pcall (require, taxon_module_name); -- attempt to load the selected data module
if ok then -- was loaded
modules_loaded['taxonomy ' .. suffix] = (modules_loaded['taxonomy ' .. suffix] and (modules_loaded['taxonomy ' .. suffix] + 1)) or 1;
--mw.log ('taxonomy_t[taxon]: ' .. mw.dumpObject (taxonomy_t[taxon]))
for k, v in pairs (taxonomy_t[taxon]) do -- copy content from taxonomy table to return table
if no_follow or 'same_as' ~= k then -- but don't copy same_as data if present
taxon_t[k] = v;
else -- here when save_as is present
same_as = v; -- so save its value
end
end
package.loaded[taxon_module_name] = nil; -- unload to save memory
if same_as then -- if there is a save_as value in the taxonomy table
suffix = module_select (same_as); -- get the suffix for the same_as taxon
local same_as_module_name = 'Module:Sandbox/trappist the monk/taxonomy ' .. suffix;
ok, taxonomy_t = pcall (require, same_as_module_name); -- attempt to load the selected data module
if ok then -- was loaded
modules_loaded['taxonomy ' .. suffix] = (modules_loaded['taxonomy ' .. suffix] and (modules_loaded['taxonomy ' .. suffix] + 1)) or 1;
--mw.log ('taxonomy_t[same_as]: ' .. mw.dumpObject (taxonomy_t[same_as]))
for k, v in pairs (taxonomy_t[same_as]) do -- copy content of the same_as_t table into the taxon_t table
if not taxon_t[k] then -- but only if taxon_t doesn;t already have a value for that parameter
taxon_t[k] = v;
end
end
package.loaded[same_as_module_name] = nil; -- unload to save memory
end
--mw.log ('taxon_t: ' .. mw.dumpObject (taxon_t))
end
return taxon_t;
end
return nil; -- unable to load data module
end
--[[--------------------------< _ C R A W L _ T R E E >--------------------------------------------------------
experimental function to see if it is possible / makes sense to replace 87k+ taxonomy templates with lua data modules
for use in Module:Autotaxobox/sandbox call this function with make_tables() from taxonomyList()
fills three tables:
tree_t: inverted sequence table of taxa and their ranks
taxon_tree_t: equivalent to Module:Autotaxobox taxonTable{} – a sequence table where [1] is <starting node> but also has [n]=number of taxa listed
rank_tree_t: equivalent to Module:Autotaxobox taxonRankTable{} – a sequence table that matches the taxa in taxonTable{}; for 'Life', Veterovata, and Ichnos, empty string
]]
local function _crawl_tree (starting_node, tree_t, taxon_tree_t, rank_tree_t)
local node = starting_node;
local taxon_t = taxon_get (node); -- initialize
while taxon_t and node do
if taxon_t.rank then -- nil for Taxonomy/Life
local rank = anglicize_rank_t[taxon_t.rank];
rank = ((taxon_t.always_display or is_always_displayed_t[taxon_t.rank:lower()]) and '\'\'\'' .. rank .. '\'\'\'') or rank;
table.insert (tree_t, 1, rank .. ': ' .. node);
if node:find ('/skip', 1, true) then
table.insert (tree_t, 1, string.rep ('·', 5 ) .. ': ' .. string.rep ('·', 5 ));
end
table.insert (taxon_tree_t, node);
table.insert (rank_tree_t, taxon_t.rank);
if taxon_t.parent then
node = taxon_t.parent; -- get the next node
taxon_t = taxon_get (node); -- and get its taxon table
if nil == taxon_t then
table.insert (tree_t, 1, '<span style="color:#d33">no path to \'Life\' at ' .. node .. ' from ' .. starting_node .. '</span>');
end
else
table.insert (tree_t, 1, '<span style="color:#d33">no parent for node ' .. node .. ' from ' .. starting_node .. '</span>');
node = nil; -- no next node
end
else
if ('Life' == node) or ('Veterovata' == node) or ('Ichnos' == node) then
table.insert (taxon_tree_t, node);
table.insert (rank_tree_t, '');
else
table.insert (tree_t, 1, '<span style="color:#d33">no rank or same_as for node ' .. node .. ' from ' .. starting_node .. '</span>');
end
node = nil; -- no next node
end
end
taxon_tree_t.n = #taxon_tree_t; -- add the number of taxa in this table
return tree_t, taxon_tree_t, rank_tree_t
end
--[[--------------------------< M A K E _ T A B L E S >--------------------------------------------------------
interface function between Module:Autotaxobox taxonomyList() and _crawl_tree()
]]
local function make_tables (taxon)
local taxon_t = {};
local rank_t = {};
local _;
_, taxon_t, rank_t = _crawl_tree (taxon, {}, taxon_t, rank_t); -- crawl the tree to get the taxon list and the rank list; empty table not used here
return taxon_t, rank_t;
end
--[[--------------------------< D E L E T E _ T A X O N >------------------------------------------------------
deletes a taxon entry from a taxonomy data module.
Calling this function finds the correct data module, reads it and removes the specified taxon entry. The output
a copy of the data module that can be copy/pasted into the data module. Yeah, I know, crude but lua can't write
wikitext.
TODO: error checking? What if the taxon isn't found?
]]
local function delete_taxon (frame)
local taxon = frame.args[1];
local taxonomy_t = {};
local suffix = module_select (taxon);
local content = mw.title.new ('Module:Sandbox/trappist the monk/taxonomy ' .. suffix):getContent()
local found = false;
local out_t = {};
for entry in content:gmatch ('\t*%[\'[^\r\n]+},[\r\n]+') do
local entry_taxon = entry:match ('^\t*%[\'([^=]+)\'%]%s*=');
if entry_taxon == taxon then
found = true;
else
table.insert (out_t, entry);
end
end
if not found then
return '<span style="color:#d33">Taxon: ' .. taxon .. ' not found in [[Module:Sandbox/trappist the monk/taxonomy ' .. suffix .. ']]';
end
table.sort (out_t)
table.insert (out_t, 1, 'return {\n')
table.insert (out_t, '\t}')
return 'deleted: ' .. taxon .. '\n\n' .. frame:callParserFunction ({name='#tag:syntaxhighlight', args={table.concat (out_t), lang='lua'}});
-- return ('deleted: ' .. taxon .. '\n\n' .. table.concat (out_t, '\n'))
end
--[[--------------------------< T E S T >----------------------------------------------------------------------
A test function that counts the number of 'parameters' used in a converted lua data file.
Also detects unknown parameters (most of the parameters in a malformed cite journal template in
Template:Taxonomy/Parmastega |refs= parameter); identified a bug in the conversion script (<noinclude>...</noinclude>
not correctly removed). The newst version of the conversion script does not retain unknown parameters.
]]
local function test ()
local data_t = mw.loadData ('Module:Sandbox/trappist the monk/taxonomy A')
local count_t = {parent = 0, rank=0, link=0, extinct=0, always_display=0, ['always display']=0, refs=0, same_as=0, ['same as']=0}
local unknown_t = {};
for _, taxon_t in pairs (data_t) do
for key, _ in pairs (taxon_t) do
if count_t[key] then
count_t[key] = count_t[key] + 1;
else
if unknown_t[key] then
unknown_t[key] = unknown_t[key] + 1;
else
unknown_t[key] = 1;
end
end
end
end
local ordered_t = {};
local unknown_ordered_t = {};
for key, value in pairs (count_t) do
table.insert (ordered_t, key .. ': ' .. value);
end
for key, value in pairs (unknown_t) do
table.insert (unknown_ordered_t, key .. ': ' .. value);
end
local function comp (a, b)
return tonumber (a:match ('%d+$')) > tonumber (b:match ('%d+$'));
end
table.sort (ordered_t, comp);
table.sort (unknown_ordered_t, comp);
return table.concat (ordered_t, '<br />') .. '<br /><br />unknowns<br />' .. table.concat (unknown_ordered_t, '<br />')
end
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
]]
local function is_set( var )
return not (var == nil or var == '');
end
--[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an
empty string.
]=]
local function make_wikilink (link, display)
if is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< S H O W _ T A X O N _ D A T A >------------------------------------------------
similar to the table produced by Template:Taxonomy key
]]
local function show_taxon_data (frame)
local taxon = frame.args[1];
local out_t = {};
local taxon_t = taxon_get (taxon, true); -- get taxon data; do not follow same_as
local same_as = taxon_t.same_as;
if same_as then
taxon_t = taxon_get (taxon); -- get taxon data; this time follow same_as
end
local parent_t = taxon_get (taxon_t.parent); -- get parent taxon's data; follow same_as
local suffix = module_select (taxon);
table.insert (out_t, '{| class="wikitable"\n|-\n|Parent:\n|');
table.insert (out_t, '<code>' .. taxon_t.parent .. '</code> [[[Module:Sandbox/trappist_the_monk/taxonomy ' .. suffix .. ']]]');
table.insert (out_t, '\n|-\n|Rank:\n|');
local rank;
if taxon_t.rank then
rank = anglicize_rank_t[taxon_t.rank];
if is_italic_taxon_t[taxon_t.rank] then
rank = '<code>' .. taxon_t.rank .. '</code> (displays as \'\'' .. rank .. '\'\')';
else
rank = '<code>' .. taxon_t.rank .. '</code> (displays as ' .. rank .. ')';
end
else
rank = '<span style="color:#d33">– a rank must be supplied</span>';
end
table.insert (out_t, rank);
local link;
if taxon_t.link then
local link_label;
local link_target;
if taxon_t.link:find ('Incertae sedis', 1, true) then
link_label = '\'\'incertae sedis\'\'';
link_target = 'Incertae sedis';
else
link_label = taxon:match ('([^/]+)/(.*)') or taxon; -- variant of Module:Autotaxobox l.stripExtra(taxon)
end
link_target = (link_target and link_target) or link_label; -- when no <link_target> make it same as <link_label>
if is_italic_taxon_t[taxon_t.rank] then
link_label = require('Module:TaxonItalics').italicizeTaxonName (link_label, false);
end
link = make_wikilink (link_target, link_label);
if taxon_t.extinct and (not link:find ('†', 1, true)) then
link = '<span style="font-style:normal;font-weight:normal;">†</span>' .. link;
end
if taxon:match ('/%?$') and not link:find ('?', 1, true) then
link = link .. '<span style="font-style:normal;font-weight:normal;"> (?)</span>'
end
link = '<code>' .. mw.text.nowiki (taxon_t.link) .. '</code> (displays as ' .. link .. ')';
end
table.insert (out_t, '\n|-\n|Link:\n|');
table.insert (out_t, (link and link) or '–');
local extinct = (taxon_t.extinct and '<code>true</code>') or 'no';
if not taxon.extinct and parent_t.extinct then
extinct = '<span style="background-color:#FCC">parent is marked as extinct</span>';
end
table.insert (out_t, '\n|-\n|Extinct:\n|');
table.insert (out_t, extinct);
table.insert (out_t, '\n|-\n|Always displayed:\n|');
table.insert (out_t, (taxon_t.always_display and '<code>true</code>') or ((is_always_displayed_t[taxon_t.rank] and 'yes (major rank)') or 'no'))
table.insert (out_t, '\n|-\n|Taxonomic references:\n|');
table.insert (out_t, taxon_t.refs or '–');
table.insert (out_t, '\n|-\n|Parent\'s taxonomic references:\n|');
table.insert (out_t, parent_t.refs or '–');
if same_as then
suffix = module_select (same_as);
table.insert (out_t, '\n|-\n|Same as taxon:\n|');
table.insert (out_t, '<code>' .. same_as .. '</code> [[[Module:Sandbox/trappist_the_monk/taxonomy ' .. suffix .. ']]]');
end
if taxon:find ('/skip$') then
suffix = module_select (taxon);
table.insert (out_t, '\n|-\n| colspan="2" | For the suffix "/skip", see [[Wikipedia:Automated_taxobox_system/advanced_taxonomy#Skip_taxonomy_templates|Skip taxonomy templates]].<br />');
table.insert (out_t, 'For the skipped taxa, see <code>' .. taxon:match ('([^/]+)/skip$') .. '</code> [[[Module:Sandbox/trappist_the_monk/taxonomy ' .. suffix .. ']]]');
end
if taxon:find ('/%?$') then
table.insert (out_t, '\n|-\n| colspan="2" | For the suffix "/?", see [[Wikipedia:Automated_taxobox_system/advanced_taxonomy#Questionable_assignments|Questionable assignments]].');
end
if taxon:find ('Incertae sedis') then
table.insert (out_t, '\n|-\n| colspan="2" |');
table.insert (out_t, 'For taxon names with "Incertae sedis", see [[Wikipedia:Automated_taxobox_system/advanced_taxonomy#Incertae_sedis_taxonomy_templates|\'\'Incertae sedis\'\' taxonomy templates]].');
end
table.insert (out_t, '\n|}');
return table.concat (out_t);
end
--[[--------------------------< W I K I D A T A _ G E T >------------------------------------------------------
]]
local TAXON_NAME_P = 'P225';
local TAXON_RANK_P = 'P105'
local TAXON_PARENT_P = 'P171';
local function wikidata_get (qid, prop)
local s_qid;
local wd_table = mw.wikibase.getBestStatements (qid, prop); -- attempt to get the taxon name
if 0 == #wd_table then
error ('no data for ' .. qid .. ' ' .. prop); -- some sort of better error handling needed
end
if wd_table[1]['mainsnak']['datavalue'] then
if 'string' == type (wd_table[1]['mainsnak']['datavalue']['value']) then
return wd_table[1]['mainsnak']['datavalue']['value']; -- return a string value; here for taxon name
end
if 'table' == type (wd_table[1]['mainsnak']['datavalue']['value']) then
s_qid = wd_table[1]['mainsnak']['datavalue']['value']['id']; -- extract the qid for taxon rank or [arent taxon]
return mw.wikibase.getLabelByLang (s_qid, 'en'), s_qid; -- return a string label and s_qid (used for parent); here for taxon rank and parent taxon
end
else
return '<span style="color:#d33">no value</span>';
end
end
--[[--------------------------< W I K I D A T A _ T E S T >----------------------------------------------------
this is an experimental function to see if I can figure out how to walk a taxotree in wikidata
]]
local function wikidata_test (taxon_qid)
-- local taxon_qid = frame.args[1]; -- qid for starting node in the taxotree
local out_t = {};
local taxon;
local rank;
local parent;
while taxon_qid do
taxon = wikidata_get (taxon_qid, TAXON_NAME_P);
rank = wikidata_get (taxon_qid, TAXON_RANK_P);
parent, taxon_qid = wikidata_get (taxon_qid, TAXON_PARENT_P);
table.insert (out_t, 1, rank .. ': ' .. taxon);
end
return table.concat (out_t, '<br />');
end
--[[--------------------------< C R A W L _ T R E E >----------------------------------------------------------
]]
local function crawl_tree (frame)
local tree_t = {};
local loaded = {};
-- tree_t = _crawl_tree (frame.args[1], tree_t, {}, {}); -- crawl the tree to get the debug taxon list of taxa and their ranks; empty tables not used here
tree_t = _crawl_tree ('Felis', tree_t, {}, {})
for module, v in pairs (modules_loaded) do -- make a sortable list
table.insert (loaded, module);
end
local function comp (a, b)
local letter_a, enum_a = a:match ('(%u)(%d*)$'); -- get letter and enumerator from 'taxonomy <letter><enum>'
local letter_b, enum_b = b:match ('(%u)(%d*)$');
enum_a = tonumber (enum_a); -- convert enumerators to number type if present; nil else
enum_b = tonumber (enum_b);
if (letter_a == letter_b) then -- when letters the same compare enumerators
if enum_a and enum_b then -- both must be enumerated (we don't do 'taxonomy 'P' and 'taxonomy P1')
return enum_a < enum_b;
end
end
return letter_a < letter_b; -- default compare letters
end
table.sort (loaded, comp);
for _, module in ipairs (loaded) do
mw.log (module .. ': ' .. modules_loaded[module]);
end
-- render crude tree and taxonomy list from Module:Autotaxobox for comparison
return '{|\n|-\n|' .. table.concat (tree_t, '<br />') .. ' || ' .. wikidata_test ('Q228283') .. ' || ' .. frame:callParserFunction ('#invoke', {'Autotaxobox/sandbox', 'taxonomyList', 'Felis'}) .. '\n|-\n|}';
-- return '{|\n|-\n|' .. table.concat (tree_t, '<br />') .. ' || ' .. wikidata_test (frame.args[1]) .. ' || ' .. frame:callParserFunction ('#invoke', {'Autotaxobox/sandbox', 'taxonomyList', frame.args[1]}) .. '\n|-\n|}';
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
test=test,
crawl_tree = crawl_tree,
make_tables = make_tables, -- interface function between Module:Autotaxobox taxonomyList() and _crawl_tree()
delete_taxon = delete_taxon,
show_taxon_data = show_taxon_data, -- similar to the table produced by Template:Taxonomy key
wikidata_test = crawl_tree,
taxomap_t = taxomap_t,
}