Модуль:Infocards

Материал из Янтарной ноосферы, свободной интернет-энциклопедии

local infocards = {}; local calculateAge = true;

--[[ Helper function that populates the argument list given that user may need to use a mix of named and unnamed parameters. This is relevant because named parameters are not identical to unnamed parameters due to string trimming, and when dealing with strings we sometimes want to either preserve or remove that whitespace depending on the application. ]] function infocards._getParameters( frame_args, arg_list )

   local new_args = {};
   local index = 1;
   local value;

   for i,arg in ipairs( arg_list ) do
       value = frame_args[arg]
       if value == nil then
           value = frame_args[index];
           index = index + 1;
       end
       new_args[arg] = value;
   end

   return new_args;

end

function infocards.isBlank( someString )

   return someString == nil or mw.ustring.match(someString, '^%s*$') ~= nil;

end

function infocards.isDate ( frame )

   local new_args = infocards._getParameters( frame.args, {'s', 't', 'f'} );
   local s = new_args['s'] or ;
   local t = new_args['t'] or ;
   local f = new_args['f'] or ;
   local result = infocards.isDateImpl ( s )
   if (result) then
       return t
   else
       return f
   end

end

function infocards.isDateImpl ( s )

   local converted = infocards.convertToDate ( s );
   return converted ~= nil

end

function infocards.dateOfBirth( frame )

   local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'nocat'} );
   local dateOfBirth = new_args['dateOfBirth'] or ;
   local dateOfDeath = new_args['dateOfDeath'] or ;
   local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText;
   return infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, nocat );

end

function infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, nocat )

   local appendToCategory = infocards.isBlank( nocat );
   if ( infocards.isBlank( dateOfBirth ) ) then
       if ( appendToCategory ) then
           return 
       else
           return 
       end
   end
   if ( mw.ustring.match( dateOfBirth, '^%s*неизвестн.%s*$' ) ~= nil
           or mw.ustring.match( dateOfBirth, '^%s*%?%s*$' ) ~= nil ) then
       if ( appendToCategory ) then
           return "неизвестно"
       else
           return "неизвестно"
       end
   end
   local appendAge = calculateAge and infocards.isBlank( dateOfDeath );
   local parsedDate = infocards.convertToDate ( dateOfBirth )
   if ( parsedDate == nil ) then
       if ( appendToCategory ) then
           return dateOfBirth .. 
       else
           return dateOfBirth
       end
   end
   local result = infocards.formatDateImpl ( parsedDate, 'bday', appendToCategory and 'Родившиеся' or nil )
   if ( appendAge ) then
       local age = infocards.age ( parsedDate,  os.date("*t") )
       if ( age > 0 ) then
           result = result .. ' (' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')'
       end
       if ( age > 150 and appendToCategory ) then
           result = result .. 
       end
   end
   return result

end

function infocards.dateOfDeath( frame )

   local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'nocat'} );
   local dateOfBirth = new_args['dateOfBirth'] or ;
   local dateOfDeath = new_args['dateOfDeath'] or ;
   local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText;
   return infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat );

end

function infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat )

   if ( infocards.isBlank( dateOfDeath ) ) then
       return 
   end
   local appendToCategory = infocards.isBlank( nocat );
   if ( mw.ustring.match( dateOfDeath, '^%s*неизвестн.%s*$' ) ~= nil
           or mw.ustring.match( dateOfDeath, '^%s*%?%s*$' ) ~= nil ) then
       if ( appendToCategory ) then
           return "неизвестно"
       else
           return "неизвестно"
       end
   end
   local parsedDateOfBirth = infocards.convertToDate ( dateOfBirth )
   local parsedDateOfDeath = infocards.convertToDate ( dateOfDeath )
   if ( parsedDateOfDeath == nil ) then
       if ( appendToCategory ) then
           return dateOfDeath .. 
       else
           return dateOfDeath
       end
   end
   local result = infocards.formatDateImpl ( parsedDateOfDeath, 'dday', appendToCategory and 'Умершие' or nil )

if ( calculateAge ) then local age = infocards.age ( parsedDateOfBirth, parsedDateOfDeath ) if ( age > 0 ) then result = result .. ' (' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')' end if ( age > 150 and appendToCategory ) then result = result .. end end

   return result

end

function infocards.age( parsedBirthDate, parsedFinishDate )

   if ( parsedBirthDate == nil or parsedFinishDate == nil ) then
       return 0
   end
   local bd = parsedBirthDate["day"]
   local bm = parsedBirthDate["month"]
   local by = parsedBirthDate["year"]
   local dd = parsedFinishDate["day"];
   local dm = parsedFinishDate["month"];
   local dy = parsedFinishDate["year"];
   if ( bd and bm and by and dd and dm and dy ) then
       if ( dm > bm or ( dm == bm and dd >= bd ) ) then
           return dy - by
       else
           return dy - by - 1
       end
   else
       return 0
   end

end

local genitivusMonthes = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',

   'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'}

