-
-
Notifications
You must be signed in to change notification settings - Fork 369
Expand file tree
/
Copy pathhomework.go
More file actions
167 lines (146 loc) · 3.78 KB
/
homework.go
File metadata and controls
167 lines (146 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package user
import (
"fmt"
"path/filepath"
"strings"
"github.com/exercism/cli/api"
"github.com/exercism/cli/config"
)
// HWFilter is used to categorize homework items.
type HWFilter int
// SummaryOption allows selective display of summary items.
type SummaryOption HWFilter
const (
// HWAll represents all items in the collection.
HWAll = iota
// HWUpdated represents problems where files have been added.
HWUpdated
// HWNew represents newly fetched problems.
HWNew
// HWNotSubmitted represents problems that have not yet been submitted for review.
HWNotSubmitted
)
// Homework is a collection of problems that were fetched from the APIs.
type Homework struct {
Items []*Item
template string
}
// NewHomework decorates a problem set with some additional data based on the
// user's system.
func NewHomework(problems []*api.Problem, c *config.Config) *Homework {
hw := Homework{}
for _, problem := range problems {
item := &Item{
Problem: problem,
dir: c.Dir,
}
hw.Items = append(hw.Items, item)
}
hw.template = "%s%s %s\n"
return &hw
}
// Save saves all problems in the problem set.
func (hw *Homework) Save() error {
for _, item := range hw.Items {
if err := item.Save(); err != nil {
return err
}
}
return nil
}
// RejectMissingTracks removes any items that are part of tracks the user
// doesn't currently have a folder for on their local machine. This
// only happens when a user calls `exercism fetch` without any arguments.
func (hw *Homework) RejectMissingTracks(dirMap map[string]bool) error {
items := []*Item{}
for _, item := range hw.Items {
dir := filepath.Join(item.dir, item.TrackID)
if dirMap[dir] {
items = append(items, item)
}
}
if len(items) == 0 {
return fmt.Errorf(`
You have yet to start a language track!
View all available language tracks with "exercism tracks"
Fetch exercises for your first track with "exercism fetch TRACK_ID"`)
}
hw.Items = items
return nil
}
// ItemsMatching returns a subset of the set of problems.
func (hw *Homework) ItemsMatching(filter HWFilter) []*Item {
items := []*Item{}
for _, item := range hw.Items {
if item.Matches(filter) {
items = append(items, item)
}
}
return items
}
// Report outputs a list of the problems in the set.
// It prints the track name, the problem name, and the full
// path to the problem on the user's filesystem.
func (hw *Homework) Report(filter HWFilter) {
if hw == nil {
return
}
width := hw.maxTitleWidth()
items := hw.ItemsMatching(filter)
hw.heading(filter, len(items), width)
for _, item := range items {
fmt.Print(item.Report(hw.template, width))
}
}
func (hw *Homework) heading(filter HWFilter, count, width int) {
if count == 0 {
return
}
fmt.Println()
if filter == HWAll {
return
}
unit := "problems"
if count == 1 {
unit = "problem"
}
var status string
switch filter {
case HWUpdated:
status = "Updated:"
case HWNew:
status = "New:"
case HWNotSubmitted:
status = "Not Submitted:"
}
summary := fmt.Sprintf("%d %s", count, unit)
var padding string
if width > len(status) {
padding = strings.Repeat(" ", width-len(status))
}
fmt.Printf(hw.template, status, padding, summary)
}
func (hw *Homework) maxTitleWidth() int {
if hw == nil {
return 0
}
var width int
for _, item := range hw.Items {
if len(item.String()) > width {
width = len(item.String())
}
}
return width
}
// Summarize prints a full report of new and updated items in the set.
func (hw *Homework) Summarize(summaryFilter SummaryOption) {
hw.Report(HWUpdated)
if summaryFilter != HWNotSubmitted {
hw.Report(HWNotSubmitted)
}
hw.Report(HWNew)
fresh := len(hw.ItemsMatching(HWNew))
updated := len(hw.ItemsMatching(HWUpdated))
unchanged := len(hw.Items) - updated - fresh
fmt.Printf("\nunchanged: %d, updated: %d, new: %d\n\n", unchanged, updated, fresh)
}