Documentación · Especificación
Un objeto JSON se convierte en un gráfico en vivo
Una especificación describe todo lo que dibuja el motor. Esta página es la referencia completa. El mismo contrato se aplica a las especificaciones de los creadores, las inserciones, las llamadas MCP y la API de renderizado.
{
"type": "column",
"theme": "editorial",
"title": "Weekly signups",
"source": "Product analytics",
"data": {
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"series": [
{
"name": "Signups",
"values": [
12,
19,
14,
27,
22
]
}
]
}
} Este gráfico representa exactamente esta especificación, en vivo.
La estructura
Dos campos obligatorios, type y data, y valores predeterminados para los demás. La mayoría de los tipos usa etiquetas y series. La matriz de estado necesita data.columns y data.cells; la tabla en vivo, data.columns y data.rows. Los tipos de jerarquía, clasificación, flujo, distribución y X-Y usan los formatos descritos a continuación. Los tipos desconocidos, datos obligatorios ausentes y valores no numéricos producen errores estructurados. Nada falla en silencio. Cada serie tiene exactamente un valor por etiqueta: una longitud incorrecta se rechaza, nunca se rellena con 0 ni se recorta. null indica un dato ausente: interrumpe la línea, omite la barra o el punto y muestra No data en la descripción emergente y la tabla oculta. No se permite en number ni dotplot.
| Campo | Obligatorio | Qué representa |
|---|---|---|
type | sí | Uno de los 27 tipos indicados a continuación |
theme | no; predeterminado: editorial | editorial · glass · ink · mint · neon. Los nombres desconocidos usan editorial. |
data.labels | no; predeterminado: 1, 2, 3… | Nombres de categorías, uno por posición |
data.series | sí | Al menos una serie { "name"?, "values": (number | null)[] } con un valor por etiqueta. null es un dato ausente. |
title, source | no | Título sobre el gráfico y fuente debajo |
options.variant | no | light · dark · auto. auto sigue primero el modo oscuro de la página mediante data-theme, una clase dark en html/body o color-scheme; después sigue el sistema operativo y cambia en vivo. Consulta Temas y variantes. |
options.target | no | Línea de referencia discontinua en los tipos cartesianos |
options.precision | no | Decimales (0–4) en etiquetas de valores, descripciones emergentes e indicador. Sin esta opción, conserva los decimales de los datos. |
options.format | no | Formato del valor: percent, currency:XXX o affix:["before","after"] |
options.notes | no | Anotaciones { "label", "text", "kind"? } por etiqueta afectada. Aparece un círculo (ⓘ; ! con warn) en barras, columnas, piruletas, líneas, áreas, dispersión, leyenda del gráfico de anillo e indicador. Pasa el cursor o toca para leer el texto; haz clic para fijarlo y pulsa Escape para soltarlo. El texto también aparece en la tabla accesible. |
options.legend | no | Solo matriz: etiquetas legibles para los estados |
data.columns, data.cells | solo matrix | Columnas de características y una fila de estados por etiqueta |
data.columns, data.rows | solo table | Columnas tipadas (text · number · status · note) y un array de celdas por fila |
options.sort, options.sticky | no; solo table | Orden inicial { column, dir }; cabecera y primera columna fijas |
options.mobile | no; solo table | Con menos de 480 px de ancho del contenedor: scroll (predeterminado, tabla compacta con desplazamiento horizontal y primera columna fija) o cards (una tarjeta por fila) |
options.font | no; solo table | inherit usa la fuente de la página en lugar de la del tema, por ejemplo en un artículo. La tabla determina su altura si la página no la establece. |
options.height, options.search | no; solo table | height (px, 120–4000) limita las tablas largas; las filas se desplazan bajo la cabecera fija. search: true añade un buscador para todos los textos visibles, etiquetas, celdas, estados y anotaciones, junto con los filtros de estado. Reset restablece ambos. |
options.pageSize | no; solo table | Filas por página, de 5 a 1000. La tabla muestra esa cantidad y debajo Previous/Next, un recuento exacto como Rows 11–20 of 63 y Show all. Primero aplica filtros, búsqueda y orden, y después pagina. Chart this column representa la selección visible de todas las páginas. Si todo cabe en una página, no muestra navegación. |
options.table.change | no; solo table | Muestra columnas numéricas como cambios: [{ "column": 2, "better": "up" }]. La flecha y el la magnitud del cambio son verdes para cambios favorables y rojos para desfavorables. better acepta up (predeterminado), down (bajar es favorable, como precios o costes) o none (sin color). Los índices de columna empiezan en 0. |
options.table.copy | no; solo table | true añade Copy y CSV para los lectores. Copy copia la selección visible tras filtrar, buscar y ordenar, de todas las páginas y con la fuente, para pegarla en una hoja de cálculo o documento. CSV la descarga con los números originales. Se desactiva si no se configura expresamente. |
Una tabla en vivo conserva, muestra y ordena números negativos, y no dibuja barras en una columna con valores negativos. Todos los tipos salvo number rechazan valores negativos: barras y áreas desde cero no pueden representarlos con fidelidad. Un error estructurado evita una representación engañosa. Un target negativo siempre se rechaza.
Flujos de Sankey
data.links contiene origen, destino y valor. Los nodos se deducen de los enlaces. data.nodes puede aportar identificadores, etiquetas y orden de entrada. Los pesos son positivos o null; los enlaces duplicados se suman. Los ciclos y enlaces a sí mismos producen errores con las rutas de las filas.
{
"type": "sankey",
"data": {
"links": [
{
"source": "Income",
"target": "Budget",
"value": 120
},
{
"source": "Budget",
"target": "Spending",
"value": 100
}
]
}
} La altura del nodo usa el mayor valor entre entradas y salidas. La descripción emergente explica las diferencias sin inventar enlaces. Se permiten 50 nodos, 100 enlaces y ocho etapas. Si llegas al límite, agrupa tú los flujos pequeños en «Otros».
options.flowColor: source (predeterminado) o stage. options.flowOrder: minimize (predeterminado) o input. options.showValues es true por defecto. Los nombres siguen visibles al ocultar valores. En pantallas estrechas, el gráfico se desplaza dentro de su marco y muestra debajo una tabla de enlaces plegada. Abre el creador de Sankey.
Ridgeline: observaciones agrupadas
Usa data.groups con id, label y observations por grupo. Los valores pueden ser negativos; null significa ausente. El uso local admite 12 grupos y 2000 observaciones. El renderizado alojado mantiene el límite de puntos del plan.
{
"type": "ridgeline",
"data": {
"groups": [
{
"id": "monday",
"label": "Monday",
"observations": [
12,
15,
16,
19,
24
]
}
]
},
"options": {
"bandwidth": 2
}
} La estimación de densidad de núcleo gaussiano usa un ancho de banda común de Silverman a partir de las desviaciones dentro de los grupos. Un options.bandwidth positivo lo sustituye. El rango X común abarca el mínimo y el máximo más cuatro anchos de banda a cada lado. Menos de cinco observaciones conocidas o valores constantes se muestran como puntos. Los grupos vacíos muestran No data. Las observaciones null permanecen en la tabla y se excluyen de la densidad.
Las alturas comparten escala de densidad. options.ridgeScale: "own" escala cada grupo según su máximo y muestra un aviso. options.sortByMedian: true ordena por mediana, con los vacíos al final. El cursor, la fijación y las flechas muestran n, mediana y el 50 % central. Abre el creador de ridgeline.
Diagrama de caja: observaciones agrupadas
El diagrama de caja usa los mismos data.groups que ridgeline: id, label y observations por grupo. Localmente admite 12 grupos y 2000 observaciones. El renderizado alojado mantiene el límite de puntos del plan. null significa ausente, nunca 0. Un grupo sin valores conocidos sigue visible y muestra No data.
{
"type": "boxplot",
"data": {
"groups": [
{
"id": "p1",
"label": "Period 1",
"observations": [
62,
68,
71,
74,
75
]
}
]
},
"options": {
"whiskers": "tukey"
}
} options.whiskers: tukey (predeterminado) llega a los valores extremos dentro de 1,5 veces el IQR por debajo o encima de la caja; los restantes son círculos atípicos. minmax llega al mínimo y máximo, sin atípicos. options.quartiles: linear (predeterminado, CUARTIL.INC de Excel) o halves (mediana de cada mitad, como TI-84). Ambos dan la misma mediana. options.showPoints: true muestra cada valor; false oculta los puntos. Sin configurarlo, aparecen si todos los grupos tienen como máximo 50 valores conocidos. options.sortByMedian: true ordena por mediana y deja los vacíos al final.
El cursor, la fijación y las flechas muestran n, mediana, mitad central, bigotes y atípicos. La tabla accesible contiene el resumen de cinco números de cada grupo. Abre el creador de diagramas de caja.
Dispersión X-Y: puntos en dos ejes numéricos
xy lee data.points: un { "x", "y", "label"?, "group"? } por fila, con títulos opcionales data.xTitle y data.yTitle de 1 a 60 caracteres. X e Y son números finitos o null. null significa ausente, nunca 0: no se dibuja el punto y la fuente indica cuántos puntos no tienen datos. Etiquetas y grupos tienen 1–120 caracteres. Asigna un grupo a todos los puntos o a ninguno. Localmente admite 2000 puntos y 12 grupos. El renderizado alojado mantiene el límite de puntos del plan.
{
"type": "xy",
"data": {
"xTitle": "Hours studied",
"yTitle": "Test score",
"points": [
{
"x": 6.5,
"y": 91,
"label": "Maya"
},
{
"x": 2,
"y": 63,
"label": "Jack"
},
{
"x": 9,
"y": 90,
"label": "Olive"
}
]
},
"options": {
"bestFit": true
}
} options.bestFit: true dibuja una recta de mínimos cuadrados por grupo con al menos tres puntos y dos valores X distintos, con ecuación, r y R². Para un grupo aparecen en una esquina. Para varios, r aparece en la leyenda si cabe y siempre en la descripción de la recta. options.fromZero: true incluye 0 en ambos ejes. options.format formatea Y y options.xFormat formatea X con la misma sintaxis (percent, currency:XXX o affix:["before","after"]).
El cursor, la fijación y las flechas muestran cada punto y su predicción. La recta indica n, ecuación, r y R². La tabla accesible contiene todos los puntos y, con la recta activa, pendiente, intersección, r y R² por grupo. Abre el creador de dispersión.
Streamgraph: capas de un flujo cambiante
Usa etiquetas temporales y series normales, como en líneas o columnas apiladas. Streamgraph admite 1–6 capas y 2–100 periodos. Los valores deben ser finitos y no negativos. null es un error; para datos ausentes, usa líneas.
La base de silueta es la mitad negativa del total de cada momento. Las capas siguen el orden de entrada. Las curvas suaves interpolan grosores no negativos y límites compartidos; los valores son exactos en cada momento. options.curve: "linear" usa límites rectos. No hay eje Y numérico. El cursor y las flechas muestran valores y proporciones exactos por momento. Los nombres aparecen dentro si caben; si no, en la leyenda.
La leyenda no permite ocultar capas, pues dejaría huecos engañosos. Los cambios de valores animan las bandas; el cambio a líneas o columnas apiladas usa un fundido. Abre el creador de streamgraph.
Bump: posiciones a lo largo del tiempo
Usa data.labels para los periodos y una serie con nombre por entidad. Define options.rankMode expresamente: values calcula posiciones de competición (1, 2, 2, 4); ranks acepta posiciones enteras positivas. El primer puesto queda arriba. Una observación null interrumpe la línea.
En modo de valores, rankDirection: "descending" coloca primero los mayores (predeterminado); ascending, los menores. showRanks es false por defecto; true muestra posiciones en los puntos. topN (1–12) puede limitar las posiciones visibles sin inventarlas al salir o volver una entidad. Los valores deben ser finitos y no negativos. Usa 1–12 entidades y 3–24 periodos con nombres únicos de hasta 120 caracteres. Los errores indican el campo y cómo corregirlo.
{
"type": "bump",
"data": {
"labels": [
"Jan",
"Feb",
"Mar"
],
"series": [
{
"name": "Atlas",
"values": [
40,
30,
45
]
},
{
"name": "Birch",
"values": [
35,
42,
45
]
}
]
},
"options": {
"rankMode": "values",
"rankDirection": "descending"
}
} El cursor destaca una entidad. Las flechas izquierda y derecha recorren periodos; arriba y abajo, posiciones de un momento. Clic o Enter fija un punto; Mayús añade una comparación. La tabla accesible conserva cada momento, posición y valor original. PNG, SVG, API de renderizado e inserciones usan la misma escena. Edita los datos en el creador de bump charts. El gráfico de líneas muestra los huecos de valores; el gráfico de pendiente sirve para dos periodos.
Treemap y sunburst: grupos y elementos
Treemap y sunburst leen data.nodes. Los grupos tienen identificador y etiqueta. Los elementos indican su grupo con parentId y un valor positivo finito o null si falta. Los totales se calculan a partir de los elementos. Se admiten 6 grupos y 36 elementos en dos niveles, con identificadores únicos. Padres ausentes, ciclos, más niveles, grupos vacíos, ceros y negativos generan errores con la ruta del nodo y la corrección.
{
"type": "treemap",
"title": "City budget",
"data": {
"nodes": [
{
"id": "spaces",
"label": "Public spaces"
},
{
"id": "parks",
"parentId": "spaces",
"label": "Parks",
"value": 32
},
{
"id": "libraries",
"parentId": "spaces",
"label": "Libraries",
"value": 18
}
]
},
"options": {
"showValues": true,
"precision": 0,
"variant": "auto"
}
} Abre un grupo con clic, toque o Enter. All, Escape o Retroceso vuelve al total. Este estado no se guarda en la especificación. Los elementos ausentes o de menos de un píxel permanecen en la tabla y las descripciones de teclado. options.showValues: false oculta valores; los nombres aparecen si caben. Formato, precisión, tema y variante siguen las reglas habituales. Sunburst usa los mismos nodos: cambia type a sunburst. El anillo interior muestra grupos; el exterior, elementos; el centro, la suma. Las etiquetas aparecen si caben. Edita un treemap o crea un sunburst.
Los 27 tipos
| Tipo | Datos que utiliza | Ejemplos en vivo |
|---|---|---|
sankey | Enlaces dirigidos: origen, destino, valor positivo o `null`; 50 nodos, 100 enlaces y 8 etapas | Ver en vivo |
ridgeline | 1–12 grupos de observaciones originales, 2000 mediciones en total | Ver en vivo |
boxplot | 1–12 grupos de observaciones originales; mediana, cuartiles y atípicos | Ver en vivo |
streamgraph | 1–6 capas, 2–100 periodos, valores no negativos y sin datos ausentes | Ver en vivo |
column | Etiquetas y al menos una serie | Ver en vivo |
bar | Etiquetas y al menos una serie, en horizontal | Ver en vivo |
line | Etiquetas y al menos una serie | Ver en vivo |
area | Etiquetas y al menos una serie, con relleno hasta cero | Ver en vivo |
stacked | Etiquetas y al menos una serie, sumadas por etiqueta | Ver en vivo |
donut | Etiquetas y solo la PRIMERA serie | Ver en vivo |
scatter | Etiquetas y al menos una serie; un punto por valor (puntos en el creador de gráficos) | Ver en vivo |
xy | Puntos con x e y, etiqueta y grupo opcionales, en dos ejes numéricos; 2000 puntos y 12 grupos; options.bestFit añade una recta de tendencia | Ver en vivo |
dotplot | Etiquetas y recuentos, un punto por unidad; las fracciones se redondean hacia abajo | Ver en vivo |
number | Primer valor de la primera serie, con signo | Ver en vivo |
lollipop | Etiquetas y 1–3 series: tallos y puntos; con 2–3 series, solo puntos (gráfico de Cleveland) | Ver en vivo |
dumbbell | Etiquetas y exactamente 2 series: dos puntos unidos por fila con el cambio indicado | Ver en vivo |
range | Etiquetas y exactamente 2 series (límites inferior y superior, superior ≥ inferior), una banda por fila | Ver en vivo |
waterfall | Etiquetas y 1 serie con pasos ≥ 0; columnas flotantes sobre el acumulado, cierre mediante options.total | Ver en vivo |
bullet | Etiquetas y valores reales; objetivos opcionales por fila como segunda serie, sobre options.bands | Ver en vivo |
slope | Exactamente 2 etiquetas (antes, ahora) y al menos una serie; recta por serie con nombres en ambos extremos | Ver en vivo |
heatmap | Etiquetas como columnas y series como filas; celdas coloreadas por valor; options.scale fija el rango | Ver en vivo |
waffle | Etiquetas y solo la PRIMERA serie; proporciones en options.units cuadrados (100 por defecto) | Ver en vivo |
matrix | Etiquetas como filas, columnas y celdas con yes | no | partial | unknown | na | Ver en vivo |
sunburst | Los mismos nodos de dos niveles que treemap, representados en anillos | Ver en vivo |
bump | 3–24 periodos, 1–12 entidades con nombre; modo explícito de valores o posiciones | Ver en vivo |
treemap | Dos niveles de nodos: grupos y elementos con valor positivo o `null` | Ver en vivo |
table | Columnas tipadas y filas con texto, números, estados y anotaciones; tabla DOM en vivo en lugar de lienzo | Ver en vivo |
Cambiar type en un gráfico cargado no lo dibuja de nuevo. El motor anima las formas existentes hasta convertirlas en las nuevas. Es la base de este proyecto.
En column con una serie, options.histogram: true dibuja intervalos rectangulares con un color de la paleta y una separación de 1 px. Sin esta opción, dibuja columnas normales.
{ "type": "column", "options": { "histogram": true },
"data": { "labels": ["0–10", "10–20", "20–30"], "series": [{ "values": [9, 27, 38] }] } } Temas y variantes
Cinco temas con variantes clara y oscura ofrecen diez estilos. options.variant elige: light y dark fijan la variante; auto sigue primero la página mediante data-theme, una clase dark en html o body, o color-scheme, y después el sistema operativo. Los cambios se aplican en vivo. Sin el campo, cada tema usa su variante base: editorial, glass y mint claros; ink y neon oscuros. Una página con selector propio puede seguir enviando light o dark expresamente.
Anotaciones
options.notes vincula una limitación a una etiqueta: fecha de corte, subtotal conocido o afirmación sin verificar. Barras, columnas, piruletas, líneas, áreas, gráfico de anillo, dispersión e indicador muestran un círculo con i, o ! con warn. Una anotación partial conserva el color de aviso. La matriz marca las celdas de la fila en una esquina. Pasa el cursor o toca para leer el texto; haz clic para mantenerlo abierto. También figura en la tabla accesible oculta. La limitación permanece junto al gráfico, en lugar de perderse en una nota al pie.
"options": {
"notes": [
{ "label": "Vanilla", "text": "Updates stop from 1 January 2025", "kind": "warn" },
{ "label": "Circle", "text": "Known part only; processing is extra", "kind": "partial" }
]
} La matriz de estado
matrix lee celdas en lugar de series. Las filas vienen de data.labels y las características de data.columns. Cada celda contiene un estado yes | no | partial | unknown | na, como cadena o { "status", "note" } con anotación. Los estados usan formas (marca, cruz, semicírculo, interrogación, raya), nunca solo color. options.legend los renombra en leyenda, descripción y tabla accesible. Desconocido y no aplicable son distintos: la falta de un dato no se convierte en un no.
{
"type": "matrix",
"data": {
"labels": ["Discourse", "Flarum"],
"columns": ["Licence fee", "Server", "Updates"],
"cells": [
["yes", "no", "yes"],
["yes", "no", { "status": "partial", "note": "Community builds only" }]
]
},
"options": { "legend": { "yes": "None to pay / included", "no": "On the team / paid" } }
} La tabla en vivo
table es el único tipo que no es una imagen: <live-chart> crea una tabla HTML real. Solo las páginas con tabla cargan un segundo archivo pequeño. Las columnas tienen tipo text, number con format, status (estados de matriz como indicadores con forma y etiqueta opcional) o note. Cada celda es cadena, número, null, { "status", "label", "note" } o { "text", "kind", "note" }; note es opcional. La tabla ordena al pulsar cabeceras, filtra por estados, dibuja barras tras los números, despliega anotaciones al pulsar y se desplaza horizontalmente bajo 480 px. options.mobile: "cards" usa tarjetas. Chart pasa una columna numérica o de estados con valores numéricos al motor como piruletas. SVG se rechaza con una explicación estructurada. El MCP local con Pro puede renderizar PNG.
{
"type": "table",
"title": "What you are buying",
"data": {
"columns": [
{ "name": "Product" },
{ "name": "Licence cost", "kind": "status" },
{ "name": "Monthly", "kind": "number", "format": "currency:USD" },
{ "name": "What still lands on the team", "kind": "note" }
],
"rows": [
["Discourse", { "status": "yes", "label": "None" }, 100, "Server and an SMTP mail service"],
["Vanilla", "yes", null, { "text": "Updates stop from 1 January 2025", "kind": "warn" }]
]
},
"options": { "sort": { "column": 2, "dir": "desc" }, "sticky": true }
} En columnas de texto o anotación, { "text": "Limited claim", "kind": "warn", "note": "Full explanation" } mantiene visible la afirmación y abre la explicación con !. kind es note, warn o partial. La explicación es texto plano de hasta 4000 caracteres Unicode; noteText y detail generan errores. Sin note, el texto sigue visible y el icono explica su significado. Las celdas de estado existentes con + y anotación siguen funcionando. Pega el JSON completo en el creador de tablas para conservar tipos y diseño. «Descargar JSON» lo guarda sin el límite de tamaño del enlace compartido.
Líneas de objetivo
Objetivo, límite o SLA: options.target dibuja una línea discontinua con etiqueta opcional en columnas, barras, líneas, áreas, apilados, dispersión y puntos. La escala siempre se amplía para incluirla.
"options": {
"target": { "value": 120, "label": "Goal" }
} Líneas y partes
options.curve define la forma entre puntos de líneas o áreas: smooth (predeterminado), linear para segmentos rectos, step para escalones. Cada valor forma una meseta alrededor de su etiqueta; el salto queda entre etiquetas (ver gráficos escalonados). slope usa dos etiquetas como estados y nombra cada serie en ambos extremos con el valor exacto. null en un lado interrumpe la línea y muestra —. heatmap usa etiquetas como columnas y series como filas. Las celdas van del fondo del tema al primer color de la paleta. options.scale con { "min", "max" } fija el rango y limita los valores externos. Las celdas null quedan planas y sin etiqueta. waffle reparte la primera serie entre options.units cuadrados (1–400, 100 por defecto) mediante restos mayores, conservando la suma. La leyenda sigue al gráfico de anillo; el cursor sobre un cuadrado destaca toda su proporción.
{ "type": "line", "options": { "curve": "step" } }
{ "type": "slope", "data": { "labels": ["2024", "2025"], "series": [{ "name": "Search", "values": [31, 44] }] } }
{ "type": "heatmap", "options": { "scale": { "min": 0, "max": 50 } },
"data": { "labels": ["Mon", "Tue"], "series": [{ "name": "North", "values": [12, 30] }, { "name": "South", "values": [8, null] }] } }
{ "type": "waffle", "options": { "units": 100 }, "data": { "labels": ["Yes", "No"], "series": [{ "values": [73, 27] }] } } Formatos numéricos
options.format afecta a ejes, etiquetas, totales apilados, indicador y descripciones. percent añade %; currency:XXX antepone $, € o £ para USD, EUR y GBP. Otras monedas usan su código, como CAD 1,234.5. Las unidades propias usan affix:["before","after"]: affix:[""," lb"] da 1,234.5 lb y affix:["~",""] da ~1,234.5. Cada lado admite 12 caracteres, incluidos espacios. Los valores nunca se convierten. Etiquetas, descripciones, indicador y celdas conservan los decimales (99.98% sigue igual, $201.5 pasa a $201.50), agrupan millares (12,345) y no abrevian. Solo los ejes son compactos ($48k). options.precision (0–4) fija los decimales. Dos excepciones conservan su formato sencillo: la proporción de un sector circular, que ya es porcentaje, y los recuentos del diagrama de puntos, que no son dinero ni proporciones.
"options": { "format": "percent" } // 99.98 -> 99.98% on the bar, 100% on the axis
"options": { "format": "currency:USD" } // 48200 -> $48,200 on the bar, $48k on the axis
"options": { "precision": 2 } // 5 -> 5.00 everywhere a reader reads it Errores estructurados
El analizador nunca lanza excepciones ni adivina. Una especificación incorrecta devuelve objetos {path, message, hint} con el campo exacto. La misma estructura se usa en el navegador, MCP y API de renderizado, y la pueden leer personas y asistentes.
{
"ok": false,
"errors": [{
"path": "data.series[0].values[2]",
"message": "Value \"abc\" is not a finite number",
"hint": "Use numeric values, e.g. 42 or 3.14"
}]
}