Repository: EduMIPS64/edumips64
Pull request #1289: JSON-based WebUI Memory Section
Author: login: davidepatti
Created: 2025-03-28T09:31:48Z | Merged: 2025-03-30T17:30:52Z

This contribution replaces [previous wrong approach](https://github.com/EduMIPS64/edumips64/pull/1278)
Data are exported from Java with JSON object memory containing arrays for cells and intructions.
Memory.js renders the attributes exported form ResultsFactory.
Please notice that a couple of methods were added to extract some values from Memory java component, it seemed necessary, but I'm not 100% confident.

Suggestions are welcome.
![Screenshot 2025-03-28 at 10 30 47](https://github.com/user-attachments/assets/33e46480-ca99-40ef-ad65-ec3e76852fa7)



Diff:
diff --git a/src/main/java/org/edumips64/client/ResultFactory.java b/src/main/java/org/edumips64/client/ResultFactory.java
index 8da4ec30b..95a165f15 100644
--- a/src/main/java/org/edumips64/client/ResultFactory.java
+++ b/src/main/java/org/edumips64/client/ResultFactory.java
@@ -1,8 +1,8 @@
 /* ResultFactory.java
  *
  * A factory class to generate Result objects.
- * Injects a representation of the CPU status in every Result object that's created. 
- * 
+ * Injects a representation of the CPU status in every Result object that's created.
+ *
  * (c) 2020 Andrea Spadaccini
  *
  * This file is part of the EduMIPS64 project, and is released under the GNU
@@ -47,7 +47,7 @@ public class ResultFactory {
     private Memory memory;
     private Logger logger = Logger.getLogger("ResultFactory");
     private StringWriter stdout;
-    
+
     static String FromCpuStatus(CPUStatus s) {
         switch (s) {
         case READY:
@@ -102,7 +102,44 @@ private Result AddCpuInfo(Result r) {
     }
 
     private String getMemory() {
-        return memory.toString();
+        var memoryJson = new FluentJsonObject();
+        try {
+            var cells = memory.getCells();
+            var instructions = memory.getInstructions();
+
+            JSONArray cellArray = new JSONArray();
+            cells.forEach((address, element) -> {
+                cellArray.set(cellArray.size(), new FluentJsonObject()
+                        .put("address_hex", element.getAddressHex())
+                        .put("address", element.getAddress())
+                        .put("value", element.getValue())
+                        .put("value_hex", element.getValueHex())
+                        .put("label", element.getLabel())
+                        .put("code", element.getCode())
+                        .put("comment",element.getComment())
+                        .toJsonObject());
+            });
+            memoryJson.put("cells", cellArray);
+
+            JSONArray instructionArray = new JSONArray();
+
+            for (var instruction: instructions.values()) {
+                String label = instruction.getLabel();
+                String comment = instruction.getComment();
+                instructionArray.set(instructionArray.size(), new FluentJsonObject()
+                        .put("address", instruction.getParsingMetadata().address)
+                        .put("value",instruction.getRepr().getHexString())
+                        .put("label", label != null ? label : "")
+                        .put("code",instruction.getFullName())
+                        .put("comment", comment != null ? comment : "")
+                        .toJsonObject());
+            }
+
+            memoryJson.put("instructions", instructionArray);
+        } catch (Exception e) {
+            logger.warning("Error fetching memory: " + e.toString());
+        }
+        return memoryJson.toString();
     }
 
     private String getRegisters() {
diff --git a/src/main/java/org/edumips64/core/Memory.java b/src/main/java/org/edumips64/core/Memory.java
index 5d812d525..eaa43b1d2 100644
--- a/src/main/java/org/edumips64/core/Memory.java
+++ b/src/main/java/org/edumips64/core/Memory.java
@@ -62,6 +62,14 @@ public Memory() {
     logger.info("Memory built: " + this.hashCode());
   }
 
+  public SortedMap<Integer, MemoryElement> getCells() {
+    return cells;
+  }
+
+  public SortedMap<Integer, InstructionInterface> getInstructions() {
+    return instructions;
+  }
+
   /** Gets the number of instructions of the Symbol Table.
    *  @return an integer
    */
diff --git a/src/main/java/org/edumips64/core/MemoryElement.java b/src/main/java/org/edumips64/core/MemoryElement.java
index 152f02454..0471d07ec 100644
--- a/src/main/java/org/edumips64/core/MemoryElement.java
+++ b/src/main/java/org/edumips64/core/MemoryElement.java
@@ -108,6 +108,21 @@ public long getValue() {
     }
   }
 
+  public String getAddressHex() {
+      try {
+          return Converter.binToHex(Converter.positiveIntToBin(32, this.getAddress()));
+      } catch (IrregularStringOfBitsException e) {
+          throw new RuntimeException(e);
+      }
+  }
+  public String getValueHex() {
+    try {
+      return Converter.binToHex(Converter.positiveIntToBin(32, this.getValue()));
+    } catch (IrregularStringOfBitsException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   /** Returns a string represention of this MemoryElement, formatted with the address and
    * the value (in hexadecimal digits).
    * That is, if the address is 16 and the value stored within is 256 the string will be
@@ -130,6 +145,7 @@ public String toString() {
 
     return "ERRORE";
   }
+
 }
 
 
diff --git a/src/webapp/components/Memory.js b/src/webapp/components/Memory.js
index a55c64560..7527a8cdf 100644
--- a/src/webapp/components/Memory.js
+++ b/src/webapp/components/Memory.js
@@ -1,9 +1,71 @@
 import React from 'react';
 
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({hexString, value}) => {
+    return (
+        <Tooltip disableFocusListener title={value ?? ''}>
+            <Typography sx={{
+                fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+                padding: '0.1em 10px',
+                textAlign: 'right',
+            }}>
+                {hexString}
+            </Typography>
+        </Tooltip>
+    );
+};
+
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td>
+                <BinaryValue hexString={memoryelement.address_hex} value={memoryelement.address}/>
+            </td>
+            <td>
+                <BinaryValue hexString={memoryelement.value_hex} value={memoryelement.value}/>
+            </td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
 const Memory = (props) => {
-  return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
-  );
+    const memory = props.memory;
+    const {cells = []} = memory;
+    return (
+        <div>
+            {cells.length === 0 ? (
+                <Typography>No program loaded</Typography>
+            ) : (
+                <table id="memory">
+                    <thead>
+                    <tr>
+                        <th style={{textAlign: 'left'}}>Address</th>
+                        <th style={{textAlign: 'left'}}>Value</th>
+                        <th style={{textAlign: 'left'}}>Label</th>
+                        <th style={{textAlign: 'left'}}>Code</th>
+                        <th style={{textAlign: 'left'}}>Comment</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    {cells.map((memoryelement, i) => (
+                        <tr key={i}>
+                            <MemoryElement memoryelement={cells[i]} />
+                        </tr>
+                    ))}
+                    </tbody>
+                </table>
+            )}
+        </div>
+    );
 };
 
 export default Memory;
diff --git a/src/webapp/index.js b/src/webapp/index.js
index 21faa6768..feb1fc349 100644
--- a/src/webapp/index.js
+++ b/src/webapp/index.js
@@ -53,6 +53,7 @@ simulator.checkSyntax = (code) => {
 };
 simulator.parseResult = (result) => {
   result.registers = JSON.parse(result.registers);
+  result.memory = JSON.parse(result.memory);
   result.statistics = JSON.parse(result.statistics);
   return result;
 };


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR implements a JSON-based WebUI memory section by exporting memory data from Java and rendering it in a new table view within the web application.  
- Updated index.js to parse memory JSON data.  
- Refactored the Memory component to display cells and instructions in a table.  
- Added utility methods in MemoryElement.java, Memory.java, CPU.java, and updated ResultFactory.java to export memory data in JSON format.

### Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

<details>
<summary>Show a summary per file</summary>

| File                                        | Description                                                                              |
| ------------------------------------------- | ---------------------------------------------------------------------------------------- |
| src/webapp/index.js                         | Added JSON parsing for the memory attribute in the result object.                        |
| src/webapp/components/Memory.js             | Replaced a textarea with a table to render memory cells and instructions.                |
| src/main/java/org/edumips64/core/MemoryElement.java | Added helper methods to convert address/value to hexadecimal.                        |
| src/main/java/org/edumips64/core/Memory.java | Exposed getter methods for memory cells and instructions.                                |
| src/main/java/org/edumips64/core/CPU.java    | Added a getter for accessing the memory component.                                       |
| src/main/java/org/edumips64/client/ResultFactory.java | Updated memory export by constructing JSON arrays for cells and instructions.         |
</details>





state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T17:21:32Z
user: login: lupino3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-28T17:35:17Z
user: login: lupino3
body: The overall approach looks good, thanks! I have a few comments and I think we're done for a v1
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-28T17:37:42Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T18:28:00Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T18:45:04Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T18:59:27Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:20:32Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-30T15:50:00Z
user: login: lupino3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-30T16:21:48Z
user: login: lupino3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-30T16:22:45Z
user: login: lupino3
body: Overall it looks good, thanks! Please address the comment about accessing `memory` and we're good to go!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-30T16:25:01Z
user: login: lupino3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-30T16:29:43Z
user: login: davidepatti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-30T17:21:20Z

Review comments:
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
+                    <th style={{textAlign: 'left'}}>Value</th>
+                    <th style={{textAlign: 'left'}}>Label</th>
+                    <th style={{textAlign: 'left'}}>Code</th>
+                    <th style={{textAlign: 'left'}}>Comment</th>
+                </tr>
+                </thead>
+                <tbody>
+                {cells.map((memoryelement, i) => (
+                    <tr key={i}>
+                        <MemoryElement memoryelement={cells[i]}/>
+                    </tr>
+                ))}
+                {instructions.map((memoryelement, i) => (
path: src/webapp/components/Memory.js
user: login: lupino3
body: I think I would not display the code memory here, as we are already showing the code in the editor and I find it confusing that here we show both data and code memory.

How about we do not show instructions here, and instead (maybe in another PR) we figure out a way to show memory addresses in the editor itself? (maybe via custom line numbers?)
created_at: 2025-03-28T17:35:15Z
author_association: MEMBER
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
path: src/webapp/components/Memory.js
user: login: lupino3
body: Have you considered using `<BinaryValue>` for the address and the value? It will auto-convert hex to dec in the tooltip. It is currently buried inside `Registers.js`, so it needs to be extracted.
created_at: 2025-03-28T17:36:25Z
author_association: MEMBER
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
path: src/webapp/components/Memory.js
user: login: lupino3
body: Should we show something like "no program loaded" rather than these headers when the simulator is not running?
created_at: 2025-03-28T17:37:18Z
author_association: MEMBER
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
+                    <th style={{textAlign: 'left'}}>Value</th>
+                    <th style={{textAlign: 'left'}}>Label</th>
+                    <th style={{textAlign: 'left'}}>Code</th>
+                    <th style={{textAlign: 'left'}}>Comment</th>
+                </tr>
+                </thead>
+                <tbody>
+                {cells.map((memoryelement, i) => (
+                    <tr key={i}>
+                        <MemoryElement memoryelement={cells[i]}/>
+                    </tr>
+                ))}
+                {instructions.map((memoryelement, i) => (
path: src/webapp/components/Memory.js
user: login: davidepatti
body: Yes! It absolutely makes sense to me. That "show instruction memory" behaviour was a legacy from the swing UI, due to a missing editor. And having now an editor that shows pipeline stages on the code makes it useless waste of space. I'll remove it.
created_at: 2025-03-28T18:28:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
+                    <th style={{textAlign: 'left'}}>Value</th>
+                    <th style={{textAlign: 'left'}}>Label</th>
+                    <th style={{textAlign: 'left'}}>Code</th>
+                    <th style={{textAlign: 'left'}}>Comment</th>
+                </tr>
+                </thead>
+                <tbody>
+                {cells.map((memoryelement, i) => (
+                    <tr key={i}>
+                        <MemoryElement memoryelement={cells[i]}/>
+                    </tr>
+                ))}
+                {instructions.map((memoryelement, i) => (
path: src/webapp/components/Memory.js
user: login: davidepatti
body: Removed instructions in the last commit, fixing other reviews will come later. Also, I left unchanged all the java side stuff for instructions, e.g., in ResultsFactory, maybe it will useful for the future pull request on code editor memory address display? I can figure out at the moment, keeping a conservative approach.
created_at: 2025-03-28T18:45:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
path: src/webapp/components/Memory.js
user: login: davidepatti
body: Fixed
created_at: 2025-03-28T18:59:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
path: src/webapp/components/Memory.js
user: login: davidepatti
body: It would ok but (at least for me) it has an insane ratio of "improvement_you_get"/"things_to_deal_with".  I tried to look around, to import the status of the not loaded code from the event of clicking "Reset code" OR from just having some code open with the new "open code" button, but non having it loaded... I will be honest, I will not spend time on this at the moment :)
created_at: 2025-03-28T19:20:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
path: src/webapp/components/Memory.js
user: login: davidepatti
body: Ok, managed directly into the Memory rendering logic.
created_at: 2025-03-30T15:50:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,6 +102,43 @@ private Result AddCpuInfo(Result r) {
     }
 
     private String getMemory() {
+        var memory = new FluentJsonObject();
+        try {
+            var cells = cpu.getMemory().getCells();
path: src/main/java/org/edumips64/client/ResultFactory.java
user: login: lupino3
body: Now that I think about it, this object already has a reference to `memory`! You can use that one.

Could you also please remove `CPU.getMemory()`? I think it should never be needed.
created_at: 2025-03-30T16:21:48Z
author_association: MEMBER
diff_hunk: @@ -102,6 +102,43 @@ private Result AddCpuInfo(Result r) {
     }
 
     private String getMemory() {
+        var memory = new FluentJsonObject();
+        try {
+            var cells = cpu.getMemory().getCells();
path: src/main/java/org/edumips64/client/ResultFactory.java
user: login: lupino3
body: Note that you may not be seeing it because in line 105 you create another variable called `memory`, therefore hiding `this.memory`. You could call the JSON object `memoryJson` and you should be able to just access `this.memory` by calling it `memory`.
created_at: 2025-03-30T16:22:45Z
author_association: MEMBER
diff_hunk: @@ -1,9 +1,68 @@
 import React from 'react';
 
-const Memory = (props) => {
+import Typography from '@mui/material/Typography';
+import Tooltip from '@mui/material/Tooltip';
+
+
+// Component that shows a binary value.
+const BinaryValue = ({ hexString, value }) => {
   return (
-      <textarea readOnly value={props.memory} id="memory-view"/>
+      <Tooltip disableFocusListener title={value ?? ''}>
+        <Typography sx={{
+          fontFamily: "Menlo, Monaco, 'Courier New', monospace",
+          padding: '0.1em 10px',
+          textAlign: 'right',
+        }}>
+          {hexString}
+        </Typography>
+      </Tooltip>
   );
 };
 
+
+const MemoryElement = ({memoryelement}) => {
+    return (
+        <>
+            <td className="elementAddress">{memoryelement.address}</td>
+            <td className="elementValue">{memoryelement.value}</td>
+            <td className="elementLabel">{memoryelement.label}</td>
+            <td className="elementCode">{memoryelement.code}</td>
+            <td className="elementComment">{memoryelement.comment}</td>
+        </>
+    );
+};
+
+
+const Memory = (props) => {
+    const memory = props.memory;
+    const {cells = [], instructions = []} = memory;
+    return (
+        <div>
+            <table id="memory">
+                <thead>
+                <tr>
+                    <th style={{textAlign: 'left'}}>Address</th>
path: src/webapp/components/Memory.js
user: login: lupino3
body: Thank you! That's roughly what I had in mind, didn't mean to ask for very low ROI improvements :) 

But, in general, feel free to push back on review suggestions if you feel they're not quite appropriate!
created_at: 2025-03-30T16:29:43Z
author_association: MEMBER
diff_hunk: @@ -102,6 +102,43 @@ private Result AddCpuInfo(Result r) {
     }
 
     private String getMemory() {
+        var memory = new FluentJsonObject();
+        try {
+            var cells = cpu.getMemory().getCells();
path: src/main/java/org/edumips64/client/ResultFactory.java
user: login: davidepatti
body: Done
created_at: 2025-03-30T17:21:20Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-28T09:34:03Z
body: ## [Codecov](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) Report
Attention: Patch coverage is `0%` with `41 lines` in your changes missing coverage. Please review.
> Project coverage is 52.29%. Comparing base [(`01fb3ae`)](https://app.codecov.io/gh/EduMIPS64/edumips64/commit/01fb3ae3837a48a352df0dede07e0c280ff65763?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) to head [(`92327a4`)](https://app.codecov.io/gh/EduMIPS64/edumips64/commit/92327a4c868593806e6ae171276c1fb44f03833f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64).
> Report is 55 commits behind head on master.

| [Files with missing lines](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) | Patch % | Lines |
|---|---|---|
| [.../main/java/org/edumips64/client/ResultFactory.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fclient%2FResultFactory.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NsaWVudC9SZXN1bHRGYWN0b3J5LmphdmE=) | 0.00% | [33 Missing :warning: ](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) |
| [...rc/main/java/org/edumips64/core/MemoryElement.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fcore%2FMemoryElement.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NvcmUvTWVtb3J5RWxlbWVudC5qYXZh) | 0.00% | [6 Missing :warning: ](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) |
| [src/main/java/org/edumips64/core/Memory.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fcore%2FMemory.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NvcmUvTWVtb3J5LmphdmE=) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) |

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289/graphs/tree.svg?width=650&height=150&src=pr&token=Qsj3ChA5yC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64)](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64)

```diff
@@             Coverage Diff              @@
##             master    #1289      +/-   ##
============================================
- Coverage     52.49%   52.29%   -0.21%     
  Complexity     1468     1468              
============================================
  Files           252      252              
  Lines         10221    10262      +41     
  Branches       1102     1105       +3     
============================================
  Hits           5366     5366              
- Misses         4532     4573      +41     
  Partials        323      323              
```

| [Files with missing lines](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64) | Coverage Δ | |
|---|---|---|
| [src/main/java/org/edumips64/core/Memory.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fcore%2FMemory.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NvcmUvTWVtb3J5LmphdmE=) | `71.15% <0.00%> (-2.85%)` | :arrow_down: |
| [...rc/main/java/org/edumips64/core/MemoryElement.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fcore%2FMemoryElement.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NvcmUvTWVtb3J5RWxlbWVudC5qYXZh) | `63.88% <0.00%> (-12.78%)` | :arrow_down: |
| [.../main/java/org/edumips64/client/ResultFactory.java](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fedumips64%2Fclient%2FResultFactory.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64#diff-c3JjL21haW4vamF2YS9vcmcvZWR1bWlwczY0L2NsaWVudC9SZXN1bHRGYWN0b3J5LmphdmE=) | `0.00% <0.00%> (ø)` | |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64)

------

[Continue to review full report in Codecov by Sentry](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64). Last update [01fb3ae...92327a4](https://app.codecov.io/gh/EduMIPS64/edumips64/pull/1289?dropdown=coverage&src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=EduMIPS64).

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: lupino3
created_at: 2025-03-28T17:22:09Z
body: Will fix #1225 
author_association: MEMBER
user: login: lupino3
created_at: 2025-03-30T16:18:52Z
body: @davidepatti the auto-preview now works! After I approve the deployment, you can now see your version of the Web UI when you click on "View Deployment"

<img width="776" alt="image" src="https://github.com/user-attachments/assets/940a3f30-cfe2-472b-993f-a1ed40aabe00" />



author_association: MEMBER
user: login: lupino3
created_at: 2025-03-30T17:42:51Z
body: Fixes #1225 
author_association: MEMBER