8710 sujets

Développement web côté serveur, CMS

Salut tout le monde ^^

Soit 2 tables :
- carte_evenement : qui regroupe tout ce qui se passe sur une carte
- carte_cases : qui regroupe toutes les cases de la carte.

Carte_cases (qu'on appellera cc) se définit ainsi :
4 colonnes pour les coordonnées : Carte, Altitude, X et Y
2 colonnes pour les informations de la carte : marchable, territoire
les coordonnées servent de clés primaires

Carte_evenement (qu'on appellera ce) se définit ainsi
1 ID : ID
4 coordonnées : Carte, Altitude, X et Y
2 informations du type : Type et IdType
L'ID sert de clé primaire et j'ai un index regroupant Carte,Altitude,X et Y

Carte,Altitude,X et Y servent bien sûr de lien entre les 2 tables^^

Le lien entre ses tables et de type 1-n. Chaque évènement n'a qu'une case; chaque case peut avoir de 0 à n évènements.

cc.Marchable a 2 valeurs : 0 (non-marchable), 1 (marchable)
cc.Territoire a plein de valeurs.
ce.Type a 6 valeurs : 1 à 6.


J'aimerais arriver (via MySQL idéalement) à récupérer les coordonnées d'une case (Carte,Altitude,X,Y) qui répond aux données suivantes :
- cc.Marchable = 1
- cc.Territoire = valeur fixe
- ce.Type peut avoir la valeur 1,4,5
- ce.Type ne peut JAMAIS avoir la valeur 2,3,6
- aléatoire parmi celles restantes, en équiprobable (je ne peux donc pas garder 2 cases ayant les mêmes coordonnées avant l'aléatoire)

En exemple simple :
Une case 1,0,25,30 avec un seul évènement type 1 sera dans la liste
Une case 1,0,12,30 avec un évènement type 1 et un type 5 sera une fois dans la liste
Une case 1,0,23,50 avec un évènement type 2 ne sera pas dans la liste
Une case 1,0,17,20 avec un évènement type 2 et un évènement type 3 ne sera pas dans la liste
Une case 1,0,22,43 avec un évènement type 4 ET un évènement type 2 ne sera pas dans la liste

J'arrive pour l'instant à ce code, mais il ne marche pas correctement:

$rq="select distinct carte_cases.* from carte_cases 
			Left Join carte_evenement ON carte_cases.Carte = carte_evenement.Carte AND carte_cases.X = carte_evenement.X AND carte_cases.Y = carte_evenement.Y AND carte_cases.Altitude = carte_evenement.Altitude
			Where carte_cases.Territoire = '".$territoire."' AND
			carte_cases.Marchable = '1' AND
			((carte_evenement.`Type` = 1 OR carte_evenement.`Type` Is Null OR carte_evenement.`Type` = 4 OR carte_evenement.`Type` = 5 ))  order by rand() limit 1"

Modifié par Lothindil (18 Sep 2013 - 13:07)
Bonjour,

Peut-être comme ça:
select * from carte_cases cc
inner join carte_evenement ce ON ce.Carte = cc.Carte 
Where carte_cases.Territoire = '".$territoire."' 
AND carte_cases.Marchable = '1' 
AND ce.type IN(1,4,5)
AND ce.type NOT IN(2,3,6) 
order by rand() limit 1
Si ça ne marche pas, garde au moins le IN() et NOT IN()
Modifié par loicbcn (17 Sep 2013 - 15:19)
Merci, mais ça cause toujours le même problème.

Si y a un évènement + (type 1,4 ou 5) et un évènement - (2,3,6), il compte l'évènement dans la liste
Il me semble obtenir le résultat que tu cherches avec cette simple requête :

SELECT DISTINCT cc.*
FROM cc INNER JOIN ce ON (ce.carte=cc.carte and ce.x=cc.x and ce.y=cc.y and cc.altitude=ce.altitude)
WHERE cc.marchable='1' AND territoire='0' AND ce.type NOT IN (2,3,6)
ORDER BY Rand() LIMIT 1


Peux-tu me dire si j'ai zappé un truc ? J'ai écrit en dur territoire='0' pour tester, je te laisse le paramétrer.
Toujours le même éternel problème.

La case 2,0,17,15 a un PJ (type 2) et un drop (type 5). Comme elle contient un PJ, elle ne devrait pas être dans liste, hors elle y est.

Mon soucis est bien là, c'est que si y a un évènement + et un évènement -, il comptera + là où je veux -.

En gros, pour tester, on peut faire ça simplement (j'ai simplifié au max les tables sans dénaturer le problème), avec territoire=2

Table carte_cases : (X, Marchable, Territoire)
(1,1,1),(2,0,1),(3,0,2),(4,1,2),(5,1,2),(6,1,2),(7,1,2),(8,1,2),(9,1,2),(10,1,2),(11,1,2),(12,1,2),(13,1,2),(14,1,2),(15,1,2),(16,1,2)


Table carte_evenement : (X,Type)
(5,1),(6,2),(7,3),(8,4),(9,5),(10,6),(11,5),(11,2),(12,1),(12,5),(13,2),(13,3),(14,1),(14,1),(14,4),(15,4),(15,5),(15,2),(16,1),(16,1),(16,4),(16,5)

Là-dessus, je devrais arriver à une liste (select cc.X sans doublon):
4,5,8,9,12,14,16

Est ôté de la liste :
X=1 et X=2 parce que Territoire<>1
X=3 parce que marchable=0
X=6 parce que Type=2
X=7 parce que Type=3
X=10 parce que Type=6
X=11 parce que Type=2 (malgré un 2ème Type=5)
X=12 parce que Type=2 et 2ème Type=3
X=15 parce que Type=2 (même avec un 2ème Type=4 et un 3ème Type=5)


Et avec ta solution, ma liste ressemble à :
4,5,8,9,11,12,14,15,16
Modifié par Lothindil (18 Sep 2013 - 11:45)
D'accord, en effet j'avais lu trop vite. Essaye un peu ça :

SELECT DISTINCT cc.*
FROM cc INNER JOIN ce ON (ce.carte=cc.carte and ce.x=cc.x and ce.y=cc.y and cc.altitude=ce.altitude)
WHERE cc.marchable='1' AND territoire='0' AND CONCAT(cc.carte,"_",cc.x,"_",cc.y,"_",cc.altitude)NOT IN (SELECT CONCAT(cc.carte,"_",cc.x,"_",cc.y,"_",cc.altitude)
FROM cc INNER JOIN ce ON (ce.carte=cc.carte and ce.x=cc.x and ce.y=cc.y and cc.altitude=ce.altitude)
WHERE ce.type IN (2,3,6))
ORDER BY Rand() LIMIT 1


J'ai été obligé d'utiliser CONCAT du fait que la clé primaire de CC est composite. Avec un ID en auto increment, ça serait un peu moins tordu...
Modifié par petibato (18 Sep 2013 - 12:47)
Ouais, sans doute, mais un ID en auto-increment n'aurait pas empêcher le doublon sur les coordonnées ^^

Sinon ça marche nickel, j'ai simplifié un peu le concat', vu qu'un territoire est toujours situé sur une même carte et une même altitude et donc je l'ai simplifié à X-Y ^^

Un grand merci à toi ^^ serait temps que je me plonge sérieusement dans les subquery ^^ (enfin là c'est plutôt concat et le not in qu'il me manquait)