Buscar este blog

Mostrando las entradas con la etiqueta Programacion. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Programacion. Mostrar todas las entradas

lunes, 16 de junio de 2014

Separar la capa de dominio de un EDMX

Introducción

Entity Framework (EF) es un asignador objeto-relacional que permite a los desarrolladores de .NET trabajar con datos relacionales usando objetos específicos del dominio. Elimina la necesidad de la mayor parte del código de acceso a datos que los desarrolladores suelen tener que escribir.
Para empezar debemos definir si vamos a crear una nueva base de datos o si vamos a usar una existente, y definir si queremos usar solo código o utilizar un diseñador.
Lo anterior nos proporciona tres puntos de partida posibles:
  • Code First: Definir el modelo en el código y después generar una base de datos, o sino, crear un código basado en el modelo que se asigna a una base de datos existente
  • Model First: Para definir el modelo con cuadros y líneas y después generar una base de datos
  • Database First: Para crear un modelo de cuadros y líneas que se asigna a una base de datos existente
Tanto Model First como Database First usan Entity Framework Designer. El modelo se almacena en un archivo EDMX (extensión .edmx) y se puede ver y editar en Entity Framework Designer. Las clases con las que interactúa en la aplicación se generan automáticamente a partir del archivo EDMX en base a Plantillas T4 vinculadas al archivo EDMX
El problema radica en el fuerte acoplamiento de las clases generadas del modelo y Entity Framework, haciendo imposible tener una capa exclusiva para el dominio, y otra para la persistencia.
En este artículo demostraremos que si es posible hacerlo, simplemente trasladando la Plantilla T4 de las clases al proyecto adecuado
Para tal fin empezaremos con el el enfoque Model First, ya que la idea es tener un archivo EDMX, y se aplicaría también para Database First

Definiendo Proyectos

Empezaremos creando la estructura de proyectos:
  • Dominio: Ejemplo.Dominio
  • Acceso a Datos: Ejemplo.Dal
  • Presentación: Ejemplo.WinForms

Definiendo el Modelo

En el proyecto "Ejemplo.Dal", crearemos el modelo
Definimos un modelo muy básico, basado en los códigos de ubicación geográfica del Perú

Generando Base de Datos

En este punto ya es posible generar nuestra base de datos, así que vamos a hacerlo de una buena vez.
Hacemos click en nueva conexión, para generar nuestra nueva base de datos, si la conexión ya existiese, pues la eligen, y se sobreescribirá con los cambios al modelo, Ojo!! que si sobreescriben el modelo, también pierden los datos de las tablas modificadas.
Configuramos la conexion como se muestra en la siguiente imagen:
Nos aparecerá un mensaje de que la base de datos no existe y si deseamos crearla, le decimos que si, y listo.

Ahora le damos en siguiente, y si te pregunta, que Entity Framework quieres usar, escoge la que se adecue a tus necesidades, para mi caso escogeré la versión 6
Ya tenemos el Script de actualización/creación de la base de datos
Le damos en finalizar, y nos abrirá una ventana de consulta SQL, la misma que debemos ejecutarla, presionando el botón que resalto a continuación:


Separando Clases POCO del EDMX

Bien, ahora ya podemos hacer uso de nuestra base de datos, operaciones CRUD, Extensión de clases a través de las clases parciales, pero el problema radica, como se menciono anteriormente, en que los archivos de las clases están "Confinados" a estar junto al archivo EDMX, como lo vemos? pues mostrando todos los archivos:
Como se aprecia, de Modelo.edmx, cuelgan varias plantillas T4, una de ellas es Modelo.tt, de Modelo.tt cuelgan todas nuestras clases!! Esto hace que estas clases estén condenadas, según este esquema, a quedarse pegadas al edmx, y para poder usarlas necesariamente tendríamos que cargar con la mochila de Entity Framework, pero ahora viene el punto interesante de este artículo.
Vamos a copiar Modelo.tt al proyecto Ejemplo.Dominio, para eso agregamos una nueva plantilla a nuestra capa de dominio, y la llamamos Modelo.tt
Y reemplazamos su contenido por el del Modelo.tt que esta en la capa Dal.
Las plantillas T4 se ejecutan automáticamente al guardarlas, así es que cuando guarden esta nueva plantilla, tendrán un bonito mensaje de error como este:
Que paso?, pues simplemente, el contenido de la plantilla T4 sigue suponiendo que su EDMX se llama Modelo.EDMX y esta en la misma carpeta, pues entonces vamos a redireccionarlo.
Pensando un poquito, de acuerdo a la estructura de los proyectos, si tenia "Modelo.edmx" y necesito que suba una carpeta y luego vaya a "Ejemplo.dal", la ruta seria "..\Ejemplo.Dal\Modelo.edmx".
Y si guardamos ahora la plantilla, ya no debería salir ningún error, prueba de esto es que si mostramos todos los archivos en nuestra capa de dominio, veremos todas las clases de nuestro modelo
El trabajo estaría casi listo, pero como sabemos, la capa de persistencia debe tener la referencia a la capa de dominio, entonces se la agregamos

