<commit_before>package chromedp_test

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
	"github.com/chromedp/chromedp/device"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func ExampleTitle() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

	<title>fancy website title</title>

	`))
	defer ts.Close()

	var title string
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Title(&title),
	); err != nil {
		panic(err)
	}
	fmt.Println(title)

	// Output:
	// fancy website title
}

func ExampleExecAllocator() {
	dir, err := ioutil.TempDir("", "chromedp-example")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(dir)

	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.DisableGPU,
		chromedp.UserDataDir(dir),
	)

	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	// also set up a custom logger
	taskCtx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
	defer cancel()

	// ensure that the browser process is started
	if err := chromedp.Run(taskCtx); err != nil {
		panic(err)
	}

	path := filepath.Join(dir, "DevToolsActivePort")
	bs, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	lines := bytes.Split(bs, []byte("\n"))
	fmt.Printf("DevToolsActivePort has %d lines\n", len(lines))

	// Output:
	// DevToolsActivePort has 2 lines
}

func ExampleNewContext_manyTabs() {
	// new browser, first tab
	ctx1, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// ensure the first tab is created
	if err := chromedp.Run(ctx1); err != nil {
		panic(err)
	}

	// same browser, second tab
	ctx2, _ := chromedp.NewContext(ctx1)

	// ensure the second tab is created
	if err := chromedp.Run(ctx2); err != nil {
		panic(err)
	}

	c1 := chromedp.FromContext(ctx1)
	c2 := chromedp.FromContext(ctx2)

	fmt.Printf("Same browser: %t\n", c1.Browser == c2.Browser)
	fmt.Printf("Same tab: %t\n", c1.Target == c2.Target)

	// Output:
	// Same browser: true
	// Same tab: false
}

func ExampleListenTarget_consoleLog() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

	`))
	defer ts.Close()

	chromedp.ListenTarget(ctx, func(ev interface{}) {
		switch ev := ev.(type) {
		case *runtime.EventConsoleAPICalled:
			fmt.Printf("console.%s call:\n", ev.Type)
			for _, arg := range ev.Args {
				fmt.Printf("%s - %s\n", arg.Type, arg.Value)
			}
		}
	})

	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.WaitVisible("#jsFinished", chromedp.ByID),
	); err != nil {
		panic(err)
	}

	// Output:
	// console.log call:
	// string - "hello js world"
}

func ExampleWaitNewTarget() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.Handle("/first", writeHTML(`
<input id='newtab' type='button' value='open' onclick='window.open("/second", "_blank");'/>
	`))
	mux.Handle("/second", writeHTML(``))
	ts := httptest.NewServer(mux)
	defer ts.Close()

	// Grab the first spawned tab that isn't blank.
	ch := chromedp.WaitNewTarget(ctx, func(info *target.Info) bool {
		return info.URL != ""
	})
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL+"/first"),
		chromedp.Click("#newtab", chromedp.ByID),
	); err != nil {
		panic(err)
	}
	newCtx, cancel := chromedp.NewContext(ctx, chromedp.WithTargetID(<-ch))
	defer cancel()

	var urlstr string
	if err := chromedp.Run(newCtx, chromedp.Location(&urlstr)); err != nil {
		panic(err)
	}
	fmt.Println("new tab's path:", strings.TrimPrefix(urlstr, ts.URL))

	// Output:
	// new tab's path: /second
}

func ExampleListenTarget_acceptAlert() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.Handle("/second", writeHTML(``))
	ts := httptest.NewServer(writeHTML(`
<input id='alert' type='button' value='alert' onclick='alert("alert text");'/>
	`))
	defer ts.Close()

	chromedp.ListenTarget(ctx, func(ev interface{}) {
		if ev, ok := ev.(*page.EventJavascriptDialogOpening); ok {
			fmt.Println("closing alert:", ev.Message)
			go func() {
				if err := chromedp.Run(ctx,
					page.HandleJavaScriptDialog(true),
				); err != nil {
					panic(err)
				}
			}()
		}
	})

	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Click("#alert", chromedp.ByID),
	); err != nil {
		panic(err)
	}

	// Output:
	// closing alert: alert text
}

func Example_retrieveHTML() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

Original content.

	`))
	defer ts.Close()

	var outerBefore, outerAfter string
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.OuterHTML("#content", &outerBefore),
		chromedp.Click("#content", chromedp.ByID),
		chromedp.OuterHTML("#content", &outerAfter),
	); err != nil {
		panic(err)
	}
	fmt.Println("OuterHTML before clicking:")
	fmt.Println(outerBefore)
	fmt.Println("OuterHTML after clicking:")
	fmt.Println(outerAfter)

	// Output:
	// OuterHTML before clicking:
	//
Original content.

	// OuterHTML after clicking:
	//
New content!

}

func ExampleEmulate() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.Emulate(device.IPhone7),
		chromedp.Navigate(`https://google.com/`),
		chromedp.WaitVisible(`#main`, chromedp.ByID),
		chromedp.SendKeys(`input[name=q]`, "what's my user agent?\n"),
		chromedp.WaitVisible(`#rso`, chromedp.ByID),
		chromedp.CaptureScreenshot(&buf),
	); err != nil {
		panic(err)
	}

	if err := ioutil.WriteFile("google-iphone7.png", buf, 0644); err != nil {
		panic(err)
	}
}

func ExamplePrintToPDF() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.Navigate(`https://godoc.org/github.com/chromedp/chromedp`),
		chromedp.ActionFunc(func(ctx context.Context) error {
			var err error
			buf, _, err = page.PrintToPDF().
				WithDisplayHeaderFooter(false).
				WithLandscape(true).
				Do(ctx)
			return err
		}),
	); err != nil {
		panic(err)
	}

	if err := ioutil.WriteFile("page.pdf", buf, 0644); err != nil {
		panic(err)
	}
}
<commit_msg>examples: add ExampleByJSPath_OuterHTML<commit_after>package chromedp_test

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/dom"
	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
	"github.com/chromedp/chromedp/device"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func ExampleTitle() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

	<title>fancy website title</title>

	`))
	defer ts.Close()

	var title string
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Title(&title),
	); err != nil {
		panic(err)
	}
	fmt.Println(title)

	// Output:
	// fancy website title
}

func ExampleExecAllocator() {
	dir, err := ioutil.TempDir("", "chromedp-example")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(dir)

	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.DisableGPU,
		chromedp.UserDataDir(dir),
	)

	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	// also set up a custom logger
	taskCtx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
	defer cancel()

	// ensure that the browser process is started
	if err := chromedp.Run(taskCtx); err != nil {
		panic(err)
	}

	path := filepath.Join(dir, "DevToolsActivePort")
	bs, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	lines := bytes.Split(bs, []byte("\n"))
	fmt.Printf("DevToolsActivePort has %d lines\n", len(lines))

	// Output:
	// DevToolsActivePort has 2 lines
}

func ExampleNewContext_manyTabs() {
	// new browser, first tab
	ctx1, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// ensure the first tab is created
	if err := chromedp.Run(ctx1); err != nil {
		panic(err)
	}

	// same browser, second tab
	ctx2, _ := chromedp.NewContext(ctx1)

	// ensure the second tab is created
	if err := chromedp.Run(ctx2); err != nil {
		panic(err)
	}

	c1 := chromedp.FromContext(ctx1)
	c2 := chromedp.FromContext(ctx2)

	fmt.Printf("Same browser: %t\n", c1.Browser == c2.Browser)
	fmt.Printf("Same tab: %t\n", c1.Target == c2.Target)

	// Output:
	// Same browser: true
	// Same tab: false
}

func ExampleListenTarget_consoleLog() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

	`))
	defer ts.Close()

	chromedp.ListenTarget(ctx, func(ev interface{}) {
		switch ev := ev.(type) {
		case *runtime.EventConsoleAPICalled:
			fmt.Printf("console.%s call:\n", ev.Type)
			for _, arg := range ev.Args {
				fmt.Printf("%s - %s\n", arg.Type, arg.Value)
			}
		}
	})

	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.WaitVisible("#jsFinished", chromedp.ByID),
	); err != nil {
		panic(err)
	}

	// Output:
	// console.log call:
	// string - "hello js world"
}

func ExampleWaitNewTarget() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.Handle("/first", writeHTML(`
<input id='newtab' type='button' value='open' onclick='window.open("/second", "_blank");'/>
	`))
	mux.Handle("/second", writeHTML(``))
	ts := httptest.NewServer(mux)
	defer ts.Close()

	// Grab the first spawned tab that isn't blank.
	ch := chromedp.WaitNewTarget(ctx, func(info *target.Info) bool {
		return info.URL != ""
	})
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL+"/first"),
		chromedp.Click("#newtab", chromedp.ByID),
	); err != nil {
		panic(err)
	}
	newCtx, cancel := chromedp.NewContext(ctx, chromedp.WithTargetID(<-ch))
	defer cancel()

	var urlstr string
	if err := chromedp.Run(newCtx, chromedp.Location(&urlstr)); err != nil {
		panic(err)
	}
	fmt.Println("new tab's path:", strings.TrimPrefix(urlstr, ts.URL))

	// Output:
	// new tab's path: /second
}

