elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a la Factorización De Semiprimos (RSA)


  Mostrar Temas
Páginas: [1]
1  Programación / Programación C/C++ / Funcion Hash para un diccionario de palabras. en: 13 Mayo 2019, 04:44 am
¿Alguien conoce algun algoritmo especifico para generar una función hash eficiente para un diccionario(tabla hash)?

Mi problema plantea el uso de un diccionario que utiliza como generadora del hash una cadena que por el contexto del problema no debería sobresalir de más de 15 caracteres y en promedio tendría un aproximado de 10 caracteres. Hasta ahorita me he empezado a formular una manera de que no existan tantas colisiones en el entero que genera cada string con referencia a que pueden existir string diferentes pero que en si tienen los mismo caracteres, he pensado en varias formas entre las cuales se encuentra por ejemplo multiplicar los valores  de cada posion por un valor que no pueda ser generado con la suma de los anteriores es decir:
Cadena "hola"
HASH = 0;
HASH += 'H' ;
HASH += 'O' +167
HASH += 'L' + 334
HASH += 'A' + 501

El factor 167 lo eligo debido a que el último caracter que se usaria en el contexto de mi problema seria las vocales con acento que se encuentran como maximo en el valor 165 del ASCII y de esta manera puedo generar valores distintos para cadenas que contiene los mismo caracteres pero en distintas posiciones

Nota. he considerado hacer este proceso hasta los 6 caracteres como maximo ya que considero que sería muy extraño que dos palabras empiecen con el mismo patron de 6 caracteres y esto solo estaria consumiendo mas tiempo para cadenas un poco mas largas.

Mi duda surge a la hora de adaptar lo que tengo hasta ahorita al arreglo que me va representar el diccionario. Actualmente mi diccionario esta representado por un arreglo de arboles binarios que cuando encuentran colisiones simplemente se añade a una rama del árbol. Mi pregunta es como se hace para ya teniendo un algoritmo generador de hash adaptarlo a la dimension del arreglo que en mi caso es el de tamaño "101". He probado con algoritmos como el anterior y no he conseguido valores de colisiones favorables, he probado con hash algo aleatorios y he conseguido llegar a que la desviacion estandar de las colisiones sea de 2.86  con una media de aproximadamente 8.44 y un total de datos ingresados de 853 pero como menciono no quedo satisfecho debido a que el algoritmo generador de hash no tiene mucho sentido.

ACTUALIZACIÓN. Cuando digo que no se como adaptar lo que llevo hasta ahorita para ingresarlo en arreglo me refiero a que no se como hacer que se distribuya de una manera ligeramente pareja en todas las posiciones , al menos al moment de ahora lo único que hago es relizar un modulo al hash obtenido:

HASH_OBTENIDO % TAMANO_ARREGLO( Es un numero primo)

2  Programación / Bases de Datos / Implementación de una base de datos en un programa local. en: 24 Abril 2019, 04:38 am
Buenas a todos, estoy empezando con bases de datos y he comenzando a crear un sistema pequeño que me permita crear un tipo agenda-directorio por usuarios con su respectivo login etc... Mi planteamiento es primero hacerlo totalmente local, es decir, solo quiero que la cuenta y toda su información sea utilizada dentro de la computadora donde fue creada. Hasta el momento no he visto mucho sobre como se implementan las bases de datos en los programas cotidianos , solo he visto sobre consultas,tablas,etc... Mi principal duda es si en este tipo de programas vale la pena cada vez que agrego/elimino/actualizo un dato de un contacto/cita/etc... ¿ debo hacer la consulta respectiva a la base de datos inmediatamente? o se suele tener un objeto en memoria dinamica que es aquel que se carga al principio del inicio de sesión con una consulta a la bases de datos y que es el que recibe todas las modificaciones para finalmente al final de la sesión o cada cierto periodo tiempo actualiza los datos mediante una consulta a la base de datos. Imagino que si el programa estuviera emergido en un sistema distribuido estaría obligado a manejar mas detalles y todo cambio hacerlo directamente a la base de datos pero en este tipo de programas que suele hacer?. Intuyó que utilizar siempre consultas es un gasto de recursos innecesario pero tal vez no estoy viendo algún detalle importante.

