Module:Sandbox/Thisasia

local p = {}

local function dateCalculation(dateStr) local year, month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)") if not year then day, month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)") end if not year then return 'Invalid ' end local currentDate = os.date("*t") local age = currentDate.year - tonumber(year) if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then age = age - 1 end local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)}) return " ".. monthName .. " "..day..", " .. year.. " (Age " .. age.. ")" end

--[[ local function dateCalculation(dateStr)   local year, month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")    if not year then        day , month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")    end    if not year then         return 'Invalid date format'     end    local currentDate = os.date("*t")    local age        if tonumber(year) < 1582 or (tonumber(year) == 1582 and (tonumber(month) < 10 or (tonumber(month) == 10 and tonumber(day) < 4))) then        age = currentDate.year - tonumber(year)    else         age = currentDate.year - tonumber(year)         local leapYears = 0        for i = tonumber(year), currentDate.year - 1 do            if i % 4 == 0 then                leapYears = leapYears + 1            end        end                age = age - leapYears    end    if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then        age = age - 1    end    local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)})    return " ".. monthName .. " "..day..", " .. year.. " (Age " ..  age.. ")" end

]]

--❗ --Volume conversions local function litersToGallons(liters) local litersValue = tonumber(liters:match("%d+%.?%d*")) if litersValue then local gallons = litersValue * 0.264172 return "".. string.format("%.2f liters (%.2f gallons)", litersValue, gallons) end return liters end

local function gallonsToLiters(gallons) local gallonsValue = tonumber(gallons:match("%d+%.?%d*")) if gallonsValue then local liters = gallonsValue * 3.78541 return string.format("%.2f gallons (%.2f liters)", gallonsValue, liters) end return gallons end

local function cubicMetersToCubicFeet(cubicMeters) local cubicMetersValue = tonumber(cubicMeters:match("%d+%.?%d*")) if cubicMetersValue then local cubicFeet = cubicMetersValue * 35.3147 return string.format("%.2f cubic meters (%.2f cubic feet)", cubicMetersValue, cubicFeet) end return cubicMeters end

local function cubicFeetToCubicMeters(cubicFeet) local cubicFeetValue = tonumber(cubicFeet:match("%d+%.?%d*")) if cubicFeetValue then local cubicMeters = cubicFeetValue * 0.0283168 return string.format("%.2f cubic feet (%.2f cubic meters)", cubicFeetValue, cubicMeters) end return cubicFeet end

-- Area conversions local function squareMetersToSquareFeet(squareMeters) local squareMetersValue = tonumber(squareMeters:match("%d+%.?%d*")) if squareMetersValue then local squareFeet = squareMetersValue * 10.7639 return string.format("%.2f square meters (%.2f square feet)", squareMetersValue, squareFeet) end return squareMeters end

local function squareFeetToSquareMeters(squareFeet) local squareFeetValue = tonumber(squareFeet:match("%d+%.?%d*")) if squareFeetValue then local squareMeters = squareFeetValue * 0.092903 return string.format("%.2f square feet (%.2f square meters)", squareFeetValue, squareMeters) end return squareFeet end

local function hectaresToAcres(hectares) local hectaresValue = tonumber(hectares:match("%d+%.?%d*")) if hectaresValue then local acres = hectaresValue * 2.47105 return string.format("%.2f hectares (%.2f acres)", hectaresValue, acres) end return hectares end

local function acresToHectares(acres) local acresValue = tonumber(acres:match("%d+%.?%d*")) if acresValue then local hectares = acresValue * 0.404686 return string.format("%.2f acres (%.2f hectares)", acresValue, hectares) end return acres end

-- Time conversions local function hoursToMinutes(hours) local hoursValue = tonumber(hours:match("%d+%.?%d*")) if hoursValue then local minutes = hoursValue * 60 return string.format("%.2f hours (%d minutes)", hoursValue, minutes) end return hours end

local function minutesToHours(minutes) local minutesValue = tonumber(minutes:match("%d+%.?%d*")) if minutesValue then local hours = minutesValue / 60 local decimalPart = minutes:match("%.(%d+)") if decimalPart then hours = hours + tonumber("0." .. decimalPart) end return string.format("%.2f minutes (%.2f hours)", minutesValue, hours) end return minutes end

local function daysToHours(days) local daysValue = tonumber(days:match("%d+%.?%d*")) if daysValue then local hours = daysValue * 24 return string.format("%.2f days (%d hours)", daysValue, hours) end return days end

local function hoursToDays(hours) local hoursValue = tonumber(hours:match("%d+%.?%d*")) if hoursValue then local days = hoursValue / 24 return string.format("%.2f hours (%.2f days)", hoursValue, days) end return hours end

-- Energy conversions local function joulesToCalories(joules) local joulesValue = tonumber(joules:match("%d+%.?%d*")) if joulesValue then local calories = joulesValue * 0.000239006 return string.format("%.2f joules (%.6f calories)", joulesValue, calories) end return joules end

local function caloriesToJoules(calories) local caloriesValue = tonumber(calories:match("%d+%.?%d*")) if caloriesValue then local joules = caloriesValue / 0.000239006 return string.format("%.2f calories (%.2f joules)", caloriesValue, joules) end return calories end