func ExampleListenTarget_acceptAlert() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.Handle("/second", writeHTML(``))
	ts := httptest.NewServer(writeHTML(`
<input id='alert' type='button' value='alert' onclick='alert("alert text");'/>
	`))
	defer ts.Close()

	chromedp.ListenTarget(ctx, func(ev interface{}) {
		if ev, ok := ev.(*page.EventJavascriptDialogOpening); ok {
			fmt.Println("closing alert:", ev.Message)
			go func() {
				if err := chromedp.Run(ctx,
					page.HandleJavaScriptDialog(true),
				); err != nil {
					panic(err)
				}
			}()
		}
	})

	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Click("#alert", chromedp.ByID),
	); err != nil {
		panic(err)
	}

	// Output:
	// closing alert: alert text
}

func Example_retrieveHTML() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

Original content.

	`))
	defer ts.Close()

	var outerBefore, outerAfter string
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.OuterHTML("#content", &outerBefore),
		chromedp.Click("#content", chromedp.ByID),
		chromedp.OuterHTML("#content", &outerAfter),
	); err != nil {
		panic(err)
	}
	fmt.Println("OuterHTML before clicking:")
	fmt.Println(outerBefore)
	fmt.Println("OuterHTML after clicking:")
	fmt.Println(outerAfter)

	// Output:
	// OuterHTML before clicking:
	//
Original content.

	// OuterHTML after clicking:
	//
New content!

}

func ExampleEmulate() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.Emulate(device.IPhone7),
		chromedp.Navigate(`https://google.com/`),
		chromedp.WaitVisible(`#main`, chromedp.ByID),
		chromedp.SendKeys(`input[name=q]`, "what's my user agent?\n"),
		chromedp.WaitVisible(`#rso`, chromedp.ByID),
		chromedp.CaptureScreenshot(&buf),
	); err != nil {
		panic(err)
	}

	if err := ioutil.WriteFile("google-iphone7.png", buf, 0644); err != nil {
		panic(err)
	}
}

func ExamplePrintToPDF() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.Navigate(`https://godoc.org/github.com/chromedp/chromedp`),
		chromedp.ActionFunc(func(ctx context.Context) error {
			var err error
			buf, _, err = page.PrintToPDF().
				WithDisplayHeaderFooter(false).
				WithLandscape(true).
				Do(ctx)
			return err
		}),
	); err != nil {
		panic(err)
	}

	if err := ioutil.WriteFile("page.pdf", buf, 0644); err != nil {
		panic(err)
	}
}

func ExampleByJSPath_OuterHTML() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`

cool content

	`))
	defer ts.Close()

	var ids []cdp.NodeID
	var html string
	if err := chromedp.Run(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.NodeIDs(`document`, &ids, chromedp.ByJSPath),
		chromedp.ActionFunc(func(ctx context.Context) error {
			var err error
			html, err = dom.GetOuterHTML().WithNodeID(ids[0]).Do(ctx)
			return err
		}),
	); err != nil {
		panic(err)
	}

	fmt.Println("Outer HTML:")
	fmt.Println(html)

	// Output:
	// Outer HTML:
	//
	//
cool content

	//
}
<|endoftext|>


<commit_before>package gofetch_test

import (
	"fmt"
	"os"

	"github.com/c4milo/gofetch"
)

func Example() {
	gf := gofetch.New(
		gofetch.WithDestDir("/tmp"),
		gofetch.WithConcurrency(10),
		gofetch.WithETag(),
	)

	progressCh := make(chan gofetch.ProgressReport)

	var myFile *os.File
	go func() {
		var err error
		myFile, err = gf.Fetch(
			"http://releases.ubuntu.com/15.10/ubuntu-15.10-server-amd64.iso",
			progressCh)
		if err != nil {
			panic(err)
		}
	}()

	// pogressCh is closed by gofetch once a download finishes.
	var totalWritten int64
	for p := range progressCh {
		// p.WrittenBytes does not accumulate, it represents the chunk size written
		// in the current operation.
		totalWritten += p.WrittenBytes
		fmt.Printf("\r%d of %d bytes", totalWritten, p.Total)
	}
	defer myFile.Close()

	fmt.Printf("\nFile saved at %q\n", myFile.Name())
}
<commit_msg>Updates godoc example code<commit_after>package gofetch_test

import (
	"fmt"
	"os"

	"github.com/c4milo/gofetch"
)

func Example() {
	gf := gofetch.New(
		gofetch.WithDestDir("/tmp"),
		gofetch.WithConcurrency(100),
		gofetch.WithETag(),
		gofetch.WithChecksum("sha256", "29a8b9009509b39d542ecb229787cdf48f05e739a932289de9e9858d7c487c80"),
	)

	progressCh := make(chan gofetch.ProgressReport)
	doneCh := make(chan struct{})

	var myFile *os.File
	go func() {
		defer close(doneCh)

		var err error
		myFile, err = gf.Fetch(
			"http://releases.ubuntu.com/16.04.1/ubuntu-16.04.1-server-amd64.iso",
			progressCh)
		if err != nil {
			panic(err)
		}
	}()

	// pogressCh is close by gofetch once a download finishes
	var totalWritten int64
	for p := range progressCh {
		// p.WrittenBytes does not accumulate, it represents the chunk size written
		// in the current operation.
		totalWritten += p.WrittenBytes
		fmt.Printf("\r%d of %d bytes", totalWritten, p.Total)
	}

	<-doneCh
	fmt.Printf("\nFile saved at %q\n", myFile.Name())
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.nike.com/v1/me/sport/activities"

//var loginURL = "https://developer.nike.com/content/nike-developer-cq/us/en_us/index/login.html"

type nikeDataSimple struct {
	Data []struct {
		ActivityId    string
		ActivityType  string
		StartTime     string
		Status        string
		MetricSummary struct {
			Distance string
			Duration string
		}
	}
	Paging struct {
		Next     string
		Previous string
	}
}

type nikeDataComplete struct {
	Links []struct {
		Rel  string
		Href string
	}
	ActivityId       string
	ActivityType     string
	StartTime        string
	ActivityTimeZone string
	Status           string
	DeviceType       string
	MetricSummary    struct {
		Calories string
		Distance string
		Duration string
	}
	Paging struct {
		Next     string
		Previous string
	}
	Tags []struct {
		TagType  string
		TagValue string
	}
	Metrics []struct {
		IntervalMetric int16
		IntervalUnit   string
		MetricType     string
		Values         []string
	}
	IsGPSActivity  bool
	ElevationLoss  float64
	ElevationGain  float64
	ElevationMax   float64
	ElevationMin   float64
	IntervalMetric float64
	IntervalUnit   string
	Waypoints      []struct {
		Latitude  float64
		Longitude float64
		Elevation float64
	}
}

/*func main() {
	var nike nikeDataSimple
	json.Unmarshal([]byte(NikeBasic10), &nike)
	fmt.Println(nike)
}*/

func makeActivityURL(token string, count int) string {
	return baseURL + "?access_token=" + token + "&count=" + strconv.Itoa(count)
}

func makeDetailsURL(token string, activityID string) string {
	return baseURL + "/" + activityID + "?access_token=" + token
}

func makeGpsURL(token string, activityID string) string {
	return baseURL + "/" + activityID + "/gps?access_token=" + token
}

func findInterval(metric float64, interval string) time.Duration {
	switch interval {
	case "SEC":
		return time.Duration(metric) * time.Second
	case "MIN":
		return time.Duration(metric) * time.Minute
	default:
		//assume the most logical GPS measurement interval
		return time.Duration(metric) * time.Second
	}
}

func formatTimeGPS(t time.Time) string {
	return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02dZ",
		t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), t.Second())
}

func (nikeActs nikeDataComplete) makeGPX() {
	//write to the screen while we develop, eventually write to a file with
	//  the activity number as the file name
	const longForm = "2006-01-02T15:04:05Z"
	//Go time expects the refence time to be Mon Jan 2 15:04:05 MST 2006
	t, _ := time.Parse(longForm, nikeActs.StartTime)
	s := findInterval(nikeActs.IntervalMetric, nikeActs.IntervalUnit)

	fmt.Println(`<?xml version="1.0" encoding="UTF-8"?>`)
	fmt.Println(`<gpx creator="Nike2Strava" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
`)
	fmt.Println(" <metadata>")
	fmt.Println("  <time>" + nikeActs.StartTime + "</time>")
	fmt.Println(" </metadata>")
	fmt.Println(" <trk>")
	fmt.Println("  <name>" + nikeActs.StartTime + "</name>")
	fmt.Println("  <trkseg>")
	for _, m := range nikeActs.Waypoints {
		fmt.Println("   <trkpt lat=" + `"` + strconv.FormatFloat(m.Latitude, 'f', 7, 64) + `"` + " lon=" + `"` + strconv.FormatFloat(m.Longitude, 'f', 7, 64) + `">`)
		fmt.Println("    <ele>" + strconv.FormatFloat(m.Elevation, 'f', 1, 64) + "</ele>")
		fmt.Println("    <time>" + formatTimeGPS(t) + "</time>")
		fmt.Println("   </trkpt>")
		t = t.Add(s)
	}
	fmt.Println("  </trkseg>")
	fmt.Println(" </trk>")
	fmt.Println("/gpx>")
}

