বিষয়বস্তুতে চলুন

মডিউল:Exchangerate

উইকিভ্রমণ থেকে

এই মডিউলের জন্য মডিউল:Exchangerate/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

local errormsg = ('[[Category:Articles that use unexpected currency]]'
.. '<span class="exchangeinfo" style="display:none;" '
.. 'title="Exchange rate not found">Unexpected currency</span>'
.. 'rate not found')

-- বাংলা ডিজিটে রূপান্তর
local function toBengaliDigits(str)
    local map = {
        ['0']='০',['1']='১',['2']='২',['3']='৩',['4']='৪',
        ['5']='৫',['6']='৬',['7']='৭',['8']='৮',['9']='৯'
    }
    str = tostring(str)
    return (str:gsub("%d", map))
end

-- বাংলা ডিজিট থেকে ইংরেজি ডিজিটে রূপান্তর
local function toEnglishDigits(str)
    local map = {
        ['০']='0',['১']='1',['২']='2',['৩']='3',['৪']='4',
        ['৫']='5',['৬']='6',['৭']='7',['৮']='8',['৯']='9'
    }
    str = tostring(str)
    return (str:gsub("[%z\1-\127\194-\244][\128-\191]*", map))
end

local function countSigificantDigits(number)
    number = string.gsub(number, '%.', '', 1)
    number = mw.text.trim(number, '0')
    return #number
end

local function round(num, numSigificantDigits)
    local numDecimalPlaces = numSigificantDigits - math.floor(math.log10(num)) - 1
    local mult = 10^(numDecimalPlaces or 0)
    return math.floor(num * mult + 0.5) / mult
end

local function getTabularDataFieldNames(tabularData)
    local fields = {}
    for _,field in pairs(tabularData.schema.fields) do
        table.insert(fields, field.name)
    end
    return fields
end

local function getColumnIndices(fields)
    local rowCurrencyIndex, dateIndex
    local targetCurrencyIndices = {}
    local sourceCurrencyIndices = {}
    for i,v in pairs(fields) do
        if v == 'currency' then
            rowCurrencyIndex = i
        elseif v == 'date' then
            dateIndex = i
        elseif string.match(v, '^%u%u%u$') then
            sourceCurrencyIndices[v] = i
        elseif string.match(v, '^_%u%u%u$') then
            targetCurrencyIndices[string.sub(v,2)] = i
        end
    end
    return rowCurrencyIndex, dateIndex, sourceCurrencyIndices, targetCurrencyIndices
end

local function getConversionTable(dataPageName)
    local tabularData = mw.ext.data.get(dataPageName)
    if not tabularData then return nil end
    local fields = getTabularDataFieldNames(tabularData)
    local rowCurrencyIndex, dateIndex, sourceCurrencyIndices, targetCurrencyIndices = getColumnIndices(fields)

    local conversionTable = {}
    if rowCurrencyIndex then
        for _,row in pairs(tabularData.data) do
            for sourceCurrency,index in pairs(sourceCurrencyIndices) do
                if not conversionTable[sourceCurrency] then
                    conversionTable[sourceCurrency] = {}
                end
                conversionTable[sourceCurrency][row[rowCurrencyIndex]] = {rate = row[index], revisionTime = row[dateIndex]}
            end
            for targetCurrency,index in pairs(targetCurrencyIndices) do
                if not conversionTable[row[rowCurrencyIndex]] then
                    conversionTable[row[rowCurrencyIndex]] = {}
                end
                conversionTable[row[rowCurrencyIndex]][targetCurrency] = {rate = row[index], revisionTime = row[dateIndex]}
            end
        end
    end
    return conversionTable
end

local function getDataFromRateDataPage(dataPageName, source, target)
    local conversionTable = getConversionTable(dataPageName)
    if not conversionTable then return nil end
    local rate, revisionTime, rateSignificantDigits
    if conversionTable[source] and conversionTable[source][target] then
        rate = conversionTable[source][target]['rate']
        rateSignificantDigits = countSigificantDigits(rate)
        revisionTime = conversionTable[source][target]['revisionTime']
    elseif conversionTable[target] and conversionTable[target][source] then
        local targetToSourceRate = conversionTable[target][source]['rate']
        rate = targetToSourceRate^-1
        rateSignificantDigits = countSigificantDigits(targetToSourceRate)
        revisionTime = conversionTable[target][source]['revisionTime']
    end
    return rate, rateSignificantDigits, revisionTime
end

local p = {}

