Commit ca0b7423 authored by Francois Mares's avatar Francois Mares
Browse files

upgrade NewObject

parent 0bb248cb
0
\ No newline at end of file
1
\ No newline at end of file
1
\ No newline at end of file
1
\ No newline at end of file
1
\ No newline at end of file
1
\ No newline at end of file
import pandas as pd
from enum import Enum, unique
from itertools import product
from concurrent.futures import ThreadPoolExecutor
from ModelCallable import ModelCallable
......@@ -16,6 +18,19 @@ class ModelObjects(Enum):
It="Intéraction"
CP="Champ Perceptif"
def get(obj):
t=type(obj)
if t==GrapheDeComposition:
return ModelObjects.GC
elif t==Categorie:
return ModelObjects.CI
elif t==Interaction:
return ModelObjects.It
elif t==ChampPerceptif:
return ModelObjects.CP
else:
return None
class Model:
"""
Contient tous les objets construits.
......@@ -45,11 +60,32 @@ class Model:
self._data=self._data.append(newData, ignore_index=True)
self.informObjectsAdded(list(range(i, self._data.index[-1]+1)))
def createGrapheDeComposition(self, objets:set = set(), morphismes:set=set(), nom:str = None):
def createGrapheDeComposition(self, objets:set = set(), morphismes:set=set(), identifications:set=set(), nom:str = None):
"""
From str
"""
gc=GC(objets=objets, nom=nom)
self.addObject(gc)
gc|= objets
gc|= morphismes
# morphismes
dic={str(x[2]):MGC(x[0],x[1],x[2]) for x in morphismes}
gc|= list(dic.values())
# identifications
# vérifier que les morphismes existent
for x in identifications:
x[0]=[dic.get(m) for m in x[0]]
x[1]=[dic.get(m) for m in x[1]]
if (None in x[0]) or (None in x[1]):
print(f"WARNING: {x} n'est pas une identification valide.")
else:
compoG=x[0][0]
for m in x[0][1:]:
compoG @=m
compoD=x[1][0]
for m in x[1][1:]:
compoD @=m
MGC.identifier_morphismes(compoG,compoD)
"""
GETTERS
......@@ -90,6 +126,97 @@ class Model:
for rdm in self._registeredModelCallable:
rdm.informObjectsDeleted(uids)
"""
Graphviz
"""
def exporterGraphviz(self, uids):
data=self.getObject(uids)
with ThreadPoolExecutor(max_workers=len(data)) as executor:
for index, row in data.iterrows():
obj=row["object"]
if callable(getattr(obj,"transformer_graphviz",None)):
executor.submit(obj.transformer_graphviz())
class Description:
_obj:object=None
_str:str=""
def __init__(self, obj:object, *args, **kwargs):
self._obj=obj
with ThreadPoolExecutor(max_workers=1) as executor:
self._str = executor.submit(self.generer).result()
def __str__(self):
return self._str
def generer(self):
mo=ModelObjects.get(self._obj)
if mo==ModelObjects.GC:
return self._genererDescriptionCategorie()
else:
return str(self._obj)
def _genererDescriptionCategorie(self, afficher_identites:bool = True, complet:bool = True, limite_fleches:int = 30):
"""
`complet` indique s'il faut afficher toutes les flèches ou seulement les flèches élémentaires.
`limite_fleches` est le nombre maximal de flèches entre deux objets qu'on s'autorise à afficher.
"""
descr=""
if self._obj.nom:
descr+=self._obj.nom
# objets
descr+=" {"
print(self)
for o in self._obj.objets:
descr+=str(o)+","
descr=descr[:-1]+"}"
# flesches
fleches_elem = set(self._obj[self._obj.objets,self._obj.objets])
if complet:
func = lambda x,y : self._obj({x},{y})
else:
func = lambda x,y : self._obj[{x},{y}]
fleches_elementaires=[]
fleches_non_elementaires=[]
for source,cible in product(self._obj.objets,repeat=2):
nb_fleches = 0
for fleche in func(source,cible):
if afficher_identites or not fleche.is_identite:
if fleche.source not in self._obj.objets:
raise Exception("Source d'une fleche pas dans les objets de la categorie.")
if fleche.cible not in self._obj.objets:
raise Exception("Source d'une fleche pas dans les objets de la categorie.")
if len({obj for obj in self._obj.objets if obj == fleche.source}) > 1:
raise Exception("Plus d'un objet de la catégorie est source de la fleche.")
if len({obj for obj in self._obj.objets if obj == fleche.cible}) > 1:
raise Exception("Plus d'un objet de la catégorie est cible de la fleche.")
#permet d'avoir toujours un objet de la catégorie comme source
source = {obj for obj in self._obj.objets if obj == fleche.source}.pop()
#permet d'avoir toujours un objet de la catégorie comme cible
cible = {obj for obj in self._obj.objets if obj == fleche.cible}.pop()
# descriptions
if fleche in fleches_elem:
fleches_elementaires.append(f"({str(source)},{str(cible)},{str(fleche)})")
else:
fleches_non_elementaires.append(f"({str(source)},{str(cible)},{str(fleche)})")
nb_fleches += 1
if nb_fleches > limite_fleches:
if WARNING_LIMITE_FLECHES_ATTEINTE:
print("Warning : limite fleches entre "+str(source)+" et "+str(cible)+" atteinte.")
break
descr+=" flèches: "
for f in fleches_non_elementaires:
descr+=f
for f in fleches_elementaires:
descr+=f
return descr
......
......@@ -135,12 +135,7 @@ class MainWindow:
def exporterGraphviz(self):
uids=self._objFrame.getSelectedObjects()
data=self._controller.getModel().getObject(uids)
for index, row in data.iterrows():
obj=row["object"]
if callable(getattr(obj,"transformer_graphviz",None)):
obj.transformer_graphviz()
self._controller.getModel().exporterGraphviz(uids)
class ExportAsDialog(Toplevel):
......
......@@ -65,6 +65,7 @@ class BuildObjectFrame(Frame):
_validateButton=None
_textObjects=None
_textMorphismes=None
_textIdentifications=None
def __init__(self, parent, model, obj:ModelObjects, *args, **kwargs):
assert model and parent
......@@ -85,6 +86,7 @@ class BuildObjectFrame(Frame):
self.rowconfigure(0, weight=1, minsize=20)
self.rowconfigure(1, weight=1, minsize=20)
self.rowconfigure(2, weight=1, minsize=20)
self.rowconfigure(3, weight=1, minsize=20)
# Objects
self._textObjects=ObjectLabelText(self)
......@@ -94,10 +96,15 @@ class BuildObjectFrame(Frame):
self._textMorphismes=MorphismeLabelText(self)
self._textMorphismes.grid(row=2, column=0)
# Identifications
self._textIdentifications=IdentificationLabelText(self)
self._textIdentifications.grid(row=3, column=0)
# Button
def generate():
self._model.createGrapheDeComposition(objets=self._textObjects.getObjectsList(),
morphismes=self._textMorphismes.getMorphismesList(),
self._model.createGrapheDeComposition(objets=self._textObjects.getList(),
morphismes=self._textMorphismes.getList(),
identifications=self._textIdentifications.getList(),
nom = None)
self._validateButton=Button(self, text="Générer", command=generate)
self._validateButton.grid(row=0, column=0, sticky="e")
......@@ -126,7 +133,7 @@ class LabelText(LabelFrame):
if self._description:
Label(self, text=self._description, anchor="w").grid(row=0, column=0, sticky="new")
self._text=Text(self)
self._text=Text(self, height=3, width=20)
self._text.grid(row=1, column=0, sticky="nw")
self._scrollbarY=Scrollbar(self, orient =VERTICAL)
......@@ -143,7 +150,7 @@ class ObjectLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Objets", description="ex: 1,2,3...", *args, **kwargs)
def getObjectsList(self):
def getList(self):
return [x for x in split('[,\n]', self.getText()) if x]
class MorphismeLabelText(LabelText):
......@@ -151,16 +158,30 @@ class MorphismeLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Morphismes", description="ex: (1,2,f)(2,3,g)...", *args, **kwargs)
def getMorphismesList(self):
def getList(self):
# (...)
tuples=[x[1:-1] for x in findall("\([^\(\)]+\)", self.getText()) if x]
# ,\n
tuplesSplited=[[x for x in split('[,\n]', t) if x] for t in tuples]
# 3 chaînes
# 3 éléments
morphismesDescription=[x for x in tuplesSplited if len(x)==3]
# Création des morphismes
return [MGC(x[0],x[1],x[2]) for x in morphismesDescription]
return morphismesDescription
class IdentificationLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Identifications", description="ex: (g@f,h)(h@h,h)...", *args, **kwargs)
def getList(self):
# (...)
tuples=[x[1:-1] for x in findall("\([^\(\)]+\)", self.getText()) if x]
# ,\n
tuplesSplited=[[x for x in split('[,\n]', t) if x] for t in tuples]
# 2 éléments
identifications=[[split('[@]', x[0]),split('[@]', x[1])] for x in tuplesSplited if len(x)==2]
# Création des identifications
return identifications
......
......@@ -2,15 +2,17 @@
Définition de l'espace de droite
"""
from pandas import DataFrame
from tkinter import TOP, X, NO, W, Y, YES, BOTH, RIGHT, VERTICAL, \
Frame, Label
from tkinter.ttk import Treeview, Style, Scrollbar
from ModelCallable import ModelCallable
from Model import Description
from tk.InformFrame import InformFrame
from tk.Factory import *
from tkinter import TOP, X, NO, W, Y, YES, BOTH, RIGHT, VERTICAL, \
Frame, Label
from tkinter.ttk import Treeview, Style, Scrollbar
class ObjetsFrame(Frame, ModelCallable):
......@@ -52,8 +54,8 @@ class ObjetsFrame(Frame, ModelCallable):
self._tree["columns"]=("class","description")
self._tree.column("#0", width=100, minwidth=15, stretch=False)
self._tree.column("class", width=100, minwidth=100, stretch=True)
self._tree.column("description", width=100, minwidth=50, stretch=False)
self._tree.column("class", width=50, stretch=False)
self._tree.column("description", width=200, minwidth=80, stretch=True)
self._tree.heading("#0",text="UID",anchor=W)
self._tree.heading("class", text="Classe",anchor=W)
......@@ -115,7 +117,7 @@ class ObjetsFrame(Frame, ModelCallable):
self._folders[folder]=f
objects=(df['object'][df['class']==folder]).sort_index(ascending=True)
for uid, obj in objects.items():
self._tree.insert(parent=f, iid=uid, index="end", text=uid, values=(folder, obj))
self._tree.insert(parent=f, iid=uid, index="end", text=uid, values=(folder, Description(obj)))
def addObject(self, uid, obj:object):
class_name=type(obj).__name__
......@@ -123,11 +125,12 @@ class ObjetsFrame(Frame, ModelCallable):
if not f:
f=self._tree.insert(parent="", index="end", text=class_name)
self._folders[class_name]=f
self._tree.insert(parent=f, iid=uid, index="end", text=uid, values=(class_name, obj))
self._tree.insert(parent=f, iid=uid, index="end", text=uid, values=(class_name, Description(obj)))
def deleteObject(self, uid):
self._tree.delete(self._tree.item(uid))
"""
BIND FUNCTIONS
"""
......@@ -152,3 +155,4 @@ class ObjetsFrame(Frame, ModelCallable):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment