![Citação](images/primus/blue/misc/quote_icon.png)
Originally Posted by
itechcoomputers
Cara me salvo, agora queria saber porque no meu servidor tem as tabelas de horas online e elas não contabilizam sempre fica 0 "zero" ?
Então meu Jovem, vamos la:
Tabelas a serem criadas:
Código:
USE [MUOnline]
GO
ALTER TABLE [dbo].[MEMB_STAT]
ALTER COLUMN [ConnectTM] [datetime] NULL
GO
ALTER TABLE [dbo].[MEMB_STAT]
ALTER COLUMN [DisConnectTM] [datetime] NULL
GO
ALTER TABLE [dbo].[MEMB_INFO]
ADD [TimeON] [bigint] NOT NULL DEFAULT 0
GO
ALTER TABLE [dbo].[Character]
ADD [ConnectTM] [datetime] NULL
GO
ALTER TABLE [dbo].[Character]
ADD [DisConnectTM] [datetime] NULL
GO
ALTER TABLE [dbo].[Character]
ADD [TimeON] [bigint] DEFAULT ((0)) NOT NULL
GO
Cria essa Trigger
Código:
/*
| @author - Renato Valer
| @version - 2.1.2
| @last update - 2016/02/12 - 08h18min
| @warning: Não me responsabilizo por uso incorreto e possíveis deadlocks. Use por sua conta e risco.
*/
USE MuOnline
GO
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'AccountCharacter_Online' AND type = 'TR')
DROP TRIGGER [AccountCharacter_Online]
GO
CREATE TRIGGER [AccountCharacter_Online] ON [dbo].[AccountCharacter]
AFTER UPDATE AS
SET NOCOUNT ON
/*
| Hipóteses
|
|
| 1 - Se GameIDC foi atualizado, algum char foi foi logado. Surgem hipóteses:
|
| 1.1 - GameIDC e Old_GameIDC são diferentes:
|
| 1.1.1 - Old_GameIDC é NULL, logo é o primeiro char logado (e possivelmente o primeiro criado) na conta,
| pois não existe GameIDC anterior.
| 1.1.2 - Já existe um GameIDC anterior, logo significa que o cara acessou outro char. Surgem 2 hipóteses:
|
| 1.1.2.1 - O cara simplesmente trocou de char sem deslogar a conta:
| 1.1.2.1.1 - O cara logou um char, deletou ele e entrou em outro.
| 1.1.2.2 - O cara relogou a conta e entrou em outro char.
| 1.1.2.2.1 - O cara logou um char, deletou ele, saiu da conta, voltou e entrou em outro.
|
| 1.2 GameIDC e Old_GameIDC são iguais:
|
| 1.2.1 - O cara relogou o char.
| 1.2.2 - O cara relogou a conta e entrou no mesmo char.
|
| 2. Se GameIDC não foi atualizado, não precisa fazer nada, porque significa:
|
| 2.1 - Que um char foi criado, mas não foi logado.
| 2.2 - Que um char foi deletado sem nem mesmo ter sido logado.
|
|
*/
-- Hipótese 1
IF UPDATE(GameIDC) BEGIN
DECLARE @Login VARCHAR(10),
@GameIDC VARCHAR(10),
@Old_GameIDC VARCHAR(10),
@GameIDC_ConnectTM DATETIME,
@GameIDC_ConnectTM_Int INT,
@Old_GameIDC_ConnectTM DATETIME,
@Old_GameIDC_ConnectTM_Int INT,
@GameIDC_DisConnectTM DATETIME,
@GameIDC_DisConnectTM_Int INT,
@Old_GameIDC_DisConnectTM DATETIME,
@Old_GameIDC_DisConnectTM_Int INT,
@Account_DisconnectTM DATETIME,
@Account_DisconnectTM_Int INT,
@Now DATETIME,
@Now_Int INT,
@TimeON BIGINT;
SET @Login = (SELECT Id FROM INSERTED);
SET @GameIDC = (SELECT GameIDC FROM AccountCharacter WHERE Id = @Login);
SET @Old_GameIDC = (SELECT GameIDC FROM DELETED);
SET @Now = GETDATE();
SET @Now_Int = DATEDIFF(s, '19700101', @Now);
SET @Account_DisconnectTM = (SELECT DisconnectTM FROM MEMB_STAT WHERE memb___id = @Login);
SET @Account_DisconnectTM_Int = DATEDIFF(s, '19700101', @Account_DisconnectTM);
-- Hipótese 1.1
IF(@GameIDC <> @Old_GameIDC) BEGIN
-- Hipótese 1.1.1
IF(@Old_GameIDC IS NULL) BEGIN
UPDATE Character SET ConnectTM = @Now WHERE AccountID = @Login AND Name = @GameIDC;
END
-- Hipótese 1.1.2
ELSE BEGIN
SET @Old_GameIDC_DisconnectTM = @Now
SET @Old_GameIDC_DisconnectTM_Int = @Now_Int;
-- Hipótese 1.1.2.1
IF(@Account_DisconnectTM_Int <> @Old_GameIDC_DisconnectTM_Int) BEGIN
-- Verificação da Hipótese 1.1.2.1.1
IF EXISTS(SELECT Name FROM Character WHERE AccountID = @Login AND Name = @Old_GameIDC) BEGIN
SET @Old_GameIDC_ConnectTM = (SELECT ConnectTM FROM Character WHERE AccountID = @Login AND Name = @Old_GameIDC);
SET @Old_GameIDC_ConnectTM_Int = DATEDIFF(s, '19700101', @Old_GameIDC_ConnectTM);
SET @TimeON = @Old_GameIDC_DisconnectTM_Int - @Old_GameIDC_ConnectTM_Int;
UPDATE Character SET TimeON = TimeON + @TimeON, DisConnectTM = @Now WHERE AccountID = @Login AND Name = @Old_GameIDC;
END
END
-- Hipótese 1.1.2.2 e "fim" da Hipótese 1.1.2.1
-- A query é a mesma e um "else" é desnecessário.
/*
| Não é necessário atualizar tempo on, porque se o cara relogou a conta
| a WZ_DISCONNECT_MEMB já fez o serviço. Só precisamos atualizar o momento
| de connect do novo char.
*/
UPDATE Character SET ConnectTM = @Now WHERE AccountID = @Login AND Name = @GameIDC;
END
END
--Hipótese 1.2.
ELSE BEGIN
-- Apenas precaução...
IF(@GameIDC IS NOT NULL) BEGIN
/*
| Desnecessário checar se o char existe, porque se essa parte
| do script está sendo executada, é porque o char foi logado
| agora, logo é presumível que existe.
*/
SET @GameIDC_ConnectTM = (SELECT ConnectTM FROM Character WHERE AccountID = @Login AND Name = @GameIDC);
SET @GameIDC_ConnectTM_Int = DATEDIFF(s, '19700101', @GameIDC_ConnectTM);
SET @GameIDC_DisconnectTM_Int = @Now_Int;
-- Hipótese 1.2.1
IF(@Account_DisconnectTM_Int < @GameIDC_ConnectTM_Int) BEGIN
SET @TimeON = @GameIDC_DisconnectTM_Int - @GameIDC_ConnectTM_Int;
UPDATE Character SET TimeON = TimeON + @TimeON, DisConnectTM = @Now, ConnectTM = @Now WHERE AccountID = @Login AND Name = @GameIDC;
END
-- Hipótese 1.2.2
ELSE BEGIN
/*
Não é necessário atualizar tempo on, porque se o cara relogou a conta
a WZ_DISCONNECT_MEMB já fez o serviço.
*/
UPDATE Character SET ConnectTM = @Now WHERE AccountID = @Login AND Name = @GameIDC;
END
END
END
SET NOCOUNT OFF
END
Agora vamos criar a Procedure:
Código:
/*
| @modifications - Renato Valer
| @version - 2.0.0
| @last update - 2015/08/28 - 09h25min
| @warning: Não me responsabilizo por uso incorreto e possíveis deadlocks. Use por sua conta e risco.
*/
USE MuOnline
GO
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'WZ_DISCONNECT_MEMB')
DROP PROCEDURE [DBO].[WZ_DISCONNECT_MEMB]
GO
CREATE PROCEDURE [DBO].[WZ_DISCONNECT_MEMB] @memb___id VARCHAR(10) AS BEGIN
SET NOCOUNT ON
DECLARE @Find_ID VARCHAR(10),
@ConnectStat TINYINT,
@LoginTime INT,
@LogoutTime INT,
@ConnectTM INT,
@DisConnectTM INT,
@TimeON_Account BIGINT,
@TimeON_Char BIGINT,
@GameIDC VARCHAR(10),
@CharConnectTM DATETIME,
@CharConnectTM_Int INT,
@Now DATETIME,
@Now_Int INT;
SET @ConnectStat = 0
SET @Find_ID = 'NOT'
SET @Now = GETDATE();
SELECT @Find_ID = S.memb___id FROM MEMB_STAT S INNER JOIN MEMB_INFO I ON S.memb___id COLLATE DATABASE_DEFAULT = I.memb___id WHERE I.memb___id = @memb___id;
IF( @Find_ID <> 'NOT' ) BEGIN
UPDATE MEMB_STAT SET ConnectStat = @ConnectStat, DisconnectTM = @Now WHERE memb___id = @memb___id;
/*
Selecionamos os momentos de login e logout da conta e convertemos para números inteiros.
*/
SET @ConnectTM = (SELECT DATEDIFF(s, '19700101', MEMB_STAT.ConnectTM) FROM MEMB_STAT WHERE memb___id = @memb___id);
SET @DisConnectTM = DATEDIFF(s, '19700101', @Now);
/*
Executamos os cálculos para obtermos o tempo total online da conta.
*/
SET @TimeON_Account = @DisConnectTM - @ConnectTM;
/*
Atualizamos o tempo total online da conta.
*/
UPDATE MEMB_INFO SET TimeON = TimeON + @TimeON_Account WHERE memb___id = @memb___id;
/*
Selecionando nick do último char logado
*/
SET @GameIDC = (SELECT GameIDC FROM AccountCharacter WHERE Id = @memb___id);
/*
Algum char foi logado antes de sair da conta.
Mesmo que o cara tenha logado na conta e criado o char, o GameIDC
só vai ser preenchido se o cara logar na conta.
Sendo assim, se GameIDC for NULL, indica que nenhum char
nunca foi logado nessa conta, então não tem necessidade de contar tempo on.
*/
IF(@GameIDC IS NOT NULL) BEGIN
/*
Verificamos se esse char existe.
Motivo: o cara pode ter clicado em "selecionar char", deletado o char
e depois deslogado da conta.
Se não existe, não precisa fazer nada.
*/
IF EXISTS (SELECT Name FROM Character WHERE AccountID = @memb___id AND Name = @GameIDC) BEGIN
/*
Verificação: quando foi o último connect desse char que acabou de deslogar?
Se for nulo, significa que ocorreu algum problema na trigger, então
adicionamos o valor de "agora" convertido em timestamp para possibilitar o cálculo.
*/
SET @CharConnectTM = (SELECT ConnectTM FROM Character WHERE AccountID = @memb___id AND Name = @GameIDC);
IF (@CharConnectTM IS NULL) BEGIN
SET @CharConnectTM_Int = DATEDIFF(s, '19700101', @Now);
END
/*
Se não for nulo, convertemos para timestamp.
*/
ELSE BEGIN
SET @CharConnectTM_Int = DATEDIFF(s, '19700101', @CharConnectTM);
END
/*
Executamos os cálculos para obtermos o tempo total online
do último char logado.
*/
SET @TimeON_Char = (@DisConnectTM - @CharConnectTM_Int);
/*
Atualizamos o tempo total online do último char logado.
*/
UPDATE Character SET TimeON = TimeON + @TimeON_Char, DisConnectTM = @Now WHERE AccountID = @memb___id AND Name = @GameIDC;
END
END
END
SET NOCOUNT OFF
END
Caso queira informar isso no seu WebSite:
Código PHP:
<?php
$find = mssql_query("SELECT TimeON FROM MEMB_INFO WHERE memb___id='".$login."'");
$fetch = mssql_fetch_object($find);
$seconds = $fetch->TimeON;
$hours = floor($seconds / 3600);
$seconds -= $hours * 3600;
$minutes = floor($seconds / 60);
$seconds -= $minutes * 60;
$timeON = (''.$hours.'h'.$minutes.'min'.$seconds.'sec');
echo $timeON;
?>
Esse código está exibindo as horas online da Conta, caso queira exibir as horas online do Char, recomendo utilizar isso:
Código PHP:
$find = mssql_query("SELECT TimeON FROM MEMB_INFO WHERE memb___id='".$name."'");
Esse código/procedimento está perfeito, é até burrice tentar criar algo semelhante com isso já pronto.
Meu jovem, caso tenha feito algum procedimento para contabilizar as horas, recomendo você remover antes de executar esses procedimentos.
Recomendações Mínimas: Microsoft SQL Server 2008 R2
Créditos
Renato Valer