trane-project / trane-cli

A command-line interface and utilities for Trane
GNU Affero General Public License v3.0
28 stars 1 forks source link

feat: Support getting dependencies graph of course #13

Closed huang12zheng closed 2 years ago

huang12zheng commented 2 years ago

something like

~~ trane list dependencies ~~ ~~ to get all lessons in all course ~~

  • trane list dependencies [ids] to get all lessons given course ids or get all exercises given lesson ids
huang12zheng commented 2 years ago
  • trane list dependencies [ids] to get all lessons given course ids or get all exercises given lesson ids

Currently, only one ID is supported

huang12zheng commented 2 years ago

The idea seemed difficult to implement and would involved trane::graph

martinmr commented 2 years ago

No worries, I can work on this. For now, you can use the command debug unit-info. It prints the manifest, which lists the dependencies.

martinmr commented 2 years ago

Example output

trane >> debug unit-info trane::music::guitar::basic_fretboard
Unit ID: trane::music::guitar::basic_fretboard
Unit type: Course
Unit manifest:
CourseManifest {
    id: u!("trane::music::guitar::basic_fretboard"),
    name: "Basic Guitar Fretboard",
    dependencies: [],
    description: Some(
        "Learn the position of notes in the guitar frateboard",
    ),
    authors: Some(
        [
            "The Trane Project",
        ],
    ),
    metadata: Some(
        {
            "instrument": [
                "guitar",
            ],
            "musical_skill": [
                "fretboard",
            ],
            "skill": [
                "music",
            ],
        },
    ),
    course_material: None,
    course_instructions: None,
}
huang12zheng commented 2 years ago

I can also see INCOMING_calls upstream of INCOMing_calls or HANDLE_CALL_HIERARCHy_incoming. I can even find ON_Request, handle_Event, Run, and main_loop in handle_CALL_hierarchy_incoming

截屏2022-08-01 下午9 23 55
huang12zheng commented 2 years ago

After those above, we have an aspect that saves the results of multiple commands to show the results of the tree shown in the figure

huang12zheng commented 2 years ago

在上面这些之后,我们有一个切面,它保存了多个命令的结果,以显示如图所示的树的结果

Or implementation dot::GraphWalk to generator graphviz file

martinmr commented 2 years ago

I've thought of something like this for the graphical interface (I've barely started to work on it). I could add more commands to list the dependencies and dependents of a unit, but having any kind of interactivity or saved state is going to be difficult and probably not a great experience anyway given the limitations of the terminal.

The suggestion to generate a graphviz file is probably a much better option and it should be fairly easy to implement. I'll read about graphviz just to confirm.

martinmr commented 2 years ago

Generate a DOT file in trane: https://github.com/trane-project/trane/pull/36

I'll integrate this into the CLI next.

martinmr commented 2 years ago

So I've added commands list dependencies <UNIT_ID> and list dependents <UNIT_ID> to list dependencies and dependents of a unit. It doesn't have a lot of interactivity because that's going to be hard to implement on the command-line.

There's also debug export-graph which exports the dependent graph. It exports the dependent graph instead of the dependency graph because I thought this graph is easier to follow along. An edge between nodes A and B means that A needs to be mastered before B.

Below is the graph from trane-leetcode as an example.