Ahora debemos de eliminar Modelo.tt de la capa de persistencia, simplemente click derecho y eliminar.
En este momento debería aparecer una serie de errores como estos:

Esto ocurre simplemente porque en la plantilla que genera el archivo Modelo.Context.vb falta agregar el import respectivo a la capa de dominio, entonces pasemos a "reparar" Modelo.Context.tt

Como ven, simplemente le agregue el import a Ejemplo.Dominio, y si guardan la plantilla dejaran de recibir esos errores
Ahora, la capa de Presentación debe tener referencia a la de dominio, entonces agregamos la de dominio a la de presentación

Claro esta, que entre la capa de dominio y la de presentación pueden y deben haber mas capas; del mismo modo, entre la capa de dominio y la de persistencia de datos, pueden y deben haber mas capas; por ejemplo si te decantas por DDD
Con lo visto hasta aquí, la capa de dominio ha quedado libre de cualquier referencia a entity framework, y esta apta para ser ampliada mediante clases parciales y usada en cualquier capa de toda la arquitectura escogida.
Espero les sea de ayuda en algún proyecto, y para la próxima entrega, implementaremos una capa de servicios para consumir datos desde la capa de persistencia.






Visual Basic .NET: Conectarse a una tabla o base de datos VFP (DBF)

Muchas veces se ha presentado la necesidad de conectarse a fuentes de datos como las de VFP, en esta oportunidad lo haremos usando Visual Basic .NET.
Para tal fin nos hicimos con una copia del archivo de centros poblados del Perú, son alrededor de 18700 registros.
Bueno, empecemos creando un nuevo proyecto de consola y lo llamaremos ConectarseDBF

Ahora, por comodidad, agregamos una carpeta "Datos" al proyecto y copiamos el archivo de centros poblados "CCPP.dbf" a dicha carpeta, estableciendo en las propiedades "Copiar si es posterior"
Y ponemos el siguiente código:
Imports System.IO
Imports System.Data.Common

Module Module1

    Sub Main()
        Dim sConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
            Path.Combine(My.Application.Info.DirectoryPath, "Datos") &
            ";Extended Properties=dBASE IV;"

        Using dbConn As New System.Data.OleDb.OleDbConnection(sConn)
            dbConn.Open()
            Dim comando = dbConn.CreateCommand
            comando.CommandText = "Select * from ccpp"
            Dim da As New OleDb.OleDbDataAdapter(comando)
            Dim dt As New DataTable
            da.Fill(dt)
            Mostrar(dt.Rows)
            dbConn.Close()
        End Using
    End Sub

    Private Sub Mostrar(filas As DataRowCollection)
        Console.WriteLine(Format("Hay {0} Registros", filas.Count))
        Console.WriteLine("Mostrando los 10 primeros")
        For i = 0 To 9
            For Each columna In filas(i).ItemArray
                Console.Write(columna & vbTab)
            Next
        Next
        Console.ReadKey()
    End Sub

End Module
Ejecutamos y nos sale:

domingo, 22 de marzo de 2009

Cajero en JavaScript

Función Separa

Monto:

Esta funcion se encarga de dividir un monto dado en billetes de distintas denominaciones, las denominaciones las podemos pasar como un array, y en base a éste la función empezara a repartirlos si es posible.
Se pueden agregar la cantidad de denominaciones que se crea conveniente y priorizará conservar el "censillo", esto es, primero tratará de cubrir el monto con las denominaciones en los indices inferiores de la matriz de denominaciones.
Se pudo hacer con un doble array, o un array multidimencional, pero preferi hacerlo usando el "prototype" de los array en JavaScript, dotandole a cada item del array de propiedades, como es el caso de este, que le agregue las propiedades de "Denominacion" y "Cantidad"
function billete(denominacion,cantidad){
 this.denominacion=denominacion
 this.cantidad=cantidad
}
Como se aprecia, he creado una pseudo funcion, que me servira para pasarle este prototipo a los items del array que voy a necesitar.
La funcion "Separar" es recursiva, y requiere que se le pase como argumentos, el monto del que se va a dividir, la matriz o array que tenga el prototipo billete implementado anteriormente llenado con las denominaciones que se quiere analizar ordenadas por orden de importancia, luego explicaré a que me refiero con esto, como ultimo argumento se le debe pasar en que indice va empezar a trabajar, para el inicio se le debe de pasar -1, y se calculara automaticamente de donde debe de empezar basado en el tamaño del array, aqui el codigo:
function Separa(monto,billetes,inicio){
 if(inicio==-1){
  inicio=billetes.length-1
  if(monto%10>0)return monto
 }
 billetes[inicio].cantidad=parseInt(monto/billetes[inicio].denominacion)
 residuo=monto%billetes[inicio].denominacion
 while(residuo>0){
  ninicio=inicio
  ninicio--
  if(inicio>1){residuo=Separa(residuo,billetes,ninicio)} 
  if(residuo>0 && billetes[inicio].cantidad==0){break} 
  if(residuo>0 && billetes[inicio].cantidad>0){
   billetes[inicio].cantidad--
   residuo=monto-billetes[inicio].denominacion*billetes[inicio].cantidad
  }
 }
 return residuo
}
Lo que esta en la linea 4, es un control para que no necesite evaluar aquellos montos que de antemano no van a poder ser divididos, este valor debera ser el maximo comun divisor de todas las denominaciones, por motivos de simplicidad evite hacer este cálculo, ya que por el momento sólo estaremos teniendo denominaciones mayores a 20, tales como 20, 50, 100 y 200 soles, como se ve, 10 es el MCD de todas las denominaciones, entonces, 10 debemos de reemplazarlo con el MCD de todas las denominaciones existentes en el array. Esto tratare de hacerlo en otro post.
Como se aprecia, las lineas del 2 al 5 son para el escenario del inicio del calculo, aqui por ejemplo asigno a la variable "inicio" el valor del tamaño de la matriz billetes que vino como parametro, ademas como dije, controlar si de antemano no se va a poder hacer la repartición
Como se supone que la matriz billetes tiene el prototipo billete, entonces asumo que cada indice de la matriz tiene las propiedades Cantidad y Denominacion, e spor eso que las uso directamente.
Ahora, cómo uso esta funcion?
Primero necesitamos inicializar y asignar el prototipo billete a la matriz de denominaciones que vamos a usar
 
 billetes=new Array(4)
 billetes[1]=new billete(20,0)
 billetes[2]=new billete(50,0)
 billetes[3]=new billete(100,0)
 billetes[4]=new billete(200,0)
