2011-09-05 21 views
7

Estoy construyendo un sistema de calendario desde cero (requisito, ya que estoy trabajando con un tipo especial de calendario junto a Gregorian), y necesito ayuda con la lógica . Estoy escribiendo la aplicación en Django y Python.Repetir "eventos" en un calendario: CPU vs Base de datos

Básicamente, los problemas lógicos con los que me estoy enfrentando es cómo persistir la menor cantidad de objetos posible de la manera más inteligente posible sin subir la pestaña en los ciclos de la CPU. Siento que el polimorfismo sería una solución para esto, pero no estoy exactamente seguro de cómo expresarlo aquí.

Tengo dos subconjuntos básicos de eventos, eventos repetidos y eventos one-shot.

Los eventos repetitivos tendrán suscriptores, personas a las que se les notificará sobre sus cambios. Si, por ejemplo, una clase se cancela o se mueve a una dirección o tiempo diferente, las personas que se han suscrito deben saberlo. Algunos eventos simplemente ocurren todos los días hasta el final de los tiempos, no se editarán y "simplemente sucederá". El problema es que si tengo un objeto que almacena la información del evento y su política de repetición, entonces cancelar o modificar un evento en la serie realmente arruina las cosas y tendré que dar cuenta de eso de alguna manera, manteniendo a los suscriptores al tanto cambiar y mantener las series juntas como un grupo lógico.

Paradoja: generar objetos de evento únicos para cada evento normal en una serie hasta el final de los tiempos (si se repite indefinidamente) no tiene sentido si todos van a almacenar la misma información; sin embargo, si ocurre un cambio en un solo evento de la serie, casi tendrá para crear un objeto diferente en la base de datos que represente una cancelación.

¿Alguien me puede ayudar con la lógica aquí? Realmente está retorciendo mi mente y realmente no puedo pensar con claridad. Realmente me gustaría obtener información sobre cómo resolver este problema, ya que repetir eventos no es exactamente lo más lógico (repetir cada dos días, o cada M/W/F, o el primer M de cada mes, o cada 3 meses, o una vez al año en esta fecha, o una vez a la semana en esta fecha, o una vez al mes en esta fecha, oa las 9:00 a. m. los martes y a las 11:00 a. m. los jueves, etc.) y yo como ayudar a entender la mejor ruta lógica para repetir eventos también.

Aquí es un pensamiento sobre cómo hacerlo:

class EventSeries(models.Model): 
    series_name = models.TextField() 
    series_description = models.TextField() 
    series_repeat_policy = models.IHaveNoIdeaInTheWorldOnHowToRepresentThisField() 
    series_default_time = models.TimeField() 
    series_start_date = models.DateField() 
    series_end_date = models.DateField() 
    location = models.ForeignKey('Location') 

class EventSeriesAnomaly(models.Model): 
    event_series = models.ForeignKey('EventSeries', related_name="exceptions") 
    override_name = models.TextField() 
    override_description = models.TextField() 
    override_time = models.TimeField() 
    override_location = models.ForeignKey('Location') 
    event_date = models.DateField() 

class EventSeriesCancellation(models.Model): 
    event_series = models.ForeignKey('EventSeries', related_name="cancellations") 
    event_date = models.TimeField() 
    cancellation_explanation = models.TextField() 

Esto parece tener un poco de sentido, pero como se ha dicho anteriormente, esto está arruinando mi cerebro en este momento así que cualquier cosa parece que sería trabajar. (Otro problema y pregunta, si alguien quiere modificar todos los eventos restantes de la serie, ¿qué diablos hago?!!? Supongo que podría cambiar 'series_default_time' y luego generar instancias de anomalías para todas las instancias pasadas para configurarlos a la hora original, pero AHHHHHH !!!)

de ebullición se reduce a tres preguntas sencillas y concretas, tenemos:

  1. ¿Cómo puedo tener una serie de eventos que se repiten, sin embargo, permitir cancelaciones y modificaciones en eventos individuales y modificaciones en el resto de la serie como un todo, mientras se almacenan tan pocos objetos en la base de datos como sea absolutamente necesario, nunca se generan objetos para eventos individuales en ¿avanzar?
  2. ¿Cómo puedo repetir eventos de una manera altamente personalizable, sin perder la razón, ya que puedo permitir que los eventos se repitan en un number of ways, pero de nuevo facilitando las cosas y almacenando la menor cantidad de objetos posible?
  3. ¿Cómo puedo hacer todo lo anterior, permitiendo un cambio en cada serie de eventos para que no ocurra si se cae en un holiday?
+5

+1 para la clase raramente vista, pero siempre tan útil: models.IHaveNoIdeaInTheWorldOnHowToRepresentThisField – mjhm

+0

Utilizo ese campo con demasiada frecuencia. –

Respuesta

1

Deseo abordar solo la pregunta 3, sobre vacaciones.

En varias bases de datos de informes, me pareció útil definir una tabla, llamémosla "Almanaque", que tiene una fila para cada fecha, dentro de un cierto rango. Si el rango abarca diez años, la tabla contendrá alrededor de 3,652 filas. Eso es pequeño para los estándares de hoy. La clave principal es la fecha.

Algunas otras columnas son cosas como si la fecha es festiva, una jornada laboral normal o un día de fin de semana. Lo sé, lo sé, podrías calcular las cosas del fin de semana usando una función incorporada.Pero resulta conveniente incluir esto como datos. Hace que tus uniones sean más simples y más similares entre sí.