En el caso que por lo general se trabaje con objetos en memoria para los cambios entonces cual seria la mejor forma de por ejemplo verificar que elementos fueron borrados.. yo tendria mi estructura de datos de los datos que tiene el usuario al final de su sesión pero que suele hacer para saber que datos pudieron haber sido eliminado? ,simplemente deberia tener por ejemplo un array que me guarde los id de aquellos elementos que fueron eliminados para al final de la sesión saber que debo eliminarlos?.Supongo que la parte de que se modifico/anadio un nuevo objeto/registro tambien deberia ser analizada con respecto a la esctuctura de datos que tengo verificando al final de la sesión si un dato ya se encuentra en la base de datos.. En dado caso ver si se modifico durante la sesion o en caso de que el elemento no se encuentre en la base de datos hacer un insert
3  Programación / Java / JavaFx transmisiòn de datos entre escenas. en: 21 Abril 2019, 02:52 am
Buenas a todos tengo una duda con referencia a como se suelen hacer las interfaces graficas con JavaFx en casos como en el siguiente:

Tengo una interfaz gráfica que muestra una parte de información estatica que nunca cambia y tengo una área donde yo eligó una sucursal, esta parte es una tabla(GridPane) que contiene varias botones y que cada botón esta vinculado con una sucursal. Al yo darle clic a cada botón existe una barra lateral que cambia mostrando un listado de todos los articulos disponibles en dicha sucursal. Hasta el momento seria algo así...


Aún no me pongo a programarlo pero intuyo que el primer acierto que podría hacer es crear una vista-controlador para cada articulo que se muestra en la barra lateral debido a que el numero de articulos que se muestra van a ser variables con respecto al contenido de cada sucursal pero mi pregunta es.. Si yo agregara un botón de eliminar dentro de estos contenedores que representan un articulo como le haría para borrar tanto intermanete el objeto Articulo de mi "Libro articulos"(Se encuentra en el controlador de la escena principal o sea la anterior)como refrescar la vista. Puntualizando mas mi duda... Entendiendo que yo ya hice una clase vista-controlador para representar un articulo entonces esta clase seria una archivo FXML con sus label ,etc,etc.. y un boton que dice "Eliminar" . Lo que se me viene a la mente es que le agregaría en su controlador un atributo de objeto "ARTICULO" que me representaría el objeto que esta mostrando pero como le hago para al detectar el evento clic en el boton "Elimiar" este se regrese a la escena principal, la que contiene objetos como "Libro de Articulos de sucursal tal... " y lo elimine.  Se me ocurrio que podria solucionar el problema pasando el objeto "Libro de Articulos de sucursal tal... " a cada Escena que representa un articulo y que dentro de la misma escena se borre el articulo de dicho libro pero necesito regresar otra escena mas para refrescar la eliminacion de forma visual. De una forma mas explicita si yo me encuentro dentro de un botón que esta contenido en una escena como le hago para llegar desde ese boton hacia la escena de su escena y obtener finalmente el controlador de dicha escena que es donde tengo mis objetos como "Libro de Articulos de sucursal tal... " y que es desde donde debo hacer unos cambios cuando se genera un evento en el boton.

Seria algo como .....
Código
  1. btnEvento.getScene().getScene().getController();
  2.  

A este controller le haria cast al controlador que yo habia definido para poder acceder a los atributos que yo lo agregue... Lastima que ya he comprobado que no es tan facil como eso.

De antemano gracias por su tiempo.

ACTUALIZACION.
Encontre una posible solución dada para el ejemplo planteado.

Esto es cuando se carga la escena principal en la ventana.
Código
  1. FXMLLoader loader = new FXMLLoader(getClass().getResource("VentanaPrincipal.fxml"));
  2.        TabPane root =  loader.load();
  3.        Scene scene = new Scene(root);
  4.        scene.setUserData(loader);
  5.        stage.setScene(scene);..........
  6. ........
  7.  


Cuando se recolecta el controlador de la escena de la escena que en este caso no es mas que escena de la ventana.
Código
  1. FXMLLoader loader = (FXMLLoader) btn.getScene().getWindow().getScene().getUserData();
  2.            VentanaPrincipalController controller = (VentanaPrincipalController)loader.getController();
  3.  