func (nikeActs nikeDataComplete) printDetails() {
	fmt.Println("Activity ID:", nikeActs.ActivityId)
	fmt.Println("Distance:", nikeActs.MetricSummary.Distance, "km")
	fmt.Println("Date:", nikeActs.StartTime)
	for _, m := range nikeActs.Tags {
		fmt.Println(strings.ToLower(m.TagType), ":", strings.ToLower(m.TagValue))
	}
	if nikeActs.IsGPSActivity {
		fmt.Println("Activity has GPS data:", nikeActs.IsGPSActivity)
		fmt.Println("GPS read interval is", nikeActs.IntervalMetric, strings.ToLower(nikeActs.IntervalUnit))
		fmt.Println(nikeActs.Waypoints[0].Latitude, nikeActs.Waypoints[0].Longitude)
		fmt.Println(nikeActs.Waypoints[1].Latitude, nikeActs.Waypoints[1].Longitude)
	}
	fmt.Println()
}

func getDetails(token string, activityID string, debug bool) {
	var nikeActs nikeDataComplete

	if debug {
		json.Unmarshal(NikeActDetails, &nikeActs)
		json.Unmarshal(NikeActGPS, &nikeActs)
	} else {
		url := makeDetailsURL(token, activityID)
		res, err := http.Get(url)
		if err != nil {
			panic(err.Error())
		}
		body, err := ioutil.ReadAll(res.Body)
		if err != nil {
			panic(err.Error())
		}
		json.Unmarshal(body, &nikeActs)

		if nikeActs.IsGPSActivity {
			gpsURL := makeGpsURL(token, activityID)
			res, err = http.Get(gpsURL)
			if err != nil {
				panic(err.Error())
			}
			body, err = ioutil.ReadAll(res.Body)
			if err != nil {
				panic(err.Error())
			}
			json.Unmarshal(body, &nikeActs)
		}
	}
	//nikeActs.printDetails()
	nikeActs.makeGPX()
}

func wrangleJSON(token string, numRecords int, debug bool) {

	var nikeList nikeDataSimple

	if debug {
		json.Unmarshal(NikeBasic1, &nikeList)
		//fmt.Println("Using Local Test Data")
	} else {
		fmt.Println("\nUsing live data from Nike+ API\n")
		url := makeActivityURL(token, numRecords)
		res, err := http.Get(url)

		if err != nil {
			panic(err.Error())
		}
		body, err := ioutil.ReadAll(res.Body)

		if err != nil {
			panic(err.Error())
		}

		json.Unmarshal(body, &nikeList)
	}

	for _, m := range nikeList.Data {
		if m.ActivityType == "RUN" {
			getDetails(token, m.ActivityId, debug)
		}
	}
}
<commit_msg>Creates GPX file with incorrect time stamps<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.nike.com/v1/me/sport/activities"

//var loginURL = "https://developer.nike.com/content/nike-developer-cq/us/en_us/index/login.html"

type nikeDataSimple struct {
	Data []struct {
		ActivityId    string
		ActivityType  string
		StartTime     string
		Status        string
		MetricSummary struct {
			Distance string
			Duration string
		}
	}
	Paging struct {
		Next     string
		Previous string
	}
}

type nikeDataComplete struct {
	Links []struct {
		Rel  string
		Href string
	}
	ActivityId       string
	ActivityType     string
	StartTime        string
	ActivityTimeZone string
	Status           string
	DeviceType       string
	MetricSummary    struct {
		Calories string
		Distance string
		Duration string
	}
	Paging struct {
		Next     string
		Previous string
	}
	Tags []struct {
		TagType  string
		TagValue string
	}
	Metrics []struct {
		IntervalMetric int16
		IntervalUnit   string
		MetricType     string
		Values         []string
	}
	IsGPSActivity  bool
	ElevationLoss  float64
	ElevationGain  float64
	ElevationMax   float64
	ElevationMin   float64
	IntervalMetric float64
	IntervalUnit   string
	Waypoints      []struct {
		Latitude  float64
		Longitude float64
		Elevation float64
	}
}

/*func main() {
	var nike nikeDataSimple
	json.Unmarshal([]byte(NikeBasic10), &nike)
	fmt.Println(nike)
}*/

func makeActivityURL(token string, count int) string {
	return baseURL + "?access_token=" + token + "&count=" + strconv.Itoa(count)
}

func makeDetailsURL(token string, activityID string) string {
	return baseURL + "/" + activityID + "?access_token=" + token
}

func makeGpsURL(token string, activityID string) string {
	return baseURL + "/" + activityID + "/gps?access_token=" + token
}

func findInterval(metric float64, interval string) time.Duration {
	switch interval {
	case "SEC":
		return time.Duration(metric) * time.Second
	case "MIN":
		return time.Duration(metric) * time.Minute
	default:
		//assume the most logical GPS measurement interval
		return time.Duration(metric) * time.Second
	}
}

func formatTimeGPS(t time.Time) string {
	return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02dZ",
		t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), t.Second())
}

func (nikeActs nikeDataComplete) makeGPX() {
	//write to the screen while we develop, eventually write to a file with
	//  the activity number as the file name
	const longForm = "2006-01-02T15:04:05Z"
	//Go time expects the refence time to be Mon Jan 2 15:04:05 MST 2006
	t, _ := time.Parse(longForm, nikeActs.StartTime)
	s := findInterval(nikeActs.IntervalMetric, nikeActs.IntervalUnit)

	fmt.Println(`<?xml version="1.0" encoding="UTF-8"?>`)
	fmt.Println(`<gpx creator="Nike2Strava" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
`)
	fmt.Println(" <metadata>")
	fmt.Println("  <time>" + nikeActs.StartTime + "</time>")
	fmt.Println(" </metadata>")
	fmt.Println(" <trk>")
	fmt.Println("  <name>" + nikeActs.StartTime + "</name>")
	fmt.Println("  <trkseg>")
	for _, m := range nikeActs.Waypoints {
		fmt.Println("   <trkpt lat=" + `"` + strconv.FormatFloat(m.Latitude, 'f', 7, 64) + `"` + " lon=" + `"` + strconv.FormatFloat(m.Longitude, 'f', 7, 64) + `">`)
		fmt.Println("    <ele>" + strconv.FormatFloat(m.Elevation, 'f', 1, 64) + "</ele>")
		fmt.Println("    <time>" + formatTimeGPS(t) + "</time>")
		fmt.Println("   </trkpt>")
		t = t.Add(s)
	}
	fmt.Println("  </trkseg>")
	fmt.Println(" </trk>")
	fmt.Println("</gpx>")
}

func (nikeActs nikeDataComplete) printDetails() {
	fmt.Println("Activity ID:", nikeActs.ActivityId)
	fmt.Println("Distance:", nikeActs.MetricSummary.Distance, "km")
	fmt.Println("Date:", nikeActs.StartTime)
	for _, m := range nikeActs.Tags {
		fmt.Println(strings.ToLower(m.TagType), ":", strings.ToLower(m.TagValue))
	}
	if nikeActs.IsGPSActivity {
		fmt.Println("Activity has GPS data:", nikeActs.IsGPSActivity)
		fmt.Println("GPS read interval is", nikeActs.IntervalMetric, strings.ToLower(nikeActs.IntervalUnit))
		fmt.Println(nikeActs.Waypoints[0].Latitude, nikeActs.Waypoints[0].Longitude)
		fmt.Println(nikeActs.Waypoints[1].Latitude, nikeActs.Waypoints[1].Longitude)
	}
	fmt.Println()
}

func getDetails(token string, activityID string, debug bool) {
	var nikeActs nikeDataComplete

	if debug {
		json.Unmarshal(NikeActDetails, &nikeActs)
		json.Unmarshal(NikeActGPS, &nikeActs)
	} else {
		url := makeDetailsURL(token, activityID)
		res, err := http.Get(url)
		if err != nil {
			panic(err.Error())
		}
		body, err := ioutil.ReadAll(res.Body)
		if err != nil {
			panic(err.Error())
		}
		json.Unmarshal(body, &nikeActs)

		if nikeActs.IsGPSActivity {
			gpsURL := makeGpsURL(token, activityID)
			res, err = http.Get(gpsURL)
			if err != nil {
				panic(err.Error())
			}
			body, err = ioutil.ReadAll(res.Body)
			if err != nil {
				panic(err.Error())
			}
			json.Unmarshal(body, &nikeActs)
		}
	}
	//nikeActs.printDetails()
	nikeActs.makeGPX()
}