En la linea 1 creo el array y le doy el tamaño, mientras que en las lineas de la 2 a la 5 voy creando los items y asignandoles el prototipo que he creado, y poniendole las denominaciones, tener en cuenta que el orden en las que se pondran sera como priorizara para hacer las diviciones, cabe destacar que podemos usar las denominaciones que creamos conveniete.
Ahora necitaremos de una pequeña interface para el ingreso del monto y un botoncito para empezar el cálculo
Como se aprecia, el boton tiene asociada una llamada a una funcion "Calcula" en el evento onClick, entonces definamos esa funcion:
function Calcula(){
 for(i=1;i&ltbilletes.length;i++){billetes[i].cantidad=0} 
 monto=document.getElementById("txtMonto").value
 if(Separa(monto,billetes,-1)>0){
     document.getElementById("txtResultado").value = "No es posible descomponer S/."+monto+" en billetes de S/.200, S/.100, S/.50 o S/.20"
 }else{
  cadena="Solución:"
  for(i=1;i&ltbilletes.length;i++){
   (billetes[i].cantidad>0) ? cadena += "\n  Billetes de S/."+billetes[i].denominacion+"\t: "+billetes[i].cantidad : cadena +=""
  }
  document.getElementById("txtResultado").value = cadena;
 }
}
En la linea 2 hago la limpieza de las cantidades de mi array, ya que es posible que llamemos varias veces a la funcin, y podria quedarse "pegado" algun valor de la operación anterior, luego leo la cantidad de la caja de texto y en la linea 4 evaluo si mi funcion separa me devuelve algun residuo, si es asi, pues no se podra, y si es cero recorro todos los items de mi matriz billetes y voy viendo si tienen o no cantidades, y claro voy asiganadole a la varaible "cadena" los valores convenientes, y asi se genra adecuadamente la solucion.
El resultado de todo esto se encuentra arriba.

martes, 9 de diciembre de 2008

Pelotita en JavaFX

Aqui otro ejemplo, se trata de una pelotita que va rebotando, tanto en el piso, como en las paredes. en el caso del movimiento en y, la "gravedad" reduce su velocidad o aumenta, y se le puso un efecto para que "lata", cambiando su radio en cada iteracion
/*
 * Main.fx
 *
 * Created on 08/12/2008, 11:23:36 PM
 */

package rebotes;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.effect.*;

/**
 * @author GaSK
 */

var pelota : pelota[]=[pelota{}];

var timeline : Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: KeyFrame {
        time: 1ms
        canSkip: true
        action: function() {
            update();
        }
    }
};

function update() : Void {
    pelota[0].update();
}

Stage {
    scene: Scene {
        width: 400
        height: 400
        fill: Color.BLACK
        content: bind pelota
    }
    title: "Pelotita"
}

timeline.play();

