Module:Match/Dota

From TwogPedia
< Module:Match
Revision as of 21:59, 18 October 2023 by Couchor (talk | contribs)

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

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

local VariablesLua = mw.ext.VariablesLua
-- add picks/bans to hover 
function DotaMatch.main(map, hover, i)
	local mapHeader = mw.html.create('div'):wikitext('Map ' .. i .. ' '):attr('style', 'font-size: 0.9rem;')
	-- VODs etc
	if map.yt then
		mapHeader:wikitext('[[File:Youtube.png|20x20px|https://www.youtube.com/watch?v=' .. map.yt .. ']]')
	end
	if map.id then
		mapHeader:wikitext('[[File:Dotabuff.png|20x20px|https://www.dotabuff.com/matches/' .. map.id .. ']]')
		mapHeader:wikitext('[[File:Datdota.png|20x20px|https://www.datdota.com/matches/' .. map.id .. ']]')
		mapHeader:wikitext('[[File:Stratz.png|20x20px|https://stratz.com/matches/' .. map.id .. ']]')
	end

	hover:node(mapHeader)
	local dire = map.dire or 'unknown'
	local picks = mw.html.create('div'):addClass('details-game')
	local p1picks = mw.html.create('div'):addClass(dire == '1' and 'details-picks dire' or 'details-picks radiant')
	local p2picks = mw.html.create('div'):addClass(dire == '2' and 'details-picks dire' or 'details-picks radiant')
	local iconSize = '28px'
	-- Loop through first teams picks
	if map.p1picks then
		local p1picksSplit = mw.text.split(map.p1picks, ',')
		for j = 1, #p1picksSplit do
			local hero = getHero(mw.text.trim(p1picksSplit[j]))
			--p1picks:wikitext('[[File:' .. w .. '-icon.png|20px]]')
			p1picks:node(mw.html.create('div'):wikitext('[[File:' .. hero .. '.png|' .. iconSize .. '|' .. hero .. ']]'))
		end
	end
	
	-- create the duration/winner part
	local duration = mw.html.create('div'):addClass('details-duration')
		:node(mw.html.create('div'):wikitext(map.winner == '1' and 'W' or ''))
		:node(mw.html.create('div'):node(mw.html.create('abbr'):attr('title', 'Map duration'):wikitext(map.duration)))
		:node(mw.html.create('div'):wikitext(map.winner == '2' and 'W' or ''))

	-- Loop through second teams picks
	if map.p2picks then
		local p2picksSplit = mw.text.split(map.p2picks, ',')
		for j = 1, #p2picksSplit do
			local hero = getHero(mw.text.trim(p2picksSplit[j]))
			--p1picks:wikitext('[[File:' .. w .. '-icon.png|20px]]')
			p2picks:node(mw.html.create('div'):wikitext('[[File:' .. hero .. '.png|' .. iconSize .. '|' .. hero .. ']]'))
		end
	end
	hover:node(picks:node(p1picks):node(duration):node(p2picks))

	local bans = mw.html.create('div'):addClass('details-game')
	local p1bans = mw.html.create('div'):addClass('details-picks'):addClass( dire == '1' and 'details-picks dire' or 'details-picks radiant')
	local p2bans = mw.html.create('div'):addClass('details-picks'):addClass( dire == '2' and 'details-picks dire' or 'details-picks radiant')
	
	-- Loop through first teams bans
	if map.p1bans then
		local p1bansSplit = mw.text.split(map.p1bans, ',')
		for j = 1, #p1bansSplit do
			local hero = getHero(mw.text.trim(p1bansSplit[j]))
			--p1picks:wikitext('[[File:' .. w .. '-icon.png|20px]]')
			p1bans:node(mw.html.create('div'):wikitext('[[File:' .. hero .. '.png|' .. iconSize .. '|' .. hero .. ']]'))
		end
	end
		
	-- Loop through second teams bans
	if map.p2bans then
		local p2bansSplit = mw.text.split(map.p2bans, ',')
		for j = 1, #p2bansSplit do
			local hero = getHero(mw.text.trim(p2bansSplit[j]))
			--p1picks:wikitext('[[File:' .. w .. '-icon.png|20px]]')
			p2bans:node(mw.html.create('div'):wikitext('[[File:' .. hero .. '.png|' .. iconSize .. '|' .. hero .. ']]'))
		end
	end
	
	hover:node(bans:node(mw.html.create('div'):addClass('w-100'):wikitext('Bans')):node(mw.html.create('div'):addClass('w-100'):node(p1bans):node(p2bans)))
	
	
	return ''
end