local function kilowattHoursToJoules(kWh) local kWhValue = tonumber(kWh:match("%d+%.?%d*")) if kWhValue then local joules = kWhValue * 3600000 return string.format("%.2e kWh (%.2e joules)", kWhValue, joules) end return kWh end

local function joulesToKilowattHours(joules) local joulesValue = tonumber(joules:match("%d+%.?%d*")) if joulesValue then local kWh = joulesValue / 3600000 return string.format("%.2e joules (%d kWh)", joulesValue, kWh) end return joules end

-- 🔴Pressure conversions local function pascalsToPSI(pascals) local pascalsValue = tonumber(pascals:match("%d+")) if pascalsValue then local psi = pascalsValue * 0.000145038 return string.format("%d pascals (%.6f PSI)", pascalsValue, psi) end return pascals end

local function psiToPascals(psi) local psiValue = tonumber(psi:match("%d+")) if psiValue then local pascals = psiValue / 0.000145038 return string.format("%.6f PSI (%d pascals)", psiValue, pascals) end return psi end

local function atmospheresToPascals(atmospheres) local atmospheresValue = tonumber(atmospheres:match("%d+")) if atmospheresValue then local pascals = atmospheresValue * 101325 return string.format("%d atmospheres (%d pascals)", atmospheresValue, pascals) end return atmospheres end

local function pascalsToAtmospheres(pascals) local pascalsValue = tonumber(pascals:match("%d+")) if pascalsValue then local atmospheres = pascalsValue / 101325 return string.format("%d pascals (%.6f atmospheres)", pascalsValue, atmospheres) end return pascals end

-- Frequency conversions local function hertzToRPM(hertz) local hertzValue = tonumber(hertz:match("%d+")) if hertzValue then local rpm = hertzValue * 60 return string.format("%d Hertz (%d RPM)", hertzValue, rpm) end return hertz end

local function rpmToHertz(rpm) local rpmValue = tonumber(rpm:match("%d+")) if rpmValue then local hertz = rpmValue / 60 return string.format("%d RPM (%.2f Hertz)", rpmValue, hertz) end return rpm end

local function kilohertzToHertz(kHz) local kHzValue = tonumber(kHz:match("%d+")) if kHzValue then local hertz = kHzValue * 1000 return string.format("%d kHz (%d Hertz)", kHzValue, hertz) end return kHz end

local function hertzToKilohertz(hertz) local hertzValue = tonumber(hertz:match("%d+")) if hertzValue then local kHz = hertzValue / 1000 return string.format("%d Hertz (%.2f kHz)", hertzValue, kHz) end return hertz end

-- Power conversions local function wattsToHorsepower(watts) local wattsValue = tonumber(watts:match("%d+")) if wattsValue then local horsepower = wattsValue * 0.00134102 return string.format("%d watts (%.6f horsepower)", wattsValue, horsepower) end return watts end

local function horsepowerToWatts(horsepower) local horsepowerValue = tonumber(horsepower:match("%d+")) if horsepowerValue then local watts = horsepowerValue / 0.00134102 return string.format("%.6f horsepower (%d watts)", horsepowerValue, watts) end return horsepower end

local function megawattsToHorsepower(megawatts) local megawattsValue = tonumber(megawatts:match("%d+")) if megawattsValue then local horsepower = megawattsValue * 1341.02 return string.format("%d megawatts (%.2f horsepower)", megawattsValue, horsepower) end return megawatts end

local function horsepowerToMegawatts(horsepower) local horsepowerValue = tonumber(horsepower:match("%d+")) if horsepowerValue then local megawatts = horsepowerValue / 1341.02 return string.format("%.2f horsepower (%d megawatts)", horsepowerValue, megawatts) end return horsepower end

-- Add these functions to the p dynamic function to integrate them into the infobox --❗ local function ftToCm(ft) local ftValue = tonumber(ft:match("%d+%.?%d*")) if ftValue then local cm = ftValue * 30.48 return string.format("%.2f ft (%.2f cm)", ftValue, cm) end return ft end

local function cmToFeetAndInches(cm) local cmValue = tonumber(cm:match("%d+%.?%d*")) if cmValue then local totalInches = cmValue / 2.54 local feet = math.floor(totalInches / 12) local inches = math.floor(totalInches % 12) return string.format("%.2f cm (%d feet %d inches)", cmValue, feet, inches) end return cm end

local function mphToKmh(mph) local mphValue = tonumber(mph:match("%d+%.?%d*")) if mphValue then local kmh = mphValue * 1.60934 return string.format("%.2f mph (%.2f km/h)", mphValue, kmh) end return mph end

local function kmhToMph(kmh) local kmhValue = tonumber(kmh:match("%d+%.?%d*")) if kmhValue then local mph = kmhValue / 1.60934 return string.format("%.2f km/h (%.2f mph)", kmhValue, mph) end return kmh end

local function kmToMi(km) local kmValue = tonumber(km:match("%d+%.?%d*")) if kmValue then local miles = kmValue * 0.621371 return string.format("%.2f km (%.2f mi)", kmValue, miles) end return km end

