Module:MapData

From TwogPedia
Revision as of 22:28, 20 October 2023 by Couchor (talk | contribs)

Documentation for this module may be created at Module:MapData/doc

local cargo = mw.ext.cargo
local getArgs = require('Module:Arguments').getArgs
local heroesData = mw.loadData('Module:Data/Dota/Heroes')

local p = {}

function p.main(frame)
	local args = getArgs(frame)
	local game = args.game

	if args.size == 'team' then
		local p1_api = getTeamPage(args.p1, game)
		local p2_api = getTeamPage(args.p2, game)

        		

		local warnings = mw.html.create('div')
		local container = mw.html.create('div'):node(warnings)
		local output = mw.html.create('div')

        if p2_api and p1_api == nil then warnings:wikitext(args.p1 .. ' does not have an api_id entered') end
        if p1_api and not p2_api == nil then warnings:wikitext(args.p2 .. ' does not have an api_id entered') end
        
		
		if not p1_api and not p2_api then warnings:wikitext('Neither team has their api entered in their infobox. The Map/Dota string will need manual entry for more or less everything') end 
		
		if game == 'Dota2' then
			local str = ''
			local mapData = mw.ext.externaldata.getWebData({
	        	url = 'https://api.opendota.com/api/matches/' .. args.api,
				format = 'CSV with header',
			})
		
			if mapData then
				local json = mw.text.jsonDecode(mapData.__text)
				local pickBans = json.picks_bans

				local radiantPicks = {}
				local direPicks = {}
				local radiantBans = {}
				local direBans = {}
				local radiantPlayers = {}
				local direPlayers = {}
				local players = json.players

				local fp = nil
				for j = 1, #pickBans do
					local selection = pickBans[j]
					-- If first ban, then set if fp is radiant (0) or dire (1)
					if j == 1 then fp = selection.team end

					if selection.is_pick then
						if selection.team == 0 then
							table.insert(radiantPlayers, getPlayer(players, selection.hero_id))
							table.insert(radiantPicks, getHero(selection.hero_id))
						else
							table.insert(direPlayers, getPlayer(players, selection.hero_id))
							table.insert(direPicks, getHero(selection.hero_id))
						end
					else
						if selection.team == 0 then
							table.insert(radiantBans, getHero(selection.hero_id))
						else
							table.insert(direBans, getHero(selection.hero_id))
						end
					end
				end
				
	            -- Check if dire team had api_id entered
	            local dire_id = json.dire_team_id
	            local dire = dire_id == tonumber(p1_api) and 1 or dire_id == tonumber(p2_api) and 2 or nil
	            -- If dire team doesn't have api_id entered, then check if maybe radiant does
	            if dire == nil then
	            	local radiant_id = json.radiant_team_id
	            	local radiant = radiant_id == tonumber(p1_api) and 1 or radiant_id == tonumber(p2_api) and 2 or nil
	            	if radiant then dire = radiant == 1 and 2 or 1 end
	            end
	            
	            
	            local duration = json.duration
				local seconds = duration % 60
				
				local minutes = (duration - seconds) / 60
				if seconds < 10 then seconds = "0" .. tostring(seconds) end
				local duration = minutes .. ':' .. seconds
				
	            -- If neither team had api, then spell out which team did what and user has to manually assign
	            if dire == nil then
	            	local radiant_team = json.radiant_team
	            	local radiant_name = radiant_team.name
	            	local radiant_api = radiant_team.team_id
	            	local radiantStr = 'Radiant side is team ' .. radiant_name .. ' with API_ID: ' .. radiant_api
	            	local dire_team = json.dire_team
	            	local dire_name = dire_team.name
	            	local dire_api = dire_team.team_id
	            	
	            	local radiantTh = mw.html.create('th'):wikitext(radiant_name)
	            	local direTh = mw.html.create('th'):wikitext(dire_name)
	            	local header = mw.html.create('tr'):addClass('headerRow'):node(radiantTh):node(direTh)
	            	
	            	local picksRow = mw.html.create('tr'):addClass('bodyRow'):node(td(table.concat(radiantPicks, ','))):node(td(table.concat(direPicks, ',')))
	            	local playersRow = mw.html.create('tr'):addClass('bodyRow'):node(td(table.concat(radiantPlayers, ','))):node(td(table.concat(direPlayers, ',')))
	            	local bansRow = mw.html.create('tr'):addClass('bodyRow'):node(td(table.concat(radiantBans, ','))):node(td(table.concat(direBans, ',')))
	            	local apiRow = mw.html.create('tr'):addClass('bodyRow'):node(td(radiant_api)):node(td(dire_api))
	            	local side = mw.html.create('tr'):addClass('bodyRow'):node(td('Radiant')):node(td('Dire'))
	            	local fpRow = mw.html.create('tr'):addClass('bodyRow')
	            	local winRow = mw.html.create('tr'):addClass('bodyRow')
	            	local killRow = mw.html.create('tr'):addClass('bodyRow'):node(td(json.radiant_score .. ' kills')):node(td(json.dire_score .. ' kills'))
	            	
	            	local teamTable = mw.html.create('table'):addClass('striped-table'):node(header):node(side):node(apiRow):node(fpRow):node(winRow):node(killRow):node(picksRow):node(playersRow):node(bansRow)
	            	
	            	if fp == 0 then
	            		fpRow:node(td('First pick'))
	            	else
	            		fpRow:node(td('')):node(td('First pick'))
	            	end
	            	
	            	if json.radiant_win then
	            		winRow:node(td('Winner'))
		            else
		            	winRow:node(td('')):node(td('Winner'))
		            end
		            
	            	container:node(teamTable)
	            	
	            	str = '|winner=|dire=|fp=|p1picks=|p1players=|p2picks=|p2players=|p1bans=|p2bans=|p1kills=|p2kills=' .. '|duration=' .. duration
		        else 
		            -- set winner
		            local winner = nil
		            if json.radiant_win then 
		            	winner = dire == 1 and 2 or 1
		            else
		            	winner = dire == 1 and 1 or 2
		            end
		
		            if fp ~= nil then
		            	if fp == 0 then
		            		fp = dire == 1 and 2 or 1
		            	else
		            		fp = dire
		            	end
		            end
		            local radiantKills = json.radiant_score
		            local direKills = json.dire_score
		            local p1kills = dire == 1 and direKills or radiantKills
		            local p2kills = dire == 2 and direKills or radiantKills
		            local p1picks = dire == 1 and table.concat(direPicks, ',') or table.concat(radiantPicks, ',')
		            local p2picks = dire == 2 and table.concat(direPicks, ',') or table.concat(radiantPicks, ',')
		            local p1bans = dire == 1 and table.concat(direBans, ',') or table.concat(radiantBans, ',')
		            local p2bans = dire == 2 and table.concat(direBans, ',') or table.concat(radiantBans, ',')
		            local p1players = dire == 1 and table.concat(direPlayers, ',') or table.concat(radiantPlayers, ',')
		            local p2players = dire == 2 and table.concat(direPlayers, ',') or table.concat(radiantPlayers, ',')
		            
		            str = '|winner=' .. winner .. '|dire=' .. dire .. '|fp=' .. fp .. '|p1picks=' .. p1picks .. '|p1players=' .. p1players .. '|p2picks=' .. p2picks.. '|p2players=' .. p2players .. '|p1bans=' .. p1bans .. '|p2bans=' .. p2bans  .. str .. '|p1kills=' .. p1kills .. '|p2kills=' .. p2kills .. '|duration=' .. duration
	            end
				
			else
				output:wikitext('No match found. It has to be finished before data can be fetched')
			end
			str = '{{Map/Dota|id=' .. args.api .. str .. '|yt=}}'
		
			output:wikitext(str)
		end
		
		return container:node(output)
	else
		
	end