function infocards.formatDateImpl( parsedDate, infocardClass, categoryNamePrefix )

   local nd = parsedDate["day"];
   local nm = parsedDate["month"];
   local ny = parsedDate["year"];
   local od = parsedDate["osday"];
   local om = parsedDate["osmonth"];
   local oy = parsedDate["osyear"];
   
   local template =
       (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") ..
       (od ~= nil and "4" or "") .. (om ~= nil and "5" or "") .. (oy ~= nil and "6" or "")
   local datePart = ''
   if (template == "12") then
       datePart = datePart .. string.format( "%d %s", nd, genitivusMonthes[nm] )
   elseif (template == "3") then
       datePart = datePart .. infocards.nominativeYear( ny )
   elseif (template == "123") then
       datePart = datePart .. string.format( "%d %s %s",
                                       nd, genitivusMonthes[nm], infocards.nominativeYear( ny ) )
   elseif (template == "124") then
       datePart = datePart .. string.format( "%d (%d) %s",
                                       nd, genitivusMonthes[nm], od, nd, genitivusMonthes[nm] )
   elseif (template == "1234") then
       datePart = datePart .. string.format( "%d (%d) %s %s",
                                       nd, genitivusMonthes[nm], od, nd, genitivusMonthes[nm], infocards.nominativeYear( ny ) )
   elseif (template == "1245") then
       datePart = datePart .. string.format( "%d %s (%d %s)",
                                       od, genitivusMonthes[om], nd, genitivusMonthes[nm] )
   elseif (template == "12345") then
       datePart = datePart .. string.format( "%d %s (%d %s) %s",
                                       od, genitivusMonthes[om], nd, genitivusMonthes[nm], infocards.nominativeYear( ny ) )
   elseif (template == "123456") then
       datePart = datePart .. string.format( '%d %s %d (%d %s %s)',
                                       od, genitivusMonthes[om], oy, nd, genitivusMonthes[nm], infocards.nominativeYear( ny ) )
   else
       datePart = datePart .. 'формат неверен'
   end
   datePart = datePart .. ''
   local infocardTemplate =
       (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "")
   if (infocardTemplate == "123") then
       datePart = datePart .. '(' .. ny .. '-' .. nm .. '-' .. nd .. ')'
   elseif (infocardTemplate == "23") then
       datePart = datePart .. '(' .. ny .. '-' .. nm .. ')'
   elseif (infocardTemplate == "3") then
       datePart = datePart .. '(' .. ny .. ')'
   end
   if ( categoryNamePrefix ~= nil ) then
       if ( nd ~= nil and nm ~= nil) then
           datePart = datePart .. '[[Категория:' .. categoryNamePrefix .. ' ' .. nd .. ' ' .. genitivusMonthes[nm] .. ']]'
       end
       if ( ny ~= nil) then
           datePart = datePart .. 
       end
   end
   return datePart

end

function infocards.nominativeYear( year )

   if ( year >= 0 ) then
       return '' .. year .. ''
   else
       return '' .. ( 0 - year ) .. ' до н. э.'
   end

end

function infocards.inYear( year )

   if ( year >= 0 ) then
       return  .. year .. ' году'
   else
       return  .. ( 0 - year) .. ' году до н. э.'
   end

end

function infocards.convertToDate( possibleDateString )

   possibleDateString = mw.ustring.gsub( possibleDateString, '−', '-')
   local simpleDate = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*$', 0)
   if ( simpleDate ) then
       return infocards.convertToDateNewStylePart( simpleDate );
   end
   local complexDate1, complexDate2 = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*%(([%-%d%.]+)%)%s*$', 0)
   if ( complexDate1 and complexDate2) then
       local table1 = infocards.convertToDateNewStylePart( complexDate1 );
       local table2 = infocards.convertToDateOldStylePart( complexDate2 );
       if ( table1 and table2 ) then
           return {
                   year = table1["year"], month = table1["month"], day = table1["day"], 
                   osyear = table2["year"], osmonth = table2["month"], osday = table2["day"]
               }
       else
           return nil
       end
   end
   return nil

end

function infocards.convertToDateNewStylePart( possibleDateString )

   local ny = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
   if (ny ~= nil) then
       return {year = tonumber(ny)}
   end
   return infocards.convertToDateCommonPart( possibleDateString )

end

function infocards.convertToDateOldStylePart( possibleDateString )

   local nd = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
   if (nd ~= nil) then
       return {day = tonumber(nd)}
   end
   return infocards.convertToDateCommonPart( possibleDateString )

end


function infocards.convertToDateCommonPart( possibleDateString )

   local nd, nm
       = mw.ustring.match(possibleDateString, '^(%d?%d)%.(%d?%d)$', 0)
   if (nd ~= nil and nm ~= nil) then
       return {day = tonumber(nd), month = tonumber(nm)}
   end
   local nd, nm, ny
       = mw.ustring.match(possibleDateString, '^(%d?%d)%.(%d?%d)%.(%-?%d+)$', 0)
   if (nd ~= nil and nm ~= nil and ny ~= nil) then
   	local ndn = tonumber(nd)
   	local nmn = tonumber(nm)
   	local nyn = tonumber(ny)
   	if (ndn > 0 and ndn < 33 and nmn > 0 and nmn < 13) then
       	return {day = ndn, month = nmn, year = nyn}
       end
   end
   return nil

end

return infocards