Skip to content

Commit 7d28961

Browse files
committed
Report unsubmitted exercises during fetch API
1 parent 5c3366b commit 7d28961

7 files changed

Lines changed: 75 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ The exercism CLI follows [semantic versioning](http://semver.org/).
1313
* [#153](https://github.com/exercism/cli/pull/153): Refactored configuration package - [@kytrinyx](https://github.com/kytrinyx)
1414
* [#154](https://github.com/exercism/cli/pull/154): Add 'list' command to list available exercises for a language - [@lcowell](https://github.com/lcowell)
1515
* [#157](https://github.com/exercism/cli/pull/157): Refactored API package - [@Tonkpils](https://github.com/Tonkpils)
16-
* **Your contribution here**
16+
* [#155](https://github.com/exercism/cli/pull/155): Display problems not yet submitted on fetch API - [@Tonkpils](https://github.com/Tonkpils)
17+
* Your contribution here
1718

1819
## v1.9.2 (2015-01-11)
1920

api/api.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ type PayloadSubmission struct {
3131
PayloadError
3232
}
3333

34+
// SubmissionInfo contains state information about a submission.
35+
type SubmissionInfo struct {
36+
Slug string `json:"slug"`
37+
State string `json:"state"`
38+
}
39+
3440
// Fetch retrieves problems from the API.
3541
// In most cases these problems consist of a test suite and a README
3642
// from the x-api, but it is also used when restoring earlier iterations.
@@ -62,7 +68,7 @@ func (c *Client) Fetch(args []string) ([]*Problem, error) {
6268
}
6369

6470
if res.StatusCode != http.StatusOK {
65-
return nil, fmt.Errorf(`unable to fetch problems (HTTP: %d) - %s`, res.StatusCode, payload.Error)
71+
return nil, fmt.Errorf("unable to fetch problems (HTTP: %d) - %s", res.StatusCode, payload.Error)
6672
}
6773

6874
return payload.Problems, nil
@@ -83,12 +89,28 @@ func (c *Client) Restore() ([]*Problem, error) {
8389
}
8490

8591
if res.StatusCode != http.StatusOK {
86-
return nil, fmt.Errorf(`unable to fetch problems (HTTP: %d) - %s`, res.StatusCode, payload.Error)
92+
return nil, fmt.Errorf("unable to fetch problems (HTTP: %d) - %s", res.StatusCode, payload.Error)
8793
}
8894

8995
return payload.Problems, nil
9096
}
9197

98+
// Submissions gets a list of submitted exercises and their current acceptance state.
99+
func (c *Client) Submissions() (map[string][]SubmissionInfo, error) {
100+
url := fmt.Sprintf("%s/api/v1/exercises?key=%s", c.APIHost, c.APIKey)
101+
req, err := c.NewRequest("GET", url, nil)
102+
if err != nil {
103+
return nil, err
104+
}
105+
106+
var payload map[string][]SubmissionInfo
107+
if _, err := c.Do(req, &payload); err != nil {
108+
return nil, err
109+
}
110+
111+
return payload, nil
112+
}
113+
92114
// Download fetches a solution by submission key and writes it to disk.
93115
func (c *Client) Download(submissionID string) (*Submission, error) {
94116
url := fmt.Sprintf("%s/api/v1/submissions/%s", c.APIHost, submissionID)
@@ -126,7 +148,7 @@ func (c *Client) Demo() ([]*Problem, error) {
126148
}
127149

128150
if res.StatusCode != http.StatusOK {
129-
return nil, fmt.Errorf(`unable to fetch problems (HTTP: %d) - %s`, res.StatusCode, payload.Error)
151+
return nil, fmt.Errorf("unable to fetch problems (HTTP: %d) - %s", res.StatusCode, payload.Error)
130152
}
131153

132154
return payload.Problems, nil
@@ -152,7 +174,7 @@ func (c *Client) Submit(iter *Iteration) (*Submission, error) {
152174
}
153175

154176
if res.StatusCode != http.StatusCreated {
155-
return nil, fmt.Errorf(`unable to submit (HTTP: %d) - %s`, res.StatusCode, ps.Error)
177+
return nil, fmt.Errorf("unable to submit (HTTP: %d) - %s", res.StatusCode, ps.Error)
156178
}
157179

158180
return ps.Submission, nil

api/problem.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import "fmt"
44

55
// Problem represents a specific problem in a given language track.
66
type Problem struct {
7-
ID string `json:"id"`
8-
TrackID string `json:"track_id"`
9-
Language string `json:"language"`
10-
Slug string `json:"slug"`
11-
Name string `json:"name"`
12-
Files map[string]string `json:"files"`
7+
ID string `json:"id"`
8+
TrackID string `json:"track_id"`
9+
Language string `json:"language"`
10+
Slug string `json:"slug"`
11+
Name string `json:"name"`
12+
Files map[string]string `json:"files"`
13+
Submitted bool
1314
}
1415

1516
func (p *Problem) String() string {

cmd/fetch.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,32 @@ func Fetch(ctx *cli.Context) {
2222
log.Fatal(err)
2323
}
2424

25+
submissionInfo, err := client.Submissions()
26+
if err != nil {
27+
log.Fatal(err)
28+
}
29+
30+
if err := setSubmissionState(problems, submissionInfo); err != nil {
31+
log.Fatal(err)
32+
}
33+
2534
hw := user.NewHomework(problems, c)
2635
if err := hw.Save(); err != nil {
2736
log.Fatal(err)
2837
}
2938

30-
hw.Summarize()
39+
hw.Summarize(user.HWAll)
40+
}
41+
42+
func setSubmissionState(problems []*api.Problem, submissionInfo map[string][]api.SubmissionInfo) error {
43+
for _, problem := range problems {
44+
langSubmissions := submissionInfo[problem.Language]
45+
for _, submission := range langSubmissions {
46+
if submission.Slug == problem.Slug {
47+
problem.Submitted = true
48+
}
49+
}
50+
}
51+
52+
return nil
3153
}

cmd/restore.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ func Restore(ctx *cli.Context) {
2727
if err := hw.Save(); err != nil {
2828
log.Fatal(err)
2929
}
30-
hw.Summarize()
30+
hw.Summarize(user.HWNotSubmitted)
3131
}

user/homework.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import (
1010
// HWFilter is used to categorize homework items.
1111
type HWFilter int
1212

13+
// SummaryOption is an alias of HWFilter that allows
14+
// selective display of summary items
15+
type SummaryOption HWFilter
16+
1317
const (
1418
// HWAll represents all items in the collection.
1519
HWAll = iota
@@ -19,6 +23,9 @@ const (
1923
// HWNew represents problems that did not yet exist on the
2024
// user's filesystem.
2125
HWNew
26+
// HWNotSubmitted represents problems that have not been submitted
27+
// for review.
28+
HWNotSubmitted
2229
)
2330

2431
// Homework is a collection of problems that were fetched from the APIs.
@@ -96,6 +103,8 @@ func (hw *Homework) heading(filter HWFilter, count int) {
96103
status = "Updated:"
97104
case HWNew:
98105
status = "New:"
106+
case HWNotSubmitted:
107+
status = "Not Submitted:"
99108
}
100109
summary := fmt.Sprintf("%d %s", count, unit)
101110
fmt.Printf(hw.template, status, summary)
@@ -112,10 +121,14 @@ func (hw *Homework) maxTitleWidth() int {
112121
}
113122

114123
// Summarize prints a full report of new and updated items in the set.
115-
func (hw *Homework) Summarize() {
124+
func (hw *Homework) Summarize(summaryFilter SummaryOption) {
116125
hw.Report(HWUpdated)
117126
hw.Report(HWNew)
118127

128+
if summaryFilter != HWNotSubmitted {
129+
hw.Report(HWNotSubmitted)
130+
}
131+
119132
fresh := len(hw.ItemsMatching(HWNew))
120133
updated := len(hw.ItemsMatching(HWUpdated))
121134
unchanged := len(hw.Items) - updated - fresh

user/item.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ func (it *Item) Matches(filter HWFilter) bool {
3232
return it.isNew
3333
case HWUpdated:
3434
return it.isUpdated
35+
case HWNotSubmitted:
36+
return !it.Submitted
3537
}
3638
return true
3739
}

0 commit comments

Comments
 (0)