Jump to content

Recommended Posts

  • Other Languages Moderators

Eae galera.

Encontrei um bug na lista do meu painel de ranking. Onde os valores numéricos que são decimais não ficam na ordem correta do maior pro menor nem vice-versa. Eles ficam aleatórios. Os valores inteiros ficam organizados corretamente.

Já configurei para a lista considerá-los como números usando guiGridSetItemText e setando o parâmetro number como true. Ele organiza os valores inteiros corretamente, mas os valores float não. Alguém sabe como resolver?

Segue a print mostrando o problema:

Spoiler

7bcrsFc1S6WEYa_VENlEsg.png

Os valores estão sendo cortados para somente 3 casas decimais usando a função math.round, que está funcionando perfeitamente.

Parte do script que preenche a lista:

Spoiler

function scoreInfo (names, kills, deaths, ratio, given, taken, copRatio)
	guiSetVisible (scoreWindow, true)
	guiSetVisible (closeGrid, true)
	showCursor (true)
	if names then
		for i, v in ipairs (names) do
			if type (ratio[i]) == "number" then
				ratio[i] = math.round (ratio[i], 3, "floor") -- Aplica o redutor decimal no ratio.
			end
			if type (copRatio[i]) == "number" then
				copRatio[i] = math.round (copRatio[i], 3, "floor") -- Aplica o redutor decimal no copRatio.
			end
			local row = guiGridListAddRow (scoreGrid)
			guiGridListSetItemText (scoreGrid, row, nameColumn, names[i], false, false)
			guiGridListSetItemText (scoreGrid, row, nilColumn, "|", false, false)
			guiGridListSetItemText (scoreGrid, row, killsColumn, kills[i], false, true)
			guiGridListSetItemText (scoreGrid, row, deathsColumn, deaths[i], false, true)
			guiGridListSetItemText (scoreGrid, row, ratioColumn, ratio[i], false, true)
			guiGridListSetItemText (scoreGrid, row, nullColumn, "|", false, false)
			guiGridListSetItemText (scoreGrid, row, givenColumn, given[i], false, true)
			guiGridListSetItemText (scoreGrid, row, takenColumn, taken[i], false, true)
			guiGridListSetItemText (scoreGrid, row, copColumn, copRatio[i], false, true)
			guiGridListSetItemColor (scoreGrid, row, nilColumn, 255, 0, 0)
			guiGridListSetItemColor (scoreGrid, row, nullColumn, 255, 0, 0)
		end
	end
end
addEvent ("showRank", true)
addEventHandler ("showRank", getRootElement(), scoreInfo)

 

 

Edited by Lord Henry
Link to comment

Provavelmente deve ser algum bug ele não funcionar com decimais...

Fiz um teste rápido aqui e se você deixar o conteúdo como string no guiGridListSetItemText (não definir o último argumento como true) a ordenação funciona!

Lua assim como outras linguagens convertem strings numéricas em números para fazer a comparação:

-- https://www.lua.org/cgi-bin/demo
if ("2.333" < "2.5555") then
	print("ok")
else
	print("fail")
end

 

  • Like 1
Link to comment
  • Other Languages Moderators

Sim. Mas antes eu não defini como number e mesmo assim bugava a organização. Dai converti pra number pra ver se resolvia e não mudou em nada.

function scoreInfo (names, kills, deaths, ratio, given, taken, copRatio)
	guiSetVisible (scoreWindow, true)
	guiSetVisible (closeGrid, true)
	showCursor (true)
	if names then
		for i, v in ipairs (names) do
			if type (ratio[i]) == "number" then
				ratio[i] = math.round (ratio[i], 3, "floor") -- Aplica o redutor decimal no ratio.
			end
			if type (copRatio[i]) == "number" then
				copRatio[i] = math.round (copRatio[i], 3, "floor") -- Aplica o redutor decimal no copRatio.
			end
			local row = guiGridListAddRow (scoreGrid, names[i], "|", kills[i], deaths[i], ratio[i], "|", given[i], taken[i], copRatio[i])
			guiGridListSetItemColor (scoreGrid, row, nilColumn, 255, 0, 0)
			guiGridListSetItemColor (scoreGrid, row, nullColumn, 255, 0, 0)
		end
	end