func wrangleJSON(token string, numRecords int, debug bool) {

	var nikeList nikeDataSimple

	if debug {
		json.Unmarshal(NikeBasic1, &nikeList)
		//fmt.Println("Using Local Test Data")
	} else {
		fmt.Println("\nUsing live data from Nike+ API\n")
		url := makeActivityURL(token, numRecords)
		res, err := http.Get(url)

		if err != nil {
			panic(err.Error())
		}
		body, err := ioutil.ReadAll(res.Body)

		if err != nil {
			panic(err.Error())
		}

		json.Unmarshal(body, &nikeList)
	}

	for _, m := range nikeList.Data {
		if m.ActivityType == "RUN" {
			getDetails(token, m.ActivityId, debug)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Marcel Gotsch. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package goserv_test

import (
	"github.com/gotschmarcel/goserv"
	"log"
	"net/http"
)

func ExampleServer_simple() {
	// A simple server example.
	//
	// First an access logging function is registered which gets invoked
	// before the request is forwarded to the home handler. After that
	// the home handler is registered which is the final handler writing
	// a simple message to the response body.
	//
	// As a last step server.Listen is called to start listening for incoming
	// requests.
	server := goserv.NewServer()

	server.Use(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Access %s %s", r.Method, r.URL.String())
	}).Get("/", func(w http.ResponseWriter, r *http.Request) {
		goserv.WriteString(w, "Welcome Home")
	})

	log.Fatalln(server.Listen(":12345"))
}

func ExampleServer_subrouter() {
	// Example server with API sub router:
	server := goserv.NewServer()

	apiRouter := server.SubRouter("/api")

	apiRouter.Get("/users", func(w http.ResponseWriter, r *http.Request) {
		// ...
	})

	apiRouter.Get("/users/:user_id", func(w http.ResponseWriter, r *http.Request) {
		// ...
	})

	apiRouter.Param("user_id", func(w http.ResponseWriter, r *http.Request, val string) {
		// ...
	})

	log.Fatalln(server.Listen(":8080"))
}

func ExampleServer_static() {
	// Example file server:
	server := goserv.NewServer()

	server.SubRouter("/").UseHandler(goserv.FileServer("/usr/share/doc", "/", ""))
	log.Fatalln(server.Listen(":12345"))
}
<commit_msg>Add json and context examples<commit_after>// Copyright 2016 Marcel Gotsch. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package goserv_test

import (
	"github.com/gotschmarcel/goserv"
	"log"
	"net/http"
)

func ExampleServer_simple() {
	// A simple server example.
	//
	// First an access logging function is registered which gets invoked
	// before the request is forwarded to the home handler. After that
	// the home handler is registered which is the final handler writing
	// a simple message to the response body.
	//
	// As a last step server.Listen is called to start listening for incoming
	// requests.
	server := goserv.NewServer()

	server.Use(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Access %s %s", r.Method, r.URL.String())
	}).Get("/", func(w http.ResponseWriter, r *http.Request) {
		goserv.WriteString(w, "Welcome Home")
	})

	log.Fatalln(server.Listen(":12345"))
}

func ExampleServer_subrouter() {
	// Example server with API sub router:
	server := goserv.NewServer()

	apiRouter := server.SubRouter("/api")

	apiRouter.Get("/users", func(w http.ResponseWriter, r *http.Request) {
		// ...
	})

	apiRouter.Get("/users/:user_id", func(w http.ResponseWriter, r *http.Request) {
		// ...
	})

	apiRouter.Param("user_id", func(w http.ResponseWriter, r *http.Request, val string) {
		// ...
	})

	log.Fatalln(server.Listen(":8080"))
}

func ExampleServer_static() {
	// Example file server:
	server := goserv.NewServer()

	server.SubRouter("/").UseHandler(goserv.FileServer("/home/myfile", "/", "index.html"))
	log.Fatalln(server.Listen(":12345"))
}

func ExampleServer_context() {
	// Share data between handlers:
	//
	// The middleware stores a shared value in the RequestContext under the name "shared".
	// The GET handler is the next handler in line and retrieves the value from the
	// context. Since a RequestContext can store arbitrary types a type assertion
	// is necessary to get the value in it's real type.
	server := goserv.NewServer()

	server.Use(func(w http.ResponseWriter, r *http.Request) {
		goserv.Context(r).Set("shared", "something to share")
	})

	server.Get("/", func(w http.ResponseWriter, r *http.Request) {
		shared := goserv.Context(r).Get("shared").(string)
		goserv.WriteString(w, shared)
	})

	log.Fatalln(server.Listen(":12345"))
}

func ExampleServer_json() {
	// Example server showing how to read and write JSON body:
	//
	// Since WriteJSON and ReadJSONBody are based on the encoding/json
	// package of the standard library the usage is very similar.
	// One thing to notice is that occuring errors are passed to
	// the RequestContext which stops further processing and passes
	// the error to the server's error handler.
	server := goserv.NewServer()

	// Send a simple JSON response.
	server.Get("/", func(w http.ResponseWriter, r *http.Request) {
		// JSON data to send.
		data := &struct{ Title string }{"My First Todo"}

		// Try to write the data.
		// In case of an error pass it to the RequestContext
		// so it gets forwarded to the next error handler.
		if err := goserv.WriteJSON(w, data); err != nil {
			goserv.Context(r).Error(err, http.StatusInternalServerError)
			return
		}
	})

	// Handle send JSON data.
	server.Post("/", func(w http.ResponseWriter, r *http.Request) {
		var data struct{ Title string }

		// Read and decode the request's body.
		// In case of an error pass it to the RequestContext
		// so it gets forwarded to the next error handler.
		if err := goserv.ReadJSONBody(r, &data); err != nil {
			goserv.Context(r).Error(err, http.StatusBadRequest)
			return
		}

		log.Println(data)
	})

	log.Fatalln(server.Listen(":12345"))
}
<|endoftext|>


<commit_before>package commands

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"../interpreter"
)

func cmd_if(ctx context.Context, cmd *exec.Cmd) (int, error) {
	// if "xxx" == "yyy"
	args := cmd.Args
	not := false
	start := 1

	if len(args) >= 2 && args[1] == "not" {
		not = true
		args = args[1:]
		start++
	}
	status := false
	if len(args) >= 4 && args[2] == "==" {
		status = (args[1] == args[3])
		args = args[4:]
		start += 3
	} else if len(args) >= 3 && args[1] == "exist" {
		_, err := os.Stat(args[2])
		status = (err == nil)
		args = args[3:]
		start += 2
	}
	if not {
		status = !status
	}
	if status {
		it_ := ctx.Value("interpreter")
		if it, ok := it_.(*interpreter.Interpreter); ok {
			return it.InterpretContext(ctx, strings.Join(it.RawArgs[start:], " "))
		} else {
			fmt.Fprintln(cmd.Stderr, "if: not found sub shell instance")
		}
	}
	return 1, nil
}
<commit_msg>if - ignore case 'NOT' and 'EXIST'<commit_after>package commands

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"../interpreter"
)

func cmd_if(ctx context.Context, cmd *exec.Cmd) (int, error) {
	// if "xxx" == "yyy"
	args := cmd.Args
	not := false
	start := 1

	if len(args) >= 2 && strings.EqualFold(args[1], "not") {
		not = true
		args = args[1:]
		start++
	}
	status := false
	if len(args) >= 4 && args[2] == "==" {
		status = (args[1] == args[3])
		args = args[4:]
		start += 3
	} else if len(args) >= 3 && strings.EqualFold(args[1], "exist") {
		_, err := os.Stat(args[2])
		status = (err == nil)
		args = args[3:]
		start += 2
	}

	if not {
		status = !status
	}
	if status {
		it_ := ctx.Value("interpreter")
		if it, ok := it_.(*interpreter.Interpreter); ok {
			return it.InterpretContext(ctx, strings.Join(it.RawArgs[start:], " "))
		} else {
			fmt.Fprintln(cmd.Stderr, "if: not found sub shell instance")
		}
	}
	return 1, nil
}
<|endoftext|>


<commit_before>package storage

import (
	"fmt"

	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/manifest/schema1"
	"github.com/docker/distribution/reference"
	"github.com/docker/libtrust"
)

type manifestStore struct {
	repository                 *repository
	revisionStore              *revisionStore
	tagStore                   *tagStore
	ctx                        context.Context
	skipDependencyVerification bool
}

var _ distribution.ManifestService = &manifestStore{}

