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
|
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<Entry> entries
|
||||||
|
List<Category> categories
|
||||||
|
String description
|
||||||
|
|
||||||
|
public Category() {
|
||||||
|
entries = []
|
||||||
|
categories = []
|
||||||
|
description = "Unnamed Category"
|
||||||
|
}
|
||||||
|
|
||||||
public abstract boolean matchesEvent(Event e)
|
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 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
|
package com.quantumdigital.ithelp.timeanalyzer
|
||||||
|
|
||||||
import com.jdbernard.timeanalyzer.Category
|
import com.jdbernard.timeanalyzer.Category
|
||||||
|
import com.jdbernard.timeanalyzer.Entry
|
||||||
|
import com.jdbernard.timeanalyzer.Event
|
||||||
|
|
||||||
public class ITHelpCategory extends Category {
|
public class ITHelpCategory extends Category {
|
||||||
|
|
||||||
|
private def ithelpPattern = ~/^ITHelp:(.*)$/
|
||||||
|
private def ticketPattern = ~/^ITHelp:.*#(\d+).*/
|
||||||
|
|
||||||
public boolean matchesEvent(Event e) {
|
public boolean matchesEvent(Event e) {
|
||||||
return (e.description ==~ /^ITHelp:.*/)
|
return (e.description ==~ ithelpPattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITHelpEntry addEvent(Event e) {
|
public Entry addEvent(Event e) {
|
||||||
assert eventMatches(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
|
package com.quantumdigital.ithelp.timeanalyzer
|
||||||
|
|
||||||
import com.jdbernard.timeanalyzer.Category
|
import com.jdbernard.timeanalyzer.Category
|
||||||
|
import com.jdbernard.timeanalyzer.Event
|
||||||
|
|
||||||
public class TicketCategory extends Category {
|
public class TicketCategory extends Category {
|
||||||
|
|
||||||
public boolean matchesEvent(Event e) {
|
public final int ticketId
|
||||||
return (e.description ==~ /ITHelp:.*#\d+.*/)
|
|
||||||
|
public TicketCategory(int ticketId) {
|
||||||
|
super()
|
||||||
|
this.ticketId = ticketId
|
||||||
|
this.description = "Ticket #${ticketId}"
|
||||||
}
|
}
|
||||||
|
|
||||||
public TicketEntry addEvent(Event e) {
|
public boolean matchesEvent(Event e) {
|
||||||
assert eventMatches(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