Module:GU Page

From the RuneScape Wiki, the wiki for all things RuneScape
Jump to navigation Jump to search
Module documentation
This documentation is transcluded from Module:GU Page/doc. [edit] [history] [purge]
Module:GU Page's function main is invoked by Template:GU Page.
Module:GU Page requires Module:DPLlua.
Function list
L 6 — p.main
L 13 — p.get_args_subjects
L 26 — p.headfoot
L 53 — p._main
L 102 — p.list_pages
L 143 — p.bracket_match
L 173 — p.get_gu_section
L 216 — p.check_article_for_subjects
L 231 — p.extract_subject_gu_from_article
L 253 — p.get_subject_header_start_position
L 267 — p.get_all_subjects
L 282 — p.get_subject

Makes Graphical updates pages.


-- <nowiki>
local p = {}
local dpl = require('Module:DPLlua')
local MAX_PER_PAGE = 300  -- About 3 seconds time usage

function p.main(frame)
	local args = frame:getParent().args
	local page_no = tonumber(args.page) or 1
	local subjects, subjectcats = p.get_args_subjects(args)
	return p._main(args, page_no, subjects, subjectcats)
end

function p.get_args_subjects(args)
	local subjects, cats = {}, {}
	for i = 1, 20 do --arbitrary limit of 20 subjects
		if args['subject'..i] ~= nil then
			local subj = args['subject'..i]
			table.insert(subjects, subj)
			subj = string.gsub( string.lower( subj or ""), "s$", "")
			table.insert(cats, "Graphical updates with subject " .. subj)
		end
	end
	return subjects, cats
end

function p.headfoot(cats, subjectcats)
	local title = mw.title.getCurrentTitle().text
	local big_list = p.list_pages(cats, subjectcats, 5000, 0)
	local total_results = #big_list
	local shorter_title = title:match("(.+)/") -- grab everything up to but not including last /
	if shorter_title == nil then
		shorter_title = ''
	end
	if total_results<=MAX_PER_PAGE then
		return ""
	end
	local total_full_pages = math.floor((total_results - 1) / MAX_PER_PAGE)
	local starts,ends = {},{}
	for i = 1,total_full_pages do
		table.insert(starts,big_list[(i-1)*MAX_PER_PAGE+1])
		table.insert(ends,big_list[i*MAX_PER_PAGE])
	end
	table.insert(starts,big_list[total_full_pages*MAX_PER_PAGE+1])
	table.insert(ends,big_list[total_results])
	local res = {}
	for i = 1,total_full_pages+1 do
		table.insert(res,"[[" .. shorter_title .. "/" .. tostring(i) .. "|" .. starts[i] .. " to " .. ends[i] .. "]]")
	end
	return table.concat(res,"\n\n")
end


function p._main(cats, page_no, subjects, subjectcats)
	local headfoot_text = p.headfoot(cats, subjectcats)
	local off = MAX_PER_PAGE*(page_no-1)
	local pages = p.list_pages(cats, subjectcats, MAX_PER_PAGE, off)

	if pages[1] then
		table.sort(pages)

		-- Header and footer if there are multiple GU pages for these categories
		local head_text,foot_text = "",""
		if headfoot_text ~= "" then
			local catstr = "The following pages cover graphical updates of"
			for _,v in ipairs(cats) do
				if v ~= '' and string.sub(v, 1, 1) ~= '!' then
					catstr = catstr .. " " .. v
				end
			end
			catstr = catstr .. "\n\n"
			head_text = catstr .. headfoot_text
			foot_text = "==See also==\nThere are more graphical updates avaliable,\n\n" .. headfoot_text
		end

		local gu_all = {}
		local section = 'DEFAULT'
		if head_text ~="" then
			table.insert(gu_all,head_text)
		end
		table.insert(gu_all,"__NOEDITSECTION__\n{{Alphabetical header}}")
		for _,page in pairs(pages) do
			local pagegu = p.get_gu_section(page,subjects) --getting page first
			if (pagegu ~= '' and pagegu ~= nil) then
				if string.sub(page,1,1)~=section then
					section = string.sub(page,1,1)
					table.insert(gu_all,"=="..section.."==")
				end
				table.insert(gu_all,pagegu)
			end
		end
		if foot_text ~=""  then
			table.insert(gu_all,foot_text)
		end
		local gu_string = table.concat(gu_all,"\n")
		local ret = mw.getCurrentFrame():preprocess(gu_string)
		return ret
	else
		return "No graphical updates found"
	end
end

function p.list_pages(cats, subjectcats, quantity, offset)
	local andcats = { 'Pages with graphical updates' } -- Page must have all of these categories
	local notcats = { 'Graphical updates' } -- GU gallery pages should be excluded
	local orcats = {} -- Page must have at least one of these categories

	for _,v in ipairs(cats) do
		if v ~= '' then
			if string.sub(v, 1, 1) == '!' then
				table.insert(notcats, string.sub(v, 2))
			else
				table.insert(andcats, v)
			end
		end
	end

	for _, v in ipairs(subjectcats) do
		if v ~= '' then
			table.insert(orcats, v)
		end
	end
	if #orcats > 0 then
		table.insert(andcats, table.concat(orcats, '|'))
	end

	local dpltable = {
		namespace = '',
		category = andcats,
		ordermethod = "title",
		count = quantity,
		offset = offset
	}
	if #notcats > 0 then
		dpltable['notcategory'] = notcats
	end

	local page_list = dpl.ask(dpltable)
	page_list['DPL time']=nil
	page_list['Parse time']=nil
	return page_list
