Dokumentation för denna modul finns på /dok (redigera), /test


Används enbart på sidan Wiktionary:Balans efter språk och ordklass.

-- obligatory named parameter "list="
-- optional named parameter "limit="
-- optional named parameter "aggressive=true"
-- optional named parameter "debug=true"
-- MUST NOT be substituted per "subst:" if "aggressive=true" used

local exporttbl = {}
local import_lang = require ("Modul:lang")

clang    = "spr" .. string.char(195,165) .. "k"
cucflang = "Spr" .. string.char(195,165) .. "k"
cbadlang = "ok" .. string.char(195,164) .. "nt " .. clang
crekn    = "r" .. string.char(195,164) .. "kn."
crekord  = "R" .. string.char(195,164) .. "kneord"
cfor     = "f" .. string.char(195,182) .. "r"

const_table_title = '<tr><th>Kod</th><th>' .. cucflang .. 'namn</th><th>Antal<br>huvud-<br>uppslag</th>'
const_table_title = const_table_title .. '<th>%<br>subst.</th><th>%<br>verb</th><th>%<br>adj.</th><th>%<br>adverb</th>'
const_table_title = const_table_title .. '<th>Former<br>per<br>subst.</th><th>Former<br>per<br>verb</th>'
const_table_title = const_table_title .. '<th>Former<br>per<br>adj.</th><th>Former<br>per<br>adv.</th>'
const_table_title = const_table_title .. '<th>Antal<br>konj.</th><th>Antal<br>subj.</th><th>Antal<br>prep.</th>'
const_table_title = const_table_title .. '<th>Antal<br>pron.</th><th>Antal<br>' .. crekn .. '</th><th>Antal<br>mallar</th></tr>'

local big_word_classes  = {"Substantiv", "Verb", "Adjektiv", "Adverb"}
local tiny_word_classes = {"Konjunktioner", "Subjunktioner", "Prepositioner", "Pronomen", crekord}

local function ucFirst(str)
  return mw.ustring.gsub(str, "^%l", mw.ustring.upper)
end

local function ifExistEnhanced (arxinp3,strpgname,aggressive_mode)
  local boomemangada = false
  local metaa = 0
  if (aggressive_mode) then -- does NOT work with substitution
    boomemangada = ( '&#91;&#91;:' .. strpgname .. '&#93;&#93;' ~= arxinp3:preprocess ('{{msgnw::' .. strpgname .. '}}') )
  else
    metaa = mw.title.new (strpgname) -- 1 param
    boomemangada = metaa.exists -- expensive
  end--if
  return boomemangada
end--function ifExistEnhanced

local function pagesInCategoryEnhanced (strcatname)
  local metab = 0
  local numpages = 0
  local numsubcats = 0
  metab = mw.site.stats.pagesInCategory ( strcatname, "*" ) -- expensive
  numpages = metab.pages
  numsubcats = metab.subcats
  if (numpages<0) then
    numpages = 0 -- YES MediaWiki is stupid
  end--if
  if (numsubcats<0) then
    numsubcats = 0 -- YES MediaWiki is stupid
  end--if
  return numpages, numsubcats
end--function pagesInCategoryEnhanced

local function floatToString (incoming_number)
  local result_conv = ''
  local decimals = 0
  local num_temp = 0
  local remainder = 0
  local conversion_index = 0
  local boo_trim_right = true
  if (incoming_number<0) or (incoming_number>3000000000) then -- 3 G max
    result_conv = '??'
  else
    if (incoming_number<30) then
      decimals = 1
    end--if
    if (incoming_number<3) then
      decimals = 2
    end--if
    if (decimals==1) then
      incoming_number = incoming_number * 10
    end--if
    if (decimals==2) then
      incoming_number = incoming_number * 100
    end--if
    incoming_number = math.floor (incoming_number+0.5) -- now integer
    while true do
      num_temp = math.floor (incoming_number / 10)
      remainder = incoming_number - (10 * num_temp)
      incoming_number = num_temp
      if ((conversion_index==decimals) and (not boo_trim_right)) then
        result_conv = "." .. result_conv
      end--if
      num_temp = conversion_index - decimals -- can be negative
      if ((num_temp==3) or (num_temp==6) or (num_temp==9)) then
        result_conv = "'" .. result_conv
      end--if
      if ((remainder~=0) or (conversion_index==decimals)) then
        boo_trim_right = false -- never back to true
      end--if
      if (not boo_trim_right) then
        result_conv = string.char(remainder+48) .. result_conv
      end--if
      conversion_index = conversion_index + 1 -- number of digits written including trimmed ones
      if ((incoming_number==0) and (conversion_index>decimals)) then
        break
      end--if
    end--while
  end--if
  return result_conv
