Reorganized the code into new packages.

This commit is contained in:
Jonathan Bernard 2011-10-27 20:14:08 -05:00
parent 652cc8703a
commit d076b739f5
20 changed files with 533 additions and 454 deletions

View File

@ -1,5 +0,0 @@
package com.jdbernard.timeanalyzer;
public interface CategoryFilter {
public boolean matchesEvent(Event event);
}

View File

@ -1,33 +1,50 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
import org.joda.time.Duration
/**
* A category represents a collection of like events.
* A `Category` represents a collection of like `Events` and sub-categories.
*/
public abstract class Category implements Comparable<Category> {
/** List of events directly under this category. */
public List events
/** List of sub-categories under this category. */
public List categories
/** List of `CategorizationPlan`s to use when adding new `Event`s to the
* category. */
public List categorizationPlans
/** A end-user-friendly text description of the category.*/
public String description
public Category() {
events = []
categories = []
categorizationPlans = []
description = "Unnamed Category"
}
description = "Unnamed Category" }
public Category(String description) {
events = []
categories = []
categorizationPlans = []
this.description = description
}
this.description = description }
/**
* Does the given event belong in this category?
* @param e `Event` being considered.
* @return **`true`** if this event belongs in this category, **`false`**
* otherwise.
*/
public abstract boolean matchesEvent(Event e)
/**
* Add an event to this category. This method does not check to see if the
* `Event` matches this category. It assumed that the check has already been
* made and the `Event` matches.*/
public Event addEvent(Event event) {
// see if we have or can create a subcategory that will hold this event
@ -36,24 +53,22 @@ public abstract class Category implements Comparable<Category> {
// no, let's just add it on ourself
if (!addedEvent) {
events << event
addedEvent = event
}
addedEvent = event }
return addedEvent
}
return addedEvent }
public Event addToSubcategory(Event e) {
// find all matching subcategories
def matchingCategories = categories.findAll { it.matchesEvent(e) }
if (matchingCategories)
return matchingCategories[0].addEvent(e)
if (matchingCategories) {
return matchingCategories[0].addEvent(e) }
// no matching subcategories, can we create a new one based on one
// of our plans?
def matchingPlans = categorizationPlans.findAll
{ it.deservesNewCategory(e, events) }
def matchingPlans = categorizationPlans.findAll {
it.deservesNewCategory(e, events) }
if (matchingPlans) {
// create the new category
@ -71,11 +86,9 @@ public abstract class Category implements Comparable<Category> {
existingEvents.each { newCategory.addEvent(it) }
// return the new entry
return addedEvent
}
return addedEvent }
return null
}
return null }
public Category filter(List<CategoryFilter> filters) {
@ -95,12 +108,10 @@ public abstract class Category implements Comparable<Category> {
public Duration getDuration() {
return categories.sum(new Duration(0)) { it.duration } +
events.sum(new Duration(0)) { it.duration }
}
events.sum(new Duration(0)) { it.duration } }
public int compareTo(Category other) {
return this.getDuration().compareTo(other.getDuration())
}
return this.getDuration().compareTo(other.getDuration()) }
public String toString() { return description }

View File

@ -0,0 +1,7 @@
package com.jdbernard.timeanalyzer.categories;
import com.jdbernard.timeanalyzer.events.Event;
public interface CategoryFilter {
public boolean matchesEvent(Event event);
}

View File

@ -1,17 +1,15 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import org.joda.time.Duration
import com.jdbernard.timeanalyzer.events.Event
public class DescriptionBasedCategory extends Category {
public DescriptionBasedCategory(String description) {
super()
this.description = description.replaceAll(/\p{Punct}/, '')
}
this.description = description.replaceAll(/\p{Punct}/, '') }
public boolean matchesEvent(Event e) {
return e.description.replaceAll(/\p{Punct}/, '').toLowerCase() ==
description.toLowerCase()
}
description.toLowerCase() }
}

View File

@ -1,15 +1,15 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
public class FilteredCategory extends Category {
List<CategoryFilter> filters = []
public FilteredCategory(String description) {
super(description)
}
super(description) }
public boolean matchesEvent(Event e) {
return filters.every { filter -> filter.matchesEvent(e) }
}
return filters.every { filter -> filter.matchesEvent(e) } }
}

View File

@ -1,4 +1,6 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
public class GeneralCategory extends Category {

View File

@ -0,0 +1,18 @@
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
import org.joda.time.Interval
public class TimeIntervalCategory extends Category {
private final Interval interval
public TimeIntervalCategory(String desc, Interval interval) {
super(desc)
this.interval = interval }
public boolean matchesEvent(Event e) {
Interval eventIv = new Interval(e.start, e.duration)
return interval.contains(eventIv) }
}

View File

@ -1,4 +1,6 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
import org.joda.time.Interval
import org.joda.time.ReadableInstant

View File

@ -1,4 +1,6 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categories
import com.jdbernard.timeanalyzer.events.Event
public class TwoLevelCategory extends Category {
@ -7,18 +9,15 @@ public class TwoLevelCategory extends Category {
public TwoLevelCategory(String heading) {
super(heading)
descriptionPattern = ~/^${heading}:\s*(.*)/
}
descriptionPattern = ~/^${heading}:\s*(.*)/ }
public boolean matchesEvent(Event e) {
return e.description ==~ descriptionPattern
}
return e.description ==~ descriptionPattern }
public Event addEvent(Event e) {
def m = e.description =~ descriptionPattern
e = new Event(e, description: m[0][1])
super.addEvent(e)
}
super.addEvent(e) }
}