end

function p.bracket_match(text,init)
	local lefts = text:gmatch("(){") -- locations of left brackets
	local rights = text:gmatch("()}")
	local brackets = {}
	for x in lefts do
		brackets[x]=1
	end
	for x in rights do
		brackets [x]=-1
	end

	--order by keys for easy iteration
	local ordered_brackets = {}
	for k in pairs(brackets) do
		table.insert(ordered_brackets, k)
	end
	table.sort(ordered_brackets)

	--Look for same number of { as }
	local open_left=0
	for i = 1, #ordered_brackets do
		open_left = open_left + brackets[ ordered_brackets[i] ]
		if open_left==0 and ordered_brackets[i]>init then
			return ordered_brackets[i]
		end
	end

	return #text --handle init too big and syntax errors
end

function p.get_gu_section(title_text,subjects)
	local article = mw.title.new(title_text):getContent()
	local _ , a = article:find("==Graphical updates==")
	if a then
		article = article:sub(a+1) -- remove everything before GU section
		local last_gu=0
		local gu_pos = article:gmatch("(){{GU|")
		for x in gu_pos do
			if x>last_gu then
				last_gu = x
			end
		end
		local last_bracket = p.bracket_match(article,last_gu)
		article = article:sub(0,last_bracket)
		article = article:gsub("===","====")
	else -- skip if no graphical updates section found
		article	= ""
	end

    if #subjects > 0 then
		local subjectsgus = p.check_article_for_subjects(article,subjects)
		if subjectsgus == '' then
			return ''
		else
			article = subjectsgus
		end
    end

	--close unclosed comments
	local left_comment = article:gmatch("()<!--") -- locations of left comments
	local right_comment = article:gmatch("()-->")
	local left_count, right_count = 0, 0
	for _ in left_comment do
		left_count = left_count+1
	end
	for _ in right_comment do
		right_count = right_count+1
	end
	local close_comments = string.rep( "--> ", left_count-right_count )

	return "===[[" .. title_text .. "]]===" .. article .. close_comments
end

function p.check_article_for_subjects(article,filtersubjects)
	local articlesubjects = p.get_all_subjects(article)

    local subjectsgus = ''
	for _, avalue in pairs(articlesubjects) do --looping through subjects of the article
		for _, fvalue in pairs(filtersubjects) do --looping through subjects that were requested
			if avalue == fvalue then --found a match
				subjectsgus = subjectsgus .. p.extract_subject_gu_from_article(article,fvalue,#filtersubjects)
			end
		end
	end

    return subjectsgus
end

function p.extract_subject_gu_from_article(article,subject,filtersubjectsamount)
	local pos = p.get_subject_header_start_position(article,subject)
    local gu = article:sub(pos)
	local throwaway
	pos, throwaway = string.find(gu,"{")
	pos, throwaway = string.find(gu,"====",pos)
	gu = gu:sub(1,pos) --extract the specific subject GU
	pos, throwaway = string.find(gu,"}[^}]*$")
    gu = gu:sub(1,pos) --remove everything after the final closing curly bracket
    if (filtersubjectsamount == 1) then --remove header if only one subject
		throwaway, pos = string.find(gu,"====")
		if pos ~= nil then
			pos = pos + 1
			gu = gu:sub(pos)
			throwaway, pos = string.find(gu,"====\n")
			pos = pos + 1
			gu = gu:sub(pos)
		end
	end
	return '\n'..gu
end

function p.get_subject_header_start_position(article,subject)
	local pos, _ = string.find(article,'{{GU|subject='..subject)
	local prevgu = article:sub(1, pos)
	local headerpos, _ = string.find(prevgu,"====[^====]*$")
	if (headerpos ~= nil) then
		headerpos = headerpos - 1
		prevgu = prevgu:sub(1, headerpos)
		headerpos, _ = string.find(prevgu,"====[^====]*$")
	else
		headerpos = pos
	end
	return headerpos
end

function p.get_all_subjects(article)
	local subjects = {}
	local position = 1
	while true do --looking for all subjects
		local subject, position_candidate
		subject, position_candidate = p.get_subject(article,position)
		if position_candidate then position = position_candidate end
		if (subject == nil) then --no (more) subjects found
			break
		end
		table.insert(subjects, subject)
	end
	return subjects
end

function p.get_subject(article,position)
	local _ , pos = string.find(article,'|subject=',position)
	if pos == nil then --no subject found
		return nil,nil
	end
    pos = pos + 1
    local subject = article:sub(pos) -- remove everything before the subject
    local endpos = string.find(subject, "\n")
    endpos = endpos - 1
    subject = string.sub(subject,1,endpos) -- remove everything after the subject
    local nextpos = pos + endpos
    return subject,nextpos
end

return p