Skip to content

Commit

Permalink
refactors towards symmetry handling
Browse files Browse the repository at this point in the history
  • Loading branch information
WolfgangFahl committed Feb 27, 2024
1 parent 463d093 commit 08df3e0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 18 deletions.
42 changes: 26 additions & 16 deletions dcm/dcm_chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ def generate_pie_elements(
self,
level: int,
svg: SVG,
ct: CompetenceTree,
parent_element: CompetenceElement,
learner: Learner,
segment: DonutSegment,
Expand All @@ -299,11 +300,12 @@ def generate_pie_elements(
of the given parent_element at the given level
e.g. aspects, areas or facets - taking the learner
achievements into account if a corresponding achievement
is found. The segment limits the area in which the generation may operate
is found. The segment limits the area in
which the generation may operate
the symmetry level denotes at which level the rings should be symmetric
"""
sub_element_name = self.levels[level]
sub_element_name = ct.level_attr_names[level]
# get the elements to be displayed
elements = getattr(parent_element, sub_element_name)
total = len(elements)
Expand Down Expand Up @@ -354,10 +356,11 @@ def generate_pie_elements(
svg, element, learner, segment=sub_segment, ringspec=ringspec
)
start_angle = end_angle
if level + 1 < len(self.levels):
if level + 1 < ct.total_levels:
self.generate_pie_elements(
level=level + 1,
svg=svg,
ct=ct,
parent_element=element,
learner=learner,
segment=sub_segment,
Expand All @@ -374,19 +377,24 @@ def calculate_segments(self, ct: CompetenceTree, tree_segment: DonutSegment) ->
Returns:
A dictionary where keys are element paths and values are the corresponding DonutSegment objects.
"""
level_segments = {}
level_segments = {
"aspect": {},
"area": {},
"facet": {}
}

def calculate_for_element(element, parent_segment, level=0):
def calculate_for_element(parent_segment, level=1):
# Calculate segment size based on the number of elements at this level
elements = getattr(element, self.levels[level], [])
elements = ct.get_elements_for_level(level)
level_name=ct.level_names[level]
total_elements = len(elements)
if total_elements == 0:
return

angle_per_element = (parent_segment.end_angle - parent_segment.start_angle) / total_elements
start_angle = parent_segment.start_angle

for i, sub_element in enumerate(elements):
for _i, sub_element in enumerate(elements):
end_angle = start_angle + angle_per_element
# Create a new segment for this element
segment = DonutSegment(
Expand All @@ -398,17 +406,18 @@ def calculate_for_element(element, parent_segment, level=0):
end_angle=end_angle,
text_mode=tree_segment.text_mode,
)
# Store the segment with its corresponding path as the key
level_segments[sub_element.path] = segment
# add the segment with the sub element's path as the key
level_segments[level_name][sub_element.path]=segment

# Recurse for sub-elements if not at the last level
if level + 1 < len(self.levels):
calculate_for_element(sub_element, segment, level + 1)
if level + 1 < len(ct.level_names):
calculate_for_element(segment, level + 1)

start_angle = end_angle

# Start the calculation with the root of the competence tree
calculate_for_element(ct, tree_segment)
# Start the calculation with the root of
# the competence tree's circular segment
calculate_for_element(tree_segment)

return level_segments

Expand Down Expand Up @@ -457,17 +466,18 @@ def generate_svg_markup(
if competence_tree is None:
competence_tree = self.dcm.competence_tree
self.selected_paths = selected_paths
self.levels = ["aspects", "areas", "facets"]

competence_tree.calculate_ring_specs(text_mode)
svg = self.prepare_and_add_inner_circle(config, competence_tree, lookup_url)

segment = DonutSegment(
cx=self.cx, cy=self.cy, inner_radius=0, outer_radius=self.tree_radius
)
self.calculate_segments(competence_tree,segment)
segments=self.calculate_segments(competence_tree,segment)
self.generate_pie_elements(
level=0,
level=1,
svg=svg,
ct=competence_tree,
parent_element=competence_tree,
learner=learner,
segment=segment,
Expand Down
22 changes: 20 additions & 2 deletions dcm/dcm_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ def __post_init__(self):
initalize the path variables of my hierarchy
"""
super().__post_init__()
self.total_elements = {"aspects": 0, "areas": 0, "facets": 0}
self.update_paths()
self.calculate_ring_specs("empty")

Expand Down Expand Up @@ -276,15 +275,34 @@ def get_symmetry_spec(self) -> Tuple[str, str]:
if not mode in ["count","score","time"]:
raise ValueError(f"Invalid symmetry mode {mode} - must be count, score or time")
return (level,mode)

def get_elements_for_level(self,level:int)->List[CompetenceElement]:
"""
get the elements for the given hierarchy level
Args:
level(int): the hierarchy level
Returns:
List(CompetencElement): the list of elements on this level
"""
level_name=self.level_names[level]
elements=self.elements_by_level[level_name]
return elements


def update_paths(self):
"""
update my paths
"""
self.level_names = ["tree","aspect", "area", "facet"]
self.level_attr_names = [None,"aspects", "areas", "facets"]
self.total_elements = {"tree": 1, "aspects": 0, "areas": 0, "facets": 0}
self.elements_by_level = {"tree": [self],"aspect": [], "area": [], "facet": []} # Reset for re-calculation

self.path = self.id
self.total_levels = 1
self.elements_by_path = {self.path: self}
self.elements_by_level = {"aspect": [], "area": [], "facet": []} # Reset for re-calculation
# Loop through each competence aspect and set their paths and parent references
for aspect in self.aspects:
aspect.competence_tree = self
Expand Down

0 comments on commit 08df3e0

Please sign in to comment.