class pelota extends CustomNode {
    var x : Number;
    var y : Number;
    var cx : Number;
    var cy : Number;
    var ccy : Number;
    var radio: Number;
    var cradio:Number;
    override function create(): Node {
        radio=25;
        cx=1;
        cy=1;
        cradio=1;
        x=radio;
        y=radio;
        return Group {
            content: [
                Circle {
                    centerX: bind x, 
                    centerY: bind y
                    radius: bind radio
                    fill: Color.WHITE
                    effect: bind InnerShadow{radius:radio*0.8}
                },
            ]

        };
    }
    function update(): Void {
        x += cx;
        if (x+radio>400){
            cx *= -1;
            x=-radio+400;
        }
        if ((x400){
            y=400-radio;
            cy *= -0.8;
            if((cy<0)and(cy>-2)){
                cy = -(400+radio)/50;
            }
        }
        radio+=cradio;
        if((radio>26)or(radio<25)){
            cradio*=-1;
        }
    }
}

lunes, 8 de diciembre de 2008

Ejemplo Animacion en JavaFX

Aqui un pequeño ejemplo de animacion en javaFX, se trata de un circulo que recorre la ventana.
package mov1;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.ext.swing.SwingSlider;
import javafx.scene.transform.Translate;

class bola extends CustomNode {
  public var CX:Number;
  public var CY:Number;
  public var V:Number=100;
  public override function create(): Node {
    return Group {
      content: [
        Circle {
          centerX: bind CX,
          centerY: bind CY
          radius: 50
          fill: Color.BLACK
        }
      ]
    };
  }

