File size: 2,816 Bytes
3fda900
f5d16b0
 
a713797
 
 
50a2f21
f5d16b0
 
a713797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5e1c140
 
a713797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f5d16b0
 
50a2f21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>D3 Python Visualizer</title>
  <link rel="stylesheet" href="/static/style.css">
 <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
  <h2>🐍 Python Visualizer with D3.js</h2>

  <form method="post" action="/run">
    <textarea name="code" rows="10" cols="70" placeholder="Enter Python code here...">{{ code or '' }}</textarea><br>
    <button type="submit">Run Code</button>
  </form>

  {% if output %}
  <h3>Output:</h3>
  <pre>{{ output }}</pre>
  {% endif %}

  <div id="viz"></div>

  <script>
    const traceData = {{ trace_json | safe if trace_json else '[]' }};
    if (traceData.length > 0) {
      const width = 700, height = 400;
      const svg = d3.select("#viz")
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .style("background", "#f8f8f8")
        .style("border-radius", "10px");

      let currentStep = 0;

      const frameGroup = svg.append("g").attr("transform", "translate(50,80)");

      function renderStep(step) {
        frameGroup.selectAll("*").remove();

        const stepData = traceData[step];
        if (stepData.error) {
          frameGroup.append("text")
            .text("Error: " + stepData.error)
            .attr("fill", "red")
            .attr("x", 50)
            .attr("y", 20);
          return;
        }

        frameGroup.append("text")
          .text("Line: " + stepData.line)
          .attr("x", 0)
          .attr("y", -30)
          .attr("font-weight", "bold");

        const vars = Object.entries(stepData.locals);
        vars.forEach((v, i) => {
          const [name, val] = v;
          const boxY = i * 50;
          frameGroup.append("rect")
            .attr("x", 0)
            .attr("y", boxY)
            .attr("width", 200)
            .attr("height", 40)
            .attr("fill", "#fff")
            .attr("stroke", "#000");

          frameGroup.append("text")
            .text(name + " = " + val)
            .attr("x", 10)
            .attr("y", boxY + 25)
            .attr("font-family", "monospace");
        });
      }

      function addButtons() {
        const controls = d3.select("body").append("div").attr("id", "controls");
        controls.append("button").text("◀ Prev").on("click", () => {
          if (currentStep > 0) { currentStep--; renderStep(currentStep); }
        });
        controls.append("button").text("▶ Next").on("click", () => {
          if (currentStep < traceData.length - 1) { currentStep++; renderStep(currentStep); }
        });
        controls.append("span")
          .text("  Step " + (currentStep+1) + " of " + traceData.length)
          .attr("id", "stepInfo");
      }

      addButtons();
      renderStep(0);
    }
  </script>
</body>
</html>