end--function floatToString

local function secureDivide (part, whole, boo_percent)
  local my_percent = ''
  local scale = 1
  local fraction = 0
  if (boo_percent==true) then
    scale = 100
  end--if
  if (whole==0) then -- avoid criminal division by ZERO (but part>whole is legal here)
    my_percent = '??'
  else
    if (part==0) then
      my_percent = '0'
    else
      fraction = (part*scale) / whole
      if (fraction<0.03) then
        my_percent = '<0.03'
      else
        my_percent = floatToString(fraction)
      end--if
    end--if (part==0) then
  end--if
  return my_percent
end--function secureDivide

function exporttbl.go (arxframent) -- main

  local arxsomons = 0

  local temp = 0

  local lng_codes = {} -- from "list="
  local tbl_count_of_cat = {} -- backup counts

  local par_list_codes = ""
  local strlngcode = ""
  local strlngnamelc = ""
  local strlngnameup = ""
  local picked_word_class = ""
  local strcatname = ""
  local stritem = ""
  local strret = ""

  local limit_que = 0 -- shared as upvalue
  local consumed_que_total = 0 -- shared as upvalue
  local consumed_real = 0 -- shared as upvalue

  local error_code = 0 -- 0 OK | 1 ano | 2 li | 3 subst | 5 bad co | 6 cost
  local panja = 0
  local index = 0
  local posi = 0
  local chx = 0
  local numcodelen = 0

  local num_count_of_all = 0
  local num_count_of_cat = 0

  local boo_debug = false -- parameter

  local boo_existence_of_cat = false
  local boo_is_substed = false

  local boo_aggressive_ifexist = false -- shared as upvalue -- parameter
  local boo_cost_problem = false -- shared as upvalue

  arxsomons = arxframent.args -- "args" from our own "frame"
  if (arxsomons['caller']=="true") then
    arxsomons = arxframent:getParent().args -- "args" from caller's "frame"
  end--if

  local function ifExistHigh (page_name_ex) -- uses upvalues
    local boo_successcost = false
    local boo_existence = true -- bad guess
    if (consumed_que_total<limit_que) then -- upvalues
      boo_successcost,boo_existence = pcall (ifExistEnhanced, arxframent, page_name_ex, boo_aggressive_ifexist)
      if (not boo_successcost) then
        boo_cost_problem = true -- upvalue
        boo_existence = true -- bad guess -- YES do show stupid red link
      end--if
    end--if
    consumed_que_total = consumed_que_total + 1 -- inc in any case
    if (not boo_aggressive_ifexist) then
      consumed_real = consumed_real + 1
    end--if
    return boo_existence
 end--function

  local function PagesInCategoryHigh (page_name_cat) -- uses upvalues
    local boo_success_pik = false
    local result_pages = 0 -- bad guess
    local result_subcats = 0 -- bad guess
    if (consumed_que_total<limit_que) then -- upvalues
      boo_success_pik, result_pages, result_subcats = pcall (pagesInCategoryEnhanced, page_name_cat)
      if (not boo_success_pik) then
        boo_cost_problem = true -- upvalue
        result_pages = 0 -- bad guess
        result_subcats = 0 -- bad guess
      end--if
    end--if
    consumed_que_total = consumed_que_total + 1 -- inc in any case
    consumed_real = consumed_real + 1 -- inc in any case
    return result_pages, result_subcats
  end--function

  while (true) do -- fake loop

    error_code = 1 -- prepare
    if (arxsomons[1]~=nil) then
      break -- no anonymous parameters tolerated
    end--if

    error_code = 2 -- prepare -- broken "list=" parameter
    temp = arxsomons["list"]
    if (type(temp)=="string") then
      panja = string.len(temp)
      if ((panja>=2) and (panja<=100000)) then
        par_list_codes = temp
      end--if
    end--if
    if (par_list_codes=='') then
      break -- broken "list=" parameter
    end--if

    limit_que = 999999 -- default: no limit
    temp = arxsomons["limit"]
    if (type(temp)=="string") then
      panja = string.len(temp)
      if ((panja>0) and (panja<7)) then -- 0...999'999
        limit_que = tonumber (temp) or 0
      end--if
    end--if

    boo_debug = (arxsomons["debug"]=="true")
    boo_aggressive_ifexist = (arxsomons["aggressive"]=="true")

    boo_is_substed = mw.isSubsting()

    if boo_aggressive_ifexist and boo_is_substed then
      error_code = 3
      break -- this does not work together
    end--if

    error_code = 0 -- prepare -- OK
    index = 0 -- also needed far below for error complaint
    posi = 0
    panja = string.len(par_list_codes)

    while (true) do -- genuine inner loop over codes

        strlngcode = ""
        numcodelen = 0
        if (posi>=panja) then
          break -- inner loop for now
        end--if
        while (true) do -- genuine deep loop over octets
          if (posi>=panja) then
            break -- deep loop for now
          end--if
          chx = string.byte(par_list_codes,(posi+1),(posi+1))
          posi = posi + 1
          if (chx==44) then -- comma ","
            break -- deep loop for now
          end--if
          strlngcode = strlngcode .. string.char(chx)
          numcodelen = numcodelen + 1
        end--while -- deep loop
        if ((numcodelen<2) or (numcodelen>10)) then
          error_code = 2 -- broken "list=" parameter detected
          break -- inner loop
        end--if
        index = index + 1
        lng_codes[index] = strlngcode

    end--while -- genuine inner loop over codes

    if (error_code~=0) then
      break -- error inside above loop
    end--if
    if (#lng_codes==0) then
      error_code = 2 -- broken "list=" parameter detected -- empty
      break
    end--if

    table.sort(lng_codes)

    error_code = 0 -- prepare
    index = 0 -- also needed far below for error complaint

    while (true) do -- genuine inner loop over codes

      strlngcode = lng_codes[index+1]
      if (strlngcode==nil) then
        break -- done
      end--if
      boo_is_last = not lng_codes[index+2]
      strlngnamelc = import_lang.getLanguage(strlngcode)
      if (strlngnamelc==cbadlang) then
        error_code = 5 -- bad lang code detected -- inner loop for now
        break
      end--if
      strlngnameup = ucFirst(strlngnamelc)

      stritem = '<tr><td>' .. strlngcode .. '</td>' -- all base form lemmas
      stritem = stritem .. '<td>[[:Kategori:' .. strlngnameup .. '|' .. strlngnamelc .. ']]</td>'
      strcatname = strlngnameup .. "/Alla uppslag"
      num_count_of_all = PagesInCategoryHigh (strcatname)
      stritem = stritem .. '<td>[[:Kategori:' .. strcatname .. '|' .. floatToString(num_count_of_all) .. ']]</td>'

      posi = 1 -- base word class as fraction of all base form lemmas
      while true do -- genuine deep loop over big word classes
        picked_word_class = big_word_classes[posi]
        if (picked_word_class==nil) then
          break
        end--if
        strcatname = strlngnameup .. "/" .. picked_word_class
        boo_existence_of_cat = ifExistHigh ('Kategori:'..strcatname)
        num_count_of_cat = PagesInCategoryHigh (strcatname)
        if ((not boo_existence_of_cat) and (num_count_of_cat==0)) then
          stritem = stritem .. '<td>-</td>'
        else
          stritem = stritem .. '<td>[[:Kategori:' .. strcatname .. '|' .. secureDivide(num_count_of_cat,num_count_of_all,true) .. ']]</td>'
          tbl_count_of_cat[posi] = num_count_of_cat
        end--if
        posi = posi + 1
      end--while

      posi = 1 -- non-base forms divided by base forms (can be >1 or <1)
      while true do -- genuine deep loop over big word classes
        picked_word_class = big_word_classes[posi]
        if (picked_word_class==nil) then
          break
        end--if
        strcatname = strlngnameup .. "/" .. picked_word_class .. "former"
        boo_existence_of_cat = ifExistHigh ('Kategori:'..strcatname)
        num_count_of_cat = PagesInCategoryHigh (strcatname)
        if ((not boo_existence_of_cat) and (num_count_of_cat==0)) then
          stritem = stritem .. '<td>-</td>'
        else
          stritem = stritem .. '<td>[[:Kategori:' .. strcatname .. '|' .. secureDivide(num_count_of_cat,tbl_count_of_cat[posi],false) .. ']]</td>'
        end--if
        posi = posi + 1
      end--while

      posi = 1 -- raw counts for tiny word classes
      while true do -- genuine deep loop over tiny word classes
        picked_word_class = tiny_word_classes[posi]
        if (picked_word_class==nil) then
          break
        end--if
        strcatname = strlngnameup .. "/" .. picked_word_class
        boo_existence_of_cat = ifExistHigh ('Kategori:'..strcatname)
        num_count_of_cat = PagesInCategoryHigh (strcatname)
        if ((not boo_existence_of_cat) and (num_count_of_cat==0)) then
          stritem = stritem .. '<td>-</td>'
        else
          stritem = stritem .. '<td>[[:Kategori:' .. strcatname .. '|' .. floatToString(num_count_of_cat) .. ']]</td>'
        end--if
        posi = posi + 1
      end--while

      strcatname = "Wiktionary:Mallar " .. cfor .. " " .. strlngnamelc -- language-specific templates
      boo_existence_of_cat = ifExistHigh ('Kategori:'..strcatname)
      num_count_of_cat = PagesInCategoryHigh (strcatname)
      if ((not boo_existence_of_cat) and (num_count_of_cat==0)) then
        stritem = stritem .. '<td>-</td>'
      else
        stritem = stritem .. '<td>[[:Kategori:' .. strcatname .. '|' .. floatToString(num_count_of_cat) .. ']]</td></tr>'
      end--if

      strret = strret .. stritem

      if (boo_cost_problem) then -- assigned in function as upvalue
        error_code = 6
        break
      end--if
      index = index + 1

    end--while -- genuine inner loop over codes

    break -- finally to join mark
  end--while -- fake loop -- join mark

  if (error_code==0) then
    strret = '<table class="wikitable sortable" style="text-align:center>' .. const_table_title .. strret .. const_table_title .. '</table>'
  end--if

  if (error_code==1) then
    strret = 'No anonymous parameters appreciated.'
  end--if
  if (error_code==2) then
    strret = 'CSV syntax error in parameter "list=" at index ' .. tostring(index) .. '.'
  end--if
  if (error_code==3) then
    strret = 'Substitution and "aggressive=true" exclude each other.'
  end--if
  if (error_code==5) then
    strret = 'Bad language code "' .. strlngcode .. '".'
  end--if
  if (error_code==6) then
    strret = 'Cost limit exceeded with language code "' .. strlngcode .. '" at index ' .. tostring(index) .. '.'
  end--if
  if (error_code~=0) then
    strret = "ERROR: " .. strret
  end--if

  if boo_debug then
    strret = strret .. '<br>Error code : ' .. tostring (error_code)
    strret = strret .. '<br>Number of languages in list : ' .. tostring (#lng_codes)
    strret = strret .. '<br>Index on exit : ' .. tostring (index)
    strret = strret .. '<br>Limit : ' .. tostring (limit_que)
    strret = strret .. '<br>Aggressive ifexist mode : ' .. tostring (boo_aggressive_ifexist)
    strret = strret .. '<br>Subst : ' .. tostring (boo_is_substed)
    strret = strret .. '<br>Consumed possibly expensive : ' .. tostring (consumed_que_total)
    strret = strret .. '<br>Consumed really expensive : ' .. tostring (consumed_real) .. '<br>'
  end--if

  return strret

end

return exporttbl