local function miToKm(mi) local miValue = tonumber(mi:match("%d+%.?%d*")) if miValue then local km = miValue / 0.621371 return string.format("%.2f miles (%.2f km)", miValue, km) end return mi end

local function hpToKw(hp) local hpValue = tonumber(hp:match("%d+%.?%d*")) if hpValue then local kw = hpValue * 0.735499 return string.format("%.2f horsepower (%.2f kW)", hpValue, kw) end return hp end

local function kwToHp(kw) local kwValue = tonumber(kw:match("%d+%.?%d*")) if kwValue then local hp = kwValue / 0.735499 return string.format("%.2f Kilowatt(%.2f hp)", kwValue, hp) end return kw end

local function lbToKg(lb) local lbValue = tonumber(lb:match("%d+%.?%d*")) if lbValue then local kg = lbValue * 0.453592 return string.format("%.2f lb (%.2f kg)", lbValue, kg) end return lb end

local function kgToPounds(kg) --local kgValu = tonumber(kg:match("%d+")) local kgValue = tonumber(kg:match("%d+%.?%d*")) if kgValue>1 then local pounds = kgValue * 2.20462 return string.format("%.2f kgs (%.2f pounds)", kgValue, pounds) else local pounds = kgValue * 2.20462 return string.format("%.2f kg (%.2f pounds)", kgValue, pounds) end return kg end

local function mmToInches(mm) local mmValue = tonumber(mm:match("%d+%.?%d*")) if mmValue then local inches = mmValue * 0.0393701 return string.format("%.2f mm (%.2f inches)", mmValue, inches) end return mm end

local function inchesToMm(inches) local inchesValue = tonumber(inches:match("%d+%.?%d*")) if inchesValue then local mm = inchesValue / 0.0393701 return string.format("%.2f inches (%.2f mm)", inchesValue, mm) end return inches end

local function msToFts(ms) local msValue = tonumber(ms:match("%d+%.?%d*")) if msValue then local fts = msValue * 3.28084 return string.format("%.2f m/s(%.2f ft/s)", msValue, fts) end return ms end

local function ftsToMs(fts) local ftsValue = tonumber(fts:match("%d+%.?%d*")) if ftsValue then local ms = ftsValue / 3.28084 return string.format("%.2f ft/s(%.2f m/s)", ftsValue, ms) end return fts end

local function mToFeet(m) local mValue = tonumber(m:match("%d+%.?%d*")) if mValue then local feet = mValue * 3.28084 return string.format("%.2f meter (%.2f ft)", mValue, feet) end -- Check for variations of "m", "meter", and "metre" local mValueAlt = tonumber(m:match("(%d+%.?%d*)%s*[mM]")) if mValueAlt then local feetAlt = mValueAlt * 3.28084 return string.format("%.2f m (%.2f ft)", mValueAlt, feetAlt) end local mValueAlt2 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE]?[rR]?")) if mValueAlt2 then local feetAlt2 = mValueAlt2 * 3.28084 return string.format("%.2f metre (%.2f ft)", mValueAlt2, feetAlt2) end local mValueAlt3 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE][rR]?")) if mValueAlt3 then local feetAlt3 = mValueAlt3 * 3.28084 return string.format("%.2f meter (%.2f ft)", mValueAlt3, feetAlt3) end return m end --//m///

local function celsiusToFahrenheit(c) local cValue = tonumber(c:match("%d+")) if cValue then local fahrenheit = cValue * 9/5 + 32 return string.format("%.2f°C (%.2f°F)", cValue, fahrenheit) end return c end

local function fahrenheitToCelsius(f) local fValue = tonumber(f:match("%d+")) if fValue then local celsius = (fValue - 32) * 5/9 return string.format("%.2f°F (%.2f°C)", fValue, celsius) end return f end function capitalizeFirstLetter(str) return str:gsub("^%l", string.upper) end

-- Function to generate contrasting text color for a given background color local function getContrastingTextColor(bgColor) -- Convert hex color to RGB local r = tonumber(bgColor:sub(2, 3), 16) local g = tonumber(bgColor:sub(4, 5), 16) local b = tonumber(bgColor:sub(6, 7), 16)

-- Calculate relative luminance local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255

-- Choose white or black text color based on luminance if luminance > 0.5 then return "#000000" -- Black text for light backgrounds else return "#FFFFFF" -- White text for dark backgrounds end end

-- Function to generate even lighter colors function generateEvenLighterColor1 local r = math.random(0xF0, 0xFF) -- Red component local g = math.random(0xF0, 0xFF) -- Green component local b = math.random(0xF0, 0xFF) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

-- Function to generate a very light color function generateVeryLightColor2 local r = math.random(0xE0, 0xFF) -- Red component local g = math.random(0xE0, 0xFF) -- Green component local b = math.random(0xE0, 0xFF) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

-- Function to generate a random light color function generateLightColor3 local r = math.random(0xB0, 0xFF) -- Red component local g = math.random(0xB0, 0xFF) -- Green component local b = math.random(0xB0, 0xFF) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