func (ms *manifestStore) Exists(dgst digest.Digest) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Exists")

	_, err := ms.revisionStore.blobStore.Stat(ms.ctx, dgst)
	if err != nil {
		if err == distribution.ErrBlobUnknown {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

func (ms *manifestStore) Get(dgst digest.Digest) (*schema1.SignedManifest, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Get")
	return ms.revisionStore.get(ms.ctx, dgst)
}

// SkipLayerVerification allows a manifest to be Put before it's
// layers are on the filesystem
func SkipLayerVerification(ms distribution.ManifestService) error {
	if ms, ok := ms.(*manifestStore); ok {
		ms.skipDependencyVerification = true
		return nil
	}
	return fmt.Errorf("skip layer verification only valid for manifestStore")
}

func (ms *manifestStore) Put(manifest *schema1.SignedManifest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Put")

	if err := ms.verifyManifest(ms.ctx, manifest); err != nil {
		return err
	}

	// Store the revision of the manifest
	revision, err := ms.revisionStore.put(ms.ctx, manifest)
	if err != nil {
		return err
	}

	// Now, tag the manifest
	return ms.tagStore.tag(manifest.Tag, revision.Digest)
}

// Delete removes the revision of the specified manfiest.
func (ms *manifestStore) Delete(dgst digest.Digest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Delete")
	return ms.revisionStore.delete(ms.ctx, dgst)
}

func (ms *manifestStore) Tags() ([]string, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Tags")
	return ms.tagStore.tags()
}

func (ms *manifestStore) ExistsByTag(tag string) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).ExistsByTag")
	return ms.tagStore.exists(tag)
}

func (ms *manifestStore) GetByTag(tag string, options ...distribution.ManifestServiceOption) (*schema1.SignedManifest, error) {
	for _, option := range options {
		err := option(ms)
		if err != nil {
			return nil, err
		}
	}

	context.GetLogger(ms.ctx).Debug("(*manifestStore).GetByTag")
	dgst, err := ms.tagStore.resolve(tag)
	if err != nil {
		return nil, err
	}

	return ms.revisionStore.get(ms.ctx, dgst)
}

// verifyManifest ensures that the manifest content is valid from the
// perspective of the registry. It ensures that the signature is valid for the
// enclosed payload. As a policy, the registry only tries to store valid
// content, leaving trust policies of that content up to consumers.
func (ms *manifestStore) verifyManifest(ctx context.Context, mnfst *schema1.SignedManifest) error {
	var errs distribution.ErrManifestVerification

	if len(mnfst.Name) > reference.NameTotalLengthMax {
		errs = append(errs, fmt.Errorf("manifest name must not be more than %v characters", reference.NameTotalLengthMax))
	}

	if len(mnfst.History) != len(mnfst.FSLayers) {
		errs = append(errs, fmt.Errorf("mismatched history and fslayer cardinality %d != %d",
			len(mnfst.History), len(mnfst.FSLayers)))
	}

	if _, err := schema1.Verify(mnfst); err != nil {
		switch err {
		case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
			errs = append(errs, distribution.ErrManifestUnverified{})
		default:
			if err.Error() == "invalid signature" { // TODO(stevvooe): This should be exported by libtrust
				errs = append(errs, distribution.ErrManifestUnverified{})
			} else {
				errs = append(errs, err)
			}
		}
	}

	if !ms.skipDependencyVerification {
		for _, fsLayer := range mnfst.FSLayers {
			_, err := ms.repository.Blobs(ctx).Stat(ctx, fsLayer.BlobSum)
			if err != nil {
				if err != distribution.ErrBlobUnknown {
					errs = append(errs, err)
				}

				// On error here, we always append unknown blob errors.
				errs = append(errs, distribution.ErrManifestBlobUnknown{Digest: fsLayer.BlobSum})
			}
		}
	}
	if len(errs) != 0 {
		return errs
	}

	return nil
}
<commit_msg>Verify manifest name format<commit_after>package storage

import (
	"fmt"

	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/manifest/schema1"
	"github.com/docker/distribution/reference"
	"github.com/docker/libtrust"
)

type manifestStore struct {
	repository                 *repository
	revisionStore              *revisionStore
	tagStore                   *tagStore
	ctx                        context.Context
	skipDependencyVerification bool
}

var _ distribution.ManifestService = &manifestStore{}

func (ms *manifestStore) Exists(dgst digest.Digest) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Exists")

	_, err := ms.revisionStore.blobStore.Stat(ms.ctx, dgst)
	if err != nil {
		if err == distribution.ErrBlobUnknown {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

func (ms *manifestStore) Get(dgst digest.Digest) (*schema1.SignedManifest, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Get")
	return ms.revisionStore.get(ms.ctx, dgst)
}

// SkipLayerVerification allows a manifest to be Put before it's
// layers are on the filesystem
func SkipLayerVerification(ms distribution.ManifestService) error {
	if ms, ok := ms.(*manifestStore); ok {
		ms.skipDependencyVerification = true
		return nil
	}
	return fmt.Errorf("skip layer verification only valid for manifestStore")
}

func (ms *manifestStore) Put(manifest *schema1.SignedManifest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Put")

	if err := ms.verifyManifest(ms.ctx, manifest); err != nil {
		return err
	}

	// Store the revision of the manifest
	revision, err := ms.revisionStore.put(ms.ctx, manifest)
	if err != nil {
		return err
	}

	// Now, tag the manifest
	return ms.tagStore.tag(manifest.Tag, revision.Digest)
}

// Delete removes the revision of the specified manfiest.
func (ms *manifestStore) Delete(dgst digest.Digest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Delete")
	return ms.revisionStore.delete(ms.ctx, dgst)
}

func (ms *manifestStore) Tags() ([]string, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Tags")
	return ms.tagStore.tags()
}

func (ms *manifestStore) ExistsByTag(tag string) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).ExistsByTag")
	return ms.tagStore.exists(tag)
}

func (ms *manifestStore) GetByTag(tag string, options ...distribution.ManifestServiceOption) (*schema1.SignedManifest, error) {
	for _, option := range options {
		err := option(ms)
		if err != nil {
			return nil, err
		}
	}

	context.GetLogger(ms.ctx).Debug("(*manifestStore).GetByTag")
	dgst, err := ms.tagStore.resolve(tag)
	if err != nil {
		return nil, err
	}

	return ms.revisionStore.get(ms.ctx, dgst)
}

// verifyManifest ensures that the manifest content is valid from the
// perspective of the registry. It ensures that the signature is valid for the
// enclosed payload. As a policy, the registry only tries to store valid
// content, leaving trust policies of that content up to consumers.
func (ms *manifestStore) verifyManifest(ctx context.Context, mnfst *schema1.SignedManifest) error {
	var errs distribution.ErrManifestVerification

	if len(mnfst.Name) > reference.NameTotalLengthMax {
		errs = append(errs, fmt.Errorf("manifest name must not be more than %v characters", reference.NameTotalLengthMax))
	}

	if !reference.NameRegexp.MatchString(mnfst.Name) {
		errs = append(errs, fmt.Errorf("invalid manifest name format"))
	}

	if len(mnfst.History) != len(mnfst.FSLayers) {
		errs = append(errs, fmt.Errorf("mismatched history and fslayer cardinality %d != %d",
			len(mnfst.History), len(mnfst.FSLayers)))
	}

	if _, err := schema1.Verify(mnfst); err != nil {
		switch err {
		case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
			errs = append(errs, distribution.ErrManifestUnverified{})
		default:
			if err.Error() == "invalid signature" { // TODO(stevvooe): This should be exported by libtrust
				errs = append(errs, distribution.ErrManifestUnverified{})
			} else {
				errs = append(errs, err)
			}
		}
	}

	if !ms.skipDependencyVerification {
		for _, fsLayer := range mnfst.FSLayers {
			_, err := ms.repository.Blobs(ctx).Stat(ctx, fsLayer.BlobSum)
			if err != nil {
				if err != distribution.ErrBlobUnknown {
					errs = append(errs, err)
				}

				// On error here, we always append unknown blob errors.
				errs = append(errs, distribution.ErrManifestBlobUnknown{Digest: fsLayer.BlobSum})
			}
		}
	}
	if len(errs) != 0 {
		return errs
	}

	return nil
}
<|endoftext|>


<commit_before>package victor

import (
    "github.com/brettbuddin/victor/utils/google"
    "strconv"
)

func registerDefaultAbilities(brain *Brain) {
    brain.Respond("me id", func(ctx *Context) {
        id := strconv.Itoa(ctx.Message().UserId())
        ctx.Reply(id)
    })

    brain.Respond("ping", func(ctx *Context) {
        ctx.Reply("pong!")
    })

    brain.Respond("(image|img|gif|animate) (.*)", func(ctx *Context) {
        gifOnly := (ctx.Matches()[1] == "gif" || ctx.Matches()[1] == "animate")

        result, err := google.ImageSearch(ctx.Matches()[2], gifOnly)

        if err != nil {
            ctx.Send("There was error making the request.")
            return
        }

        if result == "" {
            ctx.Send("I didn't find anything.")
            return
        }

        ctx.Send(result)
    })

    brain.Respond("users (list|show)", func(ctx *Context) {
        list := ""

        for _, user := range brain.Users() {
            list += user.Name() + "\n"
        }

        ctx.Paste(list)
    })
}
<commit_msg>me is already taken. duh.<commit_after>package victor