Ahora una pregunta un como mas enfocada.. ¿ Generalmente se hace de una manera similar la transferencia de datos en aplicaciones graficas ?, ¿Se le suele dar este uso al metodo setUserData y getUserData ? o ¿Cual es su principal finalidad?
4  Programación / Programación C/C++ / Eliminación de nodos en un árbol binario ordenado. en: 5 Abril 2019, 18:52 pm
Ya he dado con la solución de las operaciones básicas del árbol sin embargo me queda la duda dentro de la operación de eliminación. Durante la operación de eliminación tenemos primeramente dos casos.
1. El nodo ha eliminar es la raíz del árbol.
2. El nodo ha eliminar no es la raíz del árbol.

Independientemente cual sea el caso de los anteriores tenemos las siguientes posibilidades:
1. El nodo ha eliminar no tiene hijos. La eliminación implica simplemente eliminar la referencia de su padre que apuntaba hacia el y liberar memoria.
2. El nodo tiene un único hijo o rama. La eliminación implica que la referencia que tenia el padre hacia el nodo que se va eliminar sea reasignada ahora hacia la rama del nodo que se va eliminar.
3. El nodo tiene las dos ramas. Es aquí donde me surge la duda!!... En mi implementación lo que hice fue buscar el nodo mayor de los menores de las rama que tiene el nodo que se va eliminar, una vez localizado ese era mi candidato que ocuparía el lugar del nodo eliminado por lo tanto para este punto lo que hacia era:
   1. Remplazar el nodo a eliminar por aquel nodo que era el mayor de los menores haciendo ajustes como que el padre de este nodo ahora apunte a todo el subárbol que puede que existiría del lado izquierdo del nodo que vamos a usar como remplazo al eliminado.

Hasta este paso creo que estar bien... Mi incógnita queda en que he visto que algunos dan mas seguimiento al caso de que el nodo a eliminar tenga las dos ramas , es decir, primero hacen lo que yo hago... que es buscar la hoja o nodo que es el mayor de los menores del nodo a eliminar,posterior a eso veo que si ese nodo auxiliar o de remplazo tiene su rama izquierda hacen otra comprobación pero ahora por parte del nodo menor de los mayores del nodo a eliminar, es decir, vuelven a hacer lo mismo que yo hice pero ahora con el nodo menor de los mayores. Una vez comprobado esto pueden tener que:
   1.El nodo menor de los mayores resulta no tener la rama de la derecha por lo cual es un mejor candidato a ser el remplazo del nodo a eliminar.
   2.El nodo menor de los mayores tiene la rama derecha por lo cual hasta este punto tiene el mismo beneficio que el nodo mayor de los menores sin embargo aquí es cuando veo que hacen una segundo cuestionamiento y es ¿ Qué rama tiene menos niveles ?, hacen un conteo de los niveles en caso de que no hayan recorrido antes y finalmente determinan cual es el mejor candidato.

Mi duda es ¿ Realmente vale la pena realizar todo este proceso?, es decir, a mi forma de verlo yo solo modificaría a mi implementación el hecho de que si el candidato del lado izquierdo que es el mayor de los menores del nodo a eliminar tiene alguna rama solo verificaría si el candidato 2 o el candidato menor de los mayores no tiene la rama derecha , en ese caso eligiria el candidato de la derecha( el menor de los mayores ) pero en el caso de que este también tuviera su rama.. directamente pondría a hacer el proceso de poner como remplazo al nodo candidato de la izquierda(mayor de los menores) sin importarme cual es que menor nivel tiene por que yo solo estaría viendo si sus ramas son distintas de null para comprobar si tienen ramas  y en caso de que quisiera hacer toda la comparación con los niveles debería recorrer ambas ramas y creo que los beneficios que me podría traer esa segunda verificación podrían ser equivalente a su desventaja.

Me gustaría saber como han hecho las implementaciones en esta parte y si consideran que valga la pena llegar hasta ese detalle de comparar los niveles de las ramas.
5  Programación / Bases de Datos / Algún uso de Statement frente a PreparedStatement en: 31 Marzo 2019, 20:22 pm
Estoy manejando una base de datos relacional a través de mysql en el lenguaje Java y he notado que el curso que sigo nunca se ha utilizado Statement y en vez de ello siempre usa PreparedStatement para estructurar y ejecutar las consultas. He investigado un poco y he visto que PreparedStatement presenta algunas optimizaciones debido a que 'prepara' la sentencia con anticipación y que ademas de eso evita inyección de SQL si se usan son métodos setString... etc para rellenar los valores de la consulta.

