2016-03-07 18:10:52 +00:00
|
|
|
// report parses life report JSON and
|
|
|
|
package report
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"html/template"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// Report represents a life report. It contains summaries and lists on
|
|
|
|
// various areas of a given person's life for the given time period --
|
|
|
|
// in this case, a month.
|
|
|
|
Report struct {
|
2016-03-07 21:03:32 +00:00
|
|
|
File string
|
2016-03-07 18:10:52 +00:00
|
|
|
Num int
|
|
|
|
Month string
|
2016-03-07 20:41:20 +00:00
|
|
|
Year int `json:"year"`
|
|
|
|
Summary string `json:"summary"`
|
|
|
|
Sections []Section `json:"sections"`
|
2016-03-07 18:10:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Section represents an area of life to report on. This contains a
|
|
|
|
// title to describe the area, a set of paragraphs representing a
|
|
|
|
// summary, and a set of details representing a list of more specific
|
|
|
|
// items.
|
|
|
|
Section struct {
|
|
|
|
Title string `json:"title"`
|
|
|
|
Summary []template.HTML `json:"summary"`
|
|
|
|
Details []template.HTML `json:"details"`
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// ParseReport takes a file and generates a life report from it. It
|
|
|
|
// assumes the file is named in the format NNN-month.json where NNN is the
|
|
|
|
// number of the report, usually named with leading zeroes so they're
|
|
|
|
// ordered correctly on your filesystem.
|
|
|
|
func ParseReport(f *os.File) (*Report, error) {
|
|
|
|
var err error
|
|
|
|
r := Report{}
|
|
|
|
|
2016-03-07 20:41:20 +00:00
|
|
|
// Parse JSON into a Report
|
|
|
|
jsonParser := json.NewDecoder(f)
|
|
|
|
if err = jsonParser.Decode(&r); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-03-07 18:10:52 +00:00
|
|
|
// Determine report number and month from filename in the format
|
|
|
|
// NNN-month.json
|
2016-03-07 21:03:32 +00:00
|
|
|
r.File = path.Base(f.Name())
|
|
|
|
fd := strings.Split(r.File[:strings.Index(r.File, ".json")], "-")
|
2016-03-07 18:10:52 +00:00
|
|
|
if len(fd) >= 2 {
|
|
|
|
r.Num, err = strconv.Atoi(fd[0])
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "Unable to parse report number: %v\n", err)
|
|
|
|
r.Num = 1
|
|
|
|
}
|
|
|
|
r.Month = strings.Title(fd[1])
|
|
|
|
} else {
|
|
|
|
r.Num = 1
|
|
|
|
r.Month = "First"
|
|
|
|
}
|
|
|
|
|
|
|
|
return &r, nil
|
|
|
|
}
|
2016-03-07 21:03:32 +00:00
|
|
|
|
|
|
|
// ByNum implements sort.Interface for []Report based on the Num field.
|
|
|
|
type ByNum []Report
|
|
|
|
|
|
|
|
func (n ByNum) Len() int { return len(n) }
|
|
|
|
func (n ByNum) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
|
|
|
|
func (n ByNum) Less(i, j int) bool { return n[i].Num < n[j].Num }
|