1 files changed, 51 insertions(+), 25 deletions(-)

M cmd/orgchart/main.go
M cmd/orgchart/main.go +51 -25
@@ 10,6 10,9 @@ import (
 	"github.com/ajstarks/svgo"
 )
 
+/**************************************************************************
+ *  Constants & global variables                                          *
+ **************************************************************************/
 const (
 	boxW    = 170
 	gapW    = 30

          
@@ 25,10 28,40 @@ const (
 
 var pageWidth int
 
+/**************************************************************************
+ *  Main                                                                  *
+ **************************************************************************/
+func main() {
+	c := flag.String("c", "", "CSV input file")
+	flag.Parse()
+	if *c == "" {
+		fmt.Println("CSV is required")
+		flag.Usage()
+		os.Exit(1)
+	}
+	f, e := os.Open(*c)
+	defer f.Close()
+	if e != nil {
+		fmt.Println(e.Error())
+		os.Exit(1)
+	}
+	ps, e := makePeople(f)
+	if e != nil {
+		fmt.Println(e.Error())
+		os.Exit(1)
+	}
+	rs := rank(ps)
+	renderSVG(os.Stdout, rs)
+}
+
+/**************************************************************************
+ *  Person & methods                                                      *
+ **************************************************************************/
 type Person struct {
-	Name    string
-	Manager *Person
-	Reports []*Person
+	Name       string
+	Manager    *Person
+	Reports    []*Person
+	Contractor bool
 }
 
 // The index of this person in the person's manager's reports

          
@@ 87,6 120,9 @@ func New(n string) *Person {
 	return &Person{Name: n, Reports: make([]*Person, 0)}
 }
 
+/**************************************************************************
+ *  Box & methods                                                         *
+ **************************************************************************/
 type Box struct {
 	X, Y int
 	Leaf bool

          
@@ 103,29 139,12 @@ func (b Box) in() (int, int) {
 	return b.X + boxW/2, b.Y
 }
 
-func main() {
-	c := flag.String("c", "", "CSV input file")
-	flag.Parse()
-	if *c == "" {
-		fmt.Println("CSV is required")
-		flag.Usage()
-		os.Exit(1)
-	}
-	f, e := os.Open(*c)
-	defer f.Close()
-	if e != nil {
-		fmt.Println(e.Error())
-		os.Exit(1)
-	}
-	ps, e := makePeople(f)
-	if e != nil {
-		fmt.Println(e.Error())
-		os.Exit(1)
-	}
-	rs := rank(ps)
-	renderSVG(os.Stdout, rs)
-}
+/**************************************************************************
+ *  Utility functions                                                     *
+ **************************************************************************/
 
+// Parses a CSV data stream, producing a map of people indexed by the person
+// name.  Returns an error if a non-EOF read error is encountered
 func makePeople(f io.Reader) (map[string]*Person, error) {
 	r := csv.NewReader(f)
 	r.LazyQuotes = true

          
@@ 159,6 178,8 @@ func makePeople(f io.Reader) (map[string
 	return ps, e
 }
 
+// Given a map of people, produces a ranking where rank[0] are people with no
+// managers, rank[1] are people who's managers are in rank[1], and so on.
 func rank(ps map[string]*Person) Ranks {
 	rs := make(Ranks, 0)
 	for _, p := range ps {

          
@@ 173,6 194,8 @@ func rank(ps map[string]*Person) Ranks {
 	return rs
 }
 
+// Adds a person and their reports to the supplied ranks structure and recurses
+// into the reports, creating new ranks as needed
 func addRecursively(p *Person, rs Ranks, i int) Ranks {
 	if len(rs) <= i {
 		rs = append(rs, make(Rank, 0))

          
@@ 184,6 207,9 @@ func addRecursively(p *Person, rs Ranks,
 	return rs
 }
 
+/**************************************************************************
+ *  SVG generating code                                                   *
+ **************************************************************************/
 func renderSVG(out io.Writer, rs Ranks) {
 	c := svg.New(out)
 	pageWidth := rs.width()