Mi pregunta es ¿ Existe algún uso para Statement ? o siempre va ser mejor optar por PreparedStatement.
6  Programación / Desarrollo Web / Objeto history y sus métodos. en: 28 Marzo 2019, 01:26 am
Hola a todos, estoy empezando a curiosear con los métodos del objeto history que forma parte del objeto window dentro del DOM y tenía la curiosidad de en que casos puede ser útil. Creo que entender que el objeto history junto con sus métodos son rutiles cuando se necesitan crear varios estados de una pagina html , es decir, cuando quiero mi pagina de registro cree un estado cada vez que hace focus a una entrada distinta del formulario de esta manera si el usuario da para atrás conseguirá que no se salga de esa pagina html si no que se vaya al estado anterior que simplemente sera la misma pagina pero antes de que hiciera focus a la entrada actual, es un ejemplo poco útil pero ¿ esta bien mi forma de pensarlo ?, a partir de eso he checado un ejemplo como este:

Código HTML
Código
  1. <!doctype html>
  2. <html lang="en">
  3.    <head>
  4.        <meta charset="utf-8">
  5.        <title>pushState and popstate</title>
  6.        <meta name="viewport" content="width=device-width,initial-scale=1">
  7.        <link rel="stylesheet" href="style.css">
  8.    </head>
  9.    <body>
  10.        <div class="boxes">
  11.            <div class="box" id="box-1">one</div>
  12.            <div class="box" id="box-2">two</div>
  13.            <div class="box" id="box-3">three</div>
  14.            <div class="box" id="box-4">four</div>
  15.        </div>
  16.        <script src="script.js"></script>
  17.    </body>
  18. </html>
  19.  

Código JS
Código
  1. let boxes = Array.from(document.getElementsByClassName('box'));
  2.  
  3. function selectBox (id) {
  4.    boxes.forEach(b => {
  5.        b.classList.toggle('selected', b.id === id);
  6.    });
  7. }
  8.  
  9. boxes.forEach(b => {
  10.    let id = b.id;
  11.    b.addEventListener('click', e => {
  12.        history.pushState({id}, `Selected: ${id}`, `./selected=${id}`)
  13.        selectBox(id);
  14.    });
  15. });
  16.  
  17. window.addEventListener('popstate', e => {
  18.    selectBox(e.state.id);
  19. });
  20.  
  21. history.replaceState({id: null}, 'Default state', './');
  22.  
  23.  
  24.  

Código CSS
Código
  1. .boxes {
  2.    display: flex;
  3. }
  4.  
  5. .box {
  6.    --box-color: black;
  7.    width: 200px;
  8.    height: 200px;
  9.    margin: 20px;
  10.    box-sizing: border-box;
  11.    display: block;
  12.    border-radius: 2px;
  13.    cursor: pointer;
  14.    color: white;
  15.    background-color: var(--box-color);
  16.    border: 5px solid var(--box-color);
  17.    font-size: 30px;
  18.    font-family: sans-serif;
  19.    font-weight: bold;
  20.    text-align: center;
  21.    line-height: 200px;
  22.    transition: all 0.2s ease-out;
  23. }
  24.  
  25. .box:hover {
  26.    background-color: transparent;
  27.    color: black;
  28. }
  29.  
  30. .box.selected {
  31.    transform: scale(1.2);
  32. }
  33.  
  34. #box-1 {
  35.    --box-color: red;
  36. }
  37.  
  38. #box-2 {
  39.    --box-color: green;
  40. }
  41.  
  42. #box-3 {
  43.    --box-color: blue;
  44. }
  45.  
  46. #box-4 {
  47.    --box-color: black;
  48. }
  49.  