function p._rate(source, target, rounded)
    local dataPageNames = {
        'ECB euro foreign exchange reference rates.tab',
        'Xe.com exchange rates.tab'}
    local rate, revisionTime, rateSignificantDigits
    for _,name in pairs(dataPageNames) do
        rate, rateSignificantDigits, revisionTime = getDataFromRateDataPage(name, source, target)
        if not rate or not revisionTime then
            for _,name in pairs(dataPageNames) do
                local USDtoTargetRate, UtoTSigDig, UtoTRevTime = getDataFromRateDataPage(name, 'USD', target)
                local USDtoSourceRate, UtoSSigDig, UtoSRevTime = getDataFromRateDataPage(name, 'USD', source)
                if USDtoTargetRate and USDtoSourceRate then
                    rate = USDtoTargetRate/USDtoSourceRate
                    revisionTime = UtoTRevTime < UtoSRevTime and UtoTRevTime or UtoSRevTime
                    rateSignificantDigits = UtoTSigDig < UtoSSigDig and UtoTSigDig or UtoSSigDig
                end
            end
        end
        if rate and revisionTime then
            break
        end
    end
    if rate and revisionTime then
        if rounded then
            rate = round(rate, rateSignificantDigits)
        end
        return rate, revisionTime
    end
end

function p._convert(source, target, amount)
    local rate = p._rate(source, target)
    if rate then
        local engAmount = tonumber(toEnglishDigits(amount))
        if not engAmount then return nil end
        local amountSigificantDigitsCount = countSigificantDigits(engAmount)
        local result = round(engAmount * rate, amountSigificantDigitsCount + 1)
        return toBengaliDigits(result)
    end
end

function p._convertSingelOrRange(source, target, amounts)
    local amounts = string.gsub(amounts, ',', '')
    local splitOffset = mw.ustring.find(amounts, '-')
    local converted
    if splitOffset then
        local firstAmount = mw.ustring.sub(amounts, 0, splitOffset -1)
        local secondAmount = mw.ustring.sub(amounts, splitOffset + 1)
        local first = p._convert(source, target, firstAmount)
        local second = p._convert(source, target, secondAmount)
        converted = first and second and first .. '&ndash;' .. second
    else
        converted = p._convert(source, target, amounts)
    end
    return converted
end

function p.rate(frame)
    local args = frame.args
    local rate = p._rate(args.source, args.target, true)
    local result = rate or args.verbose and errormsg
    return result
end

function p.revisionTime(frame)
    local args = frame.args
    local _,revisionTime = p._rate(args.source, args.target)
    local result = revisionTime or args.verbose and errormsg
    return result
end

function p.convert(frame)
    local args = frame.args
    local amount = string.gsub(args.amount, ',', '')
    local convertedAmount = p._convert(args.source, args.target, amount)
    local result = convertedAmount or args.verbose and errormsg
    return result
end

function p.convertSingelOrRange(frame)
    local args = frame.args
    local convertedAmounts = p._convertSingelOrRange(
    args.source, args.target, args.amounts)
    local result = convertedAmounts or args.verbose and errormsg
    return result
end

local function currencyWithSymbol(currency, symbolFormat, amount)
    local currencyWithSymbol = (
    symbolFormat and string.format(symbolFormat, amount)
    or currency .. amount)
    return currencyWithSymbol
end

function p.currencyWithConversions(frame)
    local args = frame.args
    local amount = (args.amount and args.amount ~= '') and args.amount or 1
    local engAmount = toEnglishDigits(amount)
    local i18n = mw.loadData('Module:Exchangerate/i18n')
    local currencySymbols = i18n.symbols[args.currency]
    local shortSymbol = currencySymbols and currencySymbols.shortSymbol
    local currencyWithShortSymbol = currencyWithSymbol(
        args.currency, shortSymbol, toBengaliDigits(engAmount))
    local uniqueSymbol = currencySymbols and currencySymbols.uniqueSymbol
    local currencyWithUniqueSymbol = currencyWithSymbol(
        args.currency, uniqueSymbol, toBengaliDigits(engAmount)) -- hover এখন বাংলায়
    local conversionCurrencies = i18n.defaultConversions or {'USD', 'EUR'}
    local convertedStrings = {}
    for _,convCurrency in ipairs(conversionCurrencies) do
        if args.currency ~= convCurrency then
            local convertedAmount = p._convertSingelOrRange(
            args.currency, convCurrency, engAmount)
            local convCurrencyUniqueSymbol = (i18n.symbols[convCurrency]
            and i18n.symbols[convCurrency].uniqueSymbol)
            local convCurrencyWithSymbol = convertedAmount and currencyWithSymbol(
            convCurrency, convCurrencyUniqueSymbol, convertedAmount)
            table.insert(convertedStrings, convCurrencyWithSymbol)
        end
    end
    local comma = mw.message.new('comma-separator'):plain()
    local allConvertedStrings = table.concat(convertedStrings, comma)
    local conversions = (allConvertedStrings ~= '') and ' ≈ ' .. allConvertedStrings or ''
    local resultFormat = '<abbr title="%s%s">%s</abbr>'
    local result = string.format(resultFormat, currencyWithUniqueSymbol,
    conversions, currencyWithShortSymbol)
    return result
end

return p