import (
    "github.com/brettbuddin/victor/utils/google"
    "strconv"
)

func registerDefaultAbilities(brain *Brain) {
    brain.Respond("campfire id", func(ctx *Context) {
        id := strconv.Itoa(ctx.Message().UserId())
        ctx.Reply(id)
    })

    brain.Respond("ping", func(ctx *Context) {
        ctx.Reply("pong!")
    })

    brain.Respond("(image|img|gif|animate) (.*)", func(ctx *Context) {
        gifOnly := (ctx.Matches()[1] == "gif" || ctx.Matches()[1] == "animate")

        result, err := google.ImageSearch(ctx.Matches()[2], gifOnly)

        if err != nil {
            ctx.Send("There was error making the request.")
            return
        }

        if result == "" {
            ctx.Send("I didn't find anything.")
            return
        }

        ctx.Send(result)
    })

    brain.Respond("users (list|show)", func(ctx *Context) {
        list := ""

        for _, user := range brain.Users() {
            list += user.Name() + "\n"
        }

        ctx.Paste(list)
    })
}
<|endoftext|>


<commit_before>// Copyright 2011 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dns

import (
	"net"
	"strconv"
	"strings"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in the ClassINET class. If
// you need other classes you are on your own.

// SetReply creates a reply packet from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question packet.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify packet.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error packet suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.Rcode = rcode
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Id = request.Id
	// Note that this is actually a FORMERR
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetRcodeFormatError creates a packet with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update packet. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates dns.Msg for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates dns.Msg for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return r.(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels, total length and true, when a domain name is valid.
// When false is returned the labelcount and length are not defined.
func IsDomainName(s string) (uint8, uint8, bool) { // copied from net package.
	// TODO(mg): check for \DDD - seems to work fine without though
	// See RFC 1035, RFC 3696.
	l := len(s)
	if l == 0 || l > 255 {
		return 0, 0, false
	}
	longer := 0
	// Simplify checking loop: make the name end in a dot.
	// Don't call Fqdn() to save another len(s).
	// Keep in mind that if we do this, otherwise we report a length+1
	if s[l-1] != '.' {
		s += "."
		l++
		longer = 1
	}
	// Preloop check for root label
	if s == "." {
		return 0, 1, true
	}

	last := byte('.')
	ok := false // ok once we've seen a letter or digit
	partlen := 0
	labels := uint8(0)
	var c byte
	for i := 0; i < l; i++ {
		c = s[i]
		switch {
		default:
			// anything escaped is legal
			if last != '\\' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*' || c == '/':
			ok = true
			partlen++
		case c == '\\': // OK
		case c == '@':
			if last != '\\' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case '0' <= c && c <= '9':
			ok = true
			partlen++
		case c == '-':
			// byte before dash cannot be dot
			if last == '.' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case c == '.':
			// byte before dot cannot be dot
			if last == '.' {
				return 0, uint8(l - longer), false
			}
			if last == '\\' { // Ok, escaped dot.
				partlen++
				c = 'A' // make current value not scary
				break
			}
			if partlen > 63 || partlen == 0 {
				return 0, uint8(l - longer), false
			}
			partlen = 0
			labels++
		}
		last = c
	}
	return labels, uint8(l - longer), ok
}

// IsSubDomain checks if child is indeed a child of the parent.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareLabels(strings.ToLower(parent), strings.ToLower(child)) == LenLabels(parent)
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false // ?
	}
	return s[l-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address addr suitable for rDNS (PTR) record lookup or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{Err: "unrecognized address", Name: addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	} else {
		return "TYPE" + strconv.Itoa(int(t))
	}
	panic("dns: not reached") // go < 1.1 compat
}

// String returns the string representation for the class c
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	} else {
		return "CLASS" + strconv.Itoa(int(c))
	}
}
<commit_msg>Fix 1.1.1 missing return error<commit_after>// Copyright 2011 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dns

import (
	"net"
	"strconv"
	"strings"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in the ClassINET class. If
// you need other classes you are on your own.

// SetReply creates a reply packet from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question packet.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify packet.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error packet suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.Rcode = rcode
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Id = request.Id
	// Note that this is actually a FORMERR
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetRcodeFormatError creates a packet with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update packet. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates dns.Msg for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates dns.Msg for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return r.(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels, total length and true, when a domain name is valid.
// When false is returned the labelcount and length are not defined.
func IsDomainName(s string) (uint8, uint8, bool) { // copied from net package.
	// TODO(mg): check for \DDD - seems to work fine without though
	// See RFC 1035, RFC 3696.
	l := len(s)
	if l == 0 || l > 255 {
		return 0, 0, false
	}
	longer := 0
	// Simplify checking loop: make the name end in a dot.
	// Don't call Fqdn() to save another len(s).
	// Keep in mind that if we do this, otherwise we report a length+1
	if s[l-1] != '.' {
		s += "."
		l++
		longer = 1
	}
	// Preloop check for root label
	if s == "." {
		return 0, 1, true
	}

	last := byte('.')
	ok := false // ok once we've seen a letter or digit
	partlen := 0
	labels := uint8(0)
	var c byte
	for i := 0; i < l; i++ {
		c = s[i]
		switch {
		default:
			// anything escaped is legal
			if last != '\\' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*' || c == '/':
			ok = true
			partlen++
		case c == '\\': // OK
		case c == '@':
			if last != '\\' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case '0' <= c && c <= '9':
			ok = true
			partlen++
		case c == '-':
			// byte before dash cannot be dot
			if last == '.' {
				return 0, uint8(l - longer), false
			}
			partlen++
		case c == '.':
			// byte before dot cannot be dot
			if last == '.' {
				return 0, uint8(l - longer), false
			}
			if last == '\\' { // Ok, escaped dot.
				partlen++
				c = 'A' // make current value not scary
				break
			}
			if partlen > 63 || partlen == 0 {
				return 0, uint8(l - longer), false
			}
			partlen = 0
			labels++
		}
		last = c
	}
	return labels, uint8(l - longer), ok
}

// IsSubDomain checks if child is indeed a child of the parent.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareLabels(strings.ToLower(parent), strings.ToLower(child)) == LenLabels(parent)
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false // ?
	}
	return s[l-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address addr suitable for rDNS (PTR) record lookup or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{Err: "unrecognized address", Name: addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	} else {
		return "TYPE" + strconv.Itoa(int(t))
	}
	panic("dns: not reached") // go < 1.1 compat
}

// String returns the string representation for the class c
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	} else {
		return "CLASS" + strconv.Itoa(int(c))
	}
	panic("dns: not reached")
}
<|endoftext|>


<commit_before>package nom

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
)

// PortUpdated is a high-level event emitted when a port is added, removed, or
// its state/configuration is changed.
type PortUpdated Port

// PortStatusChanged is emitted when a driver receives a port status
type PortStatusChanged struct {
	Port   Port
	Driver Driver
}

// Port is either a physical or a virtual port of a node.
type Port struct {
	ID      PortID      // ID is unique among the ports of this node.
	Name    string      // Human-readable name of the port.
	MACAddr MACAddr     // Hardware address of the port.
	Node    UID         // The node.
	Link    UID         // The outgoing link.
	State   PortState   // Is the state of the port.
	Config  PortConfig  // Is the configuration of the port.
	Feature PortFeature // Features of this port.
}

func (p Port) String() string {
	return fmt.Sprintf("Port (node=%v, id=%v, addr=%v)", p.Node, p.ID, p.MACAddr)
}

// PortID is the ID of a port and is unique among the ports of a node.
type PortID string

// UID returns the unique ID of the port in the form of
// net_id$$node_id$$port_id.
func (p Port) UID() UID {
	return UIDJoin(string(p.Node), string(p.ID))
}

// ParsePortUID parses a UID of a port and returns the respective node and port
// IDs.
func ParsePortUID(id UID) (NodeID, PortID) {
	s := UIDSplit(id)
	return NodeID(s[0]), PortID(s[1])
}

// GoDecode decodes the port from b using Gob.
func (p *Port) GoDecode(b []byte) error {
	return ObjGoDecode(p, b)
}

// GoEncode encodes the port into a byte array using Gob.
func (p *Port) GoEncode() ([]byte, error) {
	return ObjGoEncode(p)
}

// JSONDecode decodes the port from a byte array using JSON.
func (p *Port) JSONDecode(b []byte) error {
	return json.Unmarshal(b, p)
}

// JSONEncode encodes the port into a byte array using JSON.
func (p *Port) JSONEncode() ([]byte, error) {
	return json.Marshal(p)
}

// Ports is a slice of ports with useful auxilaries.
type Ports []Port