Luego tiene un programa de aplicación que completa el Almanaque. Tiene todos los caprichos del calendario integrados, incluidas las reglas de la empresa para determinar qué días son días festivos. Incluso puede incluir columnas para las cuales el "mes fiscal" pertenece a una fecha determinada, si eso es relevante para su caso. El resto de la aplicación, tanto los programas de entrada como los programas de extracción, todos tratan el Almanaque como datos antiguos simples.

Esto puede parecer poco óptimo porque no es mínimo. Pero confía en mí, este patrón de diseño es útil en una amplia variedad de situaciones. Depende de usted averiguar cómo se aplica a su caso.

El Almanaque es realmente un subconjunto de los principios del almacenamiento de datos y el diseño del esquema en estrella.

si quiere hacer lo mismo dentro de la CPU, podría tener un objeto "Almanac" con funciones públicas como Almanac.holiday (date).

+0

Para este caso de uso, esto tiene mucho sentido. Como las vacaciones que estoy calculando se calculan usando una lógica algo complicada (no estamos tratando con el calendario gregoriano), esta podría ser una buena idea en este caso de uso. Dado que estos tipos de objetos no serán editables y pueden almacenarse en la memoria caché como hardcore, esto tiene sentido. Probablemente crearé dos tablas, una para mapear días desde mi calendario hasta la gregoriana, la otra para mapear vacaciones a los días de mi calendario, y luego encontraré la forma de combinar los datos y hacerme más inteligente. Gracias. –

+0

Sí. Una de las columnas de su Alamanac sería, probiblemente, la fecha equivalente expresada en el calendario en el que se expresan las fechas. Luego, podría recodificar las fechas de los eventos y demás en simples fechas gregorianas, como entiende el DBMS, pero únase al almanaque para presentar las fechas en su calendario a los usuarios de sus datos. –

0

Me enfrenté a los mismos problemas que hace un tiempo. Sin embargo, la solución inicial no contenía anomalías o cancelaciones, solo repetía eventos. La forma en que modelamos un conjunto de eventos repetidos es tener un campo que indique el tipo de intervalo (como mensual/semanal/diario) y luego las distancias (como cada 2do día, cada 2da semana, etc.) a partir de un día de inicio determinado. . Esta forma simple de repetición no cubre demasiados escenarios, pero fue muy fácil calcular las fechas de repetición. También son posibles otras formas de repetición, por ejemplo, se define algo en el camino cronjobs.

para generar las repeticiones, hemos creado una función de tabla, que da un poco de ID de usuario genera todo caso repeticiones sobre la marcha hasta como 5 años en el futuro sobre la marcha utilizando SQL recursivo (así como en su enfoque, para un conjunto de repeticiones, solo debe almacenarse un evento). Hasta ahora, esto funciona muy bien y la función de tabla se puede consultar como si las repeticiones individuales estuvieran realmente almacenadas en la base de datos. También podría ampliarse fácilmente para excluir cualquier evento cancelado y para reemplazar eventos cambiados según las fechas, también sobre la marcha. No sé si esto es posible con su base de datos y su ORM.

+0

No es muy probable (para mi caso de uso), ya que realmente necesito persistir la menor cantidad posible de objetos. Realmente no veo el sentido de persistir en tantos objetos si, por algún giro de la lógica, puedo encontrar una solución que implique solo a unos pocos. Cuanto más lo pienso, mejor parece el modelo de datos que escribí (el de arriba), pero aún necesito una forma flexible de manejar repeticiones complejas, así que creo que necesito otro modelo para representar las repeticiones variantes. –

+0

¿Eh? ¿Qué quieres decir con probable? Y no veo cómo puedes tener menos persistencia que esto, quizás no expliqué lo suficientemente claro. –

3

esto podría convertirse en una fuerte discusión, como la lógica fecha generalmente es mucho más difícil que parece en un principio y cada uno tendrá su propia idea de cómo hacer que las cosas sucedan.

Probablemente sacrifique algo de espacio en blanco y haga que los modelos sean lo más tontos posible (por ejemplo, no tener que definir anomalías en una serie). La condición de repetición podría ser algunos términos simples que tendrían que analizarse (según sus requisitos) o - KISS - solo el intervalo en que ocurrirá el siguiente evento.

De esto puede generar el evento "siguiente", que copiará la condición de repetición, y generará la mayor cantidad de eventos en el futuro como sea necesario (defina una ventana de tiempo máximo en el futuro para generar eventos pero generar solo cuando, de hecho, alguien mira el intervalo de tiempo en cuestión). Los eventos pueden tener un puntero a su evento principal, por lo que toda una serie es identificable (al igual que una lista vinculada).

El modelo debe tener un indicador, independientemente de si se cancela un solo evento. (El evento permanece en el db, para poder copiar el evento en el futuro). La cancelación de una serie completa elimina la lista de eventos.

EDIT: other answers han mencionado the dateutil package para la construcción de intervalos y el análisis, que realmente se ve muy bien.

+0

+1 para dateutil. 'rrule' y' rruleset' parecen ser útiles aquí. – sandinmyjoints

1

Para un modelo de la serie de eventos que he creado, mi solución a IHaveNoIdeaInTheWorldOnHowToRepresentThisField era utilizar pickled object field guardar una regla de repetición (rrule) de dateutil en mi modelo de la serie de eventos.

Cuestiones relacionadas