From e2cf60a748d1b2a409da7adeaaa840a5c49525ae Mon Sep 17 00:00:00 2001
From: = <=>
Date: Mon, 9 Dec 2024 20:46:10 +0100
Subject: [PATCH] =?UTF-8?q?Implementadas=20funcionalidades=20b=C3=A1sicas?=
 =?UTF-8?q?=20en=20D3=20Todavia=20falta=20por=20funcionar=20el=20label=20d?=
 =?UTF-8?q?el=20eje=20Y?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/style.css          |   9 ++
 src/visualizacion.html |  15 ++-
 src/visualizacion.js   | 255 +++++++++++++++++++++++++++--------------
 3 files changed, 187 insertions(+), 92 deletions(-)
 create mode 100644 src/style.css

diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..c95cb21
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,9 @@
+.videogame_rect {
+    opacity: 0.95;
+}
+
+.videogame_title {
+    font-family: Georgia, serif;
+    font-weight: bolder;
+    font-size: 17px;
+}
\ No newline at end of file
diff --git a/src/visualizacion.html b/src/visualizacion.html
index ca75922..40a3b5c 100644
--- a/src/visualizacion.html
+++ b/src/visualizacion.html
@@ -2,15 +2,24 @@
 <html lang="es">
     <head>
         <title>Visualización DESI</title>
-    </head>
         <meta charset="utf-8">
         <script src="https://d3js.org/d3.v7.min.js"></script>
-
+        <link href="style.css" rel="stylesheet">
+    </head>
     <body>
-        <script src="visualizacion.js"></script>
+        <div>
+            <label for="color_scheme">
+                Filtrado por:
+            </label>
+            <select id="color_scheme" oninput="">
+                <option value="platform">Plataforma</option>
+                <option value="developer">Desarrollador</option>
+            </select>
+        </div>
         <div class="container" id="div-leyenda">
             <!-- En esta seccion la leyenda -->
             <!-- Interaccion con D3 para modificar HTML aqui -->
         </div>
+        <script src="visualizacion.js"></script>
     </body>
 </html>
\ No newline at end of file
diff --git a/src/visualizacion.js b/src/visualizacion.js
index 1984bc8..30e8513 100644
--- a/src/visualizacion.js
+++ b/src/visualizacion.js
@@ -1,97 +1,178 @@
 /**
- * Diccionario de correspondencia de una consola / plataforma con su color representativo
+ * Diccionario de correspondencia de colores
  */
-const consolaColores = {
-    Nintendo64:         "#E1A84E",
-    PlayStation:        "#4A7DCE",
-    PlayStation3:       "#666666",
-    Dreamcast:          "#D47A45",
-    Xbox360:            "#8BBF61",
-    Wii:                "#5EB8EC",
-    XboxOne:            "#629A62",
-    Switch:             "#C84D4D",
-    PlayStation2:       "#3A66A1",
-    PlayStation4:       "#3D76C9",
-    GameCube:           "#8B5DB7",
-    Xbox:               "#619A61",
-    PC:                 "#9A9A9A",
-    WiiU:               "#63B6D5",
-    GameBoyAdvance:     "#8574B5",
-    "3DS":              "#C1536E",
-    DS:                 "#BBBBBB",
-    PlayStationVita:    "#5A7EB0",
-    PSP:                "#545454",
-    XboxSeriesX:        "#4F5B4A",
-    PlayStation5:       "#C5D1E3",
-    Stadia:             "#D45A3B"
-};
+const colores = {
+    "platform" : {
+        Nintendo64:         "#E1A84E",
+        PlayStation:        "#4A7DCE",
+        PlayStation3:       "#6666e0",
+        Dreamcast:          "#D47A45",
+        Xbox360:            "#8BBF61",
+        Wii:                "#5EB8EC",
+        XboxOne:            "#629A62",
+        Switch:             "#C84D4D",
+        PlayStation2:       "#3A66A1",
+        PlayStation4:       "#3D76C9",
+        GameCube:           "#8B5DB7",
+        Xbox:               "#619A61",
+        PC:                 "#9A9A9A",
+        WiiU:               "#63B6D5",
+        GameBoyAdvance:     "#8574B5",
+        "3DS":              "#C1536E",
+        DS:                 "#BBBBBB",
+        PlayStationVita:    "#5A7EB0",
+        PSP:                "#5454f0",
+        XboxSeriesX:        "#4F5B4A",
+        PlayStation5:       "#C5D1E3",
+        Stadia:             "#D45A3B"
+    },
+    "developer" : {
+        Capcom:             "#C75450",
+        TelltaleGames:      "#6A9CCB",
+        EASports:           "#65A879",
+        Nintendo:           "#D84840",
+        Konami:             "#C25C74",
+        EACanada:           "#518E85",
+        UbisoftMontreal:    "#5A78B8",
+        Ubisoft:            "#4C96C9",
+        SquareEnix:         "#D48E47",
+        OmegaForce:         "#A17367",
+        ElectronicArts:     "#7A9098",
+        EATiburon:          "#68A8B9",
+        Codemasters:        "#84A85B",
+        Sega:               "#5272A5",
+        BandaiNamcoGames:   "#D69444",
+        VisualConcepts:     "#6488C0",
+        "Traveller'sTales": "#9569A1",
+        VicariousVisions:   "#A3A658",
+        Namco:              "#C87478"
+    }
+}
 