// GetPort retrieves a port by its ID, and returns false if no port is found.
func (ports Ports) GetPort(id UID) (Port, bool) {
	for _, p := range ports {
		if p.UID() == id {
			return p, true
		}
	}
	return Port{}, false
}

// HasPort returns whether port is in ports.
func (ports Ports) HasPort(port Port) bool {
	_, ok := ports.GetPort(port.UID())
	return ok
}

// AddPort adds p to ports.
func (ports *Ports) AddPort(p Port) {
	*ports = append(*ports, p)
}

// DelPort deletes port from ports. If there is no such port, it returns false.
func (ports *Ports) DelPort(port Port) bool {
	id := port.UID()
	for i, p := range *ports {
		if p.UID() == id {
			*ports = append((*ports)[:i], (*ports)[i+1:]...)
			return true
		}
	}
	return false
}

// PortState is the current state of a port.
type PortState uint8

// Valid values for PortState.
const (
	PortStateUnknown PortState = iota // Port's state is unknown.
	PortStateDown              = iota // Port is not connected to any link.
	PortStateUp                = iota // Port is up and forwarding packets.
	PortStateBlocked           = iota // Port is blocked.
)

// PortConfig is the NOM specific configuration of the port.
type PortConfig uint8

// Valid values for PortConfig.
const (
	PortConfigDown        PortConfig = 1 << iota // Down.
	PortConfigDropPackets            = 1 << iota // Drop incoming packets.
	PortConfigNoForward              = 1 << iota // Do not forward packets.
	PortConfigNoFlood                = 1 << iota // Do not include in flood.
	PortConfigNoPacketIn             = 1 << iota // Do not send packet ins.
	PortConfigDisableStp             = 1 << iota // Disable STP.
	PortConfigDropStp                = 1 << iota // Drop STP packets.
)

// PortFeature represents port features.
type PortFeature uint16

// Valid values for PortFeature
const (
	PortFeature10MBHD  PortFeature = 1 << iota // 10MB half-duplex.
	PortFeature10MBFD              = 1 << iota // 10MB full-duplex.
	PortFeature100MBHD             = 1 << iota // 100MB half-duplex.
	PortFeature100MBFD             = 1 << iota // 100MB half-duplex.
	PortFeature1GBHD               = 1 << iota // 1GB half-duplex.
	PortFeature1GBFD               = 1 << iota // 1GB half-duplex.
	PortFeature10GBHD              = 1 << iota // 10GB  half-duplex.
	PortFeature10GBFD              = 1 << iota // 10GB half-duplex.
	PortFeatureCopper              = 1 << iota // Copper.
	PortFeatureFiber               = 1 << iota // Fiber.
	PortFeatureAutoneg             = 1 << iota // Auto negotiation.
	PortPause                      = 1 << iota // Pause.
	PortPauseAsym                  = 1 << iota // Asymmetric pause.
)

func init() {
	gob.Register(Port{})
	gob.Register(PortID(""))
	gob.Register(PortStatusChanged{})
	gob.Register(PortUpdated{})
}
<commit_msg>Add NodeFromPortUID<commit_after>package nom

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
)

// PortUpdated is a high-level event emitted when a port is added, removed, or
// its state/configuration is changed.
type PortUpdated Port

// PortStatusChanged is emitted when a driver receives a port status
type PortStatusChanged struct {
	Port   Port
	Driver Driver
}

// Port is either a physical or a virtual port of a node.
type Port struct {
	ID      PortID      // ID is unique among the ports of this node.
	Name    string      // Human-readable name of the port.
	MACAddr MACAddr     // Hardware address of the port.
	Node    UID         // The node.
	Link    UID         // The outgoing link.
	State   PortState   // Is the state of the port.
	Config  PortConfig  // Is the configuration of the port.
	Feature PortFeature // Features of this port.
}

func (p Port) String() string {
	return fmt.Sprintf("Port (node=%v, id=%v, addr=%v)", p.Node, p.ID, p.MACAddr)
}

// PortID is the ID of a port and is unique among the ports of a node.
type PortID string

// UID returns the unique ID of the port in the form of
// net_id$$node_id$$port_id.
func (p Port) UID() UID {
	return UIDJoin(string(p.Node), string(p.ID))
}

// ParsePortUID parses a UID of a port and returns the respective node and port
// IDs.
func ParsePortUID(id UID) (NodeID, PortID) {
	s := UIDSplit(id)
	return NodeID(s[0]), PortID(s[1])
}

// NodeFromPortUID returns the node UID from the port's UID.
func NodeFromPortUID(port UID) (node UID) {
	n, _ := ParsePortUID(port)
	return n.UID()
}

// GoDecode decodes the port from b using Gob.
func (p *Port) GoDecode(b []byte) error {
	return ObjGoDecode(p, b)
}

// GoEncode encodes the port into a byte array using Gob.
func (p *Port) GoEncode() ([]byte, error) {
	return ObjGoEncode(p)
}

// JSONDecode decodes the port from a byte array using JSON.
func (p *Port) JSONDecode(b []byte) error {
	return json.Unmarshal(b, p)
}

// JSONEncode encodes the port into a byte array using JSON.
func (p *Port) JSONEncode() ([]byte, error) {
	return json.Marshal(p)
}

// Ports is a slice of ports with useful auxilaries.
type Ports []Port

// GetPort retrieves a port by its ID, and returns false if no port is found.
func (ports Ports) GetPort(id UID) (Port, bool) {
	for _, p := range ports {
		if p.UID() == id {
			return p, true
		}
	}
	return Port{}, false
}

// HasPort returns whether port is in ports.
func (ports Ports) HasPort(port Port) bool {
	_, ok := ports.GetPort(port.UID())
	return ok
}

// AddPort adds p to ports.
func (ports *Ports) AddPort(p Port) {
	*ports = append(*ports, p)
}

// DelPort deletes port from ports. If there is no such port, it returns false.
func (ports *Ports) DelPort(port Port) bool {
	id := port.UID()
	for i, p := range *ports {
		if p.UID() == id {
			*ports = append((*ports)[:i], (*ports)[i+1:]...)
			return true
		}
	}
	return false
}

// PortState is the current state of a port.
type PortState uint8

// Valid values for PortState.
const (
	PortStateUnknown PortState = iota // Port's state is unknown.
	PortStateDown              = iota // Port is not connected to any link.
	PortStateUp                = iota // Port is up and forwarding packets.
	PortStateBlocked           = iota // Port is blocked.
)

// PortConfig is the NOM specific configuration of the port.
type PortConfig uint8

// Valid values for PortConfig.
const (
	PortConfigDown        PortConfig = 1 << iota // Down.
	PortConfigDropPackets            = 1 << iota // Drop incoming packets.
	PortConfigNoForward              = 1 << iota // Do not forward packets.
	PortConfigNoFlood                = 1 << iota // Do not include in flood.
	PortConfigNoPacketIn             = 1 << iota // Do not send packet ins.
	PortConfigDisableStp             = 1 << iota // Disable STP.
	PortConfigDropStp                = 1 << iota // Drop STP packets.
)

// PortFeature represents port features.
type PortFeature uint16

// Valid values for PortFeature
const (
	PortFeature10MBHD  PortFeature = 1 << iota // 10MB half-duplex.
	PortFeature10MBFD              = 1 << iota // 10MB full-duplex.
	PortFeature100MBHD             = 1 << iota // 100MB half-duplex.
	PortFeature100MBFD             = 1 << iota // 100MB half-duplex.
	PortFeature1GBHD               = 1 << iota // 1GB half-duplex.
	PortFeature1GBFD               = 1 << iota // 1GB half-duplex.
	PortFeature10GBHD              = 1 << iota // 10GB  half-duplex.
	PortFeature10GBFD              = 1 << iota // 10GB half-duplex.
	PortFeatureCopper              = 1 << iota // Copper.
	PortFeatureFiber               = 1 << iota // Fiber.
	PortFeatureAutoneg             = 1 << iota // Auto negotiation.
	PortPause                      = 1 << iota // Pause.
	PortPauseAsym                  = 1 << iota // Asymmetric pause.
)

func init() {
	gob.Register(Port{})
	gob.Register(PortID(""))
	gob.Register(PortStatusChanged{})
	gob.Register(PortUpdated{})
}
<|endoftext|>


<commit_before>package rogue