end
addEvent ("showRank", true)
addEventHandler ("showRank", getRootElement(), scoreInfo)

 

Link to comment

Sem usar guiGridListSetItemText

local numeros = {1,2,2.5,2.75,2.333,3,4,5,6,7,8,9}

local grid = guiCreateGridList ( 0.5, 0.5, 0.2, 0.3, true )
local column = guiGridListAddColumn( grid, "Números", 1 )
for _,n in ipairs(numeros) do
	local row = guiGridListAddRow ( grid, n )
end

GYyQAEL.jpg

===========================================

Usando guiGridListSetItemText

local numeros = {1,2,2.5,2.75,2.333,3,4,5,6,7,8,9}

local grid = guiCreateGridList ( 0.5, 0.5, 0.2, 0.3, true )
local column = guiGridListAddColumn( grid, "Números", 1 )
for _,n in ipairs(numeros) do
	local row = guiGridListAddRow ( grid )
	guiGridListSetItemText ( grid, row, column, n, false, false )
end

1BS0bGK.jpg

 

Ou seja, quando tenta-se adicionar os itens direto pelo guiGridListAddRow a ordenação com números decimais não funciona (aparentemente no caso dos decimais ele mantém a ordem em que foram acionados), porém usando guiGridListSetItemText funciona...

Se quiser manter como estava fazendo pode tentar usar table.sort antes de adicionar no gridList

Link to comment
  • Other Languages Moderators

Continua não dando certo.

kmS3oqECRO_BrVzgY4wZbA.png

Os números decimais estão funcionando, mas os inteiros que são com mais de um dígito não aparecem na ordem correta. Ele considera 14 menor que 2.

Se eu deixar o parâmetro de number como true, os números inteiros funcionam bem, mas os decimais ficam aleatórios. (1.1 = 1.01 = 1.11)
Se eu deixar o parâmetro de number como false, os números decimais funcionam bem, mas os inteiros de 2 ou mais dígitos ficam errados. (14 < 2)

Edited by Lord Henry
Link to comment
  • Other Languages Moderators

Teste nesta tabela:

scoreGrid = guiCreateGridList (10, 20, 580, 330, false)
nameColumn = guiGridListAddColumn (scoreGrid, "Player", 0.33)
numberColumn = guiGridListAddColumn (scoreGrid, "K/D", 0.1)
nomeTable = {"Nome5", "Nome3", "Nome7", "Nome9", "Nome1", "Nome2", "Nome4", "Nome8", "Nome10", "Nome6")
numberTable = {8,4.1,4.2,4.01,4.11,10,2,4.001,5,1}

 

Edited by Lord Henry
Link to comment

Se tentar usar o table.sort direto na tabela dos números irá perder a correspondência com a tabela dos nomes... algo do tipo deve resolver:

nomeTable = {"Nome5", "Nome3", "Nome7", "Nome9", "Nome1", "Nome2", "Nome4", "Nome8", "Nome10", "Nome6"}
numberTable = {8,4.1,4.2,4.01,4.11,10,2,4.001,5,1}

sort = {}
for i=1,#nomeTable do sort[i] = {nomeTable[i],numberTable[i]} end
table.sort(sort, function(a, b) return a[2] < b[2] end)

 

Link to comment
  • Other Languages Moderators

O problema está no fato dele não reconhecer numero decimal. Pois se reconhecesse, ele organizaria direito quando colocamos true no parâmetro number.

Link to comment
  • Other Languages Moderators
2 hours ago, DNL291 said:

Tentei aqui reproduzir o bug que você tiveram, mas não consegui, usando o table.sort do código do MaligNos. Qual número decimal vocês testaram?

Essa tabela de testes:

4 hours ago, Lord Henry said:

Teste nesta tabela:


scoreGrid = guiCreateGridList (10, 20, 580, 330, false)
nameColumn = guiGridListAddColumn (scoreGrid, "Player", 0.33)
numberColumn = guiGridListAddColumn (scoreGrid, "K/D", 0.1)
nomeTable = {"Nome5", "Nome3", "Nome7", "Nome9", "Nome1", "Nome2", "Nome4", "Nome8", "Nome10", "Nome6")
numberTable = {8,4.1,4.2,4.01,4.11,10,2,4.001,5,1}

 

 

