28-03-2017, 04:48 PM
Allez, pour la curiosité de la chose, voici une proposition. La partie la plus problématique reste le cumulatif des ressources consommées. Ca peut certainement s'améliorer encore. 10secondes environ pour 65k lignes de population, 1k joueurs (65 populations/joueur)
SET PROFILING := 1;
-- Ca, c'est pour mon initialisation
DROP TABLE IF EXISTS `integers`;
CREATE TABLE integers (
n INT UNSIGNED NOT NULL,
PRIMARY KEY (`n`)
) ENGINE=InnoDB;
INSERT INTO integers (n) VALUES (0),(1),(2),(3)/*,(4),(5)*/;
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
SELECT MAX(n) FROM integers;
-- Ca, c'est la nouvelle table de population (colonnes en plus)
DROP TABLE IF EXISTS population;
CREATE TABLE population (
id INT UNSIGNED NOT NULL,
id_joueur INT UNSIGNED NOT NULL,
moral DOUBLE DEFAULT 0,
priorite DOUBLE DEFAULT 0,
eat DOUBLE DEFAULT 0,
sum_eat DOUBLE DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `idx_id_joueur` (`id_joueur`)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS `resources`;
CREATE TABLE resources (
id_joueur INT UNSIGNED NOT NULL,
quantite DOUBLE DEFAULT 0,
PRIMARY KEY(`id_joueur`)
) ENGINE=InnoDB;
INSERT INTO population (id, id_joueur) (SELECT n, CEIL(1000*RAND()) FROM integers);
INSERT INTO resources (id_joueur, quantite) (SELECT n, RAND()*100000 FROM integers WHERE n BETWEEN 1 AND 1000);
-- Fin de l'initialisation
-- Début du vrai algo
-- Là, c'est à toi de fixer l'algo disant combien de ressources veut la population
UPDATE population SET eat = RAND()*1000;
-- La priorité, soit rand, soit définie par des règles du jeu
UPDATE population SET priorite = RAND();
-- Le cumulatif des ressources consommées
UPDATE population p
INNER JOIN (
SELECT p.id, IFNULL(SUM(p2.eat),0)+p.eat AS x
FROM population p
LEFT JOIN population p2 ON p2.id_joueur = p.id_joueur AND p2.priorite > p.priorite
GROUP BY p.id) AS s
ON s.id = p.id
SET sum_eat = s.x;
-- Un petit SELECT pour voir les données
SELECT * FROM population ORDER BY id_joueur DESC, priorite DESC;
UPDATE population p
INNER JOIN resources r ON r.id_joueur = p.id_joueur
SET p.moral = IF(r.quantite >= p.sum_eat, p.moral + 20, p.moral - 20);
UPDATE resources r
SET r.quantite = GREATEST(r.quantite - (SELECT MAX(sum_eat) FROM population AS p WHERE p.id_joueur = r.id_joueur), 0);
SHOW PROFILES;
SET PROFILING := 0;