-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
281 additions
and
244 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
dist | ||
tests/__pycache__ | ||
skillmap/__pycache__ | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[tool.poetry] | ||
name = "skillmap" | ||
version = "0.2.3" | ||
version = "0.3.0" | ||
description = "Skillmap generates a skill tree from a toml file" | ||
authors = ["Yue Ni <[email protected]>"] | ||
readme = "README.md" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
SECTION_SEPARATOR = "%" * 30 | ||
|
||
def get_required_node_edges(qualified_node_id, required_node_ids): | ||
node_requires = [ | ||
f"{required_node_id}-->{qualified_node_id}" | ||
for required_node_id in required_node_ids | ||
] | ||
return "\n".join(node_requires) | ||
|
||
|
||
def get_icon(dict_value): | ||
icon = "" | ||
if "icon" in dict_value: | ||
icon = f"fa:fa-{dict_value['icon']}" | ||
return icon | ||
|
||
|
||
def get_node_content(items, multi_lines_layout=True): | ||
separator = "<br/>" if multi_lines_layout else " " | ||
# join non empty items | ||
return separator.join([i for i in items if i]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from skillmap.nodes.common import get_icon, get_node_content, get_required_node_edges, SECTION_SEPARATOR | ||
from skillmap.nodes.skill_node import create_skill_node | ||
|
||
|
||
def _qualify(group_id): | ||
return f"groups.{group_id}" | ||
|
||
|
||
def _qualified_skill_id(qualified_group_id, skill_id): | ||
return f"{qualified_group_id}.skills.{skill_id}" | ||
|
||
|
||
def create_groups_edges(map_id, groups): | ||
group_ids = [ | ||
_qualify(group_id) | ||
for group_id, group_value in groups.items() | ||
if "requires" not in group_value # all groups without requires | ||
] | ||
groups_edges = "\n".join([f"{map_id}-->{gid}" for gid in group_ids]) | ||
return groups_edges | ||
|
||
|
||
def get_group_skills_list(qualified_group_id, group_skills): | ||
group_skills = [ | ||
create_skill_node( | ||
_qualified_skill_id(qualified_group_id, skill_id), skill_value | ||
) | ||
for skill_id, skill_value in group_skills.items() | ||
] | ||
return "\n".join(group_skills) | ||
|
||
|
||
def get_group_status(group_skills): | ||
for _, skill_value in group_skills.items(): | ||
skill_status = skill_value.get("status", "") | ||
if skill_status not in ("new", ""): | ||
return "normal" | ||
return "new" | ||
|
||
|
||
def create_group_subgraph(group_id, group_value): | ||
qualified_group_id = _qualify(group_id) | ||
group_name = group_value.get("name", "") | ||
group_icon = get_icon(group_value) | ||
group_icon_label = get_node_content([group_icon, group_name], False) | ||
group_skills_list = get_group_skills_list( | ||
qualified_group_id, group_value.get("skills", {}) | ||
) | ||
group_status = get_group_status(group_value.get("skills", {})) | ||
|
||
group_requires_list = get_required_node_edges( | ||
qualified_group_id, group_value.get("requires", []) | ||
) | ||
|
||
group_id_and_name = f"subgraph {qualified_group_id}[{group_icon_label}]" | ||
group_style = f"class {qualified_group_id} {group_status}SkillGroup;" | ||
group_subgraph_end = "end" | ||
sections = [ | ||
SECTION_SEPARATOR, | ||
group_id_and_name, | ||
group_skills_list, | ||
group_subgraph_end, | ||
group_style, | ||
group_requires_list, | ||
] | ||
|
||
group_graph = "\n".join(sections) | ||
return group_graph | ||
|
||
|
||
def create_group_subgraphs(groups): | ||
group_graphs = [ | ||
create_group_subgraph(group_id, group_value) | ||
for group_id, group_value in groups.items() | ||
] | ||
return "\n\n".join(group_graphs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from skillmap.nodes.common import get_icon, get_node_content, get_required_node_edges | ||
from fractions import Fraction | ||
from enum import Enum | ||
|
||
class Status(Enum): | ||
NEW = "new" | ||
BEING_LEANRED = "beingLearned" | ||
LEARNED = "learned" | ||
UNKNOWN = "unknown" | ||
|
||
def _is_locked_skill_value(skill_value): | ||
icon = skill_value.get("icon", None) | ||
status = skill_value.get("status", None) | ||
return icon == "lock" and status == "unknown" | ||
|
||
def get_progress(skill_value): | ||
if _is_locked_skill_value(skill_value): | ||
return ("", Status.UNKNOWN) | ||
|
||
progress_string = skill_value.get("progress", None) | ||
if progress_string: | ||
Fraction(progress_string) | ||
current, total = map(int, progress_string.split("/")) | ||
status = Status.NEW | ||
if current > 0: | ||
status = Status.BEING_LEANRED if current < total else Status.LEARNED | ||
|
||
return (f"{'■' * current}{'□' * (total - current)}", status) | ||
else: | ||
return ("", Status.NEW) | ||
|
||
|
||
def create_skill_node(skill_id, skill_value): | ||
if not skill_value: | ||
locked_skill_value = {"name": "???", "icon": "lock", "status": "unknown"} | ||
skill_value = locked_skill_value | ||
skill_name = skill_value.get("name", "") | ||
skill_icon = get_icon(skill_value) | ||
skill_progress, skill_status = get_progress(skill_value) | ||
skill_icon_label = get_node_content([skill_icon, skill_name, skill_progress]) | ||
skill_id_and_name = f"{skill_id}(\"{skill_icon_label}\")" | ||
skill_style = f"class {skill_id} {skill_status.value}Skill;" | ||
skill_requires = get_required_node_edges(skill_id, skill_value.get("requires", [])) | ||
sections = [ | ||
skill_id_and_name, | ||
skill_style, | ||
skill_requires, | ||
] | ||
skill_graph = "\n".join(sections) | ||
return skill_graph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from skillmap.theme_loader import load_theme | ||
from skillmap.nodes.common import get_icon, get_node_content, SECTION_SEPARATOR | ||
from skillmap.nodes.group_node import create_group_subgraphs, create_groups_edges | ||
import re | ||
|
||
|
||
def alphanumerize(s): | ||
return re.sub(r"\W+", "_", s) | ||
|
||
|
||
def get_orientation(skill_map_dict): | ||
orientation = skill_map_dict.get("orientation", "TD") | ||
if orientation not in ["TD", "TB", "BT", "RL", "LR"]: | ||
orientation = "TD" | ||
return orientation | ||
|
||
|
||
# generate a mermaid graph from a skill map toml dict | ||
def create_skillmap_graph(skill_map): | ||
skill_map_dict = skill_map.get("skillmap", {}) | ||
map_name = skill_map_dict.get("name", "unamed_skill_map") | ||
map_id = alphanumerize(map_name) | ||
theme = skill_map_dict.get("theme", "ocean") | ||
orientation = get_orientation(skill_map_dict) | ||
map_icon = get_icon(skill_map_dict) | ||
map_icon_label = get_node_content([map_icon, map_name]) | ||
|
||
map_to_group_edges = create_groups_edges(map_id, skill_map.get("groups", {})) | ||
map_group_subgraphs = create_group_subgraphs(skill_map.get("groups", {})) | ||
|
||
skill_map_node = f"{map_id}({map_icon_label})" | ||
skill_map_node_style = f"class {map_id} normalSkillGroup;" | ||
skill_map_header = f"flowchart {orientation}" | ||
sections = [ | ||
skill_map_header, | ||
skill_map_node, | ||
map_group_subgraphs, | ||
SECTION_SEPARATOR, | ||
map_to_group_edges, | ||
load_theme(theme), | ||
skill_map_node_style, | ||
] | ||
return "\n".join(sections) |
Oops, something went wrong.