Mô đun:Status
Mô đun này được đánh giá là trong giai đoạn beta, và đã sẵn sàng để sử dụng rộng rãi. Nó vẫn còn mới và nên được sử dụng một cách thận trọng để đảm bảo đạt được kết quả như mong đợi. |
Mô đun này phụ thuộc vào các mô đun sau: |
Mô đun triển khai bản mẫu {{status}}. Xem tài liệu về cách sử dụng tại {{status}}.
-- This module implements {{status}}
-- Initialise necessary modules
local Object = require('Module:Classic')
local CountVotes = require('Module:CountVotes')._main
local yesno = require('Module:Yesno')
-- Lazily initialise modules and objects we don't always need
local lang
-- Set constants
local CONFIG_MODULE = 'Module:Status/config'
local LINE_FEED = '
'
--------------------------------------------------------------------------------
-- Helper class
--------------------------------------------------------------------------------
local Helper = Object:extend()
function Helper:validateDate(dateString)
lang = lang or mw.language.getContentLanguage()
local success, result = pcall(lang.formatDate, lang, 'U', dateString)
if success then
result = tonumber(result)
if result then
return true
end
end
error(string.format('ngày tháng không hợp lệ: %s', tostring(dateString)))
end
function Helper:isUnixTime(dateString)
local success, result = pcall(os.date, '!%Y-%m-%dT%TZ', dateString)
if success then
return true
end
return false
end
function Helper:formatDate(dateString, format)
lang = lang or mw.language.getContentLanguage()
if Helper:isUnixTime(dateString) then
if format == 'U' then
return dateString
end
return lang:formatDate(format, os.date('!%Y-%m-%dT%TZ', dateString))
end
if Helper:validateDate(dateString) then
return lang:formatDate(format, dateString)
end
end
function Helper:substParams(msg, params)
return msg:gsub('${(%u+)}', params)
end
function Helper:dayToSecond(dayNumber)
return tonumber(dayNumber) * 24 * 3600
end
function Helper:breakLines(title)
return title:gsub('%. ', '. ' .. LINE_FEED) -- Phải dùng bản mẫu trung gian để escape
end
function Helper:countdown(duration)
return string.format(
'%s ngày %s giờ %s phút %s giây',
duration.days or 0,
duration.hours or 0,
duration.minutes or 0,
duration.seconds or 0
)
end
function Helper:votesNumberTitle(positiveVotesNumber, negativeVotesNumber)
return string.format(
' ' .. LINE_FEED .. 'Số phiếu thuận là %s. '
.. LINE_FEED .. 'Số phiếu chống là %s.',
positiveVotesNumber,
negativeVotesNumber
)
end
--------------------------------------------------------------------------------
-- Status class
--------------------------------------------------------------------------------
local Status = Object:extend()
function Status:new(...)
local args, cfg = unpack({...})
-- Set cfg
self.cfg = cfg
-- Set startTime
if args[1] then args.start = args[1] end -- Tương thích ngược phiên bản cũ
if args.start and mw.text.trim(args.start) ~= '' then
self.startTime = tonumber(Helper:formatDate(args.start, 'U'))
else
error('phải có tham số start và start không được rỗng')
end
-- Set maxTime
self.maxTime = self:_getMaxTime(...)
end
function Status:_getMaxTime(...)
local args, cfg, title = unpack({...})
if args[2] then args.max = args[2] end -- Tương thích ngược phiên bản cũ
if title then
return self.startTime + Helper:dayToSecond(tonumber(args.max)
or (cfg.rootTitles[title.rootText] or {}).max or cfg.DEFAULT_MAX)
end
return self.startTime + Helper:dayToSecond(tonumber(args.max) or cfg.DEFAULT_MAX)
end
function Status:_getMinTime(...)
local _, cfg, title = unpack({...})
return self.startTime + Helper:dayToSecond((cfg.rootTitles[title.rootText] or {}).min or cfg.DEFAULT_MIN)
end
function Status:_getConsiderExtensionTime(...)
local _, cfg, title = unpack({...})
return self.startTime + Helper:dayToSecond((cfg.rootTitles[title.rootText] or {}).considerExtension
or cfg.DEFAULT_CONSIDER_EXTENSION)
end
function Status:_getExtendedTime(...)
local _, cfg, title = unpack({...})
return self.startTime + Helper:dayToSecond((cfg.rootTitles[title.rootText] or {}).extended
or cfg.DEFAULT_EXTENDED)
end
function Status:_getInfo()
local statusName, titleIndex
local now = os.time()
if now <= self.maxTime then
statusName, titleIndex = 'VALID', 1
else
statusName, titleIndex = 'INVALID', 1
end
return statusName, titleIndex
end
function Status:_getParams()
lang = lang or mw.language.getContentLanguage()
local now = os.time()
local params = {}
params.MAXTIME = Helper:formatDate(self.maxTime, 'H:i:s d-m-Y')
params.COUNTDOWNTOMAXTIME = Helper:countdown(lang:getDurationIntervals(self.maxTime - now))
if self.minTime then
params.MINTIME = Helper:formatDate(self.minTime, 'H:i:s d-m-Y')
params.COUNTDOWNTOMINTIME = Helper:countdown(lang:getDurationIntervals(self.minTime - now))
end
if self.extendedTime then
params.EXTENDEDTIME = Helper:formatDate(self.extendedTime, 'H:i:s d-m-Y')
params.COUNTDOWNTOEXTENDEDTIME = Helper:countdown(lang:getDurationIntervals(self.extendedTime - now))
end
return params
end
-- Cung cấp giá trị tham số title và background
-- cho bản mẫu trung gian Status/core
function Status:getValues()
local statusName, titleIndex = self:_getInfo()
local title = Helper:breakLines(Helper:substParams(
self.cfg.statuses[statusName].titles[titleIndex], self:_getParams()))
local votesNumberTitle = ''
if self.positiveVotesNumber and self.negativeVotesNumber then
votesNumberTitle = Helper:votesNumberTitle(self.positiveVotesNumber, self.negativeVotesNumber)
end
local background = self.cfg.statuses[statusName].background
return {title = title .. votesNumberTitle, background = background}
end
--------------------------------------------------------------------------------
-- StatusWithMinTime class extends Status class
--------------------------------------------------------------------------------
local StatusWithMinTime = Status:extend()
function StatusWithMinTime:new(...)
StatusWithMinTime.super.new(self, ...)
local _, cfg, title = unpack({...})
-- Set minTime
self.minTime = self:_getMinTime(...)
-- Set positiveVotesNumber & negativeVotesNumber
self.positiveVotesNumber, self.negativeVotesNumber = CountVotes(title)
-- Set checkSuccessConclusionFunc
self.checkSuccessConclusionFunc = (cfg.rootTitles[title.rootText] or {}).checkSuccessConclusionFunc
end
function StatusWithMinTime:_getInfo()
local statusName, titleIndex
local now = os.time()
if now <= self.minTime then
statusName, titleIndex = 'VALID', 2
elseif self.minTime < now and now <= self.maxTime then
if not self.checkSuccessConclusionFunc(self.positiveVotesNumber, self.negativeVotesNumber) then
statusName, titleIndex = 'VALID', 3
else
statusName, titleIndex = 'VALID_AND_MAY_BE_CONSIDERED_CLOSED', 1
end
else
statusName, titleIndex = 'INVALID', 2
end
return statusName, titleIndex
end
--------------------------------------------------------------------------------
-- StatusWithExtendedTime class extends Status class
--------------------------------------------------------------------------------
local StatusWithExtendedTime = Status:extend()
function StatusWithExtendedTime:new(...)
StatusWithExtendedTime.super.new(self, ...)
local args, cfg, title = unpack({...})
-- Set considerExtensionTime
self.considerExtensionTime = self:_getConsiderExtensionTime(...)
-- Set extendedTime
self.extendedTime = self:_getExtendedTime(...)
-- Set positiveVotesNumber & negativeVotesNumber
self.positiveVotesNumber, self.negativeVotesNumber = CountVotes(title)
-- Set checkValidExtensionFunc
self.checkValidExtensionFunc = (cfg.rootTitles[title.rootText] or {}).checkValidExtensionFunc
-- Set extend
self.extend = yesno(args.extend) or false
end
function StatusWithExtendedTime:_getInfo()
local statusName, titleIndex
local now = os.time()
if now <= self.considerExtensionTime then
statusName, titleIndex = 'VALID', 1
elseif self.considerExtensionTime < now and now <= self.maxTime then
if not self.checkValidExtensionFunc(self.positiveVotesNumber, self.negativeVotesNumber) then
statusName, titleIndex = 'VALID', 4
elseif not self.extend then
statusName, titleIndex = 'VALID_AND_MAY_CONSIDER_EXTENSION', 1
else
statusName, titleIndex = 'VALID_AND_HAS_BEEN_EXTENDED', 1
end
elseif now <= self.extendedTime and self.extend then
statusName, titleIndex = 'VALID_AND_IS_BEING_EXTENDED', 1
elseif now > self.extendedTime and self.extend then
statusName, titleIndex = 'INVALID', 3
else
statusName, titleIndex = 'INVALID', 1
end
return statusName, titleIndex
end
--------------------------------------------------------------------------------
-- StatusWithMinTimeAndExtendedTime class extends Status class
--------------------------------------------------------------------------------
local StatusWithMinTimeAndExtendedTime = Status:extend()
function StatusWithMinTimeAndExtendedTime:new(...)
StatusWithMinTimeAndExtendedTime.super.new(self, ...)
local args, cfg, title = unpack({...})
-- Set minTime
self.minTime = self:_getMinTime(...)
-- Set considerExtensionTime
self.considerExtensionTime = self:_getConsiderExtensionTime(...)
-- Set extendedTime
self.extendedTime = self:_getExtendedTime(...)
-- Set positiveVotesNumber & negativeVotesNumber
self.positiveVotesNumber, self.negativeVotesNumber = CountVotes(title)
-- Set checkSuccessConclusionFunc
self.checkSuccessConclusionFunc = (cfg.rootTitles[title.rootText] or {}).checkSuccessConclusionFunc
-- Set checkValidExtensionFunc
self.checkValidExtensionFunc = (cfg.rootTitles[title.rootText] or {}).checkValidExtensionFunc
-- Set extend
self.extend = yesno(args.extend) or false
end
function StatusWithMinTimeAndExtendedTime:_getInfo()
local statusName, titleIndex
local now = os.time()
statusName, titleIndex = 'VALID', 1
if now <= self.minTime then
statusName, titleIndex = 'VALID', 2
elseif self.minTime < now and now <= self.considerExtensionTime then
if not self.checkSuccessConclusionFunc(self.positiveVotesNumber, self.negativeVotesNumber) then
statusName, titleIndex = 'VALID', 3
else
statusName, titleIndex = 'VALID_AND_MAY_BE_CONSIDERED_CLOSED', 1
end
elseif self.considerExtensionTime < now and now <= self.maxTime then
if (not self.checkValidExtensionFunc(self.positiveVotesNumber, self.negativeVotesNumber))
and (not self.checkSuccessConclusionFunc(self.positiveVotesNumber, self.negativeVotesNumber))
then
statusName, titleIndex = 'VALID', 5
elseif not self.checkValidExtensionFunc(self.positiveVotesNumber, self.negativeVotesNumber) then
statusName, titleIndex = 'VALID_AND_MAY_BE_CONSIDERED_CLOSED', 1
elseif not self.extend then
statusName, titleIndex = 'VALID_AND_MAY_CONSIDER_EXTENSION', 2
else
statusName, titleIndex = 'VALID_AND_HAS_BEEN_EXTENDED', 2
end
elseif now <= self.extendedTime and self.extend then
statusName, titleIndex = 'VALID_AND_IS_BEING_EXTENDED', 1
elseif now > self.extendedTime and self.extend then
statusName, titleIndex = 'INVALID', 3
else
statusName, titleIndex = 'INVALID', 2
end
return statusName, titleIndex
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- This is used for testing purposes.
return {
Status = Status,
StatusWithMinTime = StatusWithMinTime,
StatusWithExtendedTime = StatusWithExtendedTime,
StatusWithMinTimeAndExtendedTime = StatusWithMinTimeAndExtendedTime,
}
end
function p._main(args, cfg)
args = args or {}
cfg = cfg or require(CONFIG_MODULE)
local statusObj = {}
if args.id then
if mw.text.trim(args.id) ~= '' then
local title = {}
if tonumber(args.id) then
title = mw.title.new(tonumber(args.id))
else
title = mw.title.new(args.id)
end
local group = (cfg.rootTitles[title.rootText] or {}).group
if group == 1 then
statusObj = StatusWithMinTime(args, cfg, title)
elseif group == 2 then
statusObj = StatusWithExtendedTime(args, cfg, title)
elseif group == 3 then
statusObj = StatusWithMinTimeAndExtendedTime(args, cfg, title)
else
error('khu vực không được hỗ trợ')
end
else
error('id không được rỗng')
end
else
statusObj = Status(args, cfg)
end
return statusObj:getValues()
end
function p.main(frame)
local args = frame:getParent().args
local cfg = require(CONFIG_MODULE)
return frame:expandTemplate{title = 'Status/core', args = p._main(args, cfg)}
end
return p