El programa funciona bien en la navegación del historial hacia adelante y hacia atrás pero mi duda surge conforme a la actualización de la pagina, es decir, cuando yo actualizo la página me sale un error del método get pero desconozco si es posible hacer que esto no suceda y que simplemente se regrese al mismo estado de la página sin que salte ese error.
7  Programación / Java / Diferentes formas de manejar eventos en java. en: 25 Marzo 2019, 00:07 am
Buenas a todos , tenía la curiosidad sobre saber cual era su forma de organizar las clases destinadas a las interfaces gráficas y en especifico como administraban el objeto que respondía a los eventos.

Actualmente he visto 2 formas muy particulares de hacerlo y que las mostrare con un ejemplo sencillo que tiene 3 botones, cada botón hace referencia a un color y cuando se da clic en alguno de ellos simplemente el panel se pinta de dicho color.

1ra Forma. El panel al ser el objeto que va ser afectado por el evento es el que implementa la interfaz ActionListener.

Código
  1. import java.awt.*;
  2. import java.awt.Color;
  3. import java.awt.event.*;
  4. import javax.swing.*;
  5.  
  6. public class Manejo{
  7.    public static void main(String[] args) {
  8.        Ventana v1 = new Ventana(new Dimension(400,400));
  9.        v1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  10.    }
  11.  
  12.  
  13. }
  14.  
  15.  
  16. class Ventana extends JFrame{
  17.    Lamina l1;
  18.    public Ventana(Dimension d){
  19.        setSize(d);
  20.        l1 = new Lamina();
  21.        add(l1);
  22.        setVisible(true);
  23.    }
  24.  
  25.  
  26. }
  27.  
  28. class Lamina extends JPanel implements ActionListener{
  29.    private JButton verde;
  30.    private JButton azul;
  31.    private JButton amarillo;
  32.    private Color fondo;
  33.  
  34.    public Lamina(){
  35.        verde = new JButton("Color verde");
  36.        azul = new JButton("Color azul");
  37.        amarillo = new JButton("Color amarillo");
  38.  
  39.        verde.addActionListener(this);
  40.        azul.addActionListener(this);
  41.        amarillo.addActionListener(this);
  42.        add(verde);
  43.        add(azul);
  44.        add(amarillo);
  45.    }
  46.  
  47.    @Override
  48.    public void actionPerformed(ActionEvent e){
  49.        Object fuente = e.getSource();
  50.  
  51.        if(fuente  == verde){
  52.            fondo = Color.GREEN;
  53.            setBackground(fondo);
  54.  
  55.        }else if( fuente == azul){
  56.            fondo = Color.BLUE;
  57.            setBackground(fondo);
  58.  
  59.        }else{
  60.            fondo = Color.YELLOW;
  61.            setBackground(fondo);
  62.  
  63.        }
  64.    }
  65.  
  66. }

2da Forma. Se crea una clase anidada que controla el evento e implementa la interfaz actionListener .

Código
  1. import java.awt.*;
  2. import java.awt.Color;
  3. import java.awt.event.*;
  4. import javax.swing.*;
  5.  
  6. public class Manejo{
  7.    public static void main(String[] args) {
  8.        Ventana v1 = new Ventana(new Dimension(400,400));
  9.        v1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  10.    }  
  11. }
  12.  
  13.  
  14. class Ventana extends JFrame{
  15.    Lamina l1;
  16.    public Ventana(Dimension d){
  17.        setSize(d);
  18.        l1 = new Lamina();
  19.        add(l1);
  20.        setVisible(true);
  21.    }
  22.  
  23.  
  24. }
  25.  
  26. class Lamina extends JPanel {
  27.    private JButton verde;
  28.    private JButton azul;
  29.    private JButton amarillo;
  30.    private Color fondo;
  31.  
  32.    public Lamina(){
  33.        verde = new JButton("Color verde");
  34.        azul = new JButton("Color azul");
  35.        amarillo = new JButton("Color amarillo");
  36.  
  37.        verde.addActionListener(new ColorFondo(Color.GREEN));
  38.        azul.addActionListener(new ColorFondo(Color.BLUE));
  39.        amarillo.addActionListener(new ColorFondo(Color.YELLOW));
  40.  
  41.        add(verde);
  42.        add(azul);
  43.        add(amarillo);
  44.    }
  45.  
  46.  
  47.    private class ColorFondo implements ActionListener{
  48.        private Color c;
  49.  
  50.        public ColorFondo(Color c){
  51.            this.c = c;
  52.        }
  53.  
  54.        @Override
  55.        public void actionPerformed(ActionEvent e){
  56.            setBackground(c);
  57.        }
  58.  
  59.    }
  60.  
  61. }
  62.  