end

function getPlayer(tbl, hero_id)
	for _, player in pairs(tbl) do
    -- Check if the current player's hero_id matches the target hero_id
    if player.hero_id == hero_id then
        -- Found the player with the desired hero_id
        local tables = 'People'
		local fields = '_pageName'
		local cargoArgs = {
			where = 'api_id="' .. player.account_id .. '"'
		}
		
		local results = cargo.query(tables, fields, cargoArgs)

		if #results > 0  then
			return results[1]._pageName
		else
			-- local player = mw.ext.externaldata.getWebData({
	  --      	url = 'https://api.opendota.com/api/players/' .. player.account_id,
			-- 	format = 'CSV with header',
			-- })
		
			-- if player then
			-- 	return player.__text.profile.name
			-- else
				return player.account_id
			-- end
		end
    end
end
end
function td (value)
	return mw.html.create('td'):wikitext(value)	
end

function getHero(idOrName)
	if type(idOrName) == "string" then idOrName = string.lower(idOrName) end
    for _, hero in ipairs(heroesData) do
        if hero.id == idOrName then
            return hero.localized_name
        else 
        	for _, name in ipairs(hero.names) do
	            if name == idOrName then
	                return hero.localized_name
	            end
	        end
        end
    end
    return "Hero not found " .. idOrName
end

function getTeamPage(team, game)
	-- Check if shorthand of a team was used
	local tables = 'Teams'
	local fields = '_pageName, shorthand, api_id'
	local cargoArgs = {
		where = 'api_id IS NOT NULL AND _pageName LIKE "' .. game .. '/%" AND ( shorthand = "' .. team .. '" OR _pageName="' .. game .. '/' .. team .. '")'
	}
	local results = cargo.query(tables, fields, cargoArgs)
	
    return #results > 0 and results[1].api_id or nil
end

return p