-- Functions to generate mixed light-dark colors function generateDarkColor4 local r = math.random(0x60, 0x80) -- Red component local g = math.random(0x60, 0x80) -- Green component local b = math.random(0x60, 0x80) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

function generateDarkColor5 local r = math.random(0x50, 0x70) -- Red component local g = math.random(0x50, 0x70) -- Green component local b = math.random(0x50, 0x70) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

function generateDarkColor6 local r = math.random(0x40, 0x60) -- Red component local g = math.random(0x40, 0x60) -- Green component local b = math.random(0x40, 0x60) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

function generateDarkColor7 local r = math.random(0x20, 0x40) -- Red component local g = math.random(0x20, 0x40) -- Green component local b = math.random(0x20, 0x40) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

function generateDarkColor8 local r = math.random(0x30, 0x70) -- Red component local g = math.random(0x30, 0x70) -- Green component local b = math.random(0x30, 0x70) -- Blue component return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color end

function generateDarkColor9 return string.format("#%02x%02x%02x", math.random(0x30, 0x50), math.random(0x40, 0x70), math.random(0x50, 0x70)) end

function generateDarkColor10 return string.format("#%06x", math.random(0x30, 0x70)) end

-- Function to generate a random color local function generateRandomColor local r = math.random(0, 255) local g = math.random(0, 255) local b = math.random(0, 255) return string.format("#%02X%02X%02X", r, g, b) end

-- local conversionPatterns = {       { pattern = "%s*kilohertz%s*", convertedValue = kilohertzToHertz},        { pattern = "%s*kg%s*", conversion = kgToPounds },        { pattern = "%s*mph%s*", conversion = mphToKmh },        -- Add more conversion patterns as needed    }

function p.dynamic(frame) local args = frame:getParent.args local output = ' \n|-\n' -- local firstDescriptionFound = false local cmProcessed = false local abvParams = {} -- Store abv parameters separately local abvProcessed = false local upProcessed = false local imageProcessed =false --go over arguments to find "up" and "abv" parameters   for key, value in pairs(args) do        if key:sub(1, 2) == 'up' then            if value ~= "" then                output = output .. ' <th style='..(args.header or"")..'"background:lightgra;font-size:20px;text-align: center; background-color: ' .. (args.headcolor or "

local values = {}

for key, value in pairs(args) do   if key:sub(1, 2) == 'up' and value ~= "" then table.insert(values, {key = key, value = value}) end end table.sort(values, function(a, b) return a.key < b.key end) for _, entry in ipairs(values) do   local key = entry.key local value = entry.value value = value:gsub("^%l", string.upper) local first_char = value:match("%a") -- Find the first alphabet character if first_char then value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character end output = output .. ' ' .. value .. '\n \n' end

--[[ for key, value in pairs(args) do       if value ~= "" then            if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then                if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed) and key ~= 'abv' and not abvProcessed then                    -- Your existing conversion logic goes here                end            end        end end

for key, value in pairs(args) do       if value ~= "" then if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and key ~= 'abv' and not upProcessed then -- Your existing conversion logic goes here end end end end ]] local hasImage = false for key, _ in pairs(args) do   if key:sub(1, 5) == "image" then hasImage = true break end end

if not hasImage then local defaultImage = "\n" output = output .. defaultImage end

if args.image then local processedKeys = {} local processedSizeCaption = {} local images = {} local div = ''

for key, value in pairs(args) do       if key:sub(1, 5) == "image" and value ~= "" and not processedKeys[key] then processedKeys[key] = true local captionKey = "caption" .. key:sub(6) local sizeKey = "size" .. key:sub(6)

if not processedSizeCaption[captionKey] and not processedSizeCaption[sizeKey] then processedSizeCaption[captionKey] = true processedSizeCaption[sizeKey] = true

local caption = args[captionKey] or "" local imagesize = args[sizeKey] or "" local isFrameless = string.match(value, '|frameless') local imageExtension = value:match("%.([^.]+)$")

if not imageExtension then value = value:gsub("|", "".. ".jpg|").. ".jpg" end local grid ="" local wikiMarkup = '' if isFrameless then local remo = value:gsub("(%[%[.-|)File:", "%1") wikiMarkup = wikiMarkup .. '|' .. ' ' .. remo .. ' ' .. '' .. caption .. ' \n|-\n' else local imageName, imageSize = value:match("%[%[File:(.-)|([^|%]]+)]]") if imageName then wikiMarkup = wikiMarkup .. "[[File:" .. imageName                       if imageSize then                            wikiMarkup = wikiMarkup .. "|" .. imageSize                        end                        wikiMarkup = wikiMarkup .. "]]" else local imageSizeMarkup = "" if imagesize ~= "" then imageSizeMarkup = "|" .. imagesize end wikiMarkup = wikiMarkup .. "[[File:" .. value:gsub("%[%[", ""):gsub("%]%]", "") .. imageSizeMarkup .. "]]" end wikiMarkup = ' ' .. wikiMarkup .. '' .. caption .. ' \n' end