Link to comment
  • Other Languages Moderators
10 hours ago, DNL291 said:

Aqui funcionou com essa tabela:

https://imgur.com/a/MWYrJAB

Você apenas realocou os elementos pelo script. Vc não clicou na coluna para reorganizar.

Preciso que os números fiquem na ordem correta quando eu clicar na coluna dos números. Tanto do maior pro menor, quanto do menor pro maior.

Pois a tabela que estou usando possui várias colunas de números, o usuário pode escolher qual delas quer usar o filtro.

Link to comment
  • 2 weeks later...
  • Moderators

Bom, fiz um código aqui pra resolver isso, foi algo meio radical mas consegui resolver. Na verdade eu fiz um sistema de ordenação personalizado, que usa as propriedades "SortDirection" e "SortColumnID" para fazer tudo separadamente da coluna ratio. Quanto à coluna ratio, eu usei o table.sort que já foi mostrado aqui no tópico.

Fiz tudo com detecção de clique nas áreas de cada coluna, sendo que a ordenação é feita pelo próprio script como já disse. Deixei o código comentado, testei ele e funcionou muito bem. Aqui está:


local sortTable = {
	-- nick, kills, deaths, ratio
	{ "Nome5", 10, 8, 8 },
	{ "Nome3", 2, 5, 4.1 },
	{ "Nome7", 3, 8, 4.2 },
	{ "Nome9", 4, 10, 4.01 },
	{ "Nome1", 5, 14, 4.11 },
	{ "Nome2", 12, 3, 10 },
	{ "Nome4", 2, 7, 5 },
	{ "Nome8", 20, 1, 2 },
	{ "Nome10", 5, 0, 1 },
	{ "Nome6", 7, 22, 4.001 }
}

local ratio_column = 4

--[[-------------------------------------------------------------
-	Você deve estruturar uma tabela para a lista
-	como acima.
-	
-	A coluna do ratio pode ser definida na variável 'ratio_column'
------------------------------------------------------------------]]

local columns = {}
local lastClickedColumn
local selectedRowText

addEventHandler( "onClientResourceStart", resourceRoot,
	function()
		createGridListInterface()
		showCursor (true)
		scoreInfo()
		
		-- mapeando as dimensões das colunas
		local gridX, gridY = guiGetPosition( scoreGrid, false )
		local columnStartX = gridX + 8
		local columnTop = gridY + 1
		local columnBottom = columnTop + 22

		columns[1] = {
					columnStartX,
					columnTop,
					columnStartX + guiGridListGetColumnWidth( scoreGrid, 1, false ),
					columnBottom
		}
		
		-- adicionando as posições das colunas na tabela
		for i=2, guiGridListGetColumnCount( scoreGrid ) do
	
			local left = columns[i-1][3]
			local columnW = guiGridListGetColumnWidth( scoreGrid, i, false )
			columns[i] = { left, columnTop, (left + columnW), columnBottom }
		end
		-- teste
		-- Descomente esta linha se quiser testar as áreas do clique das colunas
		--addEventHandler("onClientRender", root, drawLines)
	end
)

function createGridListInterface()
	scoreGrid = guiCreateGridList (10, 20, 580, 330, false)
	guiGridListSetSortingEnabled( scoreGrid, false )
	
	nameColumn = guiGridListAddColumn (scoreGrid, "Player", 0.33)
	kills = guiGridListAddColumn (scoreGrid, "kills", 0.2)
	deaths = guiGridListAddColumn (scoreGrid, "daths", 0.2)
	numberColumn = guiGridListAddColumn (scoreGrid, "ratio", 0.1)
	
	-- criando uma label por cima das colunas para evitar o redimensionamento manual
	local gridX, gridY = guiGetPosition( scoreGrid, false )
	guiSetProperty(guiCreateLabel(gridX, gridY, 580, 22, "", false), "AlwaysOnTop", "True")
end