-/**
- * Diccionario de correspondencia de una desarrolladora con su color correspondiente.
- * Si una desarrolladora no está dentro del diccionario tomará un color gris claro #BBBBBB
- * En este diccionario solo aparecen los 20 desarrolladores que más aparecen
- */
-const developerColores = {
-    Capcom:             "#C75450",
-    TelltaleGames:      "#6A9CCB",
-    EASports:           "#65A879",
-    Nintendo:           "#D84840",
-    Konami:             "#C25C74",
-    EACanada:           "#518E85",
-    UbisoftMontreal:    "#5A78B8",
-    Ubisoft:            "#4C96C9",
-    SquareEnix:         "#D48E47",
-    OmegaForce:         "#A17367",
-    ElectronicArts:     "#7A9098",
-    EATiburon:          "#68A8B9",
-    Codemasters:        "#84A85B",
-    Sega:               "#5272A5",
-    BandaiNamcoGames:   "#D69444",
-    VisualConcepts:     "#6488C0",
-    "Traveller'sTales": "#9569A1",
-    VicariousVisions:   "#A3A658",
-    Namco:              "#C87478"
-};
+const width = 1000;
+const height = 500;
+const margin_x = 62;
+const margin_y = 60;
+const right_margin = 300;
 
 
-const width = 1000;
-const height = 600;
-const margin_x = 32;
-const margin_y = 20;
+let selection = "platform"
+
 const svg = d3.select('body').append('svg')
     .attr("width", width + 2 * margin_x).attr("height", height + 2 * margin_y)
     .append('g').attr("transform", `translate(${margin_x},${margin_y})`);
 