-- Store the image markup along with its key table.insert(images, { key = key, markup = wikiMarkup, insertionOrder = #images + 1 })           end end end

-- Sort the images based on their keys to maintain the insertion order --table.sort(images, function(a, b) return a.key < b.key end)

-- Generate the output markup local columnCount = 0 local gridOpen = false for _, imageData in ipairs(images) do   local wikiMarkup = imageData.markup if imageData.key:sub(-1) == "+" then if not gridOpen then output = output .. '| ' .. div.. ' \n|-\n' -- Open the grid container if it's not already open gridOpen = true end --output = output ..'|'.. wikiMarkup .. '\n|-\n' -- For keys not ending with '+', display normally

output = output .. '| ' .. wikiMarkup .. ' \n' columnCount = (columnCount + 1) % 2 else if gridOpen then output = output .. ' \n|-\n' -- Close the grid container if it's open gridOpen = false end output = output ..' '.. wikiMarkup .. ' \n|-\n' -- For keys not ending with '+', display normally end end

-- If there are unclosed div tags, close them if gridOpen then output = output .. ' \n|-\n' end end

local values = {}

for key, value in pairs(args) do   if key:sub(1, 3) == "mdl"or key:match("^(%d+)mdl") and value ~= "" then table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") }) end end

table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)

for _, entry in ipairs(values) do   local key = entry.key local value = entry.value value = value:gsub("^%l", string.upper) local first_char = value:match("%a") -- Find the first alphabet character if first_char then value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character end --  local transcludedContent = transcludeTemplate("User:Thisasia/sandbox3", { value = "" }) --output = output .. '   \n|-\n' output = output .. ' '.. value .. ' \n|-\n' end

--[[ if key:sub(6, 6) == "+" then                    table.insert(gridImages, {value = value, caption = caption, isFrameless = isFrameless})                else                    table.insert(normalImages, {value = value, caption = caption, imagesize = imagesize, isFrameless = isFrameless})                end            end        end    end    -- Begin HTML output for grid layout    local div='\n'     -- Output grid images    for _, image in ipairs(gridImages) do        local wikiMarkup = ""        local remo = image.value        wikiMarkup = wikiMarkup .. div.. ' ' ..' '.. remo.. ' '..'' .. image.caption .. ' \n \n'        output = output .. wikiMarkup    end

if args.image then local caption = args.caption or "" local imagesize = args.imagesize or "" output = output .. '|' ..' '.. args.image.. ' '..'' .. caption .. ' \n|-\n' end --/// ]]

-- -- local values = {} for key, value in pairs(args) do   if key == key and value ~= "" then table.insert(values, {key = key, value = value}) end end --local function generateUUID   return uuid end local function extractNumber(key) return tonumber(key:match("^%d+")) or 0 end

--❗ Insertion Sort algorithm for i = 1, #values do   local current = values[i] local j = i - 1 while j > 0 and (extractNumber(values[j].key) > extractNumber(current.key) or                     (extractNumber(values[j].key) == extractNumber(current.key) and values[j].key > current.key)) do        values[j + 1] = values[j] j = j - 1 end values[j + 1] = current end

--[[ table.sort(values, function(a, b)   local aKey = a.key:match(".*%*$") and 1 or 0    local bKey = b.key:match(".*%*$") and 1 or 0

-- Keys with asterisks should come before keys without asterisks if aKey ~= bKey then return aKey < bKey else if aKey == 1 and bKey == 1 then return a.key < b.key elseif aKey == 0 and bKey == 0 then local numA = tonumber(a.key) local numB = tonumber(b.key) if numA and numB then return numA < numB else return a.key < b.key end else -- If one has asterisk and the other doesn't, prioritize the one with the asterisk return aKey == 1 end end end) ]] --[[

--Insertion Sort algorithm for modified_key for i = 2, #values do   local current = values[i] local j = i - 1 while j > 0 and values[j].key > current.key do       values[j + 1] = values[j] j = j - 1 end values[j + 1] = current end for i = 2, #values do   local current = values[i] local j = i - 1 while j > 0 and values[j].key > current.key do       values[j + 1] = values[j] j = j - 1 end values[j + 1] = current end ]]

local matchedKeys = {} local bgStyles = {} -- Table to store background styles for each matched key local generatedColors = {}

for _, entry in ipairs(values) do   local key = entry.key local value = entry.value local modified_key = key:gsub("^[%d]*", "") local found_alpha = false for i = 1, #modified_key do       if modified_key:sub(i, i):match("%a") then modified_key = modified_key:sub(1, i - 1) .. modified_key:sub(i, i):upper .. modified_key:sub(i + 1) found_alpha = true break end end if not found_alpha then modified_key = modified_key:gsub("^.", string.upper, 5) end local matched = false repeat local bgs = modified_key:match(".*%*$") or "" if bgs ~= "" and not matchedKeys[modified_key] then local bgStyle = bgStyles[modified_key] if not bgStyle then local manualBgColor = args["bgColor_" .. (modified_key:match(".*%*$"))] or "" local manualTextColor = args["textColor_" .. (modified_key:match(".*%*$"))] or "" local bgColor, textColor

if generatedColors[modified_key] then bgColor, textColor = generatedColors[modified_key].bgColor, generatedColors[modified_key].textColor else local randf1=args.rd1 =="yes" or args.Rd1=="yes" local randf2=args.rd2 =="yes" or args.Rd2=="yes" local randf3=args.rd3 =="yes" or args.Rd3=="yes" local randf4=args.rd4 =="yes" or args.Rd4=="yes" local randf5=args.rd5 =="yes" or args.Rd5=="yes" local randf6=args.rd6 =="yes" or args.Rd6=="yes" local randf7=args.rd7 =="yes" or args.Rd7=="yes" local randf8=args.rd8 =="yes" or args.Rd8=="yes" local randf9=args.rd9 =="yes" or args.Rd9=="yes" local randf10=args.rd10 =="yes" or args.Rd10=="yes" local randf11=args.rd11 =="yes" or args.Rd11=="yes" local randf12=args.rd12 =="yes" or args.Rd12=="yes"

if manualBgColor ~= "" and manualTextColor ~= "" then bgColor = manualBgColor textColor = manualTextColor elseif randf1 then bgColor = generateEvenLighterColor1 textColor = getContrastingTextColor(bgColor) elseif randf2 then bgColor = generateVeryLightColor2 textColor = getContrastingTextColor(bgColor) elseif randf3 then bgColor = generateLightColor3 textColor = getContrastingTextColor(bgColor) elseif randf4 then bgColor = generateDarkColor4 textColor = getContrastingTextColor(bgColor) elseif randf5 then bgColor = generateDarkColor5 textColor = getContrastingTextColor(bgColor) elseif randf6 then bgColor = generateDarkColor6 textColor = getContrastingTextColor(bgColor) elseif randf7 then bgColor = generateDarkColor7 textColor = getContrastingTextColor(bgColor) elseif randf8 then bgColor = generateDarkColor8 textColor = getContrastingTextColor(bgColor) elseif randf9 then bgColor = generateDarkColor9 textColor = getContrastingTextColor(bgColor) elseif randf10 then bgColor = generateDarkColor10 textColor = getContrastingTextColor(bgColor) elseif randf11 then bgColor = generateRandomColor textColor = getContrastingTextColor(bgColor) else bgColor = "#" .. string.format("%06x", math.random(0x000000, 0xFFFFFF)) bgColor = bgColor .. "00" -- append alpha value (00 for fully transparent) textColor = "#000000" end

generatedColors[modified_key] = {bgColor = bgColor, textColor = textColor} end

bgStyle = string.format("background-color: %s; color: %s;", bgColor, textColor) bgStyles[modified_key] = bgStyle end for _, val in pairs(args) do               if val == value and val ~= "" then local alreadyAdded = string.match(output, val:gsub("^%l", string.upper)) if not alreadyAdded then output = output .. string.format(' %s \n \n', args.style or "", bgStyle, val:gsub("^%l", string.upper)) matchedKeys[modified_key] = true matched = true break end end end end modified_key = modified_key:gsub("%*+$", "") -- Remove the last asterisks until not modified_key:match(".*%*+%*$") or matched

-- local randFlag = args["*rand"] == "yes" -- Check if *rand=yes flag is present   if randFlag then        bgColor = generateRandomColor -- Generate a random color    else        -- Handle other cases or default behavior for background color    end -- Handle infinite occurrences of modified_key:match(".*%*$")

--local modified_key = key:gsub("^%D*(%d+).*", "%1") -- if tonumber(string.sub(key, 1, 1)) ~= nil then        modified_key= string.sub(key, 2)  -- Exclude the first character if it's a number    end if key ~= 'image'and not key:match("^image[%a%d]+$") --and not (key:sub(1, 5)=="image") and key ~= 'caption' and not key:match(".*%*$") and key ~= 'headcolor' and key ~= 'color' and key~='header' and not key:match("^abv%d+$")and not key:match("^up[%a%d]+$") and not key:match("^%d+mdl[%a%d]+$") then if key ~= 'up' and not (key:sub(1, 2) == 'up'=="image"and upProcessed) and key ~= 'abv'and key~="imagesize" and key~="rd" and not abvProcessed and not key:match("^Rd%d+$")then --if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed) then if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and not key:match("^rd%d+$") and not key:match("^mdl[%a%d]+$")then if key~="size" and not key:match("^size[%a%d]+$")and not(key:sub(-1)=="+") and not key:match("^caption[%a%d]+$") and key~="rd"and not(key:sub(1, 3)=="mdl") and not key:match("^(%d+)mdl") then --//m local convertedValue = value local originalValue = value if not cmProcessed and (value:match("%s*cm#%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")) then -- If centimeters conversion not done yet, do it here --cmProcessed = true convertedValue = cmToFeetAndInches(value) end --/////❗                 if type(value) == "string" then local age=dateCalculation(value) --                       --local ag = calculateAg(value ) --if value:match("%d%d%d%d[/.-]%d%d[/.-]%d%d[./-]") then if value:match("%d+%d+%d+[./-]") then --value =value:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "%1".. age )--:gsub("(%d%d%d%d)", "") value =value:gsub("(%d+%d+%d+)[/.-]", "".. age ):gsub("%d+[./-]", "")--:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "".. age ) --else --value="Invalid date format" end --end value = value:gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("", "") value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "") --[[ if value:match("%d+%d+%d+[/.,~]") then   value = value:gsub("(%d+%d+%d+)[/.,~]", "%1"..age) end

value = value:gsub("(%d%d%d%d)[. /-] (%d%d)[/-.] (%d%d)", ""):gsub("(%d%d)[. - /] (%d%d)", ""):gsub("", "") --value = value:gsub("(%d%d%d%d)%p(%d%d)%p(%d%d)", ""):gsub("", "") ]]

if value:match("%s*cm%W%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")  then convertedValue = cmToFeetAndInches(value).."" elseif value:match("%s*kg%W%s*") or value:match("%s*kgs#%s*")or value:match("%s*kilograms#%s*") or value:match("%s*kilogram#%s*") then convertedValue = kgToPounds(value) elseif value:match("%s*mph#%s*")or value:match("%s*mp/h#%s*")or value:match("%s*miles per hour#%s*")or value:match("%s*mile per hour#%s*") then convertedValue = mphToKmh(value) elseif value:match("%s*kmh#%s*")or value:match("%s*km/h#%s*")or value:match("%s*kilometers per hour#%s*")or value:match("%s*kilometer per hour#%s*")or value:match("%s*kilometres per hour#%s*")or value:match("%s*kilometre per hour#%s*") then convertedValue = kmhToMph(value) elseif value:match("%s*kms#%s*")or value:match("%s*km#%s*")or value:match("%s*kilometer#%s*")or value:match("%s*kilometers#%s*")or value:match("%s*kilometre#%s*")or value:match("%s*kilometres#%s*") then convertedValue = kmToMi(value) elseif value:match("%s*mi#%s*")or value:match("%s*mile#%s*")or value:match("%s*miles#%s*") then convertedValue = miToKm(value) elseif value:match("%s*hp#%s*")or value:match("%s*hps#%s*")or value:match("%s*horsepower#%s*")or value:match("%s*horsepowers#%s*") then convertedValue = hpToKw(value) elseif value:match("%s*kw#%s*")or value:match("%s*kws#%s*")or value:match("%s*kilowatt#%s*")or value:match("%s*kilowatts#%s*") then convertedValue = kwToHp(value)                   elseif value:match("%s*ft#%s*") then                                          elseif value:match("%s*lb#%s*")or value:match("%s*pound#%s*")or value:match("%s*pounds#%s*") then convertedValue = lbToKg(value) elseif value:match("%s*mmms#%s*")or value:match("%s*mm#%s*")or value:match("%s*millimeter#%s*")or value:match("%s*millimetre#%s*")or value:match("%s*millimeters#%s*")or value:match("%s*millimetres#%s*") then convertedValue = mmToInches(value) elseif value:match("%s*in#%s*")or value:match("%s*ins#%s*")or value:match("%s*inch#%s*")or value:match("%s*inche#%s*")or value:match("%s*inches#%s*") then convertedValue = inchesToMm(value) elseif value:match("%s*ms#%s*")or value:match("%s*millisecond#%s*")or value:match("%s*milliseconds#%s*") then convertedValue = msToFts(value) elseif value:match("%s*fts#%s*")or value:match("%s*ft/s#%s*")or value:match("%s*fps#%s*")or value:match("%s*footperseconds#%s*") then convertedValue = ftsToMs(value) elseif value:match("%s*°c#%s*") or value:match("%s*celsius#%s*") or value:match("%s*Celsius#%s*") then convertedValue = celsiusToFahrenheit(value) elseif value:match("%s*°f#%s*") or value:match("%s*fahrenheit#%s*") then convertedValue = fahrenheitToCelsius(value) --❗                        elseif value:match("%s*liters#%s*")or value:match("%s*litres#%s*")or value:match("%s*litre#%s*")or value:match("%s*liter#%s*") then convertedValue = litersToGallons(value) elseif value:match("%s*gallons#%s*")or value:match("%s*gallon#%s*") then convertedValue = gallonsToLiters(value) elseif value:match("%s*m³#%s*")or value:match("%s*m3#%s*")or value:match("%s*cubicmeters#%s*")or value:match("%s*cubicmetres#%s*")or value:match("%s*cubicmetre#%s*")or value:match("%s*cubicmeter#%s*") then convertedValue = cubicMetersToCubicFeet(value) elseif value:match("%s*ft³#%s*")or value:match("%s*ft3#%s*")or value:match("%s*cubicfeet#%s*")or value:match("%s*cubicfoot#%s*")or value:match("%s*cubicfeets#%s*")or value:match("%s*cubicfoots#%s*") then convertedValue = cubicFeetToCubicMeters(value)                                        elseif value:match("%s*sqm#%s*")or value:match("%s*sqms#%s*")or value:match("%s*sqmetre#%s*")or value:match("%s*sqmetres#%s*")or value:match("%s*squaremeter#%s*")or value:match("%s*squaremeters#%s*")or value:match("%s*sqmeter#%s*")or value:match("%s*sqmeters#%s*") then convertedValue = squareMetersToSquareFeet(value) elseif value:match("%s*sqft#%s*")or value:match("%s*sqfoot#%s*")or value:match("%s*sqfeet#%s*")or value:match("%s*squarefoots#%s*")or value:match("%s*squarefeets#%s*")or value:match("%s*squarefeet#%s*") then convertedValue = squareFeetToSquareMeters(value) elseif value:match("%s*hectares#%s*")or value:match("%s*hectare#%s*") then convertedValue = hectaresToAcres(value) elseif value:match("%s*acres#%s*")or value:match("%s*acre#%s*") then convertedValue = acresToHectares(value) elseif value:match("%s*hours#%s*")or value:match("%s*hour#%s*") then convertedValue = hoursToMinutes(value) elseif value:match("%s*minutes#%s*")or value:match("%s*minute#%s*") then convertedValue = minutesToHours(value) elseif value:match("%s*days#%s*")or value:match("%s*day#%s*") then convertedValue = daysToHours(value) elseif value:match("%s*joules#%s*")or value:match("%s*joule#%s*") then convertedValue = joulesToCalories(value) elseif value:match("%s*calories#%s*")or value:match("%s*calorie#%s*") then convertedValue = caloriesToJoules(value) elseif value:match("%s*kwh#%s*")or value:match("%s*kilowatthours#%s*")or value:match("%s*kilowatthour#%s*") then convertedValue = kilowattHoursToJoules(value) elseif value:match("%s*psi#%s*")or value:match("%s*pounds per square inch#%s*")or value:match("%s*pound per square inches#%s*") then convertedValue = psiToPascals(value) elseif value:match("%s*pascals#%s*")or value:match("%s*pascal#%s*") then convertedValue = pascalsToPsi(value) elseif value:match("%s*atm#%s*")or value:match("%s*atmospheres#%s*")or value:match("%s*atmosphere#%s*") then convertedValue = atmospheresToPascals(value) elseif value:match("%s*rpm#%s*") then convertedValue = rpmToHertz(value) elseif value:match("%s*kilohertz#%s*")or value:match("%s*khz#%s*") then convertedValue = kilohertzToHertz(value) elseif value:match("%s*hertz#%s*") then convertedValue = hertzToRPM(value) elseif value:match("%s*horsepower#%s*") then convertedValue = horsepowerToWatts(value) elseif value:match("%s*megawatts#%s*") or value:match("%s*megawatt#%s*")then convertedValue = megawattsToHorsepower(value) elseif value:match("%s*watts#%s*") or value:match("%s*watt#%s*")then convertedValue = wattsToHorsepower(value) elseif value:match("%s*hp#%s*") then convertedValue = horsepowerToMegawatts(value) elseif value:match("%s*m#%s*")or value:match("%s*meters#%s*")or value:match("%s*metres#%s*")or value:match("%s*meter#%s*")or value:match("%s*metre#%s*") then convertedValue = mToFeet(value) elseif value:match("%s*ft%W%s*") or value:match("%s*feet%P%s*")or value:match("%s*feets%P%s*")or value:match("%s*foot%P%s*")or value:match("%s*foots%P%s*") then --local ft=convertedValue --convertedValue =convertValue:gsub("^ft[%a%d]+$", "" .. ft) --ftToCm(value) value =ftToCm(value) end --local age=calculateAge(value) --value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "")

--❗           modified_key = key:gsub("^[_%d]*", "")

value = value:gsub("^%l", string.upper) local first_char = value:match("%a") -- Find the first alphabet character if first_char then value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character end output = output .. '| style="font-size:15px; font-weight:bolder;padding-right:1em;" | ' ..modified_key:gsub("^[_%-%d]*", "") .. "\n" if originalValue ~= convertedValue then output = output .. '| '..convertedValue.. '\n|-\n' else output = output .. '| ' .. value .. '\n|-\n' end

end end end end end end

--[[

local values = {}

for key, value in pairs(args) do   if key:sub(1, 3) == 'abv' and value ~= "" then table.insert(values, {key = key, value = value}) end end table.sort(values, function(a, b) return a.key < b.key end) for _, entry in ipairs(values) do   local key = entry.key local value = entry.value output = output .. '| style="background:lightgray;font-size:20px;text-align:center;background-color:' .. (args.abvheadcolor or "#f2f2f2") .. ';color:' .. (args.abvcolor or "inherit") .. ';font-weight:bold;" | ' .. value .. '\n|-\n' end mw.text.unstrip

local frame = mw.getCurrentFrame --local infoboxContent = frame:preprocess('')

local function transcludeTemplate(templateName, args) local frame = mw.getCurrentFrame local templateContent = frame:expandTemplate { title = templateName, args = args } return templateContent end ]] --local frame = mw.getCurrentFrame local values = {}

for key, value in pairs(args) do   if key:sub(1, 3) == "abv" and value ~= "" then table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") }) end end

table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)

for _, entry in ipairs(values) do   local key = entry.key local value = entry.value value = value:gsub("^%l", string.upper) local first_char = value:match("%a") -- Find the first alphabet character if first_char then value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character end output = output .. '  '.. value .. ' \n|-\n' --output = mw.getCurrentFrame:preprocess('') end output = output .. ' \n' --  output = mw.getCurrentFrame:preprocess('') return output end

return p