llamada - llamar javascript desde html
¿Cómo puedo analizar ASCII Art en HTML usando Java o Javascript? (4)
Vi que la API de Neo4j usa ASCII Art muy inteligentemente con su API:
http://jaxenter.com/getting-started-with-neo4j-the-java-graph-database-47955.html
Quiero probar algo similar, pero con ASCI Art to HTML. Cómo se puede analizar el arte ASCII, así que, por ejemplo, si se le da una entrada de Arte ASCII, se puede decir algo como:
--------------------------------
I I
I ------- ------- I
I I I I I I
I I A I I B I I
I I I I I I
I ------- ------- I
I I
I I
--------------------------------
: podría resultar en una salida HTML algo así como:
<div>
<div style=''display:inline;''>
A
</div>
<div style=''display:inline;''>
B
</div>
</div>
Actualizar
La pregunta fue cerrada citando que necesito "demostrar una comprensión mínima del problema que se está resolviendo". Tengo una comprensión del problema a resolver. El problema es que lo que quiero resolver es hacer que el HTML con plantillas sea más fácil de entender en el código fuente para el siguiente marco web:
https://github.com/zubairq/coils
: aunque la solución podría aplicarse a cualquier marco web. Desde entonces, he visto a alguien intentar hacer una versión inicial en C ++ aquí:
https://github.com/h3nr1x/asciidivs2html/blob/master/asciidivs2html.cpp
: ¡muy impresionante! Si puede hacer que funcione en Java o Clojure, entonces si podemos reabrir la pregunta, nominaré una recompensa para que pueda obtener más puntos por la solución :)
Ejecuté la solución Java proporcionada por @meewok y aquí está el resultado:
$ java AsciiToDIVs.RunConverter
Created a box(ID=0,X=0,Y=0,width=33,height=10)
Created a box(ID=1,X=2,Y=4,width=8,height=5,parent=0)
Created a char(Char=A,X=4,Y=7,parent=1)
Created a box(ID=2,X=2,Y=21,width=8,height=5,parent=0)
Created a char(Char=B,X=4,Y=24,parent=2)
<div><div><div>A</div></div><div><div>B</div></div></div>
Metodología
Una solución para implementar es la siguiente:
- crear una matriz 2D en memoria (matriz de matrices) que es similar a un tablero de ajedrez.
Luego crearé un algoritmo que cuando detecte caracteres "-", inicializo la búsqueda de un método para detectar las esquinas restantes (arriba a la derecha, abajo a la izquierda, abajo a la derecha) siguiendo los caracteres y dónde terminan.
Ejemplo (pseudocódigo rápido):
while(selectedCell==I) selectedCell=selectedCell.goDown();
Utilizando dicha estrategia puede mapear sus cajas y qué cajas están contenidas dentro de qué.
Restante sería imprimir esta información como html ..
Implementación rápida y sucia
Como estaba de humor, pasé una hora + para cocinar rápidamente una implementación de juguete. Lo que sigue no está optimizado con respecto a que no utilizo Iteradores para repasar Células, y necesitaría refactorizar para convertirme en un marco serio.
Cell.java
package AsciiToDIVs;
public class Cell {
public char Character;
public CellGrid parentGrid;
private int rowIndex;
private int colIndex;
public Cell(char Character, CellGrid parent, int rowIndex, int colIndex)
{
this.Character = Character;
this.parentGrid = parent;
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
}
CellGrid.java
package AsciiToDIVs;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
public class CellGrid {
private ArrayList<ArrayList<Cell>> CellGridData;
public CellGrid(String asciiFile) throws IOException {
readDataFile(asciiFile);
}
public ArrayList<FoundObject> findBoxes(FoundBoxObject parent)
{
int startRowIndex = 0, startColIndex = 0,
parentRowLimit = Integer.MAX_VALUE,
parentColLimit = Integer.MAX_VALUE,
startingColIndex = 0;
if(parent != null)
{
startRowIndex = parent.getRowIndex()+1;
startColIndex = startingColIndex = parent.getColIndex()+1;
parentRowLimit = parent.getRowIndex() + parent.getHeight();
parentColLimit = parent.getColIndex() + parent.getWidth();
}
ArrayList<FoundObject> results = new ArrayList<FoundObject>();
Cell currentCell;
if(startRowIndex>=CellGridData.size())
return null;
for(; startRowIndex<CellGridData.size() && startRowIndex<parentRowLimit; startRowIndex++ )
{
startColIndex = startingColIndex;
for(; startColIndex< CellGridData.get(startRowIndex).size() && startColIndex<parentColLimit; startColIndex++)
{
FoundBoxObject withinBox = checkWithinFoundBoxObject(results, startRowIndex, startColIndex);
if(withinBox !=null)
startColIndex+=withinBox.getWidth();
currentCell = getCell(startRowIndex, startColIndex);
if(currentCell!=null)
{
if(currentCell.Character == ''-'') // Found a TOP-CORNER
{
int boxHeight = getConsecutiveIs(startRowIndex+1, startColIndex) + 1;
if(boxHeight>1)
{
int boxWidth = getConsecutiveDashes(startRowIndex, startColIndex);
FoundBoxObject box = new FoundBoxObject(startRowIndex, startColIndex, boxWidth, boxHeight, parent);
results.add(box);
findBoxes(box);
startColIndex+=boxWidth;
}
}
//This is a character
else if(currentCell.Character != ''-'' && currentCell.Character != ''I'' && currentCell.Character != '' ''
&& currentCell.Character != ''/n'' && currentCell.Character != ''/n'' && currentCell.Character != ''/t'')
{
FoundCharObject Char = new FoundCharObject(startRowIndex, startColIndex, parent, currentCell.Character);
results.add(Char);
}
}
}
}
if(parent!=null)
parent.containedObjects = results;
return results;
}
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
result+="<div>";
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
}
result+="</div>";
}
return result;
}
private FoundBoxObject checkWithinFoundBoxObject(ArrayList<FoundObject> results, int rowIndex, int colIndex)
{
Iterator<FoundObject> it = results.iterator();
FoundObject f;
FoundBoxObject fbox = null;
while(it.hasNext())
{
f = it.next();
if(f instanceof FoundBoxObject)
{
fbox = (FoundBoxObject) f;
if(rowIndex >= fbox.getRowIndex() && rowIndex <= fbox.getRowIndex() + fbox.getHeight())
{
if(colIndex >= fbox.getColIndex() && colIndex <= fbox.getColIndex() + fbox.getWidth())
{
return fbox;
}
}
}
}
return null;
}
private int getConsecutiveDashes(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character ==''-'')
{
counter++;
cell = getCell(startRowIndex, startColIndex++);
}
return counter;
}
private int getConsecutiveIs(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character ==''I'')
{
counter++;
cell = getCell(startRowIndex++, startColIndex);
}
return counter;
}
public Cell getCell(int rowIndex, int columnIndex)
{
ArrayList<Cell> row;
if(rowIndex<CellGridData.size())
row = CellGridData.get(rowIndex);
else return null;
Cell cell = null;
if(row!=null){
if(columnIndex<row.size())
cell = row.get(columnIndex);
}
return cell;
}
public Iterator<ArrayList<Cell>> getRowGridIterator(int StartRow) {
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
int CurrentRow = 0;
while (itRow.hasNext()) {
// Itrate to Row
if (CurrentRow++ < StartRow)
itRow.next();
}
return itRow;
}
private void readDataFile(String asciiFile) throws IOException {
CellGridData = new ArrayList<ArrayList<Cell>>();
ArrayList<Cell> row;
FileInputStream fstream = new FileInputStream(asciiFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
// Read File Line By Line
int rowIndex = 0;
while ((strLine = br.readLine()) != null) {
CellGridData.add(row = new ArrayList<Cell>());
// System.out.println (strLine);
for (int colIndex = 0; colIndex < strLine.length(); colIndex++) {
row.add(new Cell(strLine.charAt(colIndex), this, rowIndex,colIndex));
// System.out.print(strLine.charAt(i));
}
rowIndex++;
// System.out.println();
}
// Close the input stream
br.close();
}
public String printGrid() {
String result = "";
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
Iterator<Cell> itCol;
Cell cell;
while (itRow.hasNext()) {
itCol = itRow.next().iterator();
while (itCol.hasNext()) {
cell = itCol.next();
result += cell.Character;
}
result += "/n";
}
return result;
}
}
FoundBoxObject.java
package AsciiToDIVs;
import java.util.ArrayList;
public class FoundBoxObject extends FoundObject {
public ArrayList<FoundObject> containedObjects = new ArrayList<FoundObject>();
public static int boxCounter = 0;
public final int ID = boxCounter++;
public FoundBoxObject(int rowIndex, int colIndex, int width, int height, FoundBoxObject parent) {
super(rowIndex, colIndex, width, height);
if(parent!=null)
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
",parent="+parent.ID+")");
else
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
")");
}
}
FoundCharObject.java
package AsciiToDIVs;
public class FoundCharObject extends FoundObject {
private Character Char;
public FoundCharObject(int rowIndex, int colIndex,FoundBoxObject parent, char Char) {
super(rowIndex, colIndex, 1, 1);
if(parent!=null)
System.out.println("Created a char(" +
"Char="+Char+
",X="+rowIndex+
",Y="+colIndex+
",parent="+parent.ID+")");
else
System.out.println("Created a char(" +
",X="+rowIndex+
",Y="+colIndex+")");
this.Char = Char;
}
public Character getChar() {
return Char;
}
}
FoundObject.java
package AsciiToDIVs;
public class FoundObject {
private int rowIndex;
private int colIndex;
private int width = 0;
private int height = 0;
public FoundObject(int rowIndex, int colIndex, int width, int height )
{
this.rowIndex = rowIndex;
this.colIndex = colIndex;
this.width = width;
this.height = height;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
Método principal
public static void main(String args[])
{
try {
CellGrid grid = new CellGrid("ascii.txt");
System.out.println(CellGrid.printDIV(grid.findBoxes(null)));
//System.out.println(grid.printGrid());
} catch (IOException e) {
e.printStackTrace();
}
}
Actualizar
El ''printDIV'' debería ser así (se estaban imprimiendo más '''' de lo necesario).
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
result+="<div>";
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
result+="</div>";
}
}
return result;
}
Aquí hay una solución bastante simple en JavaScript, probada a través de Node. Por supuesto, deberá ajustar los métodos de entrada y salida.
var s = "/n/
--------------------------------/n/
I I/n/
I ------- ------- I/n/
I I I I I I/n/
I I A I I B I I/n/
I I I I I I/n/
I ------- ------- I/n/
I I/n/
I I/n/
--------------------------------/n/
";
var lines = s.split(''/n'');
var outer_box_top_re = /--+/g;
var i;
for (i=0; i<lines.length; i++) {
while ((res = outer_box_top_re.exec(lines[i])) != null) {
L = res.index
R = outer_box_top_re.lastIndex
process_box(i, L, R)
}
}
function process_box(T, L, R) {
console.log(''<div top="'' + T + ''" left="'' + L + ''" right="'' + R + ''">'')
blank_out(T, L, R)
var i = T;
while (1) {
i += 1;
if (i >= lines.length) {
console.log(''Fell off bottom of ascii-art without finding bottom of box'');
process.exit(1);
}
var line = lines[i];
if (line[L] == ''I'' && line[R-1] == ''I'') {
// interior
// Look for (the tops of) sub-boxes.
// (between L+1 and R-2)
var inner_box_top_re = /--+/g;
// Inner and outer need to be separate so that
// inner doesn''t stomp on outer''s lastIndex.
inner_box_top_re.lastIndex = L+1;
while ((res = inner_box_top_re.exec(lines[i])) != null) {
sub_L = res.index;
sub_R = inner_box_top_re.lastIndex;
if (sub_L > R-1) { break; }
process_box(i, sub_L, sub_R);
}
// Look for any other content (i.e., a box label)
content = lines[i].substring(L+1, R-1);
if (content.search(/[^ ]/) != -1) {
console.log(content);
}
blank_out(i, L, R);
}
else if (line.substring(L,R).match(/^-+$/)) {
// bottom
blank_out(i, L, R);
break;
}
else {
console.log("line " + i + " doesn''t contain a valid continuation of the box");
process.exit(1)
}
}
console.log(''</div>'')
}
function blank_out(i, L, R) {
lines[i] = (
lines[i].substring(0,L)
+ lines[i].substring(L,R).replace(/./g, '' '')
+ lines[i].substring(R)
);
}
Lo que desea es la idea del análisis bidimensional, que detecta entidades en 2D y verifica que tienen relaciones legítimas.
Ver http://mmi.tudelft.nl/pub/siska/TSD%202DVisLangGrammar.pdf
Lo que será difícil es definir los conjuntos de posibles restricciones de "Arte ASCII". ¿Solo quieres reconocer letras? Hecho solo de los mismos caracteres de la letra? letras "cursivas"? cajas? (Su ejemplo tiene cuadros cuyos lados no están hechos del mismo carácter ASCII). Cajas con paredes gruesas arbitrarias? Cajas anidadas? Diagramas con flechas (delgadas / gruesas)? Kilroy-estaba-aquí-nariz-sobre-la-pared? Imágenes de Mona Lisa en las que los píxeles de los personajes proporcionan relaciones de densidad. ¿Qué quieres decir exactamente con "arte ASCII"?
El verdadero problema es definir el rango de cosas que intenta reconocer. Si limita ese rango, sus probabilidades de éxito aumentan (vea el documento al que se hace referencia).
El problema aquí tiene poco que ver específicamente con Java o Javascript. Esto está mucho más relacionado con los algoritmos. Elija una clase limitada de arte, elija los algoritmos correctos, y luego lo que tiene es un problema de codificación que debería ser relativamente fácil de resolver. Sin límites, sin algoritmos -> ninguna cantidad de Javascript te salvará.
Suponiendo que haya generado el arte ASCII.
En HTML, hay 2 cosas que necesitarías hacer.
- Establezca la fuente en una fuente monoespaciada.
- Analice ASCII a códigos HTML. p.ej.
<space> to line break to <br/> etc
http://jsfiddle.net/kenthaha/9rCXP/
espero que vaya.