Finised initial implementation. Need to test.
This commit is contained in:
parent
9f4008a775
commit
68b51640af
44
build.xml
Normal file
44
build.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<project name="Time Analyzer" default="compile">
|
||||
|
||||
<property environment="env"/>
|
||||
<property file="project.properties"/>
|
||||
|
||||
<path id="groovy.lib">
|
||||
<fileset dir="${env.GROOVY_HOME}/lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="local.compile.lib">
|
||||
<fileset dir="lib/compile">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="local.runtime.lib">
|
||||
<fileset dir="lib/runtime">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<taskdef name="groovyc" classpathref="groovy.lib"
|
||||
classname="org.codehaus.groovy.ant.Groovyc"/>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
</target>
|
||||
|
||||
<target name="compile">
|
||||
<mkdir dir="build/main"/>
|
||||
<groovyc srcdir="src/main" destdir="build/main"
|
||||
includeAntRuntime="false">
|
||||
|
||||
<classpath>
|
||||
<path refid="groovy.lib"/>
|
||||
<path refid="local.compile.lib"/>
|
||||
</classpath>
|
||||
|
||||
<javac/>
|
||||
</groovyc>
|
||||
</target>
|
||||
</project>
|
@ -1,15 +1,79 @@
|
||||
package com.jdbernard.timeanalyzer
|
||||
|
||||
public abstract class Category implements Comparable<T extends Category> {
|
||||
import org.joda.time.Duration
|
||||
|
||||
/**
|
||||
* A category represents a collection of like events.
|
||||
*/
|
||||
public abstract class Category implements Comparable<Category> {
|
||||
|
||||
List<Entry> entries
|
||||
List<Category> categories
|
||||
String description
|
||||
|
||||
public Category() {
|
||||
entries = []
|
||||
categories = []
|
||||
description = "Unnamed Category"
|
||||
}
|
||||
|
||||
public abstract boolean matchesEvent(Event e)
|
||||
public abstract Entry addEvent(Event e)
|
||||
|
||||
public Category() { entries = [] }
|
||||
public Entry addEvent(Event e) {
|
||||
Entry entry
|
||||
|
||||
public int compareTo(C other) {
|
||||
// see if we have a subcategory that will hold this event
|
||||
entry = addToSubCategory(e)
|
||||
|
||||
if (!entry) {
|
||||
// if not, do we have another entry that could be grouped with
|
||||
// this one to create a new category, based on the description?
|
||||
def existingEntry = entries.find
|
||||
{ it.description == e.description }
|
||||
|
||||
// yes
|
||||
if (existingEntry) {
|
||||
// create the new category
|
||||
category = new DescriptionBasedCategory(e.description)
|
||||
|
||||
// remove the existing entry from this category and
|
||||
// add it to the subcategory
|
||||
this.entries -= existingEntry
|
||||
category.entries << existingEntry
|
||||
|
||||
// add the new event to the category
|
||||
entry = category.addEvent(e)
|
||||
|
||||
// add the category to our list of subcategories
|
||||
categories << category
|
||||
}
|
||||
|
||||
// no, let's create a generic entry and add it
|
||||
else {
|
||||
entry = new Entry(this, e)
|
||||
entries << entry
|
||||
}
|
||||
}
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
public Entry addToSubcategory(Event e) {
|
||||
|
||||
// find all matching subcategories
|
||||
def matchingCategories = categories.findAll { it.matchesEvent(e) }
|
||||
|
||||
if (matchingCategories)
|
||||
return matchingCategories[0].addEvent(e)
|
||||
return null
|
||||
}
|
||||
|
||||
public Duration getDuration() {
|
||||
return categories.sum { it.duration } + entries.sum { it.duration }
|
||||
}
|
||||
|
||||
public int compareTo(Category other) {
|
||||
return this.getDuration().compareTo(other.getDuration())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.jdbernard.timeanalyzer
|
||||
|
||||
import org.joda.time.Duration
|
||||
|
||||
public class DescriptionBasedCategory extends Category {
|
||||
|
||||
public DescriptionBasedCategory(String description) {
|
||||
super()
|
||||
this.description = description
|
||||
}
|
||||
|
||||
public boolean matchesEvent(Event e) {
|
||||
return e.description == description
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,32 @@
|
||||
package com.jdbernard.timanalyzer;
|
||||
package com.jdbernard.timeanalyzer;
|
||||
|
||||
public class Entry extends Event {
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
public class Entry {
|
||||
|
||||
public String description;
|
||||
public String notes;
|
||||
public DateTime start;
|
||||
public Duration duration;
|
||||
public Category category;
|
||||
|
||||
public Entry(Category c, String description, DateTime start,
|
||||
Duration duration) {
|
||||
this(c, description, "", start, duration);
|
||||
}
|
||||
|
||||
public Entry(Category c, Event e) {
|
||||
this(c, e.description, e.notes, e.start, e.duration);
|
||||
}
|
||||
|
||||
public Entry(Category c, String description, String notes, DateTime start,
|
||||
Duration duration) {
|
||||
this.description = description;
|
||||
this.notes = notes;
|
||||
this.start = start;
|
||||
this.duration = duration;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
package com.jdbernard.timeanalyzer;
|
||||
|
||||
public abstract class EventTransformation {
|
||||
|
||||
private Category category;
|
||||
|
||||
public EventTransformation(Category cat) {
|
||||
this.category = cat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this transformation is applicable for a given event.
|
||||
* @param e An event to match.
|
||||
* @return *true* if this transformation is applicable to the given event,
|
||||
* *false* otherwise.
|
||||
*/
|
||||
public abstract boolean matches(Event e);
|
||||
|
||||
/**
|
||||
* Transform an entry.
|
||||
* @param e The Event to transform.
|
||||
* @return A new Entry.
|
||||
*/
|
||||
public abstract Entry transform(Event e);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package com.jdbernard.timeanalyzer
|
||||
|
||||
public class EventTransformer {
|
||||
|
||||
List transformations
|
||||
|
||||
public EventTransformer(List transformations) {
|
||||
this.transformations = transformations
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an event. The first matching transformation is used.
|
||||
* @param e The event to transform.
|
||||
* @return The resulting Entry.
|
||||
*/
|
||||
public Entry transform(Event e) {
|
||||
for (t : transformations)
|
||||
if (t.matches(e))
|
||||
return t.transform(t)
|
||||
}
|
||||
}
|
12
src/main/com/jdbernard/timeanalyzer/GeneralCategory.groovy
Normal file
12
src/main/com/jdbernard/timeanalyzer/GeneralCategory.groovy
Normal file
@ -0,0 +1,12 @@
|
||||
package com.jdbernard.timeanalyzer
|
||||
|
||||
public class GeneralCategory {
|
||||
|
||||
public GeneralCategory() {
|
||||
super()
|
||||
description = "General"
|
||||
}
|
||||
|
||||
public boolean matchesEvent(Event e) { true }
|
||||
|
||||
}
|
@ -1,15 +1,58 @@
|
||||
package com.quantumdigital.ithelp.timeanalyzer
|
||||
|
||||
import com.jdbernard.timeanalyzer.Category
|
||||
import com.jdbernard.timeanalyzer.Entry
|
||||
import com.jdbernard.timeanalyzer.Event
|
||||
|
||||
public class ITHelpCategory extends Category {
|
||||
|
||||
private def ithelpPattern = ~/^ITHelp:(.*)$/
|
||||
private def ticketPattern = ~/^ITHelp:.*#(\d+).*/
|
||||
|
||||
public boolean matchesEvent(Event e) {
|
||||
return (e.description ==~ /^ITHelp:.*/)
|
||||
return (e.description ==~ ithelpPattern)
|
||||
}
|
||||
|
||||
public ITHelpEntry addEvent(Event e) {
|
||||
assert eventMatches(e)
|
||||
public Entry addEvent(Event e) {
|
||||
|
||||
Entry entry
|
||||
|
||||
// try to add to an existing category
|
||||
entry = addToSubcategory(e)
|
||||
|
||||
// no existing category matches
|
||||
if (!entry) {
|
||||
|
||||
// see if it is a new ticket entry
|
||||
def ticketMatch = e.description =~ ticketPattern
|
||||
|
||||
// if is a new ticket
|
||||
if(ticketMatch) {
|
||||
// parse the ticket number
|
||||
int ticketId = ticketMatch[0][1] as int
|
||||
|
||||
// create the category
|
||||
TicketCategory category = new TicketCategory(ticketId)
|
||||
|
||||
// add the category to our list
|
||||
categories << category
|
||||
|
||||
// add the event to the category
|
||||
entry = category.addEvent(e)
|
||||
}
|
||||
|
||||
// not a new ticket, use the general logic for adding
|
||||
else {
|
||||
|
||||
// add a general entry to this category
|
||||
entry = super.addEvent(e)
|
||||
|
||||
// adjust the description (remove the ITHelp tag)
|
||||
def m = entry.description =~ ithelpPattern
|
||||
entry.description = m[0][1]
|
||||
}
|
||||
}
|
||||
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
package com.quantumdigital.ithelp.timeanalyzer
|
||||
|
||||
import com.jdbernard.timeanalyzer.Event
|
||||
|
||||
public class ITHelpEntry extends Entry
|
@ -1,12 +0,0 @@
|
||||
package com.quantumdigital.ithelp.timeanalyzer
|
||||
|
||||
import com.jdbernard.timeanalyzer.EventTransformation
|
||||
|
||||
public class ITHelpEventTransformation extends EventTransformation {
|
||||
|
||||
public boolean matches(Event e) {
|
||||
return e.description ==~ /^ITHelp: .*/
|
||||
}
|
||||
|
||||
public Entry
|
||||
}
|
@ -1,15 +1,20 @@
|
||||
package com.quantumdigital.ithelp.timeanalyzer
|
||||
|
||||
import com.jdbernard.timeanalyzer.Category
|
||||
import com.jdbernard.timeanalyzer.Event
|
||||
|
||||
public class TicketCategory extends Category {
|
||||
|
||||
public boolean matchesEvent(Event e) {
|
||||
return (e.description ==~ /ITHelp:.*#\d+.*/)
|
||||
public final int ticketId
|
||||
|
||||
public TicketCategory(int ticketId) {
|
||||
super()
|
||||
this.ticketId = ticketId
|
||||
this.description = "Ticket #${ticketId}"
|
||||
}
|
||||
|
||||
public TicketEntry addEvent(Event e) {
|
||||
assert eventMatches(e)
|
||||
public boolean matchesEvent(Event e) {
|
||||
return (e.description ==~ /ITHelp:.*#${ticketId}.*/)
|
||||
}
|
||||
|
||||
TicketEntry entry = new TicketEntry(e)
|
||||
entries << entry
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.quantumdigital.ithelp.timeanalyzer
|
||||
|
||||
import com.jdbernard.timeanalyzer.Entry
|
||||
import com.jdbernard.timeanalyzer.Event
|
||||
|
||||
public class TicketEntry extends Entry {
|
||||
|
||||
public int id
|
||||
|
||||
public TicketEntry(ITHelpCategory category, Event e) {
|
||||
super(category, e)
|
||||
|
||||
def m = e.description =~ /^ITHelp:(.*#(\d+).*)$/
|
||||
this.description = m[0][1]
|
||||
this.id = m[0][2] as int
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user