Module:Sidebar games events: Difference between revisions
Appearance
Content deleted Content added
No edit summary |
use require('strict') instead of require('Module:No globals') |
||
(46 intermediate revisions by 5 users not shown) | |||
Line 3: | Line 3: | ||
-- This module was created using code taken directly from [[Module:Sidebar]] |
-- This module was created using code taken directly from [[Module:Sidebar]] |
||
-- |
-- |
||
require(' |
require('strict') |
||
local p = {} |
local p = {} |
||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
local navbar = require('Module:Navbar')._navbar |
|||
local tracking, preview = {}, {} |
|||
local function checkargs(args) |
|||
for k, v in pairs(args) do |
|||
if v ~= '' then |
|||
if k and type(k) == 'string' then |
|||
if k == 'event' or k == 'games' or k == 'name' or k == 'image' or |
|||
k == 'imageright' or k =='caption' or k =='above' or |
|||
k == 'title' or k == 'alignresults' or k == 'alignevents' or |
|||
k == 'width' or k == 'maxwidth' or k == 'float' or |
|||
k == 'below' or k == 'prev' or k == 'next' then |
|||
-- valid |
|||
elseif k:match('^title%d+$') or k:match('^event%d+$') or |
|||
k:match('^image%d+$') or k:match('^type%d+[a-e]$') or |
|||
k:match('^event%d+%.%d+$') or |
|||
k:match('^results%d+%.%d+[a-e]?$') or |
|||
k:match('^border%d+%.%d+$') then |
|||
-- valid |
|||
elseif k == 'categories' or k == 'nocat' or k == 'demo' then |
|||
-- valid for doc page |
|||
else |
|||
-- invalid |
|||
local vlen = mw.ustring.len(k) |
|||
k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) |
|||
k = mw.ustring.gsub(k, '[^%w\-_ ]', '?') |
|||
table.insert(tracking, '[[Category:Pages using sidebar games events with unknown parameters|' .. k .. ']]') |
|||
table.insert(preview, '"' .. k .. '"') |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
function p.sidebar(frame, args) |
function p.sidebar(frame, args) |
||
if not args then |
if not args then |
||
args = getArgs(frame) |
args = getArgs(frame) |
||
end |
end |
||
local root = mw.html.create() |
local root = mw.html.create() |
||
root = root |
root = root |
||
:tag('table') |
:tag('table') |
||
:addClass(' |
:addClass('sidebar-games-events') |
||
:addClass(args.float == 'left' and 'sidebar-games-events-left' or nil) |
|||
:addClass('nowraplinks') |
|||
: |
:addClass(args.float == 'none' and 'sidebar-games-events-none' or nil) |
||
:addClass('sidebar') |
|||
:css('clear', (args.float == 'none' and 'both') or args.float or 'right') |
|||
:addClass('nomobile') |
|||
:css('width', args.width or 'auto') |
|||
:css(' |
:css('width', args.width or nil) |
||
:css(' |
:css('max-width', args.maxwidth or nil) |
||
:css('border', '1px solid #B8C7D9') |
|||
:css('padding', '0.2em') |
|||
:css('border-spacing', '0.4em 0') |
|||
:css('text-align', 'center') |
|||
:css('font-size', '88%') |
|||
-- enumerate the rows and count the columns |
-- enumerate the rows and count the columns |
||
local cols = 1 |
local cols = 1 |
||
local colindex = {a = '2', b = '3', c = '4'} |
local colindex = {a = '2', b = '3', c = '4', d = '5', e = '6'} |
||
local lets = {'a', 'b', 'c'} |
local lets = {'a', 'b', 'c', 'd', 'e'} |
||
local rowNums = {} |
local rowNums = {} |
||
local subevents = 0 |
local subevents = 0 |
||
Line 42: | Line 70: | ||
for k, v in pairs(args) do |
for k, v in pairs(args) do |
||
k = '' .. k |
k = '' .. k |
||
-- find rows |
|||
local num = k:match('^event(%d+)$') |
local num = k:match('^event(%d+)$') |
||
or k:match('^image(%d+)$') |
or k:match('^image(%d+)$') |
||
or k:match('^ |
or k:match('^title(%d+)$') |
||
or k:match('^type(%d+)[a-e]$') |
|||
or k:match('^event(%d+)%.%d+$') |
or k:match('^event(%d+)%.%d+$') |
||
or k:match('^results(%d+)%.%d+[a- |
or k:match('^results(%d+)%.%d+[a-e]?$') |
||
if num then table.insert(rowNums, tonumber(num)) end |
if num then table.insert(rowNums, tonumber(num)) end |
||
-- find number of columns |
|||
local let = k:match('^results%d+%.%d+([a-c])$') |
|||
if k:match('^results%d+%.(%d+)$') then |
|||
cols = (2 > cols) and 2 or cols |
|||
end |
|||
-- find number of columns based on let(s) |
|||
local let = k:match('^results%d+%.%d+([a-e])$') |
|||
or k:match('^type%d+([a-e])$') |
|||
if let and colindex[let] then |
if let and colindex[let] then |
||
local n = tonumber(colindex[let]) |
local n = tonumber(colindex[let]) |
||
Line 56: | Line 93: | ||
end |
end |
||
-- find subevents |
|||
local subnum = k:match('^results%d+%.(%d+)[a-c]$') |
|||
local subnum = k:match('^results%d+%.(%d+)[a-e]?$') |
|||
or k:match('^event%d+%.(%d+)$') |
or k:match('^event%d+%.(%d+)$') |
||
if subnum then |
if subnum then |
||
Line 63: | Line 101: | ||
end |
end |
||
-- identify events (that match looks awfully similar to subevents) |
|||
if k:match('^(event%d+%.%d+)$') then |
if k:match('^(event%d+%.%d+)$') then |
||
hasevents = true |
hasevents = true |
||
Line 73: | Line 112: | ||
table.remove(rowNums, i) |
table.remove(rowNums, i) |
||
end |
end |
||
end |
|||
-- alignment |
|||
local alignevents = nil |
|||
if args.alignevents and args.alignevents == 'right' then |
|||
alignevents = 'event-r' |
|||
end |
|||
local alignresults = nil |
|||
if args.alignresults and args.alignresults == 'right' then |
|||
alignresults = 'result-r' |
|||
elseif args.alignresults and args.alignresults == 'left' then |
|||
alignresults = 'result-l' |
|||
end |
end |
||
-- add the top level header |
-- add the top level header |
||
if args.event then |
if args.event or args.title then |
||
local t = args.event |
local t = args.event |
||
if args. |
if args.title then |
||
t = args.title |
|||
elseif args.games then |
|||
t = '[[' .. args.event .. ' at the ' .. args.games .. '|' .. args.event .. ']]' |
t = '[[' .. args.event .. ' at the ' .. args.games .. '|' .. args.event .. ']]' |
||
.. ' at the<br>' .. '[[' .. args.games .. ']]' |
|||
end |
|||
local cell = root:tag('tr'):tag('th') |
|||
cell |
|||
:addClass('sidebar-games-events-title') |
|||
:attr('colspan', cols) |
|||
if args.imageright then |
|||
local d = cell:tag('div') |
|||
:addClass('sidebar-games-events-ir-cont') |
|||
d:tag('div') |
|||
:addClass('sidebar-games-events-ir-title') |
|||
:wikitext(t) |
|||
d:tag('div') |
|||
:addClass('sidebar-games-events-ir') |
|||
:wikitext(args.imageright) |
|||
else |
|||
cell:wikitext(t) |
|||
end |
end |
||
root |
|||
:tag('tr') |
|||
:tag('th') |
|||
:css('padding', '0.2em 0.4em 0.2em') |
|||
:css('font-size', '100%') |
|||
:css('line-height', '1.5em') |
|||
:css('background', '#cedff2') |
|||
:attr('colspan', cols) |
|||
:wikitext(t) |
|||
end |
end |
||
Line 97: | Line 157: | ||
imageCell |
imageCell |
||
:addClass('sidebar-games-events-image') |
|||
:css('padding', '0 0 0.2em') |
|||
:css('background', '#cedff2') |
|||
:attr('colspan', cols) |
:attr('colspan', cols) |
||
:wikitext(args.image) |
:wikitext(args.image) |
||
if args.caption then |
if args.caption then |
||
imageCell |
imageCell |
||
:tag('div') |
:tag('div') |
||
: |
:addClass('sidebar-games-events-caption') |
||
:css('line-height', '1.2em') |
|||
:wikitext(args.caption) |
:wikitext(args.caption) |
||
end |
end |
||
Line 112: | Line 169: | ||
if args.above then |
if args.above then |
||
local cell root:tag('tr'):tag('td') |
local cell = root:tag('tr'):tag('td') |
||
cell:attr('colspan', cols) |
cell:attr('colspan', cols) |
||
:wikitext(args.above) |
:wikitext(args.above) |
||
Line 122: | Line 179: | ||
local event = args['event' .. num] |
local event = args['event' .. num] |
||
local image = args['image' .. num] |
local image = args['image' .. num] |
||
local title = args['title' .. num] |
|||
if title then |
|||
root:tag('tr') |
|||
:tag('th') |
|||
:addClass('event-title') |
|||
:attr('colspan', cols) |
|||
:wikitext(title) |
|||
end |
|||
if event and image then |
if event and image then |
||
heading = event .. '<br>' .. image |
heading = event .. '<br>' .. image |
||
Line 134: | Line 200: | ||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
: |
:addClass('sidebar-games-events-heading') |
||
:css('background', '#deeaf6') |
|||
:css('border-top', '1px solid #f5faff') |
|||
:attr('colspan', cols) |
:attr('colspan', cols) |
||
:wikitext(heading) |
:wikitext(heading) |
||
Line 151: | Line 215: | ||
if showtypes == true then |
if showtypes == true then |
||
local row = root:tag('tr') |
local row = root:tag('tr') |
||
row:tag('th'): |
row:tag('th'):addClass((hasevents == false) and 'no-event' or nil) |
||
for j, let in ipairs(lets) do |
for j, let in ipairs(lets) do |
||
if j < cols then |
if j < cols then |
||
Line 158: | Line 222: | ||
if t then |
if t then |
||
cell |
cell |
||
: |
:addClass('type-let') |
||
:css(' |
:css('width', (cols > 2) and tostring(math.floor(100/(cols-1))) .. '%' or nil) |
||
:css('background', '#deeaf6') |
|||
:wikitext(t) |
:wikitext(t) |
||
end |
end |
||
Line 169: | Line 232: | ||
for k=1,subevents do |
for k=1,subevents do |
||
local hasresults = false |
local hasresults = false |
||
if args['results' .. num .. '.' .. k] then |
|||
for j, let in ipairs(lets) do |
|||
hasresults = true |
|||
else |
|||
if args['results' .. num .. '.' .. k .. let] then |
|||
for j, let in ipairs(lets) do |
|||
hasresults = true |
|||
if j < cols then |
|||
if args['results' .. num .. '.' .. k .. let] then |
|||
hasresults = true |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 179: | Line 246: | ||
if hasresults then |
if hasresults then |
||
local row = root:tag('tr') |
local row = root:tag('tr') |
||
local cell = row:tag('th'): |
local cell = row:tag('th'):addClass((hasevents == false) and 'no-event' or nil) |
||
local t = args['event' .. num .. '.' .. k] |
local t = args['event' .. num .. '.' .. k] |
||
local border = args['border' .. num .. '.' .. k] and ' |
local border = args['border' .. num .. '.' .. k] and 'erl-border' or nil |
||
if t then |
if t then |
||
cell |
cell |
||
: |
:addClass('event') |
||
: |
:addClass(alignevents) |
||
:addClass(border) |
|||
:css('padding', '0.1em 0.4em 0.2em 0.1em') |
|||
:css('font-weight', 'normal') |
|||
:css('border-bottom', border) |
|||
:wikitext(t) |
:wikitext(t) |
||
end |
end |
||
if args['results' .. num .. '.' .. k] then |
|||
for j, let in ipairs(lets) do |
|||
row:tag('td') |
|||
:addClass(border) |
|||
t = args['results' .. num .. '.' .. k .. let] |
|||
:addClass(alignresults) |
|||
: |
:attr('colspan', cols - 1) |
||
: |
:wikitext(args['results' .. num .. '.' .. k]) |
||
else |
|||
for j, let in ipairs(lets) do |
|||
if j < cols then |
|||
t = args['results' .. num .. '.' .. k .. let] |
|||
row:tag('td') |
|||
:addClass(border) |
|||
:addClass(alignresults) |
|||
:wikitext(t) |
|||
end |
|||
end |
end |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
|||
if args.below then |
|||
root |
|||
:tag('tr') |
|||
:tag('td') |
|||
:addClass(args.belowclass) |
|||
:attr('colspan', cols) |
|||
:cssText(args.belowstyle) |
|||
:wikitext(args.below) |
|||
end |
end |
||
if args.prev or args.next then |
|||
local row = root:tag('tr'):tag('td') |
|||
if navbarArg ~= 'none' and navbarArg ~= 'off' and (args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar games events') then |
|||
:addClass('sidebar-games-events-prevnext') |
|||
:attr('colspan', cols) |
|||
:tag('div') |
|||
row:tag('div') |
|||
:addClass('sidebar-games-events-prev') |
|||
:wikitext(args.prev) |
|||
row:tag('div') |
|||
:addClass('sidebar-games-events-next') |
|||
:wikitext(args.next) |
|||
end |
|||
if args.navbar ~= 'none' and args.navbar ~= 'off' and |
|||
(args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar games events') then |
|||
root |
root |
||
:tag('tr') |
:tag('tr') |
||
:tag('td') |
:tag('td') |
||
: |
:addClass('sidebar-games-events-navbar') |
||
:css('font-size', '115%') |
|||
:css('padding-top', '0') |
|||
:css('border-top', 'solid 1px #deeaf6') |
|||
:attr('colspan', cols) |
:attr('colspan', cols) |
||
:wikitext( |
:wikitext(require('Module:Navbar')._navbar{ |
||
args.name, |
args.name, |
||
mini = 1, |
mini = 1, |
||
fontstyle = args.navbarfontstyle |
fontstyle = args.navbarfontstyle |
||
}) |
}) |
||
end |
end |
||
if mw.title.getCurrentTitle().namespace == 10 and (args.name ~= mw.title.getCurrentTitle().text) and not (mw.title.getCurrentTitle().text:match('Sidebar games events')) then |
|||
root:wikitext("[[Category:Templates using sidebar games events without correct name]]") |
|||
end |
|||
checkargs(args) |
|||
local trackstr = (#tracking > 0) and table.concat(tracking, '') or '' |
|||
return tostring(root) |
|||
if #preview > 0 then |
|||
end |
|||
trackstr = require('Module:If preview')._warning({ |
|||
'Unknown parameters ' .. table.concat(preview, '; ') .. '.' |
|||
}) .. trackstr |
|||
end |
|||
return mw.getCurrentFrame():extensionTag{ |
|||
name = 'templatestyles', args = { src = 'Module:Sidebar games events/styles.css' } |
|||
} .. tostring(root) .. trackstr |
|||
end |
|||
return p |
return p |
Latest revision as of 21:24, 21 October 2022
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module depends on the following other modules: |
This module uses TemplateStyles: |
This module implements template {{Sidebar games events}}.
--
-- This module implements {{Sidebar games events}}
-- This module was created using code taken directly from [[Module:Sidebar]]
--
require('strict')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local tracking, preview = {}, {}
local function checkargs(args)
for k, v in pairs(args) do
if v ~= '' then
if k and type(k) == 'string' then
if k == 'event' or k == 'games' or k == 'name' or k == 'image' or
k == 'imageright' or k =='caption' or k =='above' or
k == 'title' or k == 'alignresults' or k == 'alignevents' or
k == 'width' or k == 'maxwidth' or k == 'float' or
k == 'below' or k == 'prev' or k == 'next' then
-- valid
elseif k:match('^title%d+$') or k:match('^event%d+$') or
k:match('^image%d+$') or k:match('^type%d+[a-e]$') or
k:match('^event%d+%.%d+$') or
k:match('^results%d+%.%d+[a-e]?$') or
k:match('^border%d+%.%d+$') then
-- valid
elseif k == 'categories' or k == 'nocat' or k == 'demo' then
-- valid for doc page
else
-- invalid
local vlen = mw.ustring.len(k)
k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25)
k = mw.ustring.gsub(k, '[^%w\-_ ]', '?')
table.insert(tracking, '[[Category:Pages using sidebar games events with unknown parameters|' .. k .. ']]')
table.insert(preview, '"' .. k .. '"')
end
end
end
end
end
function p.sidebar(frame, args)
if not args then
args = getArgs(frame)
end
local root = mw.html.create()
root = root
:tag('table')
:addClass('sidebar-games-events')
:addClass(args.float == 'left' and 'sidebar-games-events-left' or nil)
:addClass(args.float == 'none' and 'sidebar-games-events-none' or nil)
:addClass('sidebar')
:addClass('nomobile')
:css('width', args.width or nil)
:css('max-width', args.maxwidth or nil)
-- enumerate the rows and count the columns
local cols = 1
local colindex = {a = '2', b = '3', c = '4', d = '5', e = '6'}
local lets = {'a', 'b', 'c', 'd', 'e'}
local rowNums = {}
local subevents = 0
local hasevents = false
for k, v in pairs(args) do
k = '' .. k
-- find rows
local num = k:match('^event(%d+)$')
or k:match('^image(%d+)$')
or k:match('^title(%d+)$')
or k:match('^type(%d+)[a-e]$')
or k:match('^event(%d+)%.%d+$')
or k:match('^results(%d+)%.%d+[a-e]?$')
if num then table.insert(rowNums, tonumber(num)) end
-- find number of columns
if k:match('^results%d+%.(%d+)$') then
cols = (2 > cols) and 2 or cols
end
-- find number of columns based on let(s)
local let = k:match('^results%d+%.%d+([a-e])$')
or k:match('^type%d+([a-e])$')
if let and colindex[let] then
local n = tonumber(colindex[let])
cols = (n > cols) and n or cols
end
-- find subevents
local subnum = k:match('^results%d+%.(%d+)[a-e]?$')
or k:match('^event%d+%.(%d+)$')
if subnum then
subnum = tonumber(subnum)
subevents = (subnum > subevents) and subnum or subevents
end
-- identify events (that match looks awfully similar to subevents)
if k:match('^(event%d+%.%d+)$') then
hasevents = true
end
end
-- remove duplicates from the list (e.g. 3 will be duplicated if both event3 and image3 are specified)
table.sort(rowNums)
for i = #rowNums, 1, -1 do
if rowNums[i] == rowNums[i - 1] then
table.remove(rowNums, i)
end
end
-- alignment
local alignevents = nil
if args.alignevents and args.alignevents == 'right' then
alignevents = 'event-r'
end
local alignresults = nil
if args.alignresults and args.alignresults == 'right' then
alignresults = 'result-r'
elseif args.alignresults and args.alignresults == 'left' then
alignresults = 'result-l'
end
-- add the top level header
if args.event or args.title then
local t = args.event
if args.title then
t = args.title
elseif args.games then
t = '[[' .. args.event .. ' at the ' .. args.games .. '|' .. args.event .. ']]'
.. ' at the<br>' .. '[[' .. args.games .. ']]'
end
local cell = root:tag('tr'):tag('th')
cell
:addClass('sidebar-games-events-title')
:attr('colspan', cols)
if args.imageright then
local d = cell:tag('div')
:addClass('sidebar-games-events-ir-cont')
d:tag('div')
:addClass('sidebar-games-events-ir-title')
:wikitext(t)
d:tag('div')
:addClass('sidebar-games-events-ir')
:wikitext(args.imageright)
else
cell:wikitext(t)
end
end
if args.image then
local imageCell = root:tag('tr'):tag('td')
imageCell
:addClass('sidebar-games-events-image')
:attr('colspan', cols)
:wikitext(args.image)
if args.caption then
imageCell
:tag('div')
:addClass('sidebar-games-events-caption')
:wikitext(args.caption)
end
end
if args.above then
local cell = root:tag('tr'):tag('td')
cell:attr('colspan', cols)
:wikitext(args.above)
end
-- start adding rows
for i, num in ipairs(rowNums) do
local heading = nil
local event = args['event' .. num]
local image = args['image' .. num]
local title = args['title' .. num]
if title then
root:tag('tr')
:tag('th')
:addClass('event-title')
:attr('colspan', cols)
:wikitext(title)
end
if event and image then
heading = event .. '<br>' .. image
elseif event then
heading = event
elseif image then
heading = image
end
if heading then
root
:tag('tr')
:tag('th')
:addClass('sidebar-games-events-heading')
:attr('colspan', cols)
:wikitext(heading)
end
local showtypes = false
for j, let in ipairs(lets) do
if j < cols then
if args['type' .. num .. let] then
showtypes = true
end
end
end
if showtypes == true then
local row = root:tag('tr')
row:tag('th'):addClass((hasevents == false) and 'no-event' or nil)
for j, let in ipairs(lets) do
if j < cols then
local t = args['type' .. num .. let]
local cell = row:tag('th')
if t then
cell
:addClass('type-let')
:css('width', (cols > 2) and tostring(math.floor(100/(cols-1))) .. '%' or nil)
:wikitext(t)
end
end
end
end
for k=1,subevents do
local hasresults = false
if args['results' .. num .. '.' .. k] then
hasresults = true
else
for j, let in ipairs(lets) do
if j < cols then
if args['results' .. num .. '.' .. k .. let] then
hasresults = true
end
end
end
end
if hasresults then
local row = root:tag('tr')
local cell = row:tag('th'):addClass((hasevents == false) and 'no-event' or nil)
local t = args['event' .. num .. '.' .. k]
local border = args['border' .. num .. '.' .. k] and 'erl-border' or nil
if t then
cell
:addClass('event')
:addClass(alignevents)
:addClass(border)
:wikitext(t)
end
if args['results' .. num .. '.' .. k] then
row:tag('td')
:addClass(border)
:addClass(alignresults)
:attr('colspan', cols - 1)
:wikitext(args['results' .. num .. '.' .. k])
else
for j, let in ipairs(lets) do
if j < cols then
t = args['results' .. num .. '.' .. k .. let]
row:tag('td')
:addClass(border)
:addClass(alignresults)
:wikitext(t)
end
end
end
end
end
end
if args.below then
root
:tag('tr')
:tag('td')
:addClass(args.belowclass)
:attr('colspan', cols)
:cssText(args.belowstyle)
:wikitext(args.below)
end
if args.prev or args.next then
local row = root:tag('tr'):tag('td')
:addClass('sidebar-games-events-prevnext')
:attr('colspan', cols)
:tag('div')
row:tag('div')
:addClass('sidebar-games-events-prev')
:wikitext(args.prev)
row:tag('div')
:addClass('sidebar-games-events-next')
:wikitext(args.next)
end
if args.navbar ~= 'none' and args.navbar ~= 'off' and
(args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar games events') then
root
:tag('tr')
:tag('td')
:addClass('sidebar-games-events-navbar')
:attr('colspan', cols)
:wikitext(require('Module:Navbar')._navbar{
args.name,
mini = 1,
fontstyle = args.navbarfontstyle
})
end
if mw.title.getCurrentTitle().namespace == 10 and (args.name ~= mw.title.getCurrentTitle().text) and not (mw.title.getCurrentTitle().text:match('Sidebar games events')) then
root:wikitext("[[Category:Templates using sidebar games events without correct name]]")
end
checkargs(args)
local trackstr = (#tracking > 0) and table.concat(tracking, '') or ''
if #preview > 0 then
trackstr = require('Module:If preview')._warning({
'Unknown parameters ' .. table.concat(preview, '; ') .. '.'
}) .. trackstr
end
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Sidebar games events/styles.css' }
} .. tostring(root) .. trackstr
end
return p