import (
	"image/png"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

func BenchmarkGenerateIsland(b *testing.B) {
	for n := 0; n < b.N; n++ {

		generateIsland(666, 220, 140)
	}
}

func prepareIsland() {
	if island == nil {
		seed := int64(123)
		island = generateIsland(seed, 200, 100)

		islandColImgFile, _ := os.Create("island_test.png")
		png.Encode(islandColImgFile, island.ColoredHeightMapAsImage())
	}

	// clear spawns between tests
	island.Spawns = nil
}

func TestWithinRadiusOfType(t *testing.T) {

	prepareIsland()
	assert.Equal(t, true, len(island.Spawns) == 0)

	island.addNpcFromName("small fireplace", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)

	assert.Equal(t, 1, len(island.withinRadiusOfName("small fireplace", 0, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfName("small fireplace", 30, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfType("fireplace", 0, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfType("fireplace", 30, island.Spawns[0].Position)))
}

func TestFindFoodAndEat(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc hungry
	dw.Hunger = dw.hungerCap() + 1
	island.Tick()

	// make sure planned action: find food
	assert.Equal(t, "find food", dw.CurrentAction.Name)
	assert.Equal(t, false, dw.hasItemTypeInInventory("food"))

	// progress until npc found food
	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure that npc has aged
	assert.Equal(t, true, dw.Age > 0)

	// make sure food was found
	assert.Equal(t, true, len(dw.Inventory) > 0)
	assert.Equal(t, true, dw.hasItemTypeInInventory("food"))
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	oldHunger := dw.Hunger
	island.Tick()

	// make sure npc consumed food
	assert.Equal(t, false, dw.hasItemTypeInInventory("food"))

	// make sure hunger went down
	assert.Equal(t, true, dw.Hunger < oldHunger)
	assert.Equal(t, false, dw.isHungry())
}

func TestFindWaterAndDrink(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc thirsty
	dw.Thirst = dw.thirstCap() + 1
	island.Tick()

	// make sure npc planned action: find water
	assert.Equal(t, "find water", dw.CurrentAction.Name)
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	// progress until npc found food
	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure water was found
	assert.Equal(t, true, len(dw.Inventory) > 0)
	assert.Equal(t, true, dw.hasItemTypeInInventory("drink"))

	oldThirst := dw.Thirst
	island.Tick()

	// make sure npc consumed water
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	// make sure thirst went down
	assert.Equal(t, true, dw.Thirst < oldThirst)
	assert.Equal(t, false, dw.isThirsty())
}

/*
func TestFindFirewood(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 5)
	dw := island.Spawns[0]

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "find firewood", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, dw.hasItemTypeInInventory("wood"))
}
*/
func TestSleep(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc tired
	dw.Tiredness = dw.tirednessCap() + 1
	island.Tick()

	// make sure npc planned action: sleep
	assert.Equal(t, "sleep", dw.CurrentAction.Name)

	oldTiredness := dw.Tiredness

	island.Tick()
	assert.Equal(t, true, dw.isSleeping())

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	// progress until npc wakes up
	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure tiredness went down
	assert.Equal(t, true, dw.Tiredness < oldTiredness)
	assert.Equal(t, false, dw.isTired())
	assert.Equal(t, false, dw.isSleeping())
}

func TestRabbitDigHole(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("rabbit", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, "dig small hole", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfName("small hole", 0, dw.Position)) == 1)
	assert.Equal(t, true, len(island.withinRadiusOfType("shelter", 0, dw.Position)) == 1)
}

func TestBuildFireplace(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, "build small fireplace", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfName("small fireplace", 0, dw.Position)) == 1)
	assert.Equal(t, true, len(island.withinRadiusOfType("fireplace", 0, dw.Position)) == 1)
}

func TestBuildShelter(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	assert.Equal(t, true, len(island.withinRadiusOfType("fireplace", 0, dw.Position)) == 1)

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "build small shelter", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfType("shelter", 0, dw.Position)) == 1)
}

func TestBuildFarmland(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "build farmland", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, 1, len(island.withinRadiusOfName("farmland", 0, dw.Position)))
	assert.Equal(t, 2, len(island.withinRadiusOfType("food producer", 0, dw.Position))) // including apple tree
}
<commit_msg>add find firewood test<commit_after>package rogue

import (
	"image/png"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

func BenchmarkGenerateIsland(b *testing.B) {
	for n := 0; n < b.N; n++ {

		generateIsland(666, 220, 140)
	}
}

func prepareIsland() {
	if island == nil {
		seed := int64(123)
		island = generateIsland(seed, 200, 100)

		islandColImgFile, _ := os.Create("island_test.png")
		png.Encode(islandColImgFile, island.ColoredHeightMapAsImage())
	}

	// clear spawns between tests
	island.Spawns = nil
}

func TestWithinRadiusOfType(t *testing.T) {

	prepareIsland()
	assert.Equal(t, true, len(island.Spawns) == 0)

	island.addNpcFromName("small fireplace", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)

	assert.Equal(t, 1, len(island.withinRadiusOfName("small fireplace", 0, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfName("small fireplace", 30, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfType("fireplace", 0, island.Spawns[0].Position)))
	assert.Equal(t, 1, len(island.withinRadiusOfType("fireplace", 30, island.Spawns[0].Position)))
}

func TestFindFoodAndEat(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc hungry
	dw.Hunger = dw.hungerCap() + 1
	island.Tick()

	// make sure planned action: find food
	assert.Equal(t, "find food", dw.CurrentAction.Name)
	assert.Equal(t, false, dw.hasItemTypeInInventory("food"))

	// progress until npc found food
	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure that npc has aged
	assert.Equal(t, true, dw.Age > 0)

	// make sure food was found
	assert.Equal(t, true, len(dw.Inventory) > 0)
	assert.Equal(t, true, dw.hasItemTypeInInventory("food"))
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	oldHunger := dw.Hunger
	island.Tick()

	// make sure npc consumed food
	assert.Equal(t, false, dw.hasItemTypeInInventory("food"))

	// make sure hunger went down
	assert.Equal(t, true, dw.Hunger < oldHunger)
	assert.Equal(t, false, dw.isHungry())
}

func TestFindWaterAndDrink(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc thirsty
	dw.Thirst = dw.thirstCap() + 1
	island.Tick()

	// make sure npc planned action: find water
	assert.Equal(t, "find water", dw.CurrentAction.Name)
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	// progress until npc found food
	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure water was found
	assert.Equal(t, true, len(dw.Inventory) > 0)
	assert.Equal(t, true, dw.hasItemTypeInInventory("drink"))

	oldThirst := dw.Thirst
	island.Tick()

	// make sure npc consumed water
	assert.Equal(t, false, dw.hasItemTypeInInventory("drink"))

	// make sure thirst went down
	assert.Equal(t, true, dw.Thirst < oldThirst)
	assert.Equal(t, false, dw.isThirsty())
}

func TestFindFirewood(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 5)
	dw := island.Spawns[0]

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "find firewood", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, dw.hasItemTypeInInventory("wood"))
}

func TestSleep(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	// make npc tired
	dw.Tiredness = dw.tirednessCap() + 1
	island.Tick()

	// make sure npc planned action: sleep
	assert.Equal(t, "sleep", dw.CurrentAction.Name)

	oldTiredness := dw.Tiredness

	island.Tick()
	assert.Equal(t, true, dw.isSleeping())

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	// progress until npc wakes up
	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	// make sure tiredness went down
	assert.Equal(t, true, dw.Tiredness < oldTiredness)
	assert.Equal(t, false, dw.isTired())
	assert.Equal(t, false, dw.isSleeping())
}

func TestRabbitDigHole(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("rabbit", island.randomPointAboveWater())
	assert.Equal(t, true, len(island.Spawns) == 1)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, "dig small hole", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfName("small hole", 0, dw.Position)) == 1)
	assert.Equal(t, true, len(island.withinRadiusOfType("shelter", 0, dw.Position)) == 1)
}

func TestBuildFireplace(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, "build small fireplace", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfName("small fireplace", 0, dw.Position)) == 1)
	assert.Equal(t, true, len(island.withinRadiusOfType("fireplace", 0, dw.Position)) == 1)
}

func TestBuildShelter(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("farmland", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	assert.Equal(t, true, len(island.withinRadiusOfType("fireplace", 0, dw.Position)) == 1)

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "build small shelter", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, true, len(island.withinRadiusOfType("shelter", 0, dw.Position)) == 1)
}

func TestBuildFarmland(t *testing.T) {

	prepareIsland()

	island.addNpcFromRace("dwarf", island.randomPointAboveWater())

	// add nessecities, so they dont need to be built
	island.addNpcFromName("small fireplace", island.Spawns[0].Position)
	island.addNpcFromName("small shelter", island.Spawns[0].Position)
	island.addNpcFromName("apple tree", island.Spawns[0].Position)

	assert.Equal(t, true, len(island.Spawns) == 4)
	dw := island.Spawns[0]
	dw.addToInventory("firewood")

	island.Tick()
	assert.Equal(t, false, dw.CurrentAction == nil)
	assert.Equal(t, "build farmland", dw.CurrentAction.Name)

	duration := dw.CurrentAction.Duration
	assert.Equal(t, true, duration > 0)

	for i := 0; i <= duration; i++ {
		island.Tick()
	}

	assert.Equal(t, 1, len(island.withinRadiusOfName("farmland", 0, dw.Position)))
	assert.Equal(t, 2, len(island.withinRadiusOfType("food producer", 0, dw.Position))) // including apple tree
}
<|endoftext|>