A partir de las anteriores formas de dar solución al problema me causa la incógnita el saber cual podría ser la mejor forma de hacerlo, personalmente no encuentro mucha diferencia para inclinarme hacia un lado pero me gustaría saber si alguien pudiera compartir su experiencia y explicar cual prefiere y la razón del por que.


8  Programación / Programación C/C++ / Contenedores estandar en C++ en: 7 Marzo 2019, 05:29 am
Buenas a todos,estaba comenzando a ver las especificaciones que tienen los contenedores estandar en c++ tales como deque,queue,stacks y me tope con que el autor menciona incialmente como esta implementado el contenedor deque en c++,mencionando que realmente no seria una implementación del todo adecuada a un estructura 'deque' debido a que en el fondo contiene un vector map que permite la interfaz de una pila doble. A partir de lo anterior menciona que el contenenedor 'stack' es realmente un contenedor que puede tener en su interior otro contenedor como list,queue o vector y que realmente stack lo único que proporciona es una interfaz que simula una pila pero que realmente tiene otro contenedor dentro de el. Finalmente menciona que el contenedor 'queue' realmente contiene un contenedor 'deque' con el cual finalmente interactua para proporcionar un contenedor que se comporte como una cola.

Con respecto a lo anterior me surge la incognita de si esto succede en la mayoria de los lenguajes, realmente no logro visualizar que tan buena pueda ser la desicion de componer a los contenedores de esta forma pero me crea la duda debido a que anteriormente yo visualizaba a estas clases como la tipica lista ligada o vector que interactuaba como una cola con un cierto numero de nodos,etc. Mas que poner en duda sobre la buena/mala implementacion de dichos contenedores me gustaria simplemente saber que tan habitual o comun es toparte con lenguajes que tengan una implementacion parecida.
9  Programación / Programación General / Inicios de inteligencia artificial. en: 6 Marzo 2019, 06:22 am
Buenas a todos, quisiera saber si saben sobre algun curso/libro que de inicio al área de inteligencia artificial. Actualmente tengo conocimientos en materias como calculo integral/diferencial,algebra,logica matematica... etc y quisiera empezar a enfocar mis conocimientos en un área de mi interés antes de que empiece a olvidar algunas temas sobre ellas.

De antemano,gracias.
10  Programación / Programación C/C++ / Preservacion del contenido de la memoria en contra de tiempo de vida de variable en: 5 Marzo 2019, 04:11 am
Buenas a todos, teniendo en cuenta el siguiente programa:

Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4. int *ptr;
  5.  
  6. void h(){
  7.     int a = 333;
  8.     ptr = &a;
  9.     cout << "Direccion de memoria" << ptr << endl;
  10. }
  11.  
  12.  
  13. int main(){
  14.  
  15.     h();
  16.     cout << *ptr << endl;
  17. }
  18.  

A través del programa anterior tengo un puntero global, este puntero lo hago que apunte a una variable y simplemente despues verifico que realmente si apunte a ella. Mi pregunta es... la variable 'a' que esta declarada en la función 'h' a la cual hago que apunte ptr dentro de la función tiene un tiempo de vida que se ve limitada por las llaves de la función, cuando yo regreso al main el tiempo de vida de la variable 'a' ha terminado sin embargo el espacio de memoria donde estaba contenido y que ahora es apuntado por el puntero ¿sigue estando reservado?, es decir, ¿ese espacio de memoria sigue siendo considerado como ocupado por una variable? o fue liberado al mismo tiempo que termino el tiempo de vida de la variable 'a'. Tengo la incertidumbre de si ese pedazo de memoria regreso al conjunto de la memoria disponible pero sin embargo sigue teniendo los valores que anteriormente fueron utilizados para representar a la variable 'a' y que pueda ser posible que por ahora el apuntador me siga mostrando ese valor pero sin embargo conforme vaya avanzando un programa y se reserve memoria etc... Ese segmento de memoria pueda llegar a ser sobrescrito por un nuevo valor de una variable .
Páginas: [1]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines