Modul:Mathe für Nicht-Freaks/Sitemap

Aus Wikibooks

Informationen zu dieser Dokumentation
Modul Mathe für Nicht-Freaks

Es existiert keine Dokumentation. Wenn du eine anlegen willst, solltest du keine „/Doku“-Unteseite benutzen, sondern LuaDokumentation.


Information


local utils = require("Modul: Utils")
local sitemap_title = "Mathe für Nicht-Freaks: Sitemap"

local Node = {}
Node.__index = Node

function Node:new(link, name, nr, char, progress)
    link = link or "root"
    
    return setmetatable({
        link = link, name = name or link, children = {}, nr = nr, char = char, level = 0, progress = progress
    }, Node)
end

function Node:find(predicate_fn)
   if predicate_fn(self) then
       return self
   end
       
   for _, child in ipairs(self.children) do
      result = child:find(predicate_fn)
      
      if result then return result end
   end
   
   return nil
end

function Node:find_parent(predicate_fn)
   if predicate_fn(self) then
       return self
   end
       
   if self.parent ~= nil then
      return self.parent:find_parent(predicate_fn)
   end
   
   return nil
end

function Node:is_under(other_node)
    -- node2 is root node
    if other_node.char == nil then return true end
    
    -- list type of node1 shows, that it is the child of node2
    if self.char == '*' and other_node.char == '=' then return true end
    
    -- same type -> node with more chars is child of the other
    if self.char == other_node.char then return self.nr > other_node.nr end
    
    return false
end

function Node:is_over(other_node) 
    return self == other_node or (other_node.parent ~= nil and self:is_over(other_node.parent))
end

function Node:add_child(child)
    self.children[#self.children + 1] = child
    
    child.parent = self
    child.level  = self.level + 1
    child.index  = #self.children
end

function Node:next_site()
    if self.parent ~= nil then
        if self.index < #self.parent.children then
            return self.parent.children[self.index + 1]
        else
            return self.parent:next_site()
        end
    else
        return nil
    end
end

function Node:last_child()
    return self.children[#self.children]
end

function Node:add_child_at_right_position(other_node)
    local last_child = self:last_child()
    
    if last_child == nil or (other_node:is_under(self) and not other_node:is_under(last_child)) then
        self:add_child(other_node)
    else
        last_child:add_child_at_right_position(other_node)
    end
end

function Node:to_link()
    local target = self:target_node()
    local result = nil
    
    if utils.starts(target.link, "Serlo: EN: ") then
    	result = "<span class='plainlinks'>[" .. tostring(mw.uri.fullUrl(target.link, "uselang=en")) .. " " .. self.name .. "]</span>"
    else 
    	result = "[[" .. target.link .. "|" .. self.name .. "]]"
    end

    if target.progress then
        result = result .. "&nbsp;" .. mw.getCurrentFrame():expandTemplate{ title = "Symbol", args = { tostring(target.progress) .. "%" } }
    end
    
    return result
end

function Node:target_node()
    if self.level <= 1 or #self.children == 0 then
        return self
    else
        return self.children[1]:target_node()
    end
end

function Node:site_link()
    return self:target_node().link
end

local Sitemap = {}

local utils = require("Modul:Utils")

function Sitemap.parse()
    local sitemap = assert(mw.title.new(sitemap_title), "no site with name " .. sitemap_title)
    
    return Sitemap.parseSource(sitemap:getContent())
end

function Sitemap.parseSource(src)
    local lines  = string.gmatch(src, "[^\r\n]+")
    local index  = 0
    local nr     = 0
    local name   = nil
    local line   = nil
    local progress = nil
    local result = Node:new()
    
    -- iterator function over all nodes
    function nodes()
        -- get next line of source code
        line = lines()

        -- end of source -> return nil
        if line == nil then
            return nil
        end

        for _, char in ipairs({ "*", "=" }) do
            if utils.starts(line, char) then
                index = string.find(line, '[^' .. char .. ']')
                nr    = index - 1 
                name  = nil
                
                line = string.sub(line, index) -- strip `=' or `*' at the beginning
                line = mw.text.trim(line)      -- trim whitespaces
                line = mw.text.trim(line, "=") -- strip `=' at the end of the line
                line = mw.text.trim(line)      -- trim whitespaces

                progress = string.match(line, "^.*%{%{Symbol%|(%d+)%%%}%}$")

                if progress then
                   line = mw.text.trim(string.match(line, "^(.*)%{%{Symbol%|%d+%%%}%}$"))
                end 

                if utils.starts(line, "[[") and utils.ends(line, "]]") then
                    -- strip `[[' at beginning and `]]' at the end of the line
                    line = string.match(line, '^%[%[(.*)%]%]')
                    
                    index = line.find(line, '%|')
                    
                    if index then
                        name = string.sub(line, index+1)
                        line = string.sub(line, 1, index-1)
                    end
                end
                
                return Node:new(line, name, nr, char, tonumber(progress))
            end
        end
            
        -- ignore current line -> return next node
        return nodes()
    end
    
    for node in nodes do
        result:add_child_at_right_position(node)
    end

    return result
end

return Sitemap