function DotaMatch.picksBans(maps, p1_api, p2_api, hover, results, frame)
	if #maps > 0 then
		for i = 1, #maps do
			local map = maps[i]
			if map.id and map.winner and not map.p1picks and not map.p1bans then
				local tables = 'Maps_Dota'
				local fields = 'winner, p1picks, p2picks, p1bans, p2bans, dire, fp, p1kills, p2kills, duration'
				local whereStr = 'api_id="' .. map.id .. '" AND winner IS NOT NULL'
			
				local cargoArgs = {
					where = whereStr
				}
				
				local results = cargo.query(tables, fields, cargoArgs)
				if #results == 0 then
			        local mapData = mw.ext.externaldata.getWebData({
			        	url = 'https://api.opendota.com/api/matches/' .. map.id,
						format = 'CSV with header',
					})
              
					if mapData then
						local json = mw.text.jsonDecode(mapData.__text)
						local pickBans = json.picks_bans
						map.p1picks = ''
						map.p2picks = ''
						map.p1bans = ''
						map.p2bans = ''
						local fp = nil
						for j = 1, #pickBans do
							local selection = pickBans[j]
							if j == 1 then fp = selection.team end
							if selection.is_pick then 
								map['p' .. selection.team + 1 .. 'picks'] = map['p' .. selection.team + 1 .. 'picks'] .. getHero(selection.hero_id) .. ','
							else
								map['p' .. selection.team + 1 .. 'bans'] = 	map['p' .. selection.team + 1 .. 'bans'] .. getHero(selection.hero_id) .. ','
							end
						end
		                
			            map.p1picks = removeEndComma(map.p1picks)
		                map.p2picks = removeEndComma(map.p2picks)
		                map.p1bans = removeEndComma(map.p1bans)
		                map.p2bans = removeEndComma(map.p2bans)
		                -- 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
		                -- set winner
		                -- if json.radiant_win then 
		                -- 	map.winner = dire == 1 and 2 or 1
		                -- else
		                -- 	map.winner = dire == 1 and 1 or 2
		                -- end

		                if not map.dire and dire then
							map.dire = dire
		                end
		                if not map.fp and fp ~= nil then
		                	if fp == 0 then
		                		map.fp = dire == 1 and 2 or 1
		                	else
		                		map.fp = dire
		                	end
		                end
		                local radiantKills = json.radiant_score
		                local direKills = json.dire_score
		                if not map.p1kills then
		                	map.p1kills = dire == 1 and direKills or radiantKills
		                end
		                if not map.p2kills then
		                	map.p2kills = dire == 2 and direKills or radiantKills
		                end
		                
						local duration = json.duration
						local seconds = duration % 60
						
						local minutes = (duration - seconds) / 60
						if seconds < 10 then seconds = "0" .. tostring(seconds) end
						map.duration = minutes .. ':' .. seconds
					end
				else
					map.p1picks = results[1].p1picks
					map.p2picks = results[1].p2picks
					map.p1bans = results[1].p1bans
					map.p2bans = results[1].p2bans
					map.dire = results[1].dire
					map.fp = results[1].fp
					map.p1kills = results[1].p1kills
					map.p2kills = results[1].p2kills
					map.duration = results[1].duration
				end
			else 
				-- Go through normal picks and bans and turn them into proper hero names
				if map.p1picks then map1.p1cks = listToNames(map, map.p1picks, "p1picks") end
				if map.p2picks then map1.p2picks = listToNames(map, map.p2picks, "p2picks") end
				if map.p1bans then map1.p1bans = listToNames(map, map.p1bans, "p1bans") end
				if map.p2bans then map1.p2bans = listToNames(map, map.p2bans, "p2bans") end
			end
			
			frame:callParserFunction{name = '#cargo_store:', args = {_table = 'Maps_Dota', map=i, api_id = map.id, matchID = results[1]._ID, duration = map.duration, p1picks = map.p1picks, p2picks = map.p2picks, p1bans = map.p1bans, p2bans = map.p2bans, dire = map.dire, fp = map.fp, winner = map.winner, p1kills = map.p1kills, p2kills = map.p2kills, yt = map.yt, vod = map.vod}}

			DotaMatch.main(map, hover, i, results)
		end
    	
	end
	return map
end

function listToNames(map, list, var)
	local split = mw.text.split(list, ',')
	map[var] = ''

	for i = 1, #split do 
		map[var] = map[var] .. getHero(mw.text.trim(split[i])) .. ','
        map[var] = removeEndComma(map[var])
	end
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 removeEndComma(inputString)
    -- Use the string.match function to check if the string ends with a comma
    if inputString:match(",$") then
        -- If it does, use string.sub to remove the last character (the comma)
        return inputString:sub(1, -2)
    else
        -- If not, return the input string as it is
        return inputString
    end
end

return DotaMatch