function scoreInfo( direction )
	if direction then
		--[[-------------------------------------------------------------
		-	workaround para fazer a ordenação manual.
		-	por algum motivo que eu não consegui descobrir,
		-	as rows simplesmente não são atualizadas quando
		-	clica na coluna do ratio (talvez pelo uso do guiSetProperty).
		-	Nem mesmo removendo as colunas e recriando-as
		-	eu pude resolver, pois me surgiu outro bug com
		-	a posição das colunas
		-----------------------------------------------------------------]]
		
		destroyElement(scoreGrid)
		createGridListInterface()
		
		table.sort( sortTable, 
			function(a, b)
				if direction == "Ascending" then return a[ratio_column] > b[ratio_column]
				else return a[ratio_column] < b[ratio_column]
				end
			end
		)
	end
	for i,v in ipairs(sortTable) do
		local row = guiGridListAddRow (scoreGrid)
		guiGridListSetItemText ( scoreGrid, row, nameColumn, v[1], false, false )
		guiGridListSetItemText ( scoreGrid, row, kills, v[2], false, true )
		guiGridListSetItemText ( scoreGrid, row, deaths, v[3], false, true )
		guiGridListSetItemText ( scoreGrid, row, numberColumn, v[ratio_column], false, true )
		
		local itemText = guiGridListGetItemText( scoreGrid, row, 1 ) 
		if selectedRowText and (itemText == selectedRowText) then
			guiGridListSetSelectedItem( scoreGrid, row, 1 )
		end
	end
end

-- (teste) destacando as áreas de cada coluna
function drawLines()
	if not scoreGrid then return end
	for i=1, guiGridListGetColumnCount( scoreGrid ) do
		local left = columns[i][1]
		local top = columns[i][2]
		local right = columns[i][3]
		local bottom = columns[i][4]
	
		dxDrawLine ( left, top, right, top, tocolor(255, 20, 20), 1, true ) -- Top
		dxDrawLine ( left, top, left, bottom, tocolor(255, 20, 20), 1, true ) -- Left
		dxDrawLine ( left, bottom, right, bottom, tocolor(255, 20, 20), 1, true ) -- Bottom
		dxDrawLine ( right, top, right, bottom, tocolor(255, 20, 20), 1, true ) -- Right
	end
end

addEventHandler ( "onClientGUIClick", guiRoot, 
	function()
		if source == scoreGrid then
			selectedRowText = guiGridListGetSelectedText(scoreGrid)
		end
	end
)

-- detecção do clique nas colunas
addEventHandler( "onClientClick", root,
	function ( button, state )
		if button == "left" and state == "up" and not (isMainMenuActive()) and scoreGrid then
			for i=1, guiGridListGetColumnCount( scoreGrid ) do
				local left = columns[i][1]
				local top = columns[i][2]
				local right = columns[i][3]
				local bottom = columns[i][4]
				if isMouseInPosition( left, top, right-left, bottom-top ) then
					onColumnClick( i )
					break
				end
			end
		end
	end
)

-- essa função é chamada quando uma coluna for clicada,
-- o parâmetro 'id' é o índice da tabela correspondente à coluna
local d = { "Ascending", "Descending" }
function onColumnClick( id )

	outputChatBox( "@onColumnClick: #" .. tostring(id) )
	lastClickedColumn = id
	if lastClickedColumn ~= id then
		columns[lastClickedColumn].dir = nil
		columns[id].dir = d[1]
		guiSetProperty( scoreGrid, "SortDirection", d[1] )
	else
		local direction = (columns[id].dir == d[1]) and d[2] or d[1]
		guiSetProperty( scoreGrid, "SortDirection", direction )
		columns[id].dir = direction
	end
	if id == ratio_column then -- coluna ratio
		scoreInfo( columns[id].dir )
	else
		guiSetProperty(scoreGrid, "SortColumnID", id )
	end
end

-- funções úteis
function isMouseInPosition ( x, y, width, height )
	if ( not isCursorShowing( ) ) then
		return false
	end
    local sx, sy = guiGetScreenSize ( )
    local cx, cy = getCursorPosition ( )
    local cx, cy = ( cx * sx ), ( cy * sy )
    if ( cx >= x and cx <= x + width ) and ( cy >= y and cy <= y + height ) then
        return true
    else
        return false
    end
end

function guiGridListGetSelectedText(gridList)
    local selectedItem = guiGridListGetSelectedItem(gridList)
    if (selectedItem) then
        local text = guiGridListGetItemText(gridList, selectedItem, 1)
        if (text) and not (text == "") then
            return text
        end
    end
    return false
end

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...