func (p *project) processSlip(data []byte) error {
	t, err := newTask(data)
	if err != nil {
		return err
	}
	if p.name == "" {
		p.name = t.project
	}
	if p.timePeriod.IsSet() && !p.withinTimePeriod(t) {
		return nil
	}
	if _, ok := p.tasks[t.name]; !ok {
		p.tasks[t.name] = t
	} else {
		p.tasks[t.name].timeWorked += t.timeWorked
	}
	p.totalTimeWorked += t.timeWorked
	return nil
}
Process a timeslip as a task and add the time worked to the project total.

If a task name already exists then the time worked is added to the current
entry, otherwise the timeslip is saved as a new entry. A new project is
given the name as found in the first task.
package reports
import (
	"bufio"
	"io"
	"sort"
	"strings"
	"github.com/mrcook/time_warrior/reports/period"
)
type project struct {
	name            string
	timePeriod      *period.Period
	totalTimeWorked int
	tasks           map[string]*task
	scanErrors      []scanError
}
type scanError struct {
	scanner  error
	timeslip string
}
func newProject(p *period.Period) *project {
	return &project{
		timePeriod: p,
		tasks:      make(map[string]*task),
	}
}
func (p *project) process(file io.Reader) error {
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		err := p.processSlip(scanner.Bytes())
		if err != nil {
			p.scanErrors = append(p.scanErrors, scanError{scanner: err, timeslip: scanner.Text()})
		}
	}
	return scanner.Err()
}