update
This commit is contained in:
Binary file not shown.
BIN
arbre.png
BIN
arbre.png
Binary file not shown.
Before Width: | Height: | Size: 664 KiB After Width: | Height: | Size: 1015 KiB |
84
family.json
84
family.json
@ -125,12 +125,22 @@
|
|||||||
"565561317189091328": {
|
"565561317189091328": {
|
||||||
"name": "BardimeduSAFF Hamilton ofthemind",
|
"name": "BardimeduSAFF Hamilton ofthemind",
|
||||||
"avatar": "https://cdn.discordapp.com/avatars/565561317189091328/c77280ab4a455cd482f73a2ef38d72f8.png?size=1024",
|
"avatar": "https://cdn.discordapp.com/avatars/565561317189091328/c77280ab4a455cd482f73a2ef38d72f8.png?size=1024",
|
||||||
"parents": []
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"582633859967877133": {
|
"582633859967877133": {
|
||||||
"name": "L'incarn\u00e9 zzz",
|
"name": "L'incarn\u00e9 zzz",
|
||||||
"avatar": "https://cdn.discordapp.com/avatars/582633859967877133/89c60709a5e4c47ee16001844f0d51ad.png?size=1024",
|
"avatar": "https://cdn.discordapp.com/avatars/582633859967877133/89c60709a5e4c47ee16001844f0d51ad.png?size=1024",
|
||||||
"parents": []
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"689487017557360662": {
|
"689487017557360662": {
|
||||||
"name": "Ama-teramisu godess of Tiramisu",
|
"name": "Ama-teramisu godess of Tiramisu",
|
||||||
@ -159,6 +169,76 @@
|
|||||||
"name": "L'incarn\u00e9 zzz"
|
"name": "L'incarn\u00e9 zzz"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"691556011772739624": {
|
||||||
|
"name": "Gomar le ComeBack",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/691556011772739624/c34a971e013de812ed54f7f156195c66.png?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"984779875053371432": {
|
||||||
|
"name": "Troubadort zzz",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/984779875053371432/19d0f7994cfa6f8d5712a95a075c150b.png?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"1010673571850367078": {
|
||||||
|
"name": "TwinkMarket",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/1010673571850367078/a_f6099fc01cd019fb17e7a86452766b6e.gif?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"1052630499471937546": {
|
||||||
|
"name": "Firsting the Jalapeno nuggies",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/1052630499471937546/a_40a55abb361c7fea1d6390e88de10014.gif?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"903022775017562202": {
|
||||||
|
"name": "Kaboom",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/903022775017562202/e8b0baa91861840c39f3d7512b781bf9.png?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"758446383354216488": {
|
||||||
|
"name": "Sonic Fuzzbear",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/758446383354216488/ebdef758a78cc3e1f42148e5c96f646d.png?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"704610422619242536": {
|
||||||
|
"name": "Lysa_Swanson",
|
||||||
|
"avatar": "https://cdn.discordapp.com/avatars/704610422619242536/2d7379c11fe013d1146d9cbbe2974af8.png?size=1024",
|
||||||
|
"parents": [
|
||||||
|
{
|
||||||
|
"id": "1111230921954304000",
|
||||||
|
"name": "NYM N'EST PAS UN CODE BARRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"couples": [
|
"couples": [
|
||||||
|
99
tree.py
99
tree.py
@ -61,75 +61,68 @@ def generate_tree(input_file, output_file, root_id=None):
|
|||||||
"arrowsize": "1.2"
|
"arrowsize": "1.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
couple_style = {
|
||||||
|
"style": "dashed",
|
||||||
|
"color": "#FF69B4",
|
||||||
|
"penwidth": "2.5",
|
||||||
|
"dir": "none"
|
||||||
|
}
|
||||||
|
|
||||||
os.makedirs("temp_avatars", exist_ok=True)
|
os.makedirs("temp_avatars", exist_ok=True)
|
||||||
|
|
||||||
# Traitement de tous les membres
|
# 1. Création de tous les nœuds
|
||||||
for user_id, info in data["members"].items():
|
for user_id, info in data["members"].items():
|
||||||
original_avatar = f"avatars/{user_id}.png"
|
original_avatar = f"avatars/{user_id}.png"
|
||||||
combined_avatar = f"temp_avatars/combined_{user_id}.png"
|
combined_avatar = f"temp_avatars/combined_{user_id}.png"
|
||||||
|
|
||||||
if os.path.exists(original_avatar):
|
if os.path.exists(original_avatar):
|
||||||
create_avatar_with_name(
|
create_avatar_with_name(user_id, info["name"], original_avatar, combined_avatar)
|
||||||
user_id,
|
G.add_node(user_id, image=combined_avatar, **node_style)
|
||||||
info["name"],
|
|
||||||
original_avatar,
|
|
||||||
combined_avatar
|
|
||||||
)
|
|
||||||
G.add_node(
|
|
||||||
user_id,
|
|
||||||
image=combined_avatar,
|
|
||||||
**node_style
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
G.add_node(
|
G.add_node(user_id, label=info["name"], **{**node_style, "fontcolor": "white"})
|
||||||
user_id,
|
|
||||||
label=info["name"],
|
|
||||||
**{**node_style, "fontcolor": "white"}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Nouveau : Dictionnaire pour forcer les rangs des couples
|
# 2. Identification des niveaux
|
||||||
forced_ranks = {}
|
top_level = set()
|
||||||
|
|
||||||
# Traitement des couples
|
# Ajout des racines explicites
|
||||||
|
if root_id:
|
||||||
|
top_level.add(root_id)
|
||||||
|
else:
|
||||||
|
for root in data.get("roots", []):
|
||||||
|
top_level.add(root)
|
||||||
|
|
||||||
|
# Ajout des couples sans parents
|
||||||
|
for couple in data.get("couples", []):
|
||||||
|
if all(m in data["members"] and not data["members"][m].get("parents") for m in couple):
|
||||||
|
top_level.update(couple)
|
||||||
|
|
||||||
|
# 3. Création des sous-graphes hiérarchiques
|
||||||
|
if top_level:
|
||||||
|
G.add_subgraph(top_level, name="rank_top", rank="same")
|
||||||
|
|
||||||
|
# Niveau des enfants directs
|
||||||
|
children_level = set()
|
||||||
|
for user_id, info in data["members"].items():
|
||||||
|
parents = info.get("parents", [])
|
||||||
|
if any(p["id"] in top_level for p in parents):
|
||||||
|
children_level.add(user_id)
|
||||||
|
|
||||||
|
if children_level:
|
||||||
|
G.add_subgraph(children_level, name="rank_children", rank="same")
|
||||||
|
|
||||||
|
# 4. Gestion des couples
|
||||||
for couple in data.get("couples", []):
|
for couple in data.get("couples", []):
|
||||||
if all(m in data["members"] for m in couple):
|
if all(m in data["members"] for m in couple):
|
||||||
member1, member2 = couple
|
member1, member2 = couple
|
||||||
|
|
||||||
# Style spécial pour les liens de couple
|
# Lien conjugal
|
||||||
G.add_edge(member1, member2,
|
G.add_edge(member1, member2, **couple_style)
|
||||||
style="dashed",
|
|
||||||
color="#FF69B4",
|
|
||||||
penwidth="2.5",
|
|
||||||
dir="none")
|
|
||||||
|
|
||||||
# Force les partenaires au même rang
|
# Alignement forcé pour les couples racines
|
||||||
partner_group = f"couple_{min(couple)}_{max(couple)}"
|
if member1 in top_level and member2 in top_level:
|
||||||
G.add_subgraph(couple, name=partner_group, rank="same")
|
G.add_subgraph(couple, name=f"couple_{member1}_{member2}", rank="same")
|
||||||
forced_ranks[member1] = partner_group
|
|
||||||
forced_ranks[member2] = partner_group
|
|
||||||
|
|
||||||
# Organisation hiérarchique améliorée
|
# 5. Liens parent-enfant
|
||||||
if root_id:
|
|
||||||
roots = [root_id]
|
|
||||||
else:
|
|
||||||
roots = data.get("roots", [k for k,v in data["members"].items() if not v.get("parents")])
|
|
||||||
|
|
||||||
# Nouvelle approche pour les niveaux
|
|
||||||
levels = {}
|
|
||||||
for user_id in data["members"]:
|
|
||||||
gen = data["members"][user_id].get("generation",
|
|
||||||
len(data["members"][user_id].get("parents", [])))
|
|
||||||
if gen not in levels:
|
|
||||||
levels[gen] = []
|
|
||||||
levels[gen].append(user_id)
|
|
||||||
|
|
||||||
# Création des sous-graphes par niveau
|
|
||||||
for level, members in levels.items():
|
|
||||||
filtered_members = [m for m in members if m not in forced_ranks]
|
|
||||||
if filtered_members:
|
|
||||||
G.add_subgraph(filtered_members, name=f"rank{level}", rank="same")
|
|
||||||
|
|
||||||
# Connexions parent-enfant
|
|
||||||
for user_id, info in data["members"].items():
|
for user_id, info in data["members"].items():
|
||||||
for parent in info.get("parents", []):
|
for parent in info.get("parents", []):
|
||||||
if parent["id"] in data["members"]:
|
if parent["id"] in data["members"]:
|
||||||
|
Reference in New Issue
Block a user