Skip to content

Commit

Permalink
Add very basic track endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
kytrinyx committed Oct 14, 2014
1 parent db0f990 commit 47d6fd4
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
25 changes: 25 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,28 @@ func Unsubmit(url string) error {
}
return fmt.Errorf("failed to unsubmit - %s", pe.Error)
}

// Tracks gets the current list of active and inactive language tracks.
func Tracks(url string) ([]*Track, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return []*Track{}, err
}
req.Header.Set("User-Agent", UserAgent)

res, err := http.DefaultClient.Do(req)
if err != nil {
return []*Track{}, err
}
defer res.Body.Close()

var payload struct {
Tracks []*Track
}
dec := json.NewDecoder(res.Body)
err = dec.Decode(&payload)
if err != nil {
return []*Track{}, err
}
return payload.Tracks, nil
}
20 changes: 20 additions & 0 deletions api/track.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package api

import "fmt"

// Track is a collection of problems in a given language.
type Track struct {
ID string `json:"id"`
Language string `json:"language"`
Active bool `json:"active"`
Problems []string `json:"problems"`
}

// Len lists the number of problems a track has.
func (t *Track) Len() int {
return len(t.Problems)
}

func (t *Track) String() string {
return fmt.Sprintf("%s (%s)", t.Language, t.ID)
}
37 changes: 37 additions & 0 deletions cmd/tracks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmd

import (
"fmt"
"log"

"github.com/codegangsta/cli"
"github.com/exercism/cli/api"
"github.com/exercism/cli/config"
"github.com/exercism/cli/user"
)

// Tracks lists available tracks.
func Tracks(ctx *cli.Context) {
c, err := config.Read(ctx.GlobalString("config"))
if err != nil {
log.Fatal(err)
}

tracks, err := api.Tracks(fmt.Sprintf("%s/tracks", c.XAPI))
if err != nil {
log.Fatal(err)
}

curr := user.NewCurriculum(tracks)
fmt.Println("\nActive language tracks:")
curr.Report(user.TrackActive)
fmt.Println("\nInactive language tracks:")
curr.Report(user.TrackInactive)

// TODO: implement `list` command to list problems in a track
msg := `
Related commands:
exercism fetch (see 'exercism help fetch')
`
fmt.Println(msg)
}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
descRestore = "Restores completed and current problems on from exercism.io, along with your most recent iteration for each."
descSubmit = "Submits a new iteration to a problem on exercism.io."
descUnsubmit = "Deletes the most recently submitted iteration."
descTracks = "List the available language tracks"
descLogin = "DEPRECATED: Interactively saves exercism.io api credentials."
descLogout = "DEPRECATED: Clear exercism.io api credentials"

Expand Down Expand Up @@ -112,6 +113,12 @@ func main() {
Usage: descUnsubmit,
Action: cmd.Unsubmit,
},
{
Name: "tracks",
ShortName: "t",
Usage: descTracks,
Action: cmd.Tracks,
},
}
if err := app.Run(os.Args); err != nil {

Expand Down
77 changes: 77 additions & 0 deletions user/curriculum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package user

import (
"fmt"
"strings"

"github.com/exercism/cli/api"
)

// Status is the status of a track (active/inactive).
type Status bool

const (
// TrackActive represents an active track.
// Problems from active tracks will be delivered with the `fetch` command.
TrackActive Status = true
// TrackInactive represents an inactive track.
// It is possible to fetch problems from an inactive track, and
// submit them to the website, but these will not automatically be
// delivered in the global `fetch` command.
TrackInactive Status = false
)

// Curriculum is a collection of language tracks.
type Curriculum struct {
Tracks []*api.Track
wLang int
wID int
}

// NewCurriculum returns a collection of language tracks.
func NewCurriculum(tracks []*api.Track) *Curriculum {
return &Curriculum{Tracks: tracks}
}

// Report creates a table of the tracks that have the requested status.
func (cur *Curriculum) Report(status Status) {
for _, track := range cur.Tracks {
if Status(track.Active) == status {
fmt.Println(
" ",
track.Language,
strings.Repeat(" ", cur.lenLang()-len(track.Language)+1),
track.ID,
strings.Repeat(" ", cur.lenID()-len(track.ID)+1),
track.Len(),
"problems",
)
}
}
}

func (cur *Curriculum) lenLang() int {
if cur.wLang > 0 {
return cur.wLang
}

for _, track := range cur.Tracks {
if len(track.Language) > cur.wLang {
cur.wLang = len(track.Language)
}
}
return cur.wLang
}

func (cur *Curriculum) lenID() int {
if cur.wID > 0 {
return cur.wID
}

for _, track := range cur.Tracks {
if len(track.ID) > cur.wID {
cur.wID = len(track.ID)
}
}
return cur.wID
}

0 comments on commit 47d6fd4

Please sign in to comment.