diff --git a/index.html b/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..52a386532143f2359126f49b1ed09b805791e65d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,427 @@
+<!DOCTYPE html>
+<html lang="es">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Proyecto Visualización</title>
+    <script src="https://d3js.org/d3.v7.min.js"></script>
+    <style>
+        body {
+            font-family: Arial, sans-serif;
+            justify-content: center;
+            align-items: center;
+            height: 100%;
+            margin: 0;
+            background-color: #fff;
+        }
+
+        .div-histograma {
+            border: 0em solid #222222;
+            width: 40em;
+            height: 20em;
+            text-align: center;
+            margin: 1em;
+            padding: 2em;
+            color: #f9f9f9;
+            font-weight: bold;
+            border-radius: 0em;
+            box-shadow: 0 1em 3em rgba(22, 22, 22, 0.6);
+            transition: transform 0.3s;
+        }
+
+        .div-histograma:hover {
+            transform: scale(1.05);
+        }
+
+        #div1 {
+            background-color: #fff;
+        }
+
+        #div2 {
+            background-color: #fff;
+        }
+
+        #dropdownDiv {
+            display: flex;
+            flex-direction: column;
+            align-items: flex-start;
+            margin: 1em;
+            padding: 1em;
+            border: 0em solid #222222;
+            border-radius: 0em;
+            box-shadow: 0 1em 3em rgba(22, 22, 22, 0.6);
+            background-color: #f9f9f9;
+            transition: transform 0.3s;
+        }
+
+        #keyDropdown {
+            margin-top: 0.5em;
+            padding: 0.5em;
+            border-radius: 0em;
+            border: 0em solid #ccc;
+            font-size: 1em;
+            transition: transform 0.3s;
+        }
+
+        #opcinesDiv1 {
+            display: flex;
+            flex-direction: row;
+            justify-content: center;
+            align-items: center;
+            margin: 1em;
+            padding: 0em;
+        }
+
+        #sliderAnimationContainer,
+        #sliderBarrasContainer,
+        #checkboxContainer,
+        #distributionCheckboxContainer {
+            width: max-content;
+            height: fit-content;
+            display: block;
+            margin: 1em 1em 1em 1em;
+            padding: 1em;
+            border: 0em solid #222222;
+            border-radius: 0em;
+            box-shadow: 0 1em 3em rgba(22, 22, 22, 0.6);
+            background-color: #f9f9f9;
+            transition: transform 0.3s;
+        }
+
+        #dropdownDiv:hover,
+        #keyDropdown:hover,
+        #checkboxContainer:hover,
+        #sliderAnimationContainer:hover,
+        #sliderBarrasContainer:hover,
+        #distributionCheckboxContainer:hover {
+            transform: scale(1.05);
+        }
+
+        label {
+            font-weight: bold;
+            margin-bottom: 0.5em;
+        }
+    </style>
+</head>
+
+<body>
+    <div style="text-align: center">
+        <h1 style="color: #222222; font-size: 2em; font-weight: bold;">Resultados de simulaciones de un proceso
+            estocástico</h1>
+        <p style="color: #555555; font-size: 1em;">Visualización de las distribuciones que determinan la duración y
+            estado del sistema al finalizar el proceso</p>
+    </div>
+    <div style="display:flex; justify-content: center; align-items: center;margin:5em;">
+        <div id="histogramas" style="display:flex">
+            <div id="div1" class="div-histograma"></div>
+            <div id="div2" class="div-histograma"></div>
+        </div>
+        <div id="dropdownDiv">
+            <label for="keyDropdown">Tamaño<br>sistema:</label>
+            <select id="keyDropdown" onchange="onDropdownChange(this)"></select>
+        </div>
+    </div>
+    <div id="opcinesDiv1">
+        <div id="checkboxContainer">
+            <label for="mediaCheckbox">Mostrar media:</label>
+            <input type="checkbox" id="mediaCheckbox" onchange="onCheckboxMediaChange()">
+        </div>
+        <div id="distributionCheckboxContainer">
+            <label for="distributionCheckbox">Mostrar distribución:</label>
+            <input type="checkbox" id="distributionCheckbox" onchange="onCheckboxDistributionChange()">
+        </div>
+        <div id="sliderAnimationContainer">
+            <label for="animationSlider">Tiempo animación:</label>
+            <input type="range" id="animationSlider" min="0" max="2000" step="100" value="600"
+                oninput="onSliderChange()" onchange="onSliderChange()">
+            <span id="animationTimeValue">1000 ms</span>
+        </div>
+
+        <div id="sliderBarrasContainer">
+            <label for="barsSlider">Barras:</label>
+            <input type="range" id="barsSlider" min="5" max="100" step="1" value="20" oninput="onBarsSliderChange()"
+                onchange="onBarsSliderChange()">
+            <span id="barsCountValue">10</span>
+        </div>
+    </div>
+
+    <script type="text/javascript">
+        const datasetFolder = "./dataset/"
+        const fileNamesList = ['10 1', '10 10', '10 11', '10 12', '10 13', '10 14', '10 15', '10 2', '10 3', '10 4', '10 5', '10 6', '10 7', '10 8', '10 9', '11 1', '11 10', '11 11', '11 12', '11 13', '11 14', '11 15', '11 2', '11 3', '11 4', '11 5', '11 6', '11 7', '11 8', '11 9', '12 1', '12 12', '12 2', '12 3', '12 4', '12 5', '12 6', '13 1', '13 10', '13 11', '13 12', '13 13', '13 14', '13 15', '13 2', '13 3', '13 4', '13 5', '13 6', '13 7', '13 8', '13 9', '14 1', '14 10', '14 11', '14 12', '14 13', '14 14', '14 15', '14 2', '14 3', '14 4', '14 5', '14 6', '14 7', '14 8', '14 9', '15 1', '15 10', '15 11', '15 12', '15 13', '15 14', '15 15', '15 2', '15 3', '15 4', '15 5', '15 6', '15 7', '15 8', '15 9', '16 1', '16 10', '16 11', '16 12', '16 13', '16 14', '16 15', '16 16', '16 2', '16 3', '16 4', '16 5', '16 6', '16 7', '16 8', '16 9', '17 1', '17 10', '17 11', '17 12', '17 13', '17 14', '17 15', '17 16', '17 17', '17 2', '17 3', '17 4', '17 5', '17 6', '17 7', '17 8', '17 9', '18 1', '18 18', '18 2', '18 3', '18 4', '18 5', '18 6', '18 7', '19 1', '19 19', '20 1', '20 20', '21 1', '21 21', '22 1', '22 22', '23 1', '23 23', '24 1', '24 24', '25 1', '25 25', '26 1', '26 26', '27 1', '27 27', '28 1', '28 28', '29 1', '29 29', '3 1', '3 3', '30 1', '30 30', '31 1', '31 31', '32 1', '32 32', '33 1', '33 33', '34 1', '34 34', '35 1', '35 35', '36 1', '36 36', '37 1', '37 37', '38 1', '38 38', '39 1', '39 39', '4 1', '4 4', '40 1', '40 40', '41 1', '41 41', '42 1', '42 42', '43 1', '43 43', '44 1', '44 44', '45 1', '45 45', '46 1', '46 46', '47 1', '47 47', '48 1', '48 48', '49 1', '5 1', '5 10', '5 11', '5 12', '5 13', '5 14', '5 15', '5 2', '5 3', '5 4', '5 5', '5 6', '5 7', '5 8', '5 9', '6 1', '6 10', '6 11', '6 12', '6 13', '6 14', '6 15', '6 2', '6 3', '6 4', '6 5', '6 6', '6 7', '6 8', '6 9', '7 1', '7 10', '7 11', '7 12', '7 13', '7 14', '7 15', '7 2', '7 3', '7 4', '7 5', '7 6', '7 7', '7 8', '7 9', '8 1', '8 10', '8 11', '8 12', '8 13', '8 14', '8 15', '8 2', '8 3', '8 4', '8 5', '8 6', '8 7', '8 8', '8 9', '9 1', '9 10', '9 11', '9 12', '9 13', '9 14', '9 15', '9 2', '9 3', '9 4', '9 5', '9 6', '9 7', '9 8', '9 9'];
+        fileNamesList.sort((a, b) => a.split(" ")[0] - b.split(" ")[0] || a.split(" ")[1] - b.split(" ")[1]);
+        const dropdown = document.getElementById("keyDropdown");
+        const mediaCheckbox = document.getElementById("mediaCheckbox");
+        const distributionCheckbox = document.getElementById("distributionCheckbox");
+        const animationSlider = document.getElementById("animationSlider");
+        const animationTimeValue = document.getElementById("animationTimeValue");
+        const barsSlider = document.getElementById("barsSlider");
+        const barsCountValue = document.getElementById("barsCountValue");
+
+        var key = fileNamesList[107];
+        var animationTime = 600;
+        var bins = 10;
+        var currentData = null;
+        var currentKey = null;
+
+        async function getData(key) {
+            try {
+                const response = await fetch(datasetFolder + key + ".json");
+                if (!response.ok) {
+                    throw new Error("Error: " + response.status);
+                }
+                const data = await response.json();
+                return data[key];
+            } catch (error) {
+                console.error('Error:', error);
+                alert(error);
+            }
+        }
+
+        async function start() {
+            if (currentKey !== key) {
+                currentData = await getData(key);
+                currentKey = key;
+            }
+            histograma(currentData[0], "div1", bins, "Iteraciones");
+            histograma(currentData[1], "div2", bins, "Cantidad elementos");
+        }
+
+        function histograma(data, div, binNumber, label) {
+            const container = document.getElementById(div);
+            const width = container.clientWidth;
+            const height = container.clientHeight;
+            const heightFactor = 1.1;
+            const axisXOffset = 100;
+            const axisYOffset = 40;
+
+            const bins = d3.bin()
+                .thresholds(binNumber)
+                .value((d) => d)(data);
+
+            const x = d3.scaleLinear()
+                .domain([bins[0].x0, bins[bins.length - 1].x1])
+                .range([axisXOffset, width - axisXOffset]);
+
+            const yMax = d3.max(bins, d => d.length) * heightFactor;
+
+            const y = d3.scaleLinear()
+                .domain([0, yMax])
+                .range([height - axisYOffset, 0]);
+
+            let svg = d3.select("#" + div).select("svg");
+            if (svg.empty()) {
+                svg = d3.select("#" + div)
+                    .append("svg")
+                    .attr("width", width)
+                    .attr("height", height)
+                    .attr("viewBox", [0, 0, width, height])
+                    .attr("style", "max-width: 100%; height: auto;");
+            }
+
+            //Construir las barras
+            const bars = svg.selectAll("rect")
+                .data(bins, d => d.x0);
+
+            bars.exit()
+                .transition()
+                .duration(0)
+                .ease(d3.easeCubicInOut)
+                .attr("y", height - axisYOffset)
+                .attr("height", 0)
+                .remove();
+
+            bars.transition()
+                .duration(animationTime)
+                .ease(d3.easeElasticOut.amplitude(2).period(1.5))
+                .attr("x", (d) => x(d.x0) + 1)
+                .attr("width", (d) => Math.max(0, x(d.x1) - x(d.x0) - 3))
+                .attr("y", (d) => y(d.length))
+                .attr("height", (d) => y(0) - y(d.length))
+                .attr("fill", "#055902");
+
+            bars.enter()
+                .append("rect")
+                .attr("x", (d) => x(d.x0) + 1)
+                .attr("width", (d) => Math.max(0, x(d.x1) - x(d.x0) - 3))
+                .attr("y", height - axisYOffset)
+                .attr("height", 0)
+                .attr("fill", "#ff7f0e")
+                .transition()
+                .delay((d, i) => i * (animationTime / 10))
+                .duration(animationTime)
+                .ease(d3.easeCubicInOut)
+                .attr("y", (d) => y(d.length))
+                .attr("height", (d) => y(0) - y(d.length))
+                .attr("fill", "#055902");
+
+            //Ejes x e y
+            svg.selectAll(".x-axis").remove();
+            svg.append("g")
+                .attr("class", "x-axis")
+                .attr("transform", "translate(0," + (height - axisYOffset) + ")")
+                .call(d3.axisBottom(x).ticks(width / 80).tickSizeOuter(0))
+                .call((g) => g.selectAll("path, line").style("stroke", "#222222"))
+                .call((g) => g.selectAll("text").style("fill", "#222222")).style("font-size", "0.8em")
+                .call((g) => g.append("text")
+                    .attr("x", width / 2)
+                    .attr("y", 35)
+                    .attr("fill", "#222222")
+                    .attr("text-anchor", "middle")
+                    .text(label));
+
+            svg.selectAll(".y-axis").remove();
+            svg.append("g")
+                .attr("class", "y-axis")
+                .attr("transform", "translate(" + axisXOffset + ",0)")
+                .call(d3.axisLeft(y).ticks(height / 70))
+                .call((g) => g.select(".domain").remove())
+                .call((g) => g.selectAll("path, line").style("stroke", "#222222"))
+                .call((g) => g.selectAll("text").style("fill", "#222222")).style("font-size", "0.8em")
+                .call((g) => g.append("text")
+                    .attr("x", -height / 2)
+                    .attr("y", -70)
+                    .attr("fill", "#222222")
+                    .attr("text-anchor", "middle")
+                    .attr("transform", "rotate(-90)")
+                    .text("Simulaciones"));
+
+            // Mostrar línea de la media
+            svg.selectAll(".media")
+                .attr("y1", 0)
+                .transition()
+                .duration(animationTime)
+                .ease(d3.easeCubicInOut)
+                .style("opacity", 0)
+                .attr("y1", height - axisYOffset)
+                .remove();
+            if (mediaCheckbox.checked) {
+                const average = d3.mean(data);
+
+                svg.append("line")
+                    .attr("class", "media")
+                    .attr("x1", x(average))
+                    .attr("x2", x(average))
+                    .attr("y1", height - axisYOffset)
+                    .attr("y2", height - axisYOffset)
+                    .attr("stroke", "#1e90ff")
+                    .attr("stroke-width", 4)
+                    .transition()
+                    .duration(animationTime)
+                    .ease(d3.easeCubicInOut)
+                    .attr("y1", 0);
+
+                svg.append("text")
+                    .attr("class", "media")
+                    .attr("x", x(average) + 5)
+                    .attr("y", 15)
+                    .attr("fill", "#333333")
+                    .style("font-size", "1em")
+                    .style("font-weight", "bold")
+                    .text("Media: " + average.toFixed(2))
+                    .style("opacity", 0)
+                    .transition()
+                    .duration(animationTime)
+                    .ease(d3.easeCubicInOut)
+                    .style("opacity", 1);
+            }
+
+            // Mostrar curva de distribución
+            svg.selectAll(".distribution")
+                .transition()
+                .duration(animationTime)
+                .ease(d3.easeCubicInOut)
+                .attr("stroke-dashoffset", function () { return this.getTotalLength(); })
+                .remove();
+            if (distributionCheckbox.checked) {
+                const density = kde(epanechnikov(10), x.ticks(40), data.filter((_, index) => index % 30 === 0));
+
+                const yDist = d3.scaleLinear()
+                    .domain([0, d3.max(density, d => d[1]) * heightFactor])
+                    .range([height - axisYOffset, 0]);
+
+                const line = d3.line()
+                    .curve(d3.curveBasis)
+                    .x(d => x(d[0]))
+                    .y(d => yDist(d[1]));
+
+                svg.append("path")
+                    .datum(density)
+                    .attr("class", "distribution")
+                    .attr("fill", "none")
+                    .attr("stroke", "#222222")
+                    .attr("stroke-width", 2)
+                    .attr("stroke-linejoin", "round")
+                    .attr("stroke-linecap", "round")
+                    .attr("d", line)
+                    .attr("stroke-dasharray", function () { return this.getTotalLength(); })
+                    .attr("stroke-dashoffset", function () { return this.getTotalLength(); })
+                    .transition()
+                    .duration(animationTime)
+                    .ease(d3.easeCubicInOut)
+                    .attr("stroke-dashoffset", 0);
+            }
+        }
+
+        //Funciones que se ejecutan al ocurrir eventos
+        function onDropdownChange() {
+            key = dropdown.value;
+            start();
+        }
+
+        function onCheckboxMediaChange() {
+            start();
+        }
+
+        function onCheckboxDistributionChange() {
+            start();
+        }
+
+        function onSliderChange() {
+            updateAnimationTime(parseInt(animationSlider.value));
+        }
+
+        function onBarsSliderChange() {
+            updateBarsCount(parseInt(barsSlider.value));
+            start();
+        }
+
+        function updateAnimationTime(newAnimationTime) {
+            animationTime = newAnimationTime;
+            animationTimeValue.textContent = animationTime + " ms";
+        }
+
+        function updateBarsCount(newBins) {
+            bins = newBins;
+            barsCountValue.textContent = bins;
+        }
+
+        //Funciones para calcular la distribución de probabilidad
+        function kde(kernel, thresholds, data) {
+            return thresholds.map(t => [t, d3.mean(data, d => kernel(t - d))]);
+        }
+
+        function epanechnikov(bandwidth) {
+            return x => Math.abs(x /= bandwidth) <= 1 ? 0.75 * (1 - x * x) / bandwidth : 0;
+        }
+
+        //Inicializar documento
+        fileNamesList.forEach((fileName) => {
+            const option = document.createElement("option");
+            option.value = fileName;
+            option.textContent = fileName;
+            dropdown.appendChild(option);
+        });
+
+        dropdown.value = key;
+        mediaCheckbox.checked = true;
+        distributionCheckbox.checked = false;
+        animationSlider.value = 600;
+        updateAnimationTime(600);
+        updateBarsCount(20);
+        barsSlider.value = 10;
+        start();        
+    </script>
+</body>
+
+</html>
\ No newline at end of file