  init{
    var timeline=Timeline {
      repeatCount: Timeline.INDEFINITE
      keyFrames : [
        KeyFrame {time: 0s values:[CX => 50 CY => 50]}
        KeyFrame {time: 2s values:[CX => 50 CY => 450 tween Interpolator.LINEAR]}
        KeyFrame {time: 4s values:[CX => 450 CY => 450 tween Interpolator.LINEAR]}
        KeyFrame {time: 6s values:[CX => 450 CY => 50 tween Interpolator.LINEAR]}
        KeyFrame {time: 8s values:[CX => 50 CY => 50 tween Interpolator.LINEAR]}
      ]
    }
    timeline.play();
  }
}

Stage {
  title: "MyApp"
  onClose: function(){
    java.lang.System.exit(0);
  }
  scene: Scene {
  width: 500
  height: 500
  content: [bola{}]
  }
}

sábado, 6 de diciembre de 2008

Tarjeta de Navidad en javaFX

cambio la version de javaFX y tuve que hacerle modificaciones para que sea compatible con la nueva version, aqui su codigo:
package Munieco;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.*;
import javafx.scene.shape.Polygon;
import javafx.scene.paint.Color;
import javafx.scene.effect.*;
import javafx.scene.shape.*;
import javafx.scene.effect.light.*;
import javafx.scene.transform.Transform.*;
import javafx.scene.transform.Rotate;
/**
* @author GaSK
*/
Stage {
title: "Tarjeta de Navidad"
width: 1024
height: 768
scene: Scene {
fill: Color.rgb(89, 117, 154)
content: [
Polygon {//nubes
fill: Color.WHITE
smooth: true
points: [
560, 282, 593, 271, 629, 282, 609, 269, 617, 255, 579, 239,
569, 211, 697, 226, 678, 193, 630, 182, 724, 181, 833, 129,
754, 128, 684, 185, 660, 166, 556, 175, 561, 186, 628, 173,
584, 188, 600, 199, 576, 211, 537, 187, 544, 168, 481, 175,
431, 209, 374, 205, 434, 189, 436, 165, 466, 158, 707, 145,
645, 133, 443, 148, 399, 165, 433, 166, 432, 184, 382, 197,
406, 182, 384, 171, 470, 129, 681, 116, 681, 99, 646, 93,
624, 89, 641, 68, 671, 66, 716, 77, 699, 85, 731, 117,
757, 103, 838, 103, 853, 125, 830, 154, 856, 171, 895, 166,
940, 206, 924, 233, 984, 220, 906, 151, 846, 136, 854, 125,
945, 142, 999, 128, 915, 110, 984, 101, 966, 91, 927, 84,
838, 103, 774, 87, 721, 107, 713, 94, 756, 82, 828, 88,
810, 74, 718, 82, 737, 66, 832, 57, 794, 38, 840, 13,
795, 0, 666, 5, 652, 19, 541, 0, 459, 42, 457, 19,
438, 15, 451, 10, 385, 19, 435, 16, 408, 35, 351, 13,
340, 18, 369, 27, 383, 56, 370, 83, 282, 11, 236, 4,
212, 34, 123, 28, 93, 4, 61, 13, 67, 1, 39, 0,
8, 10, 5, 32, 103, 16, 123, 34, 171, 30, 166, 45,
204, 34, 177, 94, 210, 89, 220, 122, 247, 132, 283, 115,
356, 121, 417, 87, 533, 67, 483, 49, 545, 63, 544, 46,
495, 37, 551, 25, 539, 30, 579, 50, 556, 81, 483, 85,
306, 151, 286, 136, 301, 155, 277, 187, 220, 177, 243, 191,
230, 221, 146, 214, 233, 241, 250, 229, 254, 241, 278, 217,
251, 198, 271, 198, 303, 159, 421, 121, 539, 109, 559, 82,
648, 96, 408, 136, 377, 167, 346, 173, 381, 197, 323, 179,
390, 215, 484, 208, 461, 194, 487, 176, 527, 189, 509, 196,
571, 219, 578, 239, 542, 234, 593, 252
]
effect: GaussianBlur{
radius: 55
}
},
Polygon {//nieve fondo1
points : [
0, 768, 1024, 768, 1024, 416, 1007, 403, 1000, 401, 991, 400,
979, 403, 959, 410, 940, 421, 926, 426, 906, 429, 890, 422,
871, 411, 844, 400, 730, 407, 681, 406, 667, 405, 656, 403,
637, 410, 614, 411, 584, 405, 537, 408, 500, 410, 453, 423,
437, 436, 412, 439, 396, 433, 383, 423, 362, 421, 350, 422,
340, 428, 325, 423, 300, 418, 282, 426, 259, 433, 235, 446,
214, 447, 196, 445, 172, 434, 152, 423, 124, 412, 106, 410,
81, 413, 68, 417, 43, 430, 23, 446, 0, 456
]
fill: Color.LIGHTGREY
smooth: true
effect: InnerShadow{offsetX: 0 offsetY: 0 radius: 30}
},
Polygon {//nieve fondo1
points : [
0, 768, 1024, 768, 1024, 416, 1007, 403, 1000, 401, 991, 400,
979, 403, 959, 410, 940, 421, 926, 426, 906, 429, 890, 422,
871, 411, 844, 400, 730, 407, 681, 406, 667, 405, 656, 403,
637, 410, 614, 411, 584, 405, 537, 408, 500, 410, 453, 423,
437, 436, 412, 439, 396, 433, 383, 423, 362, 421, 350, 422,
340, 428, 325, 423, 300, 418, 282, 426, 259, 433, 235, 446,
214, 447, 196, 445, 172, 434, 152, 423, 124, 412, 106, 410,
81, 413, 68, 417, 43, 430, 23, 446, 0, 456
]
fill: Color.LIGHTGREY
smooth: true
effect: InnerShadow{offsetX: 0 offsetY: 0 radius: 30}
},
Polygon {//detalle en nieve
points : [
86, 768, 998, 768, 981, 762, 979, 742, 989, 727, 989, 717,
895, 758, 970, 691, 1007, 668, 844, 711, 756, 761, 702, 765,
700, 758, 714, 744, 807, 682, 961, 628, 970, 616, 948, 602,
989, 574, 941, 583, 967, 502, 924, 567, 904, 584, 790, 604,
892, 545, 922, 480, 897, 498, 903, 462, 880, 512, 737, 635,
534, 767, 496, 763, 493, 750, 516, 718, 575, 677, 578, 665,
553, 653, 623, 620, 666, 580, 561, 630, 485, 634, 310, 672,
236, 700, 135, 752, 86, 767, 30, 749, 101, 728, 286, 650,
391, 627, 481, 597, 505, 585, 525, 583, 549, 563, 562, 581,
575, 574, 558, 556, 555, 543, 537, 548, 518, 573, 497, 582,
487, 593, 402, 602, 438, 588, 505, 570, 557, 513, 515, 541,
451, 557, 416, 564, 372, 569, 348, 571, 362, 558, 378, 536,
410, 499, 417, 479, 426, 464, 407, 467, 390, 463, 372, 473,
347, 499, 333, 522, 270, 574, 259, 576, 242, 577, 243, 567,
245, 559, 251, 534, 258, 509, 273, 478, 258, 495, 245, 511,
216, 568, 156, 620, 91, 648, 66, 667, 27, 749, 52, 611,
117, 572, 127, 572, 107, 607, 160, 580, 216, 568, 181, 575,
184, 556, 183, 534, 178, 513, 169, 497, 156, 478, 149, 468,
143, 504, 135, 547, 116, 571, 89, 578, 106, 557, 118, 511,
87, 534, 76, 530, 73, 516, 94, 471, 48, 531, 29, 572,
32, 600, 41, 610
]
fill:Color.WHITE
smooth: true
effect: GaussianBlur{ radius: 40 }
},
ShapeSubtract {//base muñeco
fill: Color.WHITE
a: Circle {centerX: 768 centerY: 514 radius: 117}
b: Polygon {
points : [
647, 660, 894, 657, 896, 540, 879, 554, 871, 565, 862, 570,
850, 577, 837, 582, 825, 587, 814, 587, 798, 586, 783, 584,
761, 582, 752, 581, 740, 581, 726, 582, 712, 583, 701, 579,
697, 576, 691, 572, 682, 567, 675, 564, 668, 560, 662, 552,
654, 548, 648, 547
]
}
effect: InnerShadow{radius: 10 offsetY:-5 color: Color.DARKGRAY}
smooth: true
},
Polygon {//nieve debajo de muñeco
points : [
789, 596, 852, 582, 865, 576, 871, 568, 880, 560, 880, 555,
875, 554, 868, 556, 857, 562, 849, 563, 841, 564, 833, 569,
823, 575, 808, 577, 789, 574, 777, 573, 761, 571, 750, 569,
739, 568, 724, 569, 713, 566, 697, 565, 687, 558, 681, 552,
674, 546, 660, 540, 658, 548, 662, 566, 681, 589, 719, 594,
]
fill:Color.WHITE
smooth: true
effect: GaussianBlur{ radius: 30 }
},
Polygon {//Sombras debajo de muñeco
points : [
814, 587, 825, 587, 837, 582, 850, 577, 862, 570, 871, 565,
879, 554, 885, 539, 885, 529, 883, 520, 880, 527, 878, 530,
876, 528, 873, 525, 871, 524, 869, 528, 868, 534, 864, 539,
861, 539, 856, 538, 853, 532, 848, 523, 842, 512, 842, 516,
845, 531, 844, 543, 839, 550, 830, 555, 822, 561, 816, 566,
803, 569, 796, 573, 782, 573, 764, 572, 759, 569, 751, 563,
745, 559, 730, 553, 717, 551, 704, 547, 693, 543, 684, 540,
673, 534, 667, 530, 663, 522, 658, 515, 654, 511, 653, 513,
653, 516, 653, 528, 655, 535, 662, 552, 668, 560, 675, 564,
682, 567, 691, 572, 697, 576, 701, 579, 712, 583, 726, 582,
740, 581, 752, 581, 761, 582, 783, 584, 798, 586
]
fill:Color.DARKGREY
smooth: true
effect: GaussianBlur{ radius: 50 }
},
Circle {//torax Muñeco
centerX: 770 centerY: 372 radius: 101.5 fill: Color.WHITE
smooth: true
effect: InnerShadow{radius:36.91 offsetY:-9.23 color: Color.DARKGRAY}
},
Polygon {//chalina1
points: [
737, 334, 745, 334, 754, 333, 765, 332, 772, 332, 778, 332,
787, 333, 798, 333, 812, 330, 822, 326, 833, 318, 840, 310,
843, 302, 843, 295, 842, 290, 840, 286, 837, 283, 832, 280,
727, 288, 731, 333
]
fill: Color.RED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//chalina2
points: [
722, 403, 726, 401, 731, 396, 739, 391, 739, 388, 739, 374,
739, 354, 737, 342, 738, 331, 738, 327, 736, 322, 735, 314,
734, 304, 724, 292, 713, 279, 707, 283, 703, 286, 700, 288,
696, 293, 693, 298, 692, 304, 693, 309, 696, 318, 699, 323,
702, 330, 703, 334, 703, 348, 703, 371, 703, 380, 702, 384,
700, 389, 702, 391, 708, 392, 712, 395, 716, 398
]
fill: Color.RED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Circle {//cabeza Muñeco
centerX: 768 centerY: 252 radius: 66 fill: Color.WHITE
fill: Color.WHITE
smooth: true
effect: InnerShadow{radius:24 offsetY:-6 color: Color.DARKGRAY}
},
Circle {//ojo izquierdo
centerX: 747.65 centerY: 254.79 radius: 8.44 fill: Color.BLACK
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 270}
contentInput: DropShadow{offsetY: 3 radius: 5}
}
},
Circle {//ojo derecho
centerX: 791.75 centerY: 255.42 radius: 8.44 fill: Color.BLACK
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 270}
contentInput: DropShadow{offsetY: 3 radius: 5}
}
},
Circle {//boton1
centerX: 771.74 centerY: 353.92 radius: 8.13 fill: Color.ORANGERED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 270}
contentInput: DropShadow{offsetY: 2 radius: 5}
}
},
Circle {//boton2
centerX: 771.42 centerY: 392.70 radius: 8.13 fill: Color.ORANGERED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 270}
contentInput: DropShadow{offsetY: 2 radius: 5}
}
},
Circle {//boton3
centerX: 771.74 centerY: 432.42 radius: 8.13 fill: Color.ORANGERED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 270}
contentInput: DropShadow{offsetY: 2 radius: 5}
}
},
Polygon {//Nariz
points: [
766, 313, 767, 312, 768, 305, 771, 296, 774, 287, 771, 286,
775, 286, 776, 283, 772, 282, 776, 282, 778, 277, 773, 276,
778, 276, 778, 275, 778, 271, 776, 268, 770, 267, 767, 268,
762, 270, 761, 275, 761, 276, 772, 277, 761, 277, 762, 283,
771, 283, 762, 284, 762, 289, 770, 289, 762, 290, 762, 296,
768, 296, 762, 296, 763, 303, 766, 304, 763, 304, 764, 310
]
fill: Color.ORANGERED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//brazo izquierdo
points: [
644, 362, 647, 361, 671, 343, 677, 340, 691, 334, 696, 329,
693, 326, 670, 337, 644, 355, 627, 341, 624, 339, 598, 336,
592, 323, 588, 321, 566, 322, 559, 326, 563, 330, 568, 328,
578, 328, 585, 330, 586, 337, 590, 341, 620, 343, 632, 352,
638, 359
]
fill: Color.BROWN
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//brazo iaquierdo
points: [
848, 336, 850, 336, 853, 334, 856, 332, 862, 328, 864, 326,
869, 324, 873, 322, 876, 321, 879, 321, 883, 322, 885, 324,
889, 325, 893, 326, 896, 326, 901, 327, 905, 328, 909, 328,
912, 329, 916, 329, 919, 329, 922, 330, 927, 330, 934, 330,
943, 330, 950, 332, 958, 331, 960, 328, 964, 324, 967, 321,
969, 318, 973, 314, 980, 310, 986, 308, 991, 305, 993, 304,
992, 301, 990, 300, 986, 300, 982, 302, 978, 305, 973, 307,
967, 312, 963, 315, 960, 319, 957, 322, 953, 324, 949, 324,
941, 324, 934, 325, 929, 324, 927, 322, 923, 321, 919, 321,
911, 321, 904, 320, 896, 320, 892, 319, 888, 317, 884, 315,
879, 313, 875, 313, 872, 314, 869, 316, 867, 318, 865, 318,
863, 319, 860, 321, 858, 322, 855, 325, 851, 328, 847, 331,
846, 333, 846, 334
]
fill: Color.BROWN
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//Gorro
points: [
825, 216, 818, 203, 813, 197, 812, 190, 812, 188, 816, 189,
818, 190, 826, 193, 839, 201, 838, 198, 837, 190, 835, 185,
833, 178, 829, 174, 823, 171, 816, 164, 812, 157, 805, 149,
788, 146, 768, 145, 757, 149, 748, 161, 736, 175, 723, 192,
716, 201, 710, 214
]
fill: Color.RED
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 225}
contentInput: DropShadow{}
}
},
Polygon {//sombras gorro
points: [
788, 198, 792, 197, 797, 194, 800, 194, 798, 189, 793, 185,
792, 184, 800, 179, 802, 184, 807, 186, 810, 190, 812, 188,
810, 186, 810, 185, 811, 185, 815, 187, 830, 193, 828, 191,
822, 187, 816, 184, 813, 184, 811, 185, 810, 185, 808, 183,
804, 178, 798, 175, 797, 175, 795, 167, 804, 166, 807, 165,
810, 166, 813, 170, 814, 174, 815, 179, 820, 181, 823, 179,
826, 179, 829, 178, 827, 176, 819, 172, 815, 169, 811, 164,
806, 160, 799, 157, 796, 155, 795, 155, 789, 154, 780, 153,
772, 153, 768, 153, 778, 157, 785, 158, 790, 161, 793, 165,
794, 167, 795, 167, 797, 175, 789, 173, 792, 174, 799, 178,
799, 179, 792, 184, 788, 183, 781, 181, 784, 185, 789, 188,
792, 190, 790, 194, 785, 196, 785, 197
]
fill: Color.DARKRED
smooth: true
effect: GaussianBlur{ radius: 10 }
},
Circle {//pimpollo gorro
centerX: 839.98 centerY: 201.13 radius: 11.04 fill: Color.WHITE
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 225 elevation: 67}
contentInput: GaussianBlur{ radius: 10 }
}
},
Polygon {//blonda gorro
points: [
789, 243, 791, 243, 792, 243, 793, 241, 796, 240, 798, 241,
802, 242, 804, 241, 807, 239, 811, 240, 812, 240, 815, 238,
817, 238, 818, 238, 822, 237, 823, 233, 827, 232, 828, 232,
829, 232, 831, 232, 832, 231, 832, 229, 834, 229, 836, 231,
836, 229, 834, 229, 834, 227, 834, 227, 837, 228, 839, 227,
837, 226, 836, 225, 834, 225, 833, 224, 834, 224, 837, 224,
836, 223, 835, 222, 833, 221, 836, 221, 838, 220, 836, 219,
834, 218, 833, 217, 832, 215, 831, 214, 831, 213, 830, 211,
828, 211, 827, 211, 826, 209, 823, 207, 820, 206, 818, 204,
816, 204, 814, 203, 813, 205, 812, 207, 810, 209, 809, 209,
808, 208, 806, 207, 805, 208, 803, 209, 802, 210, 801, 210,
798, 210, 796, 211, 794, 211, 792, 209, 789, 208, 787, 208,
784, 206, 783, 207, 781, 209, 781, 210, 779, 211, 777, 210,
775, 209, 773, 209, 772, 210, 771, 211, 769, 211, 765, 210,
764, 209, 762, 208, 759, 209, 755, 208, 752, 207, 751, 206,
750, 209, 748, 210, 742, 209, 741, 209, 739, 207, 736, 206,
734, 207, 734, 207, 732, 207, 732, 206, 730, 206, 728, 205,
728, 204, 723, 205, 721, 205, 720, 204, 718, 203, 715, 203,
715, 203, 714, 202, 713, 201, 710, 201, 708, 202, 707, 205,
706, 206, 705, 207, 708, 208, 706, 208, 705, 208, 705, 210,
705, 211, 706, 211, 707, 213, 707, 214, 706, 214, 705, 214,
704, 215, 706, 217, 706, 218, 704, 217, 703, 218, 703, 220,
702, 221, 701, 223, 701, 224, 704, 228, 706, 229, 708, 231,
711, 234, 714, 236, 716, 236, 718, 236, 719, 238, 720, 238,
723, 239, 724, 238, 725, 240, 729, 240, 730, 240, 733, 241,
734, 242, 739, 242, 742, 242, 744, 242, 746, 242, 747, 242,
752, 240, 753, 240, 757, 240, 760, 239, 764, 239, 766, 240,
773, 242, 776, 241, 778, 242
]
fill: Color.WHITE
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 225 elevation: 67}
contentInput: GaussianBlur{ radius: 10 }
}
},
Polygon {//Letrero1
points: [
551, 577, 576, 573, 560, 478, 534, 483
]
fill: Color.BROWN
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//Letrero2
points: [
465, 522, 633, 492, 616, 373, 449, 395
]
fill: Color.BROWN
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300}
contentInput: DropShadow{}
}
},
Polygon {//nieve ENCIMA LETRERO
points : [
448, 424, 450, 424, 452, 422, 454, 422, 456, 422, 460, 420,
461, 417, 462, 415, 464, 415, 465, 415, 467, 414, 468, 416,
470, 420, 473, 421, 476, 420, 476, 420, 479, 419, 481, 417,
481, 414, 481, 412, 481, 411, 483, 410, 484, 409, 484, 406,
484, 403, 486, 402, 488, 402, 490, 403, 493, 404, 495, 405,
497, 406, 503, 405, 505, 403, 507, 399, 508, 396, 511, 395,
515, 392, 519, 391, 521, 391, 524, 392, 528, 392, 531, 392,
533, 393, 535, 394, 537, 394, 539, 394, 540, 396, 542, 396,
544, 394, 545, 392, 547, 390, 550, 391, 551, 390, 553, 389,
555, 389, 557, 390, 559, 391, 562, 393, 564, 394, 567, 394,
570, 395, 571, 397, 573, 398, 575, 398, 579, 397, 582, 396,
585, 395, 586, 394, 588, 393, 589, 394, 593, 395, 597, 397,
599, 398, 601, 403, 603, 407, 605, 409, 608, 410, 610, 409,
611, 409, 614, 409, 616, 409, 618, 404, 620, 402, 622, 398,
622, 394, 621, 391, 622, 381, 622, 374, 621, 368, 619, 367,
616, 365, 614, 363, 610, 362, 605, 361, 595, 362, 590, 364,
575, 363, 560, 362, 552, 363, 545, 366, 540, 365, 537, 365,
534, 363, 530, 363, 526, 365, 523, 368, 521, 370, 515, 372,
510, 372, 507, 371, 499, 372, 495, 373, 491, 371, 487, 372,
484, 374, 481, 377, 478, 380, 473, 382, 469, 383, 466, 382,
463, 382, 459, 381, 456, 382, 454, 381, 451, 380, 449, 380,
448, 382, 448, 386, 447, 387, 445, 392, 442, 394, 442, 397,
443, 399, 445, 400, 446, 401, 448, 402, 448, 404, 447, 407,
445, 410, 444, 413, 444, 417, 445, 419, 446, 421
]
fill: Color.WHITE
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 300 elevation: 55}
contentInput: DropShadow{offsetY: 2}
}
},
Polygon {//nieve DEBAJO LETRERO
points : [
586, 588, 577, 574, 571, 569, 567, 567, 561, 562, 560, 555,
558, 543, 555, 537, 549, 532, 541, 532, 537, 533, 531, 538,
528, 544, 525, 553, 519, 563, 511, 568, 504, 576, 512, 578,
526, 579, 537, 580, 546, 581, 565, 587
]
fill: Color.WHITE
smooth: true
effect: Lighting {
light: DistantLight {azimuth: 45 elevation: 65}
contentInput: GaussianBlur{ radius: 10 }
}
},
Text {
font: Font {size: 50 embolden: true name: "Mistral"}
x: 470,
y: 442
fill: Color.DARKGRAY
content: "Feliz\nNavidad"
textAlignment: TextAlignment.CENTER
transforms: Rotate {pivotX:503 pivotY:446 angle:350}
effect: Lighting{light:DistantLight{azimuth:90 elevation:20}
contentInput: DropShadow{radius:3 offsetY:4 offsetX:-2 color:Color.WHITE}
}
},
Text {
font: Font {size: 25 name: "Arial Black" }
x: 15, y: 720
fill: Color.CHOCOLATE
content: "By GaSK"
smooth: true
effect: Lighting {
light: DistantLight {azimuth:90 elevation:40}
contentInput: DropShadow{radius:5 offsetY:1 offsetX: -1 color: Color.BLACK}
}
},
]
}
}