digraph dependent_graph {
    "trane::leetcode::advanced_graphs" -> "trane::leetcode::advanced_graphs::medium"
    "trane::leetcode::advanced_graphs::medium" -> "trane::leetcode::advanced_graphs::hard"
    "trane::leetcode::arrays_hashing" -> "trane::leetcode::arrays_hashing::easy"
    "trane::leetcode::arrays_hashing::easy" -> "trane::leetcode::arrays_hashing::medium"
    "trane::leetcode::backtracking" -> "trane::leetcode::backtracking::medium"
    "trane::leetcode::backtracking::medium" -> "trane::leetcode::backtracking::hard"
    "trane::leetcode::binary_search" -> "trane::leetcode::binary_search::easy"
    "trane::leetcode::binary_search::easy" -> "trane::leetcode::binary_search::medium"
    "trane::leetcode::binary_search::medium" -> "trane::leetcode::binary_search::hard"
    "trane::leetcode::bit_manipulation" -> "trane::leetcode::bit_manipulation::easy"
    "trane::leetcode::bit_manipulation::easy" -> "trane::leetcode::bit_manipulation::medium"
    "trane::leetcode::graphs" -> "trane::leetcode::advanced_graphs"
    "trane::leetcode::graphs" -> "trane::leetcode::graphs::medium"
    "trane::leetcode::graphs::medium" -> "trane::leetcode::graphs::hard"
    "trane::leetcode::greedy" -> "trane::leetcode::greedy::medium"
    "trane::leetcode::heap_priority_queue" -> "trane::leetcode::heap_priority_queue::easy"
    "trane::leetcode::heap_priority_queue::easy" -> "trane::leetcode::heap_priority_queue::medium"
    "trane::leetcode::heap_priority_queue::medium" -> "trane::leetcode::heap_priority_queue::hard"
    "trane::leetcode::intervals" -> "trane::leetcode::intervals::easy"
    "trane::leetcode::intervals::easy" -> "trane::leetcode::intervals::medium"
    "trane::leetcode::intervals::medium" -> "trane::leetcode::intervals::hard"
    "trane::leetcode::linked_list" -> "trane::leetcode::linked_list::easy"
    "trane::leetcode::linked_list::easy" -> "trane::leetcode::linked_list::medium"
    "trane::leetcode::linked_list::medium" -> "trane::leetcode::linked_list::hard"
    "trane::leetcode::math_and_geometry" -> "trane::leetcode::math_and_geometry::easy"
    "trane::leetcode::math_and_geometry::easy" -> "trane::leetcode::math_and_geometry::medium"
    "trane::leetcode::one_d_dynamic_programming" -> "trane::leetcode::one_d_dynamic_programming::easy"
    "trane::leetcode::one_d_dynamic_programming" -> "trane::leetcode::two_d_dynamic_programming"
    "trane::leetcode::one_d_dynamic_programming::easy" -> "trane::leetcode::one_d_dynamic_programming::medium"
    "trane::leetcode::sliding_window" -> "trane::leetcode::sliding_window::easy"
    "trane::leetcode::sliding_window::easy" -> "trane::leetcode::sliding_window::medium"
    "trane::leetcode::sliding_window::medium" -> "trane::leetcode::sliding_window::hard"
    "trane::leetcode::stack" -> "trane::leetcode::stack::easy"
    "trane::leetcode::stack::easy" -> "trane::leetcode::stack::medium"
    "trane::leetcode::stack::medium" -> "trane::leetcode::stack::hard"
    "trane::leetcode::trees" -> "trane::leetcode::trees::easy"
    "trane::leetcode::trees::easy" -> "trane::leetcode::trees::medium"
    "trane::leetcode::trees::medium" -> "trane::leetcode::trees::hard"
    "trane::leetcode::tries" -> "trane::leetcode::tries::medium"
    "trane::leetcode::tries::medium" -> "trane::leetcode::tries::hard"
    "trane::leetcode::two_d_dynamic_programming" -> "trane::leetcode::two_d_dynamic_programming::medium"
    "trane::leetcode::two_d_dynamic_programming::medium" -> "trane::leetcode::two_d_dynamic_programming::hard"
    "trane::leetcode::two_pointers" -> "trane::leetcode::two_pointers::easy"
    "trane::leetcode::two_pointers::easy" -> "trane::leetcode::two_pointers::medium"
    "trane::leetcode::two_pointers::medium" -> "trane::leetcode::two_pointers::hard"
}

Just keep in mind that lessons in a course appear as dependents of the course. The graph might make it seems like Trane will move on to the next courses before it finishes traversing its lessons, but that is not the case. Properly indicating the relationships between course and lessons in the graph would require that each course have two nodes, one incoming and one outgoing, like this:

digraph dependent_graph {
    Course1_out -> Course2_in
    Course2_in -> Course2_Lesson1
    Course2_Lesson1 -> Course2_Lesson2
    Course2_Lesson2 -> Course2_out
    Course2_out -> Course3_in
}

I might eventually do the work to get the lessons to be represented like this in the graph, which would simplify the scheduler a bit, but given that things are working fine for now and this would be a big change, it's not my highest priority.

Let me know if you try it out and have any feedback about the graph output.