View File

@ -1,4 +1,7 @@
package com.jdbernard.timeanalyzer;
package com.jdbernard.timeanalyzer.categorizationplans;
import com.jdbernard.timeanalyzer.categories.Category;
import com.jdbernard.timeanalyzer.events.Event;
import java.util.List;
import java.util.Map;

View File

@ -0,0 +1,35 @@
package com.jdbernard.timeanalyzer.categorizationplans;
import com.jdbernard.timeanalyzer.categories.Category
import com.jdbernard.timeanalyzer.events.Event
import org.joda.time.DateTime
import org.joda.time.Interval
import org.joda.time.Period
public class DailyCategorizationPlan {
boolean deservesNewCategory(Event event, List<Event> existingEvents) {
Interval fullday = new Interval(
event.start.toDateMidnight(), Period.days(1))
Interval eventIv = new Interval(
event.start, event.duration)
return fullDay.contains(eventIv) }
Category newCategory(Event event, List<Event> existingEvents) {
Interval fullday = new Interval(
event.start.toDateMidnight(), Period.days(1))
return TimeIntervalCategory(
event.start.toString("EEE, MMM dd", fullday)) }
List<Event> findEventsToRecategorize(Event event,
List<Event> existingEvents) {
Interval fullday = new Interval(
event.start.toDateMidnight(), Period.days(1))
return existingEvents.findAll {
Interval iv = new Interval(it.start, it.duration)
fullday.contains(iv) } }
}

View File

@ -1,4 +1,8 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categorizationplans
import com.jdbernard.timeanalyzer.categories.Category
import com.jdbernard.timeanalyzer.categories.DescriptionBasedCategory
import com.jdbernard.timeanalyzer.events.Event
public class DescriptionBasedCategorizationPlan implements CategorizationPlan {

View File

@ -1,4 +1,8 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.categorizationplans
import com.jdbernard.timeanalyzer.categories.Category
import com.jdbernard.timeanalyzer.categories.TwoLevelCategory
import com.jdbernard.timeanalyzer.events.Event
public class TwoLevelCategorizationPlan implements CategorizationPlan {

View File

@ -1,6 +1,6 @@
package com.jdbernard.timeanalyzer.chart
import com.jdbernard.timeanalyzer.Category
import com.jdbernard.timeanalyzer.categories.Category
import org.jfree.data.general.DefaultPieDataset
import org.jfree.data.general.PieDataset
import org.jfree.util.SortOrder

View File

@ -1,6 +1,6 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.events
import org.joda.time.DateTime
import org.joda.time.ReadableDateTime
import org.joda.time.Duration
import org.joda.time.format.PeriodFormat
import org.joda.time.format.PeriodFormatter
@ -9,13 +9,13 @@ public class Event implements Cloneable {
public final String description
public final String notes
public final DateTime start
public final ReadableDateTime start
public Duration duration // bit of a hack, allows modification for the
// TimelineEventProcessor
public static PeriodFormatter periodFormatter = PeriodFormat.getDefault()
public Event(String desc, String notes, DateTime start, Duration duration) {
public Event(String desc, String notes, ReadableDateTime start, Duration duration) {
this.description = desc
this.notes = notes
this.start = start

View File

@ -1,5 +1,6 @@
package com.jdbernard.timeanalyzer
package com.jdbernard.timeanalyzer.processors
import com.jdbernard.timeanalyzer.events.Event
import com.jdbernard.timestamper.core.Timeline
import org.joda.time.DateTime
import org.joda.time.Duration

View File

@ -1,8 +1,8 @@
package com.quantumdigital.ithelp.timeanalyzer
import com.jdbernard.timeanalyzer.Category
import com.jdbernard.timeanalyzer.CategorizationPlan
import com.jdbernard.timeanalyzer.Event
import com.jdbernard.timeanalyzer.categories.Category
import com.jdbernard.timeanalyzer.categorizationplans.CategorizationPlan
import com.jdbernard.timeanalyzer.events.Event
public class TicketCategorizationPlan implements CategorizationPlan {

View File

@ -1,7 +1,7 @@
package com.quantumdigital.ithelp.timeanalyzer
import com.jdbernard.timeanalyzer.Category
import com.jdbernard.timeanalyzer.Event
import com.jdbernard.timeanalyzer.categories.Category
import com.jdbernard.timeanalyzer.events.Event
public class TicketCategory extends Category {

View File

@ -1,6 +1,6 @@
package com.quantumdigital.ithelp.timeanalyzer
import com.jdbernard.timeanalyzer.Event
import com.jdbernard.timeanalyzer.events.Event
public class TicketEvent extends Event {

View File

@ -18,7 +18,7 @@ events = tep.process(timeline)
topcat = new FilteredCategory("Top Category")
topcat.filters << new TimeIntervalCategoryFilter(
new DateTime(2011, 1, 2, 0, 0, 0, 0), new DateTime(2011, 1, 9, 0, 0, 0, 0))
new DateTime(2011, 1, 24, 0, 0, 0, 0), new DateTime(2011, 1, 25, 0, 0, 0, 0))
twoLevelCatPlan = new TwoLevelCategorizationPlan()
descriptionBasedCatPlan = new DescriptionBasedCategorizationPlan()