Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Hussay

[Resolvido] Como criar tabelas de campeonatos divididos por rodad

Recommended Posts

Boa tarde, Pessoal

Preciso criar um sistema em php com mysql, sendo que após inserir os times que disputarão o campeonato, o sistema faça todos jogarem com todos uma única vez e os separem por rodadas, sendo que nessas rodadas não pode repetir time (Ex.: Estilo campeonato brasileiro).

Eu fiz o seguinte código que faz uma análise combinatório e faz com que todos joguem com todos uma vez:

 

$nome_temporario=$_FILES["arquivo"]["tmp_name"];/* Pega o arquivo*/
$nome_arquivo = "ARQUIVO.csv"; // qualquer que seja o nome enviado e renomeado
copy($nome_temporario,"arquivos/$nome_arquivo");

$abraArq = fopen("arquivos/ARQUIVO.csv", "r");
//Apenas para ficar com mais controle melhor colocar um tratamento de erros caso o arquivo são seja aberto ai use as condições if e else. E imprima na tela com um echo()
if (!$abraArq){
echo ("<p>Arquivo não encontrado</p>");
}else{
// Caso abra faça isso agora
// usando a nova função do php 5 fgetcsv() o 2048 é apenas para colocar o número máximo de caracteres por linha.
// crie uma variável chamada $valores o que vai corresponder pelos valores das colunas para serem inseridas.
while ($valores = fgetcsv ($abraArq, 2048, ";")) {
// Só criar agora o construtor que pegou os valores das colunas do arquivo csv. E começar a inserir dentro da base de dados.
$nome1 = $valores[0];
$nome2 =explode(" ",$nome1);
$nome = $nome2[0]." ".$nome2[1];
$mes = $_POST['mes'];
$supervisor = $_POST['supervisor'];

$result = mysql_query("INSERT INTO jogadores (nome, mes, supervisor) values ('$nome', '$mes', '$supervisor')");

}
fclose($abraArq);


unlink("arquivos/$nome_arquivo");

$mes1 = $_POST['mes'];
$sql_conta_times = mysql_query("SELECT nome FROM jogadores WHERE mes='$mes1'");
$cont_times = mysql_num_rows($sql_conta_times);
$cont_times1 = $cont_times;
$i =1;
while($i < $cont_times){
$i++;

$times_jogos = $i - 2;
$sql_conta_times1 = mysql_query("SELECT nome FROM jogadores WHERE mes='$mes1' LIMIT $times_jogos,1");

while($linha_times = mysql_fetch_array($sql_conta_times1)){
$time1 = $linha_times['nome'];
$i2 = 0;
$cont_times1--;
while($i2 < $cont_times1){

$rodada = $i2;

$time1c = $time1;
$sql_conta_times2 = mysql_query("SELECT nome FROM jogadores WHERE mes='$mes1' and nome!='$time1c' ORDER BY id DESC LIMIT $rodada,1");

while($linha_times2 = mysql_fetch_array($sql_conta_times2)){
$time2 = $linha_times2['nome'];
$confere1 = $time1c.$time2;
$confere2 = $time2.$time1c;
echo $time1c." X ".$time2."<br>";


 }
$i2++;
}


}


}

 

Com esse calculo faço todo mundo jogar com todo mundo, mas não sei como separar em rodadas.

 

Alguém consegue me ajudar?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde amigo,

 

É complicado fazer as coisas aleatórias, justo porque ocorrem erros aleatórios. Eu to tentando uma coisa aqui se conseguir eu te passo. Se já tiver conseguido posta aí.

 

Abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Lembrei-me de uma materia de jornal que havia lido, a matemática parece ser complexa mas pode ser um caminho a ajudar.

 

Tipo de coisa interessante de fazer !

 

Fonte Google

 

Clássicos no fim causam situação inédita no Brasileiro

www.lancenet.com.br/.../Atletico-PR-Avai-Internacional-Brasileirao-...

16 mar. 2011 – É impossível montar uma tabela que respeite todos os critérios tradicionalmente ... e critérios que a CBF quer ver reproduzidas na tabela do campeonato. Estas são escritas por equações matemáticas chamadas às quais ...

 

http://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=8&cad=rja&ved=0CFwQFjAH&url=http%3A%2F%2Fwww.lancenet.com.br%2Fminuto%2FAtletico-PR-Avai-Internacional-Brasileirao-2011_0_444555754.html&ei=XaRTUJi7AoTo9ATAlYDACQ&usg=AFQjCNESmQBpM0_7Lac4bjHoQTWz-9ajgw

 

Veja se o Link funciona pois dis segundos depois quebrou ...

 

____________________________________________________________

Depois me lembrei que estudei Programação Linear na faculdade

e tenho até um livro, mas o professor era tão ruimque acho que

não lembro de mais nada ...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde amigo,

 

É complicado fazer as coisas aleatórias, justo porque ocorrem erros aleatórios. Eu to tentando uma coisa aqui se conseguir eu te passo. Se já tiver conseguido posta aí.

 

Abraço.

 

Tenta ai companheiro, que eu tento aqui também.

Um jeito de fazer isso que eu achei foi o seguinte:

Inicialmente fazer no braço (rsrsrs) as simulações e depois colocar condições:

Ex.:

Simulo no braço com 14 times, depois 16 times e assim sucessivamente até 26 times (Essa é a margem que eu preciso).

Depois coloco dentro de um if somente para validar (Se for 14 times faça esse, se não prossiga).

 

Vai ser chato e o código ficará imenso, mas até alguma boa alma conseguir uma lógica para isso, vou fazendo assim. rsrsrs

 

Lembrei-me de uma materia de jornal que havia lido, a matemática parece ser complexa mas pode ser um caminho a ajudar.

 

Tipo de coisa interessante de fazer !

 

Fonte Google

 

Clássicos no fim causam situação inédita no Brasileiro

www.lancenet.com.br/.../Atletico-PR-Avai-Internacional-Brasileirao-...

16 mar. 2011 – É impossível montar uma tabela que respeite todos os critérios tradicionalmente ... e critérios que a CBF quer ver reproduzidas na tabela do campeonato. Estas são escritas por equações matemáticas chamadas às quais ...

 

http://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=8&cad=rja&ved=0CFwQFjAH&url=http%3A%2F%2Fwww.lancenet.com.br%2Fminuto%2FAtletico-PR-Avai-Internacional-Brasileirao-2011_0_444555754.html&ei=XaRTUJi7AoTo9ATAlYDACQ&usg=AFQjCNESmQBpM0_7Lac4bjHoQTWz-9ajgw

 

Veja se o Link funciona pois dis segundos depois quebrou ...

 

____________________________________________________________

Depois me lembrei que estudei Programação Linear na faculdade

e tenho até um livro, mas o professor era tão ruimque acho que

não lembro de mais nada ...

 

Eu já tinha lido essa matéria, mas a meu ver a tabela do campeonato brasileiro é muito mais fácil de se fazer.

Você já tem pré-estabelecido a quantidade de times, aí fica muito mais fácil, tanto é que eu fiz uma com 16 times e foi muito fácil (Fiz no braço e depois joguei dentro do if buscando no banco de dados).

 

Tem um sisteminha (SoleCorp - Sports Manager) que também faz tabelas e está me quebrando o galho para fazer a parte do "fazer no braço".

 

Quando eu terminar o meu código que estou fazendo para esse caso, eu posto aqui para vocês verem a dimensão do meu trabalho. rsrsrsrs.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia amigo,

 

Olha eu consegui aqui 80%. Tipo dividir as rodadas todas, mas na hora de montar as mesmas aleatoriamente, sem que times se repitam e tal o negócio complica, em algum momento dá erro no MySQL por duplicidade. O que acontece é o seguinte, imagine com 3 times:

 

1ª rodada

A x B

C x D

E x F

 

Quando o MySQL vai montar a segunda rodada (não é a segunda em específico, mas isso pode ocorrer com qualquer rodada e a chance de acontecer é maior se tiver mais times - eu simulei com 10), ele já sabe que o A já jogou contra B, C contra D e E contra F, então ele não vai montar estas partidas de novo. Mas digamos que, aleatoriamente, ele monta A x D e B x C, sendo assim só sobram E e F de novo. Eu tentei fazer uma condição pra prevenir isso, até consegui pra última partida da rodada ele não deixar sobrarem apenas times que já jogaram entre si, mas percebi que isso pode acontecer não só na última mas sim nas 2 ou 3 últimas partidas, ou até mais se forem muitos times...

 

Eu tenho tudo que fiz aqui se tu quiser, é tudo em SQL tu pode tentar implementar em PHP. Da forma que eu fiz aqui, dá de gerar tudo e ignorar os erros, assim sobrariam digamos, umas 10 partidas que não foram montadas por erro. Aí essas 10 montava na mão... É ruim isso mas como o Motta disse, é uma coisa interessante de se fazer, justamente porque é bem complicada.

 

Enfim, se quiser meus códigos SQL eu posto aqui e detalho todos.

 

Abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

DiegoAngra07 acho que só no SQL não rola, teria de ter algum linguagem para auxiliar nesta tarefa.

 

O SQL faz bem o produto cartesiano dos confrontos, mas não vi como ir além disto.

 

Eu tentaria fazer a tabela do Brasileiro por software genético.

Compartilhar este post


Link para o post
Compartilhar em outros sites

DiegoAngra07 acho que só no SQL não rola, teria de ter algum linguagem para auxiliar nesta tarefa.

 

O SQL faz bem o produto cartesiano dos confrontos, mas não vi como ir além disto.

 

Eu tentaria fazer a tabela do Brasileiro por software genético.

Pois é... O SQL só conseguiu ir até uma parte aqui, mas rendeu bastante até. Eu pensei em refazer usando alguma linguagem mas não tive chances ainda.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia amigo,

 

Olha eu consegui aqui 80%. Tipo dividir as rodadas todas, mas na hora de montar as mesmas aleatoriamente, sem que times se repitam e tal o negócio complica, em algum momento dá erro no MySQL por duplicidade. O que acontece é o seguinte, imagine com 3 times:

 

1ª rodada

A x B

C x D

E x F

 

Quando o MySQL vai montar a segunda rodada (não é a segunda em específico, mas isso pode ocorrer com qualquer rodada e a chance de acontecer é maior se tiver mais times - eu simulei com 10), ele já sabe que o A já jogou contra B, C contra D e E contra F, então ele não vai montar estas partidas de novo. Mas digamos que, aleatoriamente, ele monta A x D e B x C, sendo assim só sobram E e F de novo. Eu tentei fazer uma condição pra prevenir isso, até consegui pra última partida da rodada ele não deixar sobrarem apenas times que já jogaram entre si, mas percebi que isso pode acontecer não só na última mas sim nas 2 ou 3 últimas partidas, ou até mais se forem muitos times...

 

Eu tenho tudo que fiz aqui se tu quiser, é tudo em SQL tu pode tentar implementar em PHP. Da forma que eu fiz aqui, dá de gerar tudo e ignorar os erros, assim sobrariam digamos, umas 10 partidas que não foram montadas por erro. Aí essas 10 montava na mão... É ruim isso mas como o Motta disse, é uma coisa interessante de se fazer, justamente porque é bem complicada.

 

Enfim, se quiser meus códigos SQL eu posto aqui e detalho todos.

 

Abraço.

 

Publica ai para nós, por gentileza, pode ser que conseguimos corrigir esses erros do final.

 

Vlw

Compartilhar este post


Link para o post
Compartilhar em outros sites

Criação do banco e tabelas:

 

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

DROP SCHEMA IF EXISTS `campeonato` ;
CREATE SCHEMA IF NOT EXISTS `campeonato` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `campeonato` ;

-- -----------------------------------------------------
-- Table `time`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `time` ;

CREATE  TABLE IF NOT EXISTS `time` (
 `idTime` INT NOT NULL AUTO_INCREMENT ,
 `nome` VARCHAR(50) NOT NULL ,
 PRIMARY KEY (`idTime`) 
) ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `rodada`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `rodada` ;

CREATE  TABLE IF NOT EXISTS `rodada` (
 `idRodada` int(11) NOT NULL AUTO_INCREMENT,
 `numRodada` varchar(45) NOT NULL,
 `turno` char(1) NOT NULL,
 PRIMARY KEY (`idRodada`)
) ENGINE=InnoDB;


-- -----------------------------------------------------
-- Table `partida`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `partida` ;

CREATE  TABLE IF NOT EXISTS `partida` (
 `idPartida` INT NOT NULL AUTO_INCREMENT ,
 `idRodada` INT NOT NULL ,
 `idMandante` INT NOT NULL ,
 `idVisitante` INT NOT NULL ,
 PRIMARY KEY (`idPartida`) ,
 INDEX `rodadaFkIdx` (`idRodada` ASC) ,
 INDEX `mandanteFkIdx` (`idMandante` ASC) ,
 INDEX `visitanteFkIdx` (`idVisitante` ASC) ,
 UNIQUE INDEX `timesUniqueIdx` (`idMandante` ASC, `idVisitante` ASC) ,
 CONSTRAINT `rodadaFk`
   FOREIGN KEY (`idRodada` )
   REFERENCES `rodada` (`idRodada` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT,
 CONSTRAINT `mandanteFk`
   FOREIGN KEY (`idMandante` )
   REFERENCES `time` (`idTime` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT,
 CONSTRAINT `visitanteFk`
   FOREIGN KEY (`idVisitante` )
   REFERENCES `time` (`idTime` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `partidaAux`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `partidaAux` ;

CREATE  TABLE IF NOT EXISTS `partidaAux` (
 `idPartida` INT NOT NULL AUTO_INCREMENT ,
 `idMandante` INT NULL ,
 `idVisitante` INT NULL ,
 PRIMARY KEY (`idPartida`) )
ENGINE = InnoDB;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

Inserção dos times para simulação:

 

USE `campeonato`;

INSERT INTO time (nome) VALUES ('Palmeiras');
INSERT INTO time (nome) VALUES ('São Paulo');
INSERT INTO time (nome) VALUES ('Santos');
INSERT INTO time (nome) VALUES ('Flamengo');
INSERT INTO time (nome) VALUES ('Fluminense');
INSERT INTO time (nome) VALUES ('Vasco');
INSERT INTO time (nome) VALUES ('Grêmio');
INSERT INTO time (nome) VALUES ('Internacional');
INSERT INTO time (nome) VALUES ('Criciúma');
INSERT INTO time (nome) VALUES ('Avaí');

Aqui eu criei uma PROCEDURE pra gerar as partidas com os times existentes:

 

USE `campeonato`;
DROP PROCEDURE IF EXISTS `geraPartidas`;

delimiter $$

CREATE PROCEDURE `geraPartidas`()
BEGIN
   DECLARE numTimes, iCont, iContVisitante int;

SET numTimes = (SELECT COUNT(t.idTime) FROM time t);
SET iCont = 1;

WHILE (iCont <= numTimes) DO
	SET iContVisitante = 1;

	WHILE (iContVisitante <= numTimes) DO
		IF (iCont <> iContVisitante) THEN INSERT INTO partidaAux (idMandante, idVisitante) VALUES (iCont, iContVisitante) ; END IF;
		SET iContVisitante = iContVisitante + 1;
	END WHILE;

	SET iCont = iCont + 1;
END WHILE;
END $$

CALL geraPartidas() $$

Essa PROCEDURE vai alimentar a tabela partidaAux com todas as partidas possíveis no campeonato, se houverem 4 times apenas no campeonato o resultado seria este:

 

Time 1 x Time 2

Time 1 x Time 3

Time 1 x Time 4

Time 2 x Time 1

Time 2 x Time 3

Time 2 x Time 4

Time 3 x Time 1

Time 3 x Time 2

Time 3 x Time 4

Time 4 x Time 1

Time 4 x Time 2

Time 4 x Time 3

 

Todos os times jogam 2 vezes com o outro, uma vez como mandante e outra como visitante.

 

Agora que a coisa complica...

 

Olha, eu tava preparando as coisas pra postar aqui e fui mexer de novo na PROCEDURE abaixo, e agora parece que to tendo uma luz. Vou postar ela aqui pra vocês já também, e vou continuar mexendo aqui pra ver se acho o problema porque me parece que tem um problema. Segue.

 

Essa PROCEDURE pega as partidas que geramos na tabela partidaAux e joga aleatoriamente para a tabela partida, relacionando com as rodadas. Ela só faz o 1º turno por enquanto, para o segundo turno eu ia acrescentar um pedaço de código abaixo que pega as partidas do primeiro turno e inverte os times entendem?

 

USE `campeonato`;
DROP PROCEDURE IF EXISTS `geraRodadas`;

DELIMITER $$

CREATE PROCEDURE `geraRodadas`()
BEGIN
   DECLARE numPartidas, numRodadas, partidasPorRodada, iCont, iContPartidas int;
DECLARE iRodada, varIdPartida, varIdRodada, varIdMandante, varIdVisitante int;

SET numPartidas = ((SELECT COUNT(p.idPartida) FROM partidaAux p) / 2);
SET numRodadas  = ((SELECT COUNT(t.idTime) FROM time t) - 1);
SET partidasPorRodada = (numPartidas / numRodadas);
SET iCont = 1;
SET iRodada = 1;

WHILE (iRodada <= numRodadas) DO
	SET iContPartidas = 1;

	INSERT INTO rodada (numRodada, turno) 
		VALUES (iRodada, '1'); 

	SET varIdRodada = (SELECT MAX(r.idRodada) FROM rodada r);

	WHILE (iContPartidas <= partidasPorRodada) DO
		SET varIdPartida = (
			SELECT p.idPartida FROM partidaAux p
			WHERE NOT EXISTS (
				SELECT 1 FROM partida a
				WHERE (
						(a.idMandante  = p.idMandante ) OR 
						(a.idMandante  = p.idVisitante) OR 
						(a.idVisitante = p.idMandante ) OR
						(a.idVisitante = p.idVisitante)
					)
				AND a.idRodada = varIdRodada
			)
			ORDER BY RAND() LIMIT 1
		);

		SET varIdMandante  = (SELECT p.idMandante  FROM partidaAux p WHERE p.idPartida = varIdPartida);
		SET varIdVisitante = (SELECT p.idVisitante FROM partidaAux p WHERE p.idPartida = varIdPartida);

		IF ((varIdMandante IS NOT NULL) AND (varIdVisitante IS NOT NULL)) THEN
			INSERT INTO partida (idRodada, idMandante, idVisitante) 
				VALUES (varIdRodada, varIdMandante, varIdVisitante);
			DELETE FROM partidaAux WHERE idPartida = varIdPartida;
		END IF ;

		SET iContPartidas = iContPartidas + 1;
	END WHILE;

	SET iRodada = iRodada + 1;
END WHILE;

END$$

CALL geraRodadas() $$

Eu acho que ela tem algum erro... Ou não rs Ela tinha até hoje, agora me bateu uma ideia e fiz umas modificações. Executa aí cara e vê se tá certa, que eu vo fazer a parte do 2º turno aqui e já posto.

 

Abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Minha ideia básica :

 

Para uma tabela o Sistema marca pontos negativos e pontos positivos

 

Exemplo : Um time for mandante 3 vezes seguidas -> 1 ponto negativo

Rodadas finais entre times da mesma cidade -> 1 ponto positivo

 

Seriam gerados N tabelas aleatórias.

 

Passo 01

 

O Sistema classificaria estas tabelas por pontos negativos e positivos (separado)

 

O Sistema escolhe a melhor tabela (menor ponto negaivos e maior pontos positivos nesta ordem)

 

O Sistema copia a melhor tabela e clona fazendo uma mutação aleatória outras (N-1) tabelas

 

Repete o Passo 01 até que pelo menos os Pontos negativos sejam zerados.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pois é, eu não tinha feito nada referente a mando de campo seguido ou algo assim ainda, como a CBF. Só as rotinas pra gerar as partidas por enquanto.

 

Mas é uma ideia interessante.

 

Achei o problema da minha PROCEDURE: Tá fazendo times jogarem 2 vezes no mesmo turno ainda. Exemplo, time A mandante contra time F na rodada 1, e na rodada 2 o time F mandante contra o A, sendo que isso só devia acontecer no segundo turno.

 

Vou ver aqui acho que sei a resolução.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Minha ideia básica :

 

Para uma tabela o Sistema marca pontos negativos e pontos positivos

 

Exemplo : Um time for mandante 3 vezes seguidas -> 1 ponto negativo

Rodadas finais entre times da mesma cidade -> 1 ponto positivo

 

Seriam gerados N tabelas aleatórias.

 

Passo 01

 

O Sistema classificaria estas tabelas por pontos negativos e positivos (separado)

 

O Sistema escolhe a melhor tabela (menor ponto negaivos e maior pontos positivos nesta ordem)

 

O Sistema copia a melhor tabela e clona fazendo uma mutação aleatória outras (N-1) tabelas

 

Repete o Passo 01 até que pelo menos os Pontos negativos sejam zerados.

 

No meu caso, não vou precisar de ter mandantes, porque os jogos ocorrerão somente em um campo.

Meu problema mesmo é separar por rodadas em um turno somente.

 

Esse raciocínio é muito bom, mas se eu inserir no meu código, posso ficar mais louco ainda! rsrsrsrs.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom se não precisa ter diferenciação entre mandante e visitante acho que se eu simplificar meu SQL ele te atende. Eu fiz umas mudanças aqui e por enquanto ele está assim:

 

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

DROP SCHEMA IF EXISTS `campeonato` ;
CREATE SCHEMA IF NOT EXISTS `campeonato` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `campeonato` ;

-- -----------------------------------------------------
-- Table `time`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `time` ;

CREATE  TABLE IF NOT EXISTS `time` (
 `idTime` INT NOT NULL AUTO_INCREMENT ,
 `nome` VARCHAR(50) NOT NULL ,
 PRIMARY KEY (`idTime`) 
) ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `rodada`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `rodada` ;

CREATE  TABLE IF NOT EXISTS `rodada` (
 `idRodada` int(11) NOT NULL AUTO_INCREMENT,
 `numRodada` varchar(45) NOT NULL,
 `turno` char(1) NOT NULL,
 PRIMARY KEY (`idRodada`)
) ENGINE=InnoDB;


-- -----------------------------------------------------
-- Table `partida`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `partida` ;

CREATE  TABLE IF NOT EXISTS `partida` (
 `idPartida` INT NOT NULL AUTO_INCREMENT ,
 `idRodada` INT NOT NULL ,
 `idMandante` INT NOT NULL ,
 `idVisitante` INT NOT NULL ,
 PRIMARY KEY (`idPartida`) ,
 INDEX `rodadaFkIdx` (`idRodada` ASC) ,
 INDEX `mandanteFkIdx` (`idMandante` ASC) ,
 INDEX `visitanteFkIdx` (`idVisitante` ASC) ,
 UNIQUE INDEX `timesUniqueIdx` (`idMandante` ASC, `idVisitante` ASC) ,
 CONSTRAINT `rodadaFk`
   FOREIGN KEY (`idRodada` )
   REFERENCES `rodada` (`idRodada` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT,
 CONSTRAINT `mandanteFk`
   FOREIGN KEY (`idMandante` )
   REFERENCES `time` (`idTime` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT,
 CONSTRAINT `visitanteFk`
   FOREIGN KEY (`idVisitante` )
   REFERENCES `time` (`idTime` )
   ON DELETE RESTRICT
   ON UPDATE RESTRICT)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `partidaAux`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `partidaAux` ;

CREATE  TABLE IF NOT EXISTS `partidaAux` (
 `idPartida` INT NOT NULL AUTO_INCREMENT ,
 `idMandante` INT NULL ,
 `idVisitante` INT NULL ,
 PRIMARY KEY (`idPartida`) )
ENGINE = InnoDB;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

USE `campeonato`;

INSERT INTO time (nome) VALUES ('Palmeiras');
INSERT INTO time (nome) VALUES ('São Paulo');
INSERT INTO time (nome) VALUES ('Santos');
INSERT INTO time (nome) VALUES ('Flamengo');
INSERT INTO time (nome) VALUES ('Fluminense');
INSERT INTO time (nome) VALUES ('Vasco');
INSERT INTO time (nome) VALUES ('Grêmio');
INSERT INTO time (nome) VALUES ('Internacional');
INSERT INTO time (nome) VALUES ('Criciúma');
INSERT INTO time (nome) VALUES ('Avaí');

USE `campeonato`;
DROP PROCEDURE IF EXISTS `geraPartidas`;

delimiter $$

CREATE PROCEDURE `geraPartidas`()
BEGIN
   DECLARE numTimes, iCont, iContVisitante int;

SET numTimes = (SELECT COUNT(t.idTime) FROM time t);
SET iCont = 1;

WHILE (iCont <= numTimes) DO
	SET iContVisitante = 1;

	WHILE (iContVisitante <= numTimes) DO
		IF (iCont <> iContVisitante) THEN INSERT INTO partidaAux (idMandante, idVisitante) VALUES (iCont, iContVisitante) ; END IF;
		SET iContVisitante = iContVisitante + 1;
	END WHILE;

	SET iCont = iCont + 1;
END WHILE;
END$$

CALL geraPartidas() $$

DELIMITER ;

USE `campeonato`;
DROP PROCEDURE IF EXISTS `geraRodadas`;

DELIMITER $$

CREATE PROCEDURE `geraRodadas`()
BEGIN
   DECLARE numPartidas, numRodadas, partidasPorRodada, iCont, iContPartidas int;
DECLARE iRodada, varIdPartida, varIdRodada, varIdMandante, varIdVisitante int;

SET numPartidas = ((SELECT COUNT(p.idPartida) FROM partidaAux p) / 2);
SET numRodadas  = ((SELECT COUNT(t.idTime) FROM time t) - 1);
SET partidasPorRodada = (numPartidas / numRodadas);
SET iCont = 1;
SET iRodada = 1;

WHILE (iRodada <= numRodadas) DO
	SET iContPartidas = 1;

	INSERT INTO rodada (numRodada, turno) 
		VALUES (iRodada, '1'); 

	SET varIdRodada = (SELECT MAX(r.idRodada) FROM rodada r);

	WHILE (iContPartidas <= partidasPorRodada) DO
		SET varIdPartida = (
			SELECT p.idPartida FROM partidaAux p
			WHERE NOT EXISTS (
				SELECT 1 FROM partida a
				WHERE (
						(a.idMandante  = p.idMandante ) OR 
						(a.idMandante  = p.idVisitante) OR 
						(a.idVisitante = p.idMandante ) OR
						(a.idVisitante = p.idVisitante)
					)
				AND a.idRodada = varIdRodada
			)
			AND NOT EXISTS (
				SELECT 1 FROM partida a
				WHERE (
						(a.idMandante  = p.idVisitante) AND
						(a.idVisitante = p.idMandante ) 
					)
			)
			ORDER BY RAND() LIMIT 1
		);

		SET varIdMandante  = (SELECT p.idMandante  FROM partidaAux p WHERE p.idPartida = varIdPartida);
		SET varIdVisitante = (SELECT p.idVisitante FROM partidaAux p WHERE p.idPartida = varIdPartida);

		IF ((varIdMandante IS NOT NULL) AND (varIdVisitante IS NOT NULL)) THEN
			INSERT INTO partida (idRodada, idMandante, idVisitante) 
				VALUES (varIdRodada, varIdMandante, varIdVisitante);
			DELETE FROM partidaAux WHERE idPartida = varIdPartida;

			SET iContPartidas = iContPartidas + 1;
		END IF ;
	END WHILE;

	SET iRodada = iRodada + 1;
END WHILE ;

END$$

CALL geraRodadas() $$

DELIMITER ;

USE `campeonato`;
DROP PROCEDURE IF EXISTS `geraSegundoTurno`;

DELIMITER $$

CREATE PROCEDURE `geraSegundoTurno`()
BEGIN
DECLARE f int DEFAULT 1;
DECLARE varIdMandante, varIdVisitante, varRodada, varIdRodada, varIdRodadaOld, varIdRodadaNew int;
DECLARE curPartidasIdRodada    CURSOR FOR SELECT idRodada    FROM partida ORDER BY idPartida ASC;
DECLARE curPartidasIdMandante  CURSOR FOR SELECT idMandante  FROM partida ORDER BY idPartida ASC;
DECLARE curPartidasIdVisitante CURSOR FOR SELECT idVisitante FROM partida ORDER BY idPartida ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET f = 0;

SET varRodada = (SELECT MAX(r.numRodada) FROM rodada r);
SET varIdRodadaOld = 0;
SET varIdRodadaNew = 0;

OPEN curPartidasIdRodada;
OPEN curPartidasIdMandante;
OPEN curPartidasIdVisitante;

REPEAT
	FETCH curPartidasIdRodada    INTO varIdRodadaNew;
	FETCH curPartidasIdMandante  INTO varIdMandante;
	FETCH curPartidasIdVisitante INTO varIdVisitante;

	IF (varIdRodadaNew <> varIdRodadaOld) THEN BEGIN
		SET varRodada = varRodada + 1;			

		INSERT INTO rodada (numRodada, turno) 
			VALUES (varRodada, '2'); 

		SET varIdRodada = (SELECT MAX(r.idRodada) FROM rodada r);
		SET varIdRodadaOld = varIdRodadaNew;
	END ; END IF ;

	IF ((varIdMandante IS NOT NULL) AND (varIdVisitante IS NOT NULL)) THEN
		INSERT INTO partida (idRodada, idMandante, idVisitante) 
			VALUES (varIdRodada, varIdVisitante, varIdMandante);
	END IF;
UNTIL (f = 0) END REPEAT ;

CLOSE curPartidasIdRodada;
CLOSE curPartidasIdMandante;
CLOSE curPartidasIdVisitante;

-- DROP TABLE partidaAux; -- Comentado temporariamente

END $$

CALL geraSegundoTurno();

O que está acontecendo é que trava em determinado momento, justamente por aquela questão que eu citei antes, de sobrarem apenas times que já jogaram e então o SQL entra em looping. Deixo aqui se alguém conseguir resolver, depois vou voltar a mexer nisso.

 

Abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seria melhor trabalhar com um array até montar a tabela, só dar o insert após montado em memória.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas ainda haveria uma falha na lógica pra montar as partidas e rodadas sem acontecer o erro que está acontecendo. Melhor ser feito usando alguma linguagem mesmo, implementando a lógica desse SQL.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tem de ter um tratamento para tratar a exceção de "não solução", apagar linas do array, começar de novo etc.

 

 

Achei este trabalho, poderia servir de base.

 

Lamento não ter tempo de poder pensar uma solução melhor.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tem de ter um tratamento para tratar a exceção de "não solução", apagar linas do array, começar de novo etc.

 

 

Achei este trabalho, poderia servir de base.

 

Lamento não ter tempo de poder pensar uma solução melhor.

 

Pessoal, vocês me esclareceram muito coisa a respeito, mas infelizmente, não consegui concluir uma lógica fácil nisso.

Motta, transfere meu tópico para a área do php, porque acho que eles podem me dar uma luz a mais, pelo fato de eu saber um pouco mais de php.

 

Obrigado. :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não modero esta área, vou mandar uma MP para o Moderador.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tranquilo amigo. Sinto não poder ter ajudado mais, mas realmente ficará melhor de você resolver com alguma linguagem de programação.

 

Abraço e boa sorte.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.