-/**
- * data {@type List} 
- */
+
+let xScale;
+let yScale;
+let radiusScale;
+
+
+function createAxis() {
+    const xAxis = d3.axisBottom(xScale).ticks(10);
+    const yAxis = d3.axisLeft(yScale).ticks(10);
+
+    svg.append("g")
+        .attr("class", "xAxis")
+        .attr("transform", `translate(0,${height})`)
+        .call(xAxis);
+    svg.append('text')
+        .attr('class', 'xAxisLabel')
+        .attr('x', width / 5)
+        .attr('y', height + 40)
+        .style('font-weight', 'bold')
+        .style('font-size', '20px')
+        .style('font-family', 'Georgia, serif')
+        .text("Calificacion dada por usuarios")
+    svg.append("g")
+        .attr("class", "yAxis")
+        .call(yAxis);
+    svg.append('text')
+        .attr('class', 'yAxisLabel')
+        .attr('x', -10)
+        .attr('y', height/2 + margin_y)
+        .attr('transform', 'rotate(-90)')
+        .text("Calificacion dada por expertos")
+}
+
 d3.csv('files/games-data.csv').then((data) => {
-    
-    data.forEach(d => {
-        d["user score"] = +d["user score"];
-        if(!d["user score"]) d["critics"] = -14;
-        d["score"] = +d["score"] / 10; 
+
+    data.forEach(elem => {
+        elem["user score"] = +elem["user score"];
+        if(!elem["user score"]) elem["critics"] = -14;
+        elem["score"] = +elem["score"] / 10;
         // Los datos estan entre 0 y 100, asi que normalizo a entre 0 y 10
-        d["critics"] = +d["critics"];
-        d["users"] = +d["users"];
+        elem["critics"] = +elem["critics"];
+        elem["users"] = +elem["users"];
+        elem.id = elem.name.replaceAll(/[ :'"()\[\]]*/g, '');
     });
 
-    const xScale = d3.scaleLinear().domain(
-        [0, d3.max(data, d => d["user-score"]) || 10]
-    ).range([0, width]);
-    const yScale = d3.scaleLinear().domain([0, 10]).range([height, 0]);
-    const xAxis = d3.axisBottom(xScale).ticks(10);
-    const yAxis = d3.axisLeft(yScale).ticks(10);
+    xScale = d3.scaleLinear().domain([0, 10]).range([0, width-right_margin]);
+    yScale = d3.scaleLinear().domain([0, 10]).range([height, 0]);
+
+
+    radiusScale = d3.scaleSqrt().domain([0, d3.max(data, elem => elem["critics"]) || 1]).range([5, 20]);
+
 
-    const radiusScale = d3.scaleSqrt().range([5, 20])
-        .domain([0, d3.max(data, d => d["critics"]) || 1]);
 
-    svg.append("g").attr("class", "xAxis").attr("transform", `translate(0,${height})`).call(xAxis);
-    svg.append("g").attr("class", "yAxis").call(yAxis);
     let elegibleData = data.sort((a, b) => {
         return (b["critics"] + b["users"]) - (a["critics"] + a["users"])
     }).slice(0, 50);
-    
+
+    createAxis();
+    appendBubbles(elegibleData);
+
+});
+
+function handleMouseOver(event, elem) {
+
+    const rectAparitionTime = 300;
+
+    d3.select(this)
+        .transition()
+        .duration(300)
+        .ease(d3.easeQuadInOut)
+        .attr("r", radiusScale(elem.critics) * 1.4)
+
+    svg.append('rect')
+        .attr('id', `rect${elem.id}-${elem.platform}`)
+        .attr('class', 'videogame_rect')
+        .attr('rx', 4)
+        .attr('ry', 4)
+        .attr('x', () => xScale(elem["user score"]) + 30)
+        .attr('y', () => yScale(elem.score) - 20)
+        .attr('width', elem.name.length*11)
+        .attr('height', 100)
+        .attr('fill', () => colores[selection][elem[selection]])
+        .attr('stroke', 'black')
+        .attr('stroke-width', 2)
+        .style('opacity', 0)
+        .transition()
+        .duration(rectAparitionTime)
+        .ease(d3.easeQuadInOut)
+        .style('opacity', 1)
+
+    svg.append('text')
+        .attr('id', `text${elem.id}-${elem.platform}`)
+        .attr('class', 'videogame_title')
+        .attr('x', () => xScale(elem["user score"]) + 35)
+        .attr('y', () => yScale(elem["score"]) - 5)
+        .text(elem.name)
+        .style('opacity', 0)
+        .transition()
+        .duration(rectAparitionTime)
+        .ease(d3.easeQuadInOut)
+        .style('opacity', 1)
+}
+
+function handleMouseOut(event, elem) {
+    d3.select(this)
+        .attr('r', d => radiusScale(d.critics));
+    d3.selectAll('.videogame_title').remove();
+    d3.select(`#rect${elem.id}-${elem.platform}`).remove();
+}
+
+function appendBubbles(elegibleData) {
     svg.selectAll("circle")
         .data(elegibleData)
         .enter()
@@ -99,22 +180,18 @@ d3.csv('files/games-data.csv').then((data) => {
         .attr("cx", d => xScale(d["user score"]))
         .attr("cy", d => yScale(d["score"]))
         .attr("r",  d => radiusScale(d["critics"]))
-        .attr("fill", d => consolaColores[d["platform"]])
+        .attr("fill", d => colores["platform"][d["platform"]])
         .attr("stroke", "#000000")
         .attr("stroke-width", 1)
-        .append("title")
-        .text(d => `${d.name}\nPlataforma: ${d.platform}\n` + 
-            `Desarrollador: ${d.developer}\nJugadores: ${d.players}`)
-
-    
-
-
-    
-});
-
-
-
+        .on("mouseover", handleMouseOver)
+        .on("mouseout", handleMouseOut)
+}
 
+function removeBubbles() {
+    svg.selectAll('circle').remove()
+}
 
+function changeSelection (event) {
 
+}
 
-- 
GitLab