Jump to content

Module:Xeno-canto version

From WhiskerWiki

Documentation for this module may be created at Module:Xeno-canto version/doc

-- Module:Xeno-canto version
--[[
Renders WhiskerWiki's xeno-canto coverage card from JSON:Xeno-canto_provenance,
which the R pipeline writes from scripts/02_species.R (the point where
xeno-canto's species list is matched against WhiskerWiki's species roster).

  p.infobox  the card (Template:Xeno-canto version box)
  p.data     the parsed JSON, for other modules
  p.field    one top-level JSON value, e.g. {{#invoke:Xeno-canto version|field|last_updated}}

"Xeno-canto species/recordings" are xeno-canto's counts for WhiskerWiki's
focal orders worldwide (the JSON's "scope"), not every land mammal.

Ported from HopperWiki's Module:Xeno-canto version. Uses the shared .ib-h card
classes in MediaWiki:Common.css, plus the xc-* rules there.
--]]
local json = require("Module:JSON pipeline")
local p    = {}

local PAGE = "JSON:Xeno-canto_provenance"

local function fmt_number(n)
    n = tonumber(n)
    if not n then return "—" end
    local s = tostring(math.floor(n + 0.5)):reverse():gsub("(%d%d%d)", "%1,"):reverse():gsub("^,", "")
    return s   -- one value only: gsub's second return (the match count) would leak into callers' argument lists
end

local function cell(label, value)
    return string.format(
        '<div class="ib-h-cell"><div class="ib-h-label">%s</div><div class="ib-h-value">%s</div></div>',
        label, value
    )
end

function p.infobox(frame)
    local data, err = json.load(PAGE)
    if not data then
        return '<span class="error">Xeno-canto version data unavailable: ' .. tostring(err) .. '</span>'
    end

    local counts     = type(data.record_counts) == "table" and data.record_counts or {}
    local source     = data.source       or "xeno-canto"
    local source_url = data.source_url   or ""
    local updated    = data.last_updated or "unknown"

    local source_link = source_url ~= ""
        and string.format('[%s %s]', source_url, source)
        or source

    local header = string.format(
        '<div class="ib-h-header">' ..
            '<span class="ib-h-badge">XC</span>' ..
            '<span class="xc-title">WhiskerWiki\'s xeno-canto coverage</span>' ..
            '<span class="xc-source">%s</span>' ..
        '</div>',
        source_link
    )

    local linked = fmt_number(counts.linked_species)
    if counts.total_whiskerwiki_species then
        linked = linked .. ' <span class="xc-of">of ' .. fmt_number(counts.total_whiskerwiki_species) .. '</span>'
    end

    local cells = table.concat({
        cell("Last updated",          mw.text.encode(updated)),
        cell("Species linked",        linked),
        cell("Xeno-canto species",    fmt_number(counts.xc_species_available)),
        cell("Xeno-canto recordings", fmt_number(counts.xc_recordings_available)),
    })

    local scope_html = data.scope
        and string.format('<div class="xc-scope">Xeno-canto counts cover %s worldwide.</div>', mw.text.encode(data.scope))
        or ""

    local html = string.format(
        '<div class="ib-h xc-version-box">' ..
            '%s' ..
            '<div class="ib-h-cells ib-h-cols-4">%s</div>' ..
            '%s' ..
        '</div>',
        header, cells, scope_html
    )

    return frame:preprocess(html)
end

function p.data()
    return json.load(PAGE)
end

function p.field(frame)
    local args = frame.args or frame
    local key  = args[1] or args.key
    if not key then return "" end
    local data = json.load(PAGE)
    if not data then return "" end
    return tostring(data[key] or "")
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.