<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	log "github.com/Sirupsen/logrus"
	"github.com/parnurzeal/gorequest"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

const (
	delay = time.Second
)

var (
	client              = &http.Client{Timeout: (2 * time.Second)}
	lastGoogleRequest   = time.Now()
	lastTransltrRequest = time.Now()
	lastHonyakuRequest  = time.Now()
)

func checkThrottle(lastReq time.Time) {
	timePassed := time.Since(lastReq)
	if timePassed < delay {
		sleep := delay - timePassed
		log.Debugf("Throttling request for %f seconds", sleep.Seconds())
		time.Sleep(sleep)
	}
}

func translateWithGoogle(req *translateRequest) (string, error) {
	start := time.Now()

	checkThrottle(lastGoogleRequest)

	var URL *url.URL
	URL, err := url.Parse("https://translate.google.com/translate_a/single")

	parameters := url.Values{}
	parameters.Add("client", "gtx")
	parameters.Add("dt", "t")
	parameters.Add("sl", req.From)
	parameters.Add("tl", req.To)
	parameters.Add("ie", "UTF-8")
	parameters.Add("oe", "UTF-8")
	parameters.Add("q", req.Text)

	// /translate_a/single?client=gtx&dt=t&sl=%hs&tl=%hs&ie=UTF-8&oe=UTF-8&q=%s
	URL.RawQuery = parameters.Encode()

	r, err := http.NewRequest("GET", URL.String(), nil)
	if err != nil {
		log.Errorln("Failed to create request", err)
		return "", err
	}

	r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko")

	lastGoogleRequest = time.Now()

	resp, err := client.Do(r)
	if err != nil {
		log.Errorln("Failed to do request", err)
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("%+v", resp)
	}

	// [[["It will be saved","助かるわい",,,3]],,"ja"]
	contents, err := ioutil.ReadAll(resp.Body)
	check(err)

	allStrings := regexp.MustCompile("\"(.+?)\",\"(.+?)\",?").FindAllStringSubmatch(string(contents), -1)

	if len(allStrings) < 1 {
		return "", fmt.Errorf("Bad response %s", contents)
	}

	var out string
	for _, v := range allStrings {
		if len(v) < 3 {
			continue
		}

		out += v[1]
	}

	// Delete garbage output which often leaves the output empty, fix your shit google tbh
	out2 := regexp.MustCompile(`\s?_{2,3}(\s\d)?`).ReplaceAllString(out, "")
	if len(out) < 1 || (len(out2) < len(out)/2) {
		return "", fmt.Errorf("Bad response %q", out)
	}

	out = out2

	// Replace escaped quotes
	out = strings.Replace(out, "\\\"", "\"", -1)

	// Replace escaped newlines
	out = strings.Replace(out, "\\n", "\n", -1)

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Google: %q", out)

	return out, nil
}

func translateWithTransltr(req *translateRequest) (string, error) {
	start := time.Now()

	checkThrottle(lastTransltrRequest)

	// Convert json object to string
	jsonString, err := json.Marshal(req)
	if err != nil {
		log.Error("Failed to marshal JSON API request", err.Error())
	}

	lastTransltrRequest = time.Now()

	// Post the request
	resp, reply, errs := gorequest.New().Post("http://transltr.org/api/translate").Send(string(jsonString)).EndBytes()
	for _, err := range errs {
		log.WithFields(log.Fields{
			"response": resp,
			"reply":    reply,
		}).Error(err.Error())
		return "", err
	}

	var response translateResponse
	if err := json.Unmarshal(reply, &response); err != nil {
		log.Error("Failed to unmarshal JSON API response", err.Error())
		return "", err
	}

	out := response.TranslationText

	// Seems to use google translate as backend as well so it will mostly output the same garbage
	out2 := regexp.MustCompile(`\s?_{2,3}(\s\d)?`).ReplaceAllString(out, "")
	if len(out) < 1 || (len(out2) < len(out)/2) {
		return "", fmt.Errorf("Garbage translation %q", out)
	}

	out = out2

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Transltr: %q", out)

	return out, nil
}

func translateWithHonyaku(req *translateRequest) (string, error) {
	start := time.Now()

	checkThrottle(lastHonyakuRequest)

	var URL *url.URL
	URL, err := url.Parse("http://honyaku.yahoo.co.jp/transtext")
	check(err)

	parameters := url.Values{}
	parameters.Add("both", "TH")
	parameters.Add("eid", "CR-JE")
	parameters.Add("text", req.Text)

	URL.RawQuery = parameters.Encode()

	r, err := http.NewRequest("GET", URL.String(), nil)
	if err != nil {
		log.Errorln("Failed to create request", err)
		return "", err
	}

	r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko")

	lastHonyakuRequest = time.Now()

	resp, err := client.Do(r)
	if err != nil {
		log.Errorln("Failed to do request", err)
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		contents, err := ioutil.ReadAll(resp.Body)
		check(err)
		return "", fmt.Errorf("%d %s", resp.StatusCode, contents)
	}

	doc, err := goquery.NewDocumentFromResponse(resp)
	if err != nil {
		return "", fmt.Errorf("Can't open response document %s", err)
	}

	out := doc.Find("#transafter").Text()
	out = strings.TrimSpace(out)

	if len(out) < 1 {
		return "", fmt.Errorf("Bad response %q", out)
	}

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Honyaku: %q", out)

	return out, nil
}
<commit_msg>Lock last request to avoid bursting<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	log "github.com/Sirupsen/logrus"
	"github.com/parnurzeal/gorequest"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"time"
)

const (
	delay = time.Second
)

var (
	client              = &http.Client{Timeout: (2 * time.Second)}
	lastGoogleRequest   = time.Now()
	lastTransltrRequest = time.Now()
	lastHonyakuRequest  = time.Now()

	googleMutex   = &sync.Mutex{}
	transltrMutex = &sync.Mutex{}
	honyakuMutex  = &sync.Mutex{}
)

func checkThrottle(lastReq time.Time) {
	timePassed := time.Since(lastReq)
	if timePassed < delay {
		sleep := delay - timePassed
		log.Debugf("Throttling request for %f seconds", sleep.Seconds())
		time.Sleep(sleep)
	}
}

func translateWithGoogle(req *translateRequest) (string, error) {
	start := time.Now()

	googleMutex.Lock()
	checkThrottle(lastGoogleRequest)

	var URL *url.URL
	URL, err := url.Parse("https://translate.google.com/translate_a/single")

	parameters := url.Values{}
	parameters.Add("client", "gtx")
	parameters.Add("dt", "t")
	parameters.Add("sl", req.From)
	parameters.Add("tl", req.To)
	parameters.Add("ie", "UTF-8")
	parameters.Add("oe", "UTF-8")
	parameters.Add("q", req.Text)

	// /translate_a/single?client=gtx&dt=t&sl=%hs&tl=%hs&ie=UTF-8&oe=UTF-8&q=%s
	URL.RawQuery = parameters.Encode()

	r, err := http.NewRequest("GET", URL.String(), nil)
	if err != nil {
		log.Errorln("Failed to create request", err)
		return "", err
	}

	r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko")

	lastGoogleRequest = time.Now()
	googleMutex.Unlock()

	resp, err := client.Do(r)
	if err != nil {
		log.Errorln("Failed to do request", err)
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("%+v", resp)
	}

	// [[["It will be saved","助かるわい",,,3]],,"ja"]
	contents, err := ioutil.ReadAll(resp.Body)
	check(err)

	allStrings := regexp.MustCompile("\"(.+?)\",\"(.+?)\",?").FindAllStringSubmatch(string(contents), -1)

	if len(allStrings) < 1 {
		return "", fmt.Errorf("Bad response %s", contents)
	}

	var out string
	for _, v := range allStrings {
		if len(v) < 3 {
			continue
		}

		out += v[1]
	}

	// Delete garbage output which often leaves the output empty, fix your shit google tbh
	out2 := regexp.MustCompile(`\s?_{2,3}(\s\d)?`).ReplaceAllString(out, "")
	if len(out) < 1 || (len(out2) < len(out)/2) {
		return "", fmt.Errorf("Bad response %q", out)
	}

	out = out2

	// Replace escaped quotes
	out = strings.Replace(out, "\\\"", "\"", -1)

	// Replace escaped newlines
	out = strings.Replace(out, "\\n", "\n", -1)

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Google: %q", out)

	return out, nil
}

func translateWithTransltr(req *translateRequest) (string, error) {
	start := time.Now()

	transltrMutex.Lock()
	checkThrottle(lastTransltrRequest)

	// Convert json object to string
	jsonString, err := json.Marshal(req)
	if err != nil {
		log.Error("Failed to marshal JSON API request", err.Error())
	}

	lastTransltrRequest = time.Now()
	transltrMutex.Unlock()

	// Post the request
	resp, reply, errs := gorequest.New().Post("http://transltr.org/api/translate").Send(string(jsonString)).EndBytes()
	for _, err := range errs {
		log.WithFields(log.Fields{
			"response": resp,
			"reply":    reply,
		}).Error(err.Error())
		return "", err
	}

	var response translateResponse
	if err := json.Unmarshal(reply, &response); err != nil {
		log.Error("Failed to unmarshal JSON API response", err.Error())
		return "", err
	}

	out := response.TranslationText

	// Seems to use google translate as backend as well so it will mostly output the same garbage
	out2 := regexp.MustCompile(`\s?_{2,3}(\s\d)?`).ReplaceAllString(out, "")
	if len(out) < 1 || (len(out2) < len(out)/2) {
		return "", fmt.Errorf("Garbage translation %q", out)
	}

	out = out2

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Transltr: %q", out)

	return out, nil
}

func translateWithHonyaku(req *translateRequest) (string, error) {
	start := time.Now()

	honyakuMutex.Lock()
	checkThrottle(lastHonyakuRequest)

	var URL *url.URL
	URL, err := url.Parse("http://honyaku.yahoo.co.jp/transtext")
	check(err)

	parameters := url.Values{}
	parameters.Add("both", "TH")
	parameters.Add("eid", "CR-JE")
	parameters.Add("text", req.Text)

	URL.RawQuery = parameters.Encode()

	r, err := http.NewRequest("GET", URL.String(), nil)
	if err != nil {
		log.Errorln("Failed to create request", err)
		return "", err
	}

	r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko")

	lastHonyakuRequest = time.Now()
	honyakuMutex.Unlock()

	resp, err := client.Do(r)
	if err != nil {
		log.Errorln("Failed to do request", err)
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		contents, err := ioutil.ReadAll(resp.Body)
		check(err)
		return "", fmt.Errorf("%d %s", resp.StatusCode, contents)
	}

	doc, err := goquery.NewDocumentFromResponse(resp)
	if err != nil {
		return "", fmt.Errorf("Can't open response document %s", err)
	}

	out := doc.Find("#transafter").Text()
	out = strings.TrimSpace(out)

	if len(out) < 1 {
		return "", fmt.Errorf("Bad response %q", out)
	}

	log.WithFields(log.Fields{
		"time": time.Since(start),
	}).Debugf("Honyaku: %q", out)

	return out, nil
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"unicode"

	log "github.com/Sirupsen/logrus"
	"github.com/parnurzeal/gorequest"
)

type translateRequest struct {
	Text string `json:"text"`
	From string `json:"from"`
	To   string `json:"to"`
}

type translateResponse struct {
	Text            string `json:"text"`
	From            string `json:"from"`
	To              string `json:"to"`
	TranslationText string `json:"translationText"`
}

func translateString(text string) (string, error) {
	if !shouldTranslateText(text) {
		return text, nil
	}

	var response translateResponse

	request := translateRequest{
		From: "ja",
		To:   "en",
		Text: text,
	}

	resp, reply, errs := gorequest.New().Post("http://127.0.0.1:3000/api/translate").
		Type("json").SendStruct(&request).EndStruct(&response)
	for _, err := range errs {
		log.WithFields(log.Fields{
			"response": resp,
			"reply":    reply,
		}).Error(err)

		return "", err
	}

	out := response.TranslationText

	if len(out) < 1 {
		log.Warnf("Translator returned empty string, replacing with original text %q", text)
		out = text
	} else {
		out = cleanTranslation(out)
	}

	return out, nil
}

func cleanTranslation(text string) string {
	// Removes any rune that isn't printable or a space
	isValid := func(r rune) rune {
		if !unicode.IsPrint(r) && !unicode.IsSpace(r) {
			return -1
		}

		return r
	}

	text = strings.Map(isValid, text)

	text = strings.Replace(text, "\\u0026", "＆", -1)

	if strings.Contains(text, "\\u0") {
		log.Warnf("Found unexpected escaped character in translation %s", text)
	}

	// Repeated whitespace
	text = replaceRegex(text, `\s{2,}`, " ")

	// ー ー ー ー
	text = replaceRegex(text, `\s+((\s+)?[-―ー]){2,}`, " ー")

	// · · · ·
	text = replaceRegex(text, `(\s+)?((\s+)?[·]+){3,}`, " ···")

	text = replaceRegex(text, `((\s+)?っ)+`, "")

	return text
}
<commit_msg>Attempt to remove leftover \ from translation<commit_after>package main

import (
	"strings"
	"unicode"

	log "github.com/Sirupsen/logrus"
	"github.com/parnurzeal/gorequest"
)

type translateRequest struct {
	Text string `json:"text"`
	From string `json:"from"`
	To   string `json:"to"`
}

type translateResponse struct {
	Text            string `json:"text"`
	From            string `json:"from"`
	To              string `json:"to"`
	TranslationText string `json:"translationText"`
}

func translateString(text string) (string, error) {
	if !shouldTranslateText(text) {
		return text, nil
	}

	var response translateResponse

	request := translateRequest{
		From: "ja",
		To:   "en",
		Text: text,
	}

	resp, reply, errs := gorequest.New().Post("http://127.0.0.1:3000/api/translate").
		Type("json").SendStruct(&request).EndStruct(&response)
	for _, err := range errs {
		log.WithFields(log.Fields{
			"response": resp,
			"reply":    reply,
		}).Error(err)

		return "", err
	}

	out := response.TranslationText

	if len(out) < 1 {
		log.Warnf("Translator returned empty string, replacing with original text %q", text)
		out = text
	} else {
		out = cleanTranslation(out)
	}

	return out, nil
}

func cleanTranslation(text string) string {
	// Removes any rune that isn't printable or a space
	isValid := func(r rune) rune {
		if !unicode.IsPrint(r) && !unicode.IsSpace(r) {
			return -1
		}

		return r
	}

	text = strings.Map(isValid, text)

	text = strings.Replace(text, "\\u0026", "＆", -1)

	if strings.Contains(text, "\\u0") {
		log.Warnf("Found unexpected escaped character in translation %s", text)
	}

	text = strings.Replace(text, "\\", "", -1)

	// Repeated whitespace
	text = replaceRegex(text, `\s{2,}`, " ")

	// ー ー ー ー
	text = replaceRegex(text, `\s+((\s+)?[-―ー]){2,}`, " ー")

	// · · · ·
	text = replaceRegex(text, `(\s+)?((\s+)?[·]+){3,}`, " ···")

	text = replaceRegex(text, `((\s+)?っ)+`, "")

	return text
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/bwmarrin/discordgo"
)

// for !en
func handleEnglish(s *discordgo.Session, m *discordgo.MessageCreate, tokens []string) error {

	channel, _ := s.Channel(m.ChannelID)
	guild, err := s.Guild(channel.GuildID)
	if err != nil {
		fmt.Println(err)
		return err
	}

	settings := getSetting(guild.ID)
	if !settings.Translation && !isOwner(m.Author.ID) {
		return errors.New("not allowed")
	}

	query := strings.TrimLeft(m.Content, "!en ")

	resp, err := translate("en", query)
	if err != nil {
		return err
	}

	_, err = s.ChannelMessageSend(channel.ID, fmt.Sprintf("```%s```", resp))

	return err
}

// for !ja
func handleJapanese(s *discordgo.Session, m *discordgo.MessageCreate, tokens []string) error {

	channel, _ := s.Channel(m.ChannelID)
	guild, err := s.Guild(channel.GuildID)
	if err != nil {
		fmt.Println(err)
		return err
	}

	settings := getSetting(guild.ID)
	if !settings.Translation && !isOwner(m.Author.ID) {
		return errors.New("not allowed")
	}

	query := strings.Join(tokens, " ")
	query = strings.TrimSpace(query)

	resp, err := translate("ja", query)
	if err != nil {
		return err
	}

	_, err = s.ChannelMessageSend(channel.ID, fmt.Sprintf("```%s```", resp))

	return err
}

func translate(t, q string) (string, error) {
	url := fmt.Sprintf("https://tensei.moe/api/v1/translate?q=%s&t=%s", url.QueryEscape(q), t)

	resp, err := http.Get(url)
	if err != nil || resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		return "", err
	}

	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", errors.New("error translating")
	}

	rc, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	if string(rc) == "" {
		return "", errors.New("empty response")
	}

	return string(rc), nil
}
<commit_msg>trim that shit<commit_after>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/bwmarrin/discordgo"
)

// for !en
func handleEnglish(s *discordgo.Session, m *discordgo.MessageCreate, tokens []string) error {

	channel, _ := s.Channel(m.ChannelID)
	guild, err := s.Guild(channel.GuildID)
	if err != nil {
		fmt.Println(err)
		return err
	}

	settings := getSetting(guild.ID)
	if !settings.Translation && !isOwner(m.Author.ID) {
		return errors.New("not allowed")
	}

	query := strings.Join(tokens, " ")
	query = strings.TrimSpace(query)

	resp, err := translate("en", query)
	if err != nil {
		return err
	}

	_, err = s.ChannelMessageSend(channel.ID, fmt.Sprintf("```%s```", resp))

	return err
}

// for !ja
func handleJapanese(s *discordgo.Session, m *discordgo.MessageCreate, tokens []string) error {

	channel, _ := s.Channel(m.ChannelID)
	guild, err := s.Guild(channel.GuildID)
	if err != nil {
		fmt.Println(err)
		return err
	}

	settings := getSetting(guild.ID)
	if !settings.Translation && !isOwner(m.Author.ID) {
		return errors.New("not allowed")
	}

	query := strings.Join(tokens, " ")
	query = strings.TrimSpace(query)

	resp, err := translate("ja", query)
	if err != nil {
		return err
	}

	_, err = s.ChannelMessageSend(channel.ID, fmt.Sprintf("```%s```", resp))

	return err
}

func translate(t, q string) (string, error) {
	url := fmt.Sprintf("https://tensei.moe/api/v1/translate?q=%s&t=%s", url.QueryEscape(q), t)

	resp, err := http.Get(url)
	if err != nil || resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		return "", err
	}

	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", errors.New("error translating")
	}

	rc, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	ns := strings.TrimSpace(string(rc))

	if ns == "" {
		return "", errors.New("empty response")
	}
	return ns, nil
}
<|endoftext|>


<commit_before>package baa

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

// print the route map
func (t *Tree) print(prefix string, root *leaf) {
	if root == nil {
		for m := range t.nodes {
			fmt.Println(m)
			t.print("", t.nodes[m])
		}
		return
	}
	prefix = fmt.Sprintf("%s -> %s", prefix, root.pattern)
	fmt.Println(prefix)
	root.children = append(root.children, root.paramChild)
	root.children = append(root.children, root.wideChild)
	for i := range root.children {
		if root.children[i] != nil {
			t.print(prefix, root.children[i])
		}
	}
}

func TestTreeRouteAdd1(t *testing.T) {
	Convey("add static route", t, func() {
		r.Add("GET", "/", []HandlerFunc{f})
		r.Add("GET", "/bcd", []HandlerFunc{f})
		r.Add("GET", "/abcd", []HandlerFunc{f})
		r.Add("GET", "/abc", []HandlerFunc{f})
		r.Add("GET", "/abd", []HandlerFunc{f})
		r.Add("GET", "/abcdef", []HandlerFunc{f})
		r.Add("GET", "/bcdefg", []HandlerFunc{f})
		r.Add("GET", "/abc/123", []HandlerFunc{f})
		r.Add("GET", "/abc/234", []HandlerFunc{f})
		r.Add("GET", "/abc/125", []HandlerFunc{f})
		r.Add("GET", "/abc/235", []HandlerFunc{f})
		r.Add("GET", "/cbd/123", []HandlerFunc{f})
		r.Add("GET", "/cbd/234", []HandlerFunc{f})
		r.Add("GET", "/cbd/345", []HandlerFunc{f})
		r.Add("GET", "/cbd/456", []HandlerFunc{f})
		r.Add("GET", "/cbd/346", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd2(t *testing.T) {
	Convey("add param route", t, func() {
		r.Add("GET", "/a/:id/id", []HandlerFunc{f})
		r.Add("GET", "/a/:id/name", []HandlerFunc{f})
		r.Add("GET", "/a", []HandlerFunc{f})
		r.Add("GET", "/a/:id/", []HandlerFunc{f})
		r.Add("GET", "/a/", []HandlerFunc{f})
		r.Add("GET", "/a/*/xxx", []HandlerFunc{f})
		r.Add("GET", "/p/:project/file/:fileName", []HandlerFunc{f})
		r.Add("GET", "/cbd/:id", []HandlerFunc{f})

		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "/p/:/a", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd3(t *testing.T) {
	Convey("add param route with two different param", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "/a/:id", []HandlerFunc{f})
		r.Add("GET", "/a/:name", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd4(t *testing.T) {
	Convey("add route by group", t, func() {
		b.Group("/user", func() {
			b.Get("/info", f)
			b.Get("/info2", f)
			b.Group("/group", func() {
				b.Get("/info", f)
				b.Get("/info2", f)
			})
		})
		b.Group("/user", func() {
			b.Get("/", f)
			b.Get("/pass", f)
			b.Get("/pass2", f)
		}, f)
	})
}

func TestTreeRouteAdd5(t *testing.T) {
	Convey("add route then set name, URLFor", t, func() {
		b.Get("/article/:id/show", f).Name("articleShow")
		b.Get("/article/:id/detail", f).Name("")
		url := b.URLFor("articleShow", 123)
		So(url, ShouldEqual, "/article/123/show")
		url = b.URLFor("", nil)
		So(url, ShouldEqual, "")
		url = b.URLFor("not exits", "no")
		So(url, ShouldEqual, "")
		ru, name := r.Match("GET", "/article/123/show", c)
		So(ru, ShouldNotBeNil)
		So(name, ShouldEqual, "articleShow")
	})
}

func TestTreeRouteAdd6(t *testing.T) {
	Convey("add route with not support method", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("TRACE", "/", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd7(t *testing.T) {
	Convey("add route with empty pattern", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd8(t *testing.T) {
	Convey("add route with pattern that not begin with /", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "abc", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd9(t *testing.T) {
	Convey("other route method", t, func() {
		b2 := New()
		Convey("set auto head route", func() {
			b2.SetAutoHead(true)
			b2.Get("/head", func(c *Context) {
				So(c.Req.Method, ShouldEqual, "HEAD")
			})
			req, _ := http.NewRequest("HEAD", "/head", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("set auto training slash", func() {
			b2.SetAutoTrailingSlash(true)
			b2.Get("/slash", func(c *Context) {})
			b2.Group("/slash2", func() {
				b2.Get("/", func(c *Context) {})
				b2.Get("/exist", func(c *Context) {})
			})
			req, _ := http.NewRequest("GET", "/slash", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2/exist/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("set multi method", func() {
			b2.Route("/mul1", "*", func(c *Context) {
				c.String(200, "mul")
			})
			b2.Route("/mul2", "GET,HEAD,POST", func(c *Context) {
				c.String(200, "mul")
			})
			req, _ := http.NewRequest("HEAD", "/mul2", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)

			req, _ = http.NewRequest("GET", "/mul2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("POST", "/mul2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("methods", func() {
			b2.Get("/methods", f)
			b2.Patch("/methods", f)
			b2.Post("/methods", f)
			b2.Put("/methods", f)
			b2.Delete("/methods", f)
			b2.Options("/methods", f)
			b2.Head("/methods", f)
			b2.Any("/any", f)
			b2.SetNotFound(func(c *Context) {
				c.String(404, "baa not found")
			})
		})
	})
}

func TestTreeRouteMatch1(t *testing.T) {
	Convey("match route", t, func() {

		ru, _ := r.Match("GET", "/", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/abc/1234", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "xxx", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/a/123/id", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/p/yst/file/a.jpg", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/info", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/pass", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/pass32", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/user/xxx", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/xxxx", c)
		So(ru, ShouldBeNil)

		b.Get("/notifications/threads/:id", f)
		b.Get("/notifications/threads/:id/subscription", f)
		b.Get("/notifications/threads/:id/subc", f)
		b.Put("/notifications/threads/:id/subscription", f)
		b.Delete("/notifications/threads/:id/subscription", f)
		ru, _ = r.Match("GET", "/notifications/threads/:id", c)
		So(ru, ShouldNotBeNil)
		ru, _ = r.Match("GET", "/notifications/threads/:id/sub", c)
		So(ru, ShouldBeNil)
	})
}

func TestTreeRoutePrint1(t *testing.T) {
	Convey("print route table", t, func() {
		r.(*Tree).print("", nil)
	})
}

func TestTreeRoutePrint2(t *testing.T) {
	Convey("print routes", t, func() {
		fmt.Println("")
		for method, routes := range r.Routes() {
			fmt.Println("Method: ", method)
			for i, route := range routes {
				fmt.Printf(" %3d %s\n", i, route)
			}
		}
	})
}

func TestTreeRoutePrint3(t *testing.T) {
	Convey("print named routes", t, func() {
		fmt.Println("")
		for name, route := range r.NamedRoutes() {
			fmt.Printf("%20s \t %s", name, route)
		}
	})
}
<commit_msg>format test<commit_after>package baa

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

// print the route map
func (t *Tree) print(prefix string, root *leaf) {
	if root == nil {
		for m := range t.nodes {
			fmt.Println(m)
			t.print("", t.nodes[m])
		}
		return
	}
	prefix = fmt.Sprintf("%s -> %s", prefix, root.pattern)
	fmt.Println(prefix)
	root.children = append(root.children, root.paramChild)
	root.children = append(root.children, root.wideChild)
	for i := range root.children {
		if root.children[i] != nil {
			t.print(prefix, root.children[i])
		}
	}
}

func TestTreeRouteAdd1(t *testing.T) {
	Convey("add static route", t, func() {
		r.Add("GET", "/", []HandlerFunc{f})
		r.Add("GET", "/bcd", []HandlerFunc{f})
		r.Add("GET", "/abcd", []HandlerFunc{f})
		r.Add("GET", "/abc", []HandlerFunc{f})
		r.Add("GET", "/abd", []HandlerFunc{f})
		r.Add("GET", "/abcdef", []HandlerFunc{f})
		r.Add("GET", "/bcdefg", []HandlerFunc{f})
		r.Add("GET", "/abc/123", []HandlerFunc{f})
		r.Add("GET", "/abc/234", []HandlerFunc{f})
		r.Add("GET", "/abc/125", []HandlerFunc{f})
		r.Add("GET", "/abc/235", []HandlerFunc{f})
		r.Add("GET", "/cbd/123", []HandlerFunc{f})
		r.Add("GET", "/cbd/234", []HandlerFunc{f})
		r.Add("GET", "/cbd/345", []HandlerFunc{f})
		r.Add("GET", "/cbd/456", []HandlerFunc{f})
		r.Add("GET", "/cbd/346", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd2(t *testing.T) {
	Convey("add param route", t, func() {
		r.Add("GET", "/a/:id/id", []HandlerFunc{f})
		r.Add("GET", "/a/:id/name", []HandlerFunc{f})
		r.Add("GET", "/a", []HandlerFunc{f})
		r.Add("GET", "/a/:id/", []HandlerFunc{f})
		r.Add("GET", "/a/", []HandlerFunc{f})
		r.Add("GET", "/a/*/xxx", []HandlerFunc{f})
		r.Add("GET", "/p/:project/file/:fileName", []HandlerFunc{f})
		r.Add("GET", "/cbd/:id", []HandlerFunc{f})

		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "/p/:/a", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd3(t *testing.T) {
	Convey("add param route with two different param", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "/a/:id", []HandlerFunc{f})
		r.Add("GET", "/a/:name", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd4(t *testing.T) {
	Convey("add route by group", t, func() {
		b.Group("/user", func() {
			b.Get("/info", f)
			b.Get("/info2", f)
			b.Group("/group", func() {
				b.Get("/info", f)
				b.Get("/info2", f)
			})
		})
		b.Group("/user", func() {
			b.Get("/", f)
			b.Get("/pass", f)
			b.Get("/pass2", f)
		}, f)
	})
}

func TestTreeRouteAdd5(t *testing.T) {
	Convey("add route then set name, URLFor", t, func() {
		b.Get("/article/:id/show", f).Name("articleShow")
		b.Get("/article/:id/detail", f).Name("")
		url := b.URLFor("articleShow", 123)
		So(url, ShouldEqual, "/article/123/show")
		url = b.URLFor("", nil)
		So(url, ShouldEqual, "")
		url = b.URLFor("not exits", "no")
		So(url, ShouldEqual, "")
		ru, name := r.Match("GET", "/article/123/show", c)
		So(ru, ShouldNotBeNil)
		So(name, ShouldEqual, "articleShow")
	})
}

func TestTreeRouteAdd6(t *testing.T) {
	Convey("add route with not support method", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("TRACE", "/", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd7(t *testing.T) {
	Convey("add route with empty pattern", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd8(t *testing.T) {
	Convey("add route with pattern that not begin with /", t, func() {
		defer func() {
			e := recover()
			So(e, ShouldNotBeNil)
		}()
		r.Add("GET", "abc", []HandlerFunc{f})
	})
}

func TestTreeRouteAdd9(t *testing.T) {
	Convey("other route method", t, func() {
		b2 := New()
		Convey("set auto head route", func() {
			b2.SetAutoHead(true)
			b2.Get("/head", func(c *Context) {
				So(c.Req.Method, ShouldEqual, "HEAD")
			})
			req, _ := http.NewRequest("HEAD", "/head", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("set auto training slash", func() {
			b2.SetAutoTrailingSlash(true)
			b2.Get("/slash", func(c *Context) {})
			b2.Group("/slash2", func() {
				b2.Get("/", func(c *Context) {})
				b2.Get("/exist", func(c *Context) {})
			})
			req, _ := http.NewRequest("GET", "/slash", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("GET", "/slash2/exist/", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("set multi method", func() {
			b2.Route("/mul1", "*", func(c *Context) {
				c.String(200, "mul")
			})
			b2.Route("/mul2", "GET,HEAD,POST", func(c *Context) {
				c.String(200, "mul")
			})
			req, _ := http.NewRequest("HEAD", "/mul2", nil)
			w := httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)

			req, _ = http.NewRequest("GET", "/mul2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
			req, _ = http.NewRequest("POST", "/mul2", nil)
			w = httptest.NewRecorder()
			b2.ServeHTTP(w, req)
			So(w.Code, ShouldEqual, http.StatusOK)
		})
		Convey("methods", func() {
			b2.Get("/methods", f)
			b2.Patch("/methods", f)
			b2.Post("/methods", f)
			b2.Put("/methods", f)
			b2.Delete("/methods", f)
			b2.Options("/methods", f)
			b2.Head("/methods", f)
			b2.Any("/any", f)
			b2.SetNotFound(func(c *Context) {
				c.String(404, "baa not found")
			})
		})
	})
}

func TestTreeRouteMatch1(t *testing.T) {
	Convey("match route", t, func() {

		ru, _ := r.Match("GET", "/", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/abc/1234", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "xxx", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/a/123/id", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/p/yst/file/a.jpg", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/info", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/pass", c)
		So(ru, ShouldNotBeNil)

		ru, _ = r.Match("GET", "/user/pass32", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/user/xxx", c)
		So(ru, ShouldBeNil)

		ru, _ = r.Match("GET", "/xxxx", c)
		So(ru, ShouldBeNil)

		b.Get("/notifications/threads/:id", f)
		b.Get("/notifications/threads/:id/subscription", f)
		b.Get("/notifications/threads/:id/subc", f)
		b.Put("/notifications/threads/:id/subscription", f)
		b.Delete("/notifications/threads/:id/subscription", f)
		ru, _ = r.Match("GET", "/notifications/threads/:id", c)
		So(ru, ShouldNotBeNil)
		ru, _ = r.Match("GET", "/notifications/threads/:id/sub", c)
		So(ru, ShouldBeNil)
	})
}

func TestTreeRoutePrint1(t *testing.T) {
	Convey("print route table", t, func() {
		r.(*Tree).print("", nil)
	})
}

func TestTreeRoutePrint2(t *testing.T) {
	Convey("print routes", t, func() {
		fmt.Println("")
		for method, routes := range r.Routes() {
			fmt.Println("Method: ", method)
			for i, route := range routes {
				fmt.Printf(" %3d %s\n", i, route)
			}
		}
	})
}

func TestTreeRoutePrint3(t *testing.T) {
	Convey("print named routes", t, func() {
		fmt.Println("")
		for name, route := range r.NamedRoutes() {
			fmt.Printf("%20s \t %s\n", name, route)
		}
	})
}
<|endoftext|>


<commit_before>package trie

import (
	"bufio"
	"log"
	"os"
	"sort"
	"testing"
)

func addFromFile(t *Trie, path string) {
	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewScanner(file)

	for reader.Scan() {
		t.Add(reader.Text(), nil)
	}

	if reader.Err() != nil {
		log.Fatal(err)
	}
}

func TestTrieAdd(t *testing.T) {
	trie := New()

	n := trie.Add("foo", 1)

	if n.Meta().(int) != 1 {
		t.Errorf("Expected 1, got: %d", n.Meta().(int))
	}
}

func TestTrieFind(t *testing.T) {
	trie := New()
	trie.Add("foo", 1)

	n, ok := trie.Find("foo")
	if ok != true {
		t.Fatal("Could not find node")
	}

	if n.Meta().(int) != 1 {
		t.Errorf("Expected 1, got: %d", n.Meta().(int))
	}
}

func TestTrieFindMissingWithSubtree(t *testing.T) {
	trie := New()
	trie.Add("fooish", 1)
	trie.Add("foobar", 1)

	n, ok := trie.Find("foo")
	if ok != false {
		t.Errorf("Expected ok to be false")
	}
	if n != nil {
		t.Errorf("Expected nil, got: %v", n)
	}
}

func TestTrieHasKeysWithPrefix(t *testing.T) {
	trie := New()
	trie.Add("fooish", 1)
	trie.Add("foobar", 1)

	testcases := []struct {
		key      string
		expected bool
	}{
		{"foobar", true},
		{"foo", true},
		{"fool", false},
	}
	for _, testcase := range testcases {
		if trie.HasKeysWithPrefix(testcase.key) != testcase.expected {
			t.Errorf("HasKeysWithPrefix(\"%s\"): expected result to be %t", testcase.key, testcase.expected)
		}
	}
}

func TestTrieFindMissing(t *testing.T) {
	trie := New()

	n, ok := trie.Find("foo")
	if ok != false {
		t.Errorf("Expected ok to be false")
	}
	if n != nil {
		t.Errorf("Expected nil, got: %v", n)
	}
}

func TestRemove(t *testing.T) {
	trie := New()
	initial := []string{"football", "foostar", "foosball"}

	for _, key := range initial {
		trie.Add(key, nil)
	}

	trie.Remove("foosball")
	keys := trie.Keys()

	if len(keys) != 2 {
		t.Errorf("Expected 2 keys got %d", len(keys))
	}

	for _, k := range keys {
		if k != "football" && k != "foostar" {
			t.Errorf("key was: %s", k)
		}
	}

	keys = trie.FuzzySearch("foo")
	if len(keys) != 2 {
		t.Errorf("Expected 2 keys got %d", len(keys))
	}

	for _, k := range keys {
		if k != "football" && k != "foostar" {
			t.Errorf("Expected football got: %#v", k)
		}
	}
}

func TestTrieKeys(t *testing.T) {
	tableTests := []struct {
		name         string
		expectedKeys []string
	}{
		{"Two", []string{"bar", "foo"}},
		{"One", []string{"foo"}},
		{"Empty", []string{}},
	}

	for _, test := range tableTests {
		t.Run(test.name, func(t *testing.T) {
			trie := New()
			for _, key := range test.expectedKeys {
				trie.Add(key, nil)
			}

			keys := trie.Keys()
			if len(keys) != len(test.expectedKeys) {
				t.Errorf("Expected %v keys, got %d, keys were: %v", len(test.expectedKeys), len(keys), trie.Keys())
			}

			sort.Strings(keys)
			for i, key := range keys {
				if key != test.expectedKeys[i] {
					t.Errorf("Expected %#v, got %#v", test.expectedKeys[i], key)
				}
			}
		})
	}
}

func TestPrefixSearch(t *testing.T) {
	trie := New()
	expected := []string{
		"foo",
		"foosball",
		"football",
		"foreboding",
		"forementioned",
		"foretold",
		"foreverandeverandeverandever",
		"forbidden",
	}

	defer func() {
		r := recover()
		if r != nil {
			t.Error(r)
		}
	}()

	trie.Add("bar", nil)
	for _, key := range expected {
		trie.Add(key, nil)
	}

	tests := []struct {
		pre      string
		expected []string
		length   int
	}{
		{"fo", expected, len(expected)},
		{"foosbal", []string{"foosball"}, 1},
		{"abc", []string{}, 0},
	}

	for _, test := range tests {
		actual := trie.PrefixSearch(test.pre)
		sort.Strings(actual)
		sort.Strings(test.expected)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d for pre %s", test.length, test.pre)
		}

		for i, key := range actual {
			if key != test.expected[i] {
				t.Errorf("Expected %v got: %v", test.expected[i], key)
			}
		}
	}

	trie.PrefixSearch("fsfsdfasdf")
}

func TestFuzzySearch(t *testing.T) {
	trie := New()
	setup := []string{
		"foosball",
		"football",
		"bmerica",
		"ked",
		"kedlock",
		"frosty",
		"bfrza",
		"foo/bart/baz.go",
	}
	tests := []struct {
		partial string
		length  int
	}{
		{"fsb", 1},
		{"footbal", 1},
		{"football", 1},
		{"fs", 2},
		{"oos", 1},
		{"kl", 1},
		{"ft", 3},
		{"fy", 1},
		{"fz", 2},
		{"a", 5},
	}

	for _, key := range setup {
		trie.Add(key, nil)
	}

	for _, test := range tests {
		actual := trie.FuzzySearch(test.partial)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d, was %d for %s actual was %#v",
				test.length, len(actual), test.partial, actual)
		}
	}
}

func TestFuzzySearchSorting(t *testing.T) {
	trie := New()
	setup := []string{
		"foosball",
		"football",
		"bmerica",
		"ked",
		"kedlock",
		"frosty",
		"bfrza",
		"foo/bart/baz.go",
	}

	for _, key := range setup {
		trie.Add(key, nil)
	}

	actual := trie.FuzzySearch("fz")
	expected := []string{"bfrza", "foo/bart/baz.go"}

	if len(actual) != len(expected) {
		t.Fatalf("expected len %d got %d", len(expected), len(actual))
	}
	for i, v := range expected {
		if actual[i] != v {
			t.Errorf("Expected %s got %s", v, actual[i])
		}
	}

}

func BenchmarkTieKeys(b *testing.B) {
	trie := New()
	keys := []string{"bar", "foo", "baz", "bur", "zum", "burzum", "bark", "barcelona", "football", "foosball", "footlocker"}

	for _, key := range keys {
		trie.Add(key, nil)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		trie.Keys()
	}
}

func BenchmarkPrefixSearch(b *testing.B) {
	trie := New()
	addFromFile(trie, "/usr/share/dict/words")

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = trie.PrefixSearch("fo")
	}
}

func BenchmarkFuzzySearch(b *testing.B) {
	trie := New()
	addFromFile(trie, "/usr/share/dict/words")

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = trie.FuzzySearch("fs")
	}
}

func BenchmarkBuildTree(b *testing.B) {
	for i := 0; i < b.N; i++ {
		trie := New()
		addFromFile(trie, "/usr/share/dict/words")
	}
}

func TestSupportChinese(t *testing.T) {
	trie := New()
	expected := []string{"苹果 沂水县", "苹果", "大蒜", "大豆"}

	for _, key := range expected {
		trie.Add(key, nil)
	}

	tests := []struct {
		pre      string
		expected []string
		length   int
	}{
		{"苹", expected[:2], len(expected[:2])},
		{"大", expected[2:], len(expected[2:])},
		{"大蒜", []string{"大蒜"}, 1},
	}

	for _, test := range tests {
		actual := trie.PrefixSearch(test.pre)
		sort.Strings(actual)
		sort.Strings(test.expected)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d for pre %s", test.length, test.pre)
		}

		for i, key := range actual {
			if key != test.expected[i] {
				t.Errorf("Expected %v got: %v", test.expected[i], key)
			}
		}
	}
}
<commit_msg>add and remove tests<commit_after>package trie

import (
	"bufio"
	"log"
	"os"
	"sort"
	"testing"
)

func addFromFile(t *Trie, path string) {
	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewScanner(file)

	for reader.Scan() {
		t.Add(reader.Text(), nil)
	}

	if reader.Err() != nil {
		log.Fatal(err)
	}
}

func TestTrieAdd(t *testing.T) {
	trie := New()

	n := trie.Add("foo", 1)

	if n.Meta().(int) != 1 {
		t.Errorf("Expected 1, got: %d", n.Meta().(int))
	}
}

func TestTrieFind(t *testing.T) {
	trie := New()
	trie.Add("foo", 1)

	n, ok := trie.Find("foo")
	if ok != true {
		t.Fatal("Could not find node")
	}

	if n.Meta().(int) != 1 {
		t.Errorf("Expected 1, got: %d", n.Meta().(int))
	}
}

func TestTrieFindMissingWithSubtree(t *testing.T) {
	trie := New()
	trie.Add("fooish", 1)
	trie.Add("foobar", 1)

	n, ok := trie.Find("foo")
	if ok != false {
		t.Errorf("Expected ok to be false")
	}
	if n != nil {
		t.Errorf("Expected nil, got: %v", n)
	}
}

func TestTrieHasKeysWithPrefix(t *testing.T) {
	trie := New()
	trie.Add("fooish", 1)
	trie.Add("foobar", 1)

	testcases := []struct {
		key      string
		expected bool
	}{
		{"foobar", true},
		{"foo", true},
		{"fool", false},
	}
	for _, testcase := range testcases {
		if trie.HasKeysWithPrefix(testcase.key) != testcase.expected {
			t.Errorf("HasKeysWithPrefix(\"%s\"): expected result to be %t", testcase.key, testcase.expected)
		}
	}
}

func TestTrieFindMissing(t *testing.T) {
	trie := New()

	n, ok := trie.Find("foo")
	if ok != false {
		t.Errorf("Expected ok to be false")
	}
	if n != nil {
		t.Errorf("Expected nil, got: %v", n)
	}
}

func TestRemove(t *testing.T) {
	trie := New()
	initial := []string{"football", "foostar", "foosball"}

	for _, key := range initial {
		trie.Add(key, nil)
	}

	trie.Remove("foosball")
	keys := trie.Keys()

	if len(keys) != 2 {
		t.Errorf("Expected 2 keys got %d", len(keys))
	}

	for _, k := range keys {
		if k != "football" && k != "foostar" {
			t.Errorf("key was: %s", k)
		}
	}

	keys = trie.FuzzySearch("foo")
	if len(keys) != 2 {
		t.Errorf("Expected 2 keys got %d", len(keys))
	}

	for _, k := range keys {
		if k != "football" && k != "foostar" {
			t.Errorf("Expected football got: %#v", k)
		}
	}
}

func TestTrieKeys(t *testing.T) {
	tableTests := []struct {
		name         string
		expectedKeys []string
	}{
		{"Two", []string{"bar", "foo"}},
		{"One", []string{"foo"}},
		{"Empty", []string{}},
	}

	for _, test := range tableTests {
		t.Run(test.name, func(t *testing.T) {
			trie := New()
			for _, key := range test.expectedKeys {
				trie.Add(key, nil)
			}

			keys := trie.Keys()
			if len(keys) != len(test.expectedKeys) {
				t.Errorf("Expected %v keys, got %d, keys were: %v", len(test.expectedKeys), len(keys), trie.Keys())
			}

			sort.Strings(keys)
			for i, key := range keys {
				if key != test.expectedKeys[i] {
					t.Errorf("Expected %#v, got %#v", test.expectedKeys[i], key)
				}
			}
		})
	}
}

func TestPrefixSearch(t *testing.T) {
	trie := New()
	expected := []string{
		"foo",
		"foosball",
		"football",
		"foreboding",
		"forementioned",
		"foretold",
		"foreverandeverandeverandever",
		"forbidden",
	}

	defer func() {
		r := recover()
		if r != nil {
			t.Error(r)
		}
	}()

	trie.Add("bar", nil)
	for _, key := range expected {
		trie.Add(key, nil)
	}

	tests := []struct {
		pre      string
		expected []string
		length   int
	}{
		{"fo", expected, len(expected)},
		{"foosbal", []string{"foosball"}, 1},
		{"abc", []string{}, 0},
	}

	for _, test := range tests {
		actual := trie.PrefixSearch(test.pre)
		sort.Strings(actual)
		sort.Strings(test.expected)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d for pre %s", test.length, test.pre)
		}

		for i, key := range actual {
			if key != test.expected[i] {
				t.Errorf("Expected %v got: %v", test.expected[i], key)
			}
		}
	}

	trie.PrefixSearch("fsfsdfasdf")
}

func TestFuzzySearch(t *testing.T) {
	trie := New()
	setup := []string{
		"foosball",
		"football",
		"bmerica",
		"ked",
		"kedlock",
		"frosty",
		"bfrza",
		"foo/bart/baz.go",
	}
	tests := []struct {
		partial string
		length  int
	}{
		{"fsb", 1},
		{"footbal", 1},
		{"football", 1},
		{"fs", 2},
		{"oos", 1},
		{"kl", 1},
		{"ft", 3},
		{"fy", 1},
		{"fz", 2},
		{"a", 5},
	}

	for _, key := range setup {
		trie.Add(key, nil)
	}

	for _, test := range tests {
		actual := trie.FuzzySearch(test.partial)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d, was %d for %s actual was %#v",
				test.length, len(actual), test.partial, actual)
		}
	}
}

func TestFuzzySearchSorting(t *testing.T) {
	trie := New()
	setup := []string{
		"foosball",
		"football",
		"bmerica",
		"ked",
		"kedlock",
		"frosty",
		"bfrza",
		"foo/bart/baz.go",
	}

	for _, key := range setup {
		trie.Add(key, nil)
	}

	actual := trie.FuzzySearch("fz")
	expected := []string{"bfrza", "foo/bart/baz.go"}

	if len(actual) != len(expected) {
		t.Fatalf("expected len %d got %d", len(expected), len(actual))
	}
	for i, v := range expected {
		if actual[i] != v {
			t.Errorf("Expected %s got %s", v, actual[i])
		}
	}

}

func BenchmarkTieKeys(b *testing.B) {
	trie := New()
	keys := []string{"bar", "foo", "baz", "bur", "zum", "burzum", "bark", "barcelona", "football", "foosball", "footlocker"}

	for _, key := range keys {
		trie.Add(key, nil)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		trie.Keys()
	}
}

func BenchmarkPrefixSearch(b *testing.B) {
	trie := New()
	addFromFile(trie, "/usr/share/dict/words")

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = trie.PrefixSearch("fo")
	}
}

func BenchmarkFuzzySearch(b *testing.B) {
	trie := New()
	addFromFile(trie, "/usr/share/dict/words")

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = trie.FuzzySearch("fs")
	}
}

func BenchmarkBuildTree(b *testing.B) {
	for i := 0; i < b.N; i++ {
		trie := New()
		addFromFile(trie, "/usr/share/dict/words")
	}
}

func TestSupportChinese(t *testing.T) {
	trie := New()
	expected := []string{"苹果 沂水县", "苹果", "大蒜", "大豆"}

	for _, key := range expected {
		trie.Add(key, nil)
	}

	tests := []struct {
		pre      string
		expected []string
		length   int
	}{
		{"苹", expected[:2], len(expected[:2])},
		{"大", expected[2:], len(expected[2:])},
		{"大蒜", []string{"大蒜"}, 1},
	}

	for _, test := range tests {
		actual := trie.PrefixSearch(test.pre)
		sort.Strings(actual)
		sort.Strings(test.expected)
		if len(actual) != test.length {
			t.Errorf("Expected len(actual) to == %d for pre %s", test.length, test.pre)
		}

		for i, key := range actual {
			if key != test.expected[i] {
				t.Errorf("Expected %v got: %v", test.expected[i], key)
			}
		}
	}
}

func BenchmarkAdd(b *testing.B) {
	f, err := os.Open("/usr/share/dict/words")
	if err != nil {
		b.Fatal("couldn't open bag of words")
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	var words []string
	for scanner.Scan() {
		word := scanner.Text()
		words = append(words, word)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		trie := New()
		for k := range words {
			trie.Add(words[k], nil)
		}
	}
}

func BenchmarkAddRemove(b *testing.B) {
	words := []string{"AAAA1", "AAAA2", "ABAA1", "AABA1", "ABAA2"}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		trie := New()
		for k := range words {
			trie.Add(words[k], nil)
		}
		for k := range words {
			trie.Remove(words[k])
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>more checks for nil<commit_after><|endoftext|>


<commit_before><commit_msg>Use random name for workers (fixes #196) (#197)<commit_after><|endoftext|>


<commit_before>package main

import (
	"github.com/tus/tusd"
	"github.com/tus/tusd/filestore"
	"net/http"
)

func main() {

	store := filestore.FileStore{
		Path: "./data/",
	}

	handler, err := tusd.NewHandler(tusd.Config{
		MaxSize:   1024 * 1024 * 1024,
		BasePath:  "files/",
		DataStore: store,
	})
	if err != nil {
		panic(err)
	}

	http.Handle("/files/", http.StripPrefix("/files/", handler))
	err = http.ListenAndServe(":1080", nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>ensure filestore's directory exists<commit_after>package main

import (
	"github.com/tus/tusd"
	"github.com/tus/tusd/filestore"
	"net/http"
	"os"
)

func main() {

	if err := os.MkdirAll("./data/", os.FileMode(0666)); err != nil {
		panic(err)
	}

	store := filestore.FileStore{
		Path: "./data/",
	}

	handler, err := tusd.NewHandler(tusd.Config{
		MaxSize:   1024 * 1024 * 1024,
		BasePath:  "files/",
		DataStore: store,
	})
	if err != nil {
		panic(err)
	}

	http.Handle("/files/", http.StripPrefix("/files/", handler))
	err = http.ListenAndServe(":1080", nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package sudoku

import (
	"math"
)

//1.0 is a no op. 0.0 to 1.0 is increase goodness; 1.0 and above is decraase good
type probabilityTweak float64

type probabilityTwiddler func(*SolveStep, []*SolveStep, []*CompoundSolveStep, *Grid) probabilityTweak

type probabilityTwiddlerItem struct {
	f    probabilityTwiddler
	name string
}

//twiddlers is the list of all of the twiddlers we should apply to change the
//probability distribution of possibilities at each step. They capture biases
//that humans have about which cells to focus on (which is separate from
//Technique.humanLikelihood, since that is about how common a technique in
//general, not in a specific context.)
var twiddlers []probabilityTwiddlerItem

func init() {
	//twiddlers is not a map because a) we need to attach more info anyway,
	//and b) we want a stable ordering.
	twiddlers = []probabilityTwiddlerItem{
		{
			f:    twiddleHumanLikelihood,
			name: "Human Likelihood",
		},
		{
			f:    twiddleChainedSteps,
			name: "Chained Steps",
		},
		{
			f:    twiddleCommonNumbers,
			name: "Common Numbers",
		},
		{
			f:    twiddlePointingTargetOverlap,
			name: "Pointing Target Overlap",
		},
	}
}

//twiddlePointingTargetOverlap twiddles based on how much the targetcells
//overlap with the pointingcells of the proposed step. This tries to capture
//the fact that for cull steps in particular, we want to heavily incentivize
//steps that directly reduce possibilities in the next round of steps. This is
//conceptually similar to ChainSimilarity, but more targeted.
func twiddlePointingTargetOverlap(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {
	if len(inProgressCompoundStep) == 0 {
		return 1.0
	}
	lastStep := inProgressCompoundStep[len(inProgressCompoundStep)-1]

	if currentStep == nil {
		return 1.0
	}

	//We're going to look for two kinds of overlap: targetCell to targetCell,
	//and targetCell to PointerCell, because some techniques want one or the
	//other (do any want both?). We'll use the higher overlap.

	//Compute Target --> Pointer overlap

	currentStepPointerSet := currentStep.PointerCells.toCellSet()
	lastStepTargetSet := lastStep.TargetCells.toCellSet()

	targetPointerUnion := currentStepPointerSet.union(lastStepTargetSet)
	targetPointerIntersection := currentStepPointerSet.intersection(lastStepTargetSet)

	targetPointerOverlap := float64(len(targetPointerIntersection)) / float64(len(targetPointerUnion))

	if math.IsNaN(targetPointerOverlap) {
		targetPointerOverlap = 0.0
	}

	//Compute Target --> Target overlap

	currentStepTargetSet := currentStep.TargetCells.toCellSet()

	targetTargetUnion := currentStepTargetSet.union(lastStepTargetSet)
	targetTargetIntersection := currentStepTargetSet.intersection(lastStepTargetSet)

	targetTargetOverlap := float64(len(targetTargetIntersection)) / float64(len(targetTargetUnion))

	if math.IsNaN(targetTargetOverlap) {
		targetTargetOverlap = 0.0
	}

	//Pick the larger overlap to go with.

	overlap := targetPointerOverlap

	if targetTargetOverlap > targetPointerOverlap {
		overlap = targetTargetOverlap
		//TargetTargetOverlap is slightly better than targetPointer overlap.
		//This number will be flipped in the next step, so bigger is better.
		overlap *= 1.1
	}

	//The more overlap, the better, at an increasing rate. And the smaller the
	//output, the better the twiddle is.

	flippedOverlap := 1.0 - overlap

	//A value of 0--if there's perfect overlap--is nonsense. It's too strong!
	if flippedOverlap == 0.0 {
		flippedOverlap = 0.001
	}

	//Squaring the flipped overlap will accelerate small ones.
	return probabilityTweak(flippedOverlap * flippedOverlap)

}

//twiddleTechniqueWeight is a fundamental twiddler based on the
//HumanLikeliehood of the current technique. In fact, it's so fundamental that
//it's arguably not even a twiddler at all.
func twiddleHumanLikelihood(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {
	if currentStep == nil {
		return 1.0
	}
	return probabilityTweak(currentStep.HumanLikelihood())
}

//twiddleCommonNumbers will twiddle up steps whose TargetNumbers are over-
//represented in the grid (but not DIM). This captures that humans, in
//practice, will often choose to look for cells to fill for a number that is
//represented more in the grid, since they're more likely to be constrained by
//neighorbors with the same number.
func twiddleCommonNumbers(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {

	//Skip steps that aren't fill or fill multiple
	if !currentStep.Technique.IsFill() || len(currentStep.TargetNums) > 1 {
		return 1.0
	}

	keyNum := currentStep.TargetNums[0]

	count := 0

	for _, cell := range grid.Cells() {
		if cell.Number() == keyNum {
			count++
		}
	}

	if count == 0 || count == DIM {
		count = 1
	}

	return probabilityTweak(count)

}

//This function will tweak weights quite a bit to make it more likely that we will pick a subsequent step that
// is 'related' to the cells modified in the last step. For example, if the
// last step had targetCells that shared a row, then a step with
//target cells in that same row will be more likely this step. This captures the fact that humans, in practice,
//will have 'chains' of steps that are all related.
func twiddleChainedSteps(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {

	var lastModifiedCells CellSlice

	if len(inProgressCompoundStep) > 0 {
		lastModifiedCells = inProgressCompoundStep[len(inProgressCompoundStep)-1].TargetCells
	} else if len(pastSteps) > 0 {
		lastCompoundStep := pastSteps[len(pastSteps)-1]
		if lastCompoundStep.FillStep != nil {
			lastModifiedCells = lastCompoundStep.FillStep.TargetCells
		}
	}

	//TODO: this twiddler appears to be operating in the wrong direction!

	if lastModifiedCells == nil {
		return 1.0
	}

	//Tweak every weight by how related they are.
	//Remember: these are INVERTED weights, so tweaking them down is BETTER.

	//Logically we should be attenuating Dissimilarity here, but for some reason the math.Pow(dissimilairty, 10) doesn't actually
	//appear to work here, which is maddening.

	similarity := currentStep.TargetCells.chainSimilarity(lastModifiedCells)

	//We want it to be dissimilar is larger; flip it.
	dissimilarity := 1.0 - similarity

	return probabilityTweak(math.Pow(10, dissimilarity))

}
<commit_msg>Removed a completed TODO<commit_after>package sudoku

import (
	"math"
)

//1.0 is a no op. 0.0 to 1.0 is increase goodness; 1.0 and above is decraase good
type probabilityTweak float64

type probabilityTwiddler func(*SolveStep, []*SolveStep, []*CompoundSolveStep, *Grid) probabilityTweak

type probabilityTwiddlerItem struct {
	f    probabilityTwiddler
	name string
}

//twiddlers is the list of all of the twiddlers we should apply to change the
//probability distribution of possibilities at each step. They capture biases
//that humans have about which cells to focus on (which is separate from
//Technique.humanLikelihood, since that is about how common a technique in
//general, not in a specific context.)
var twiddlers []probabilityTwiddlerItem

func init() {
	//twiddlers is not a map because a) we need to attach more info anyway,
	//and b) we want a stable ordering.
	twiddlers = []probabilityTwiddlerItem{
		{
			f:    twiddleHumanLikelihood,
			name: "Human Likelihood",
		},
		{
			f:    twiddleChainedSteps,
			name: "Chained Steps",
		},
		{
			f:    twiddleCommonNumbers,
			name: "Common Numbers",
		},
		{
			f:    twiddlePointingTargetOverlap,
			name: "Pointing Target Overlap",
		},
	}
}

//twiddlePointingTargetOverlap twiddles based on how much the targetcells
//overlap with the pointingcells of the proposed step. This tries to capture
//the fact that for cull steps in particular, we want to heavily incentivize
//steps that directly reduce possibilities in the next round of steps. This is
//conceptually similar to ChainSimilarity, but more targeted.
func twiddlePointingTargetOverlap(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {
	if len(inProgressCompoundStep) == 0 {
		return 1.0
	}
	lastStep := inProgressCompoundStep[len(inProgressCompoundStep)-1]

	if currentStep == nil {
		return 1.0
	}

	//We're going to look for two kinds of overlap: targetCell to targetCell,
	//and targetCell to PointerCell, because some techniques want one or the
	//other (do any want both?). We'll use the higher overlap.

	//Compute Target --> Pointer overlap

	currentStepPointerSet := currentStep.PointerCells.toCellSet()
	lastStepTargetSet := lastStep.TargetCells.toCellSet()

	targetPointerUnion := currentStepPointerSet.union(lastStepTargetSet)
	targetPointerIntersection := currentStepPointerSet.intersection(lastStepTargetSet)

	targetPointerOverlap := float64(len(targetPointerIntersection)) / float64(len(targetPointerUnion))

	if math.IsNaN(targetPointerOverlap) {
		targetPointerOverlap = 0.0
	}

	//Compute Target --> Target overlap

	currentStepTargetSet := currentStep.TargetCells.toCellSet()

	targetTargetUnion := currentStepTargetSet.union(lastStepTargetSet)
	targetTargetIntersection := currentStepTargetSet.intersection(lastStepTargetSet)

	targetTargetOverlap := float64(len(targetTargetIntersection)) / float64(len(targetTargetUnion))

	if math.IsNaN(targetTargetOverlap) {
		targetTargetOverlap = 0.0
	}

	//Pick the larger overlap to go with.

	overlap := targetPointerOverlap

	if targetTargetOverlap > targetPointerOverlap {
		overlap = targetTargetOverlap
		//TargetTargetOverlap is slightly better than targetPointer overlap.
		//This number will be flipped in the next step, so bigger is better.
		overlap *= 1.1
	}

	//The more overlap, the better, at an increasing rate. And the smaller the
	//output, the better the twiddle is.

	flippedOverlap := 1.0 - overlap

	//A value of 0--if there's perfect overlap--is nonsense. It's too strong!
	if flippedOverlap == 0.0 {
		flippedOverlap = 0.001
	}

	//Squaring the flipped overlap will accelerate small ones.
	return probabilityTweak(flippedOverlap * flippedOverlap)

}

//twiddleTechniqueWeight is a fundamental twiddler based on the
//HumanLikeliehood of the current technique. In fact, it's so fundamental that
//it's arguably not even a twiddler at all.
func twiddleHumanLikelihood(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {
	if currentStep == nil {
		return 1.0
	}
	return probabilityTweak(currentStep.HumanLikelihood())
}

//twiddleCommonNumbers will twiddle up steps whose TargetNumbers are over-
//represented in the grid (but not DIM). This captures that humans, in
//practice, will often choose to look for cells to fill for a number that is
//represented more in the grid, since they're more likely to be constrained by
//neighorbors with the same number.
func twiddleCommonNumbers(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {

	//Skip steps that aren't fill or fill multiple
	if !currentStep.Technique.IsFill() || len(currentStep.TargetNums) > 1 {
		return 1.0
	}

	keyNum := currentStep.TargetNums[0]

	count := 0

	for _, cell := range grid.Cells() {
		if cell.Number() == keyNum {
			count++
		}
	}

	if count == 0 || count == DIM {
		count = 1
	}

	return probabilityTweak(count)

}

//This function will tweak weights quite a bit to make it more likely that we will pick a subsequent step that
// is 'related' to the cells modified in the last step. For example, if the
// last step had targetCells that shared a row, then a step with
//target cells in that same row will be more likely this step. This captures the fact that humans, in practice,
//will have 'chains' of steps that are all related.
func twiddleChainedSteps(currentStep *SolveStep, inProgressCompoundStep []*SolveStep, pastSteps []*CompoundSolveStep, grid *Grid) probabilityTweak {

	var lastModifiedCells CellSlice

	if len(inProgressCompoundStep) > 0 {
		lastModifiedCells = inProgressCompoundStep[len(inProgressCompoundStep)-1].TargetCells
	} else if len(pastSteps) > 0 {
		lastCompoundStep := pastSteps[len(pastSteps)-1]
		if lastCompoundStep.FillStep != nil {
			lastModifiedCells = lastCompoundStep.FillStep.TargetCells
		}
	}

	if lastModifiedCells == nil {
		return 1.0
	}

	//Tweak every weight by how related they are.
	//Remember: these are INVERTED weights, so tweaking them down is BETTER.

	//Logically we should be attenuating Dissimilarity here, but for some reason the math.Pow(dissimilairty, 10) doesn't actually
	//appear to work here, which is maddening.

	similarity := currentStep.TargetCells.chainSimilarity(lastModifiedCells)

	//We want it to be dissimilar is larger; flip it.
	dissimilarity := 1.0 - similarity

	return probabilityTweak(math.Pow(10, dissimilarity))

}
<|endoftext|>


<commit_before>package u9

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// AddTabSupport is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func AddTabSupport(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); ke.KeyIdentifier {
		case "U+0009": // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}
<commit_msg>Add comment explaining behavior.<commit_after>package u9

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// AddTabSupport is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func AddTabSupport(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); ke.KeyIdentifier {
		case "U+0009": // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			// Trigger "input" event listeners.
			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func GetComputeImageCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/global/images/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeImageApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/Image",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "Image",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeImageApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	descriptionProp, err := expandComputeImageDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	diskSizeGbProp, err := expandComputeImageDiskSizeGb(d.Get("disk_size_gb"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("disk_size_gb"); !isEmptyValue(reflect.ValueOf(diskSizeGbProp)) && (ok || !reflect.DeepEqual(v, diskSizeGbProp)) {
		obj["diskSizeGb"] = diskSizeGbProp
	}
	familyProp, err := expandComputeImageFamily(d.Get("family"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("family"); !isEmptyValue(reflect.ValueOf(familyProp)) && (ok || !reflect.DeepEqual(v, familyProp)) {
		obj["family"] = familyProp
	}
	guestOsFeaturesProp, err := expandComputeImageGuestOsFeatures(d.Get("guest_os_features"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("guest_os_features"); !isEmptyValue(reflect.ValueOf(guestOsFeaturesProp)) && (ok || !reflect.DeepEqual(v, guestOsFeaturesProp)) {
		obj["guestOsFeatures"] = guestOsFeaturesProp
	}
	labelsProp, err := expandComputeImageLabels(d.Get("labels"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
		obj["labels"] = labelsProp
	}
	labelFingerprintProp, err := expandComputeImageLabelFingerprint(d.Get("label_fingerprint"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
		obj["labelFingerprint"] = labelFingerprintProp
	}
	licensesProp, err := expandComputeImageLicenses(d.Get("licenses"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("licenses"); !isEmptyValue(reflect.ValueOf(licensesProp)) && (ok || !reflect.DeepEqual(v, licensesProp)) {
		obj["licenses"] = licensesProp
	}
	nameProp, err := expandComputeImageName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	rawDiskProp, err := expandComputeImageRawDisk(d.Get("raw_disk"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("raw_disk"); !isEmptyValue(reflect.ValueOf(rawDiskProp)) && (ok || !reflect.DeepEqual(v, rawDiskProp)) {
		obj["rawDisk"] = rawDiskProp
	}
	sourceDiskProp, err := expandComputeImageSourceDisk(d.Get("source_disk"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("source_disk"); !isEmptyValue(reflect.ValueOf(sourceDiskProp)) && (ok || !reflect.DeepEqual(v, sourceDiskProp)) {
		obj["sourceDisk"] = sourceDiskProp
	}

	return obj, nil
}

func expandComputeImageDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageFamily(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageGuestOsFeatures(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	v = v.(*schema.Set).List()
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedType, err := expandComputeImageGuestOsFeaturesType(original["type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
			transformed["type"] = transformedType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandComputeImageGuestOsFeaturesType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
	if v == nil {
		return map[string]string{}, nil
	}
	m := make(map[string]string)
	for k, val := range v.(map[string]interface{}) {
		m[k] = val.(string)
	}
	return m, nil
}

func expandComputeImageLabelFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageLicenses(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			return nil, fmt.Errorf("Invalid value for licenses: nil")
		}
		f, err := parseGlobalFieldValue("licenses", raw.(string), "project", d, config, true)
		if err != nil {
			return nil, fmt.Errorf("Invalid value for licenses: %s", err)
		}
		req = append(req, f.RelativeLink())
	}
	return req, nil
}

func expandComputeImageName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDisk(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedContainerType, err := expandComputeImageRawDiskContainerType(original["container_type"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedContainerType); val.IsValid() && !isEmptyValue(val) {
		transformed["containerType"] = transformedContainerType
	}

	transformedSha1, err := expandComputeImageRawDiskSha1(original["sha1"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedSha1); val.IsValid() && !isEmptyValue(val) {
		transformed["sha1Checksum"] = transformedSha1
	}

	transformedSource, err := expandComputeImageRawDiskSource(original["source"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedSource); val.IsValid() && !isEmptyValue(val) {
		transformed["source"] = transformedSource
	}

	return transformed, nil
}

func expandComputeImageRawDiskContainerType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDiskSha1(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDiskSource(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageSourceDisk(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseZonalFieldValue("disks", v.(string), "project", "zone", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for source_disk: %s", err)
	}
	return f.RelativeLink(), nil
}
<commit_msg>add source_image and source_snapshot to google_compute_image (#3799) (#491)<commit_after>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func GetComputeImageCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/global/images/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeImageApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/Image",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "Image",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeImageApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	descriptionProp, err := expandComputeImageDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	diskSizeGbProp, err := expandComputeImageDiskSizeGb(d.Get("disk_size_gb"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("disk_size_gb"); !isEmptyValue(reflect.ValueOf(diskSizeGbProp)) && (ok || !reflect.DeepEqual(v, diskSizeGbProp)) {
		obj["diskSizeGb"] = diskSizeGbProp
	}
	familyProp, err := expandComputeImageFamily(d.Get("family"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("family"); !isEmptyValue(reflect.ValueOf(familyProp)) && (ok || !reflect.DeepEqual(v, familyProp)) {
		obj["family"] = familyProp
	}
	guestOsFeaturesProp, err := expandComputeImageGuestOsFeatures(d.Get("guest_os_features"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("guest_os_features"); !isEmptyValue(reflect.ValueOf(guestOsFeaturesProp)) && (ok || !reflect.DeepEqual(v, guestOsFeaturesProp)) {
		obj["guestOsFeatures"] = guestOsFeaturesProp
	}
	labelsProp, err := expandComputeImageLabels(d.Get("labels"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
		obj["labels"] = labelsProp
	}
	labelFingerprintProp, err := expandComputeImageLabelFingerprint(d.Get("label_fingerprint"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
		obj["labelFingerprint"] = labelFingerprintProp
	}
	licensesProp, err := expandComputeImageLicenses(d.Get("licenses"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("licenses"); !isEmptyValue(reflect.ValueOf(licensesProp)) && (ok || !reflect.DeepEqual(v, licensesProp)) {
		obj["licenses"] = licensesProp
	}
	nameProp, err := expandComputeImageName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	rawDiskProp, err := expandComputeImageRawDisk(d.Get("raw_disk"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("raw_disk"); !isEmptyValue(reflect.ValueOf(rawDiskProp)) && (ok || !reflect.DeepEqual(v, rawDiskProp)) {
		obj["rawDisk"] = rawDiskProp
	}
	sourceDiskProp, err := expandComputeImageSourceDisk(d.Get("source_disk"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("source_disk"); !isEmptyValue(reflect.ValueOf(sourceDiskProp)) && (ok || !reflect.DeepEqual(v, sourceDiskProp)) {
		obj["sourceDisk"] = sourceDiskProp
	}
	sourceImageProp, err := expandComputeImageSourceImage(d.Get("source_image"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("source_image"); !isEmptyValue(reflect.ValueOf(sourceImageProp)) && (ok || !reflect.DeepEqual(v, sourceImageProp)) {
		obj["sourceImage"] = sourceImageProp
	}
	sourceSnapshotProp, err := expandComputeImageSourceSnapshot(d.Get("source_snapshot"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("source_snapshot"); !isEmptyValue(reflect.ValueOf(sourceSnapshotProp)) && (ok || !reflect.DeepEqual(v, sourceSnapshotProp)) {
		obj["sourceSnapshot"] = sourceSnapshotProp
	}

	return obj, nil
}

func expandComputeImageDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageFamily(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageGuestOsFeatures(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	v = v.(*schema.Set).List()
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedType, err := expandComputeImageGuestOsFeaturesType(original["type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
			transformed["type"] = transformedType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandComputeImageGuestOsFeaturesType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
	if v == nil {
		return map[string]string{}, nil
	}
	m := make(map[string]string)
	for k, val := range v.(map[string]interface{}) {
		m[k] = val.(string)
	}
	return m, nil
}

func expandComputeImageLabelFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageLicenses(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			return nil, fmt.Errorf("Invalid value for licenses: nil")
		}
		f, err := parseGlobalFieldValue("licenses", raw.(string), "project", d, config, true)
		if err != nil {
			return nil, fmt.Errorf("Invalid value for licenses: %s", err)
		}
		req = append(req, f.RelativeLink())
	}
	return req, nil
}

func expandComputeImageName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDisk(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedContainerType, err := expandComputeImageRawDiskContainerType(original["container_type"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedContainerType); val.IsValid() && !isEmptyValue(val) {
		transformed["containerType"] = transformedContainerType
	}

	transformedSha1, err := expandComputeImageRawDiskSha1(original["sha1"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedSha1); val.IsValid() && !isEmptyValue(val) {
		transformed["sha1Checksum"] = transformedSha1
	}

	transformedSource, err := expandComputeImageRawDiskSource(original["source"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedSource); val.IsValid() && !isEmptyValue(val) {
		transformed["source"] = transformedSource
	}

	return transformed, nil
}

func expandComputeImageRawDiskContainerType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDiskSha1(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageRawDiskSource(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeImageSourceDisk(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseZonalFieldValue("disks", v.(string), "project", "zone", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for source_disk: %s", err)
	}
	return f.RelativeLink(), nil
}

func expandComputeImageSourceImage(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("images", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for source_image: %s", err)
	}
	return f.RelativeLink(), nil
}

func expandComputeImageSourceSnapshot(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("snapshots", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for source_snapshot: %s", err)
	}
	return f.RelativeLink(), nil
}
<|endoftext|>


<commit_before>package google

import "github.com/hashicorp/terraform-plugin-sdk/helper/schema"

func canonicalizeServiceScope(scope string) string {
	// This is a convenience map of short names used by the gcloud tool
	// to the GCE auth endpoints they alias to.
	scopeMap := map[string]string{
		"bigquery":              "https://www.googleapis.com/auth/bigquery",
		"cloud-platform":        "https://www.googleapis.com/auth/cloud-platform",
		"cloud-source-repos":    "https://www.googleapis.com/auth/source.full_control",
		"cloud-source-repos-ro": "https://www.googleapis.com/auth/source.read_only",
		"compute-ro":            "https://www.googleapis.com/auth/compute.readonly",
		"compute-rw":            "https://www.googleapis.com/auth/compute",
		"datastore":             "https://www.googleapis.com/auth/datastore",
		"logging-write":         "https://www.googleapis.com/auth/logging.write",
		"monitoring":            "https://www.googleapis.com/auth/monitoring",
		"monitoring-write":      "https://www.googleapis.com/auth/monitoring.write",
		"pubsub":                "https://www.googleapis.com/auth/pubsub",
		"service-control":       "https://www.googleapis.com/auth/servicecontrol",
		"service-management":    "https://www.googleapis.com/auth/service.management.readonly",
		"sql":                   "https://www.googleapis.com/auth/sqlservice",
		"sql-admin":             "https://www.googleapis.com/auth/sqlservice.admin",
		"storage-full":          "https://www.googleapis.com/auth/devstorage.full_control",
		"storage-ro":            "https://www.googleapis.com/auth/devstorage.read_only",
		"storage-rw":            "https://www.googleapis.com/auth/devstorage.read_write",
		"taskqueue":             "https://www.googleapis.com/auth/taskqueue",
		"trace-append":          "https://www.googleapis.com/auth/trace.append",
		"trace-ro":              "https://www.googleapis.com/auth/trace.readonly",
		"useraccounts-ro":       "https://www.googleapis.com/auth/cloud.useraccounts.readonly",
		"useraccounts-rw":       "https://www.googleapis.com/auth/cloud.useraccounts",
		"userinfo-email":        "https://www.googleapis.com/auth/userinfo.email",
	}

	if matchedURL, ok := scopeMap[scope]; ok {
		return matchedURL
	}

	return scope
}

func canonicalizeServiceScopes(scopes []string) []string {
	cs := make([]string, len(scopes))
	for i, scope := range scopes {
		cs[i] = canonicalizeServiceScope(scope)
	}
	return cs
}

func stringScopeHashcode(v interface{}) int {
	v = canonicalizeServiceScope(v.(string))
	return schema.HashString(v)
}
<commit_msg>Added missing `monitoring-read` scope (#2813)<commit_after>package google

import "github.com/hashicorp/terraform-plugin-sdk/helper/schema"

func canonicalizeServiceScope(scope string) string {
	// This is a convenience map of short names used by the gcloud tool
	// to the GCE auth endpoints they alias to.
	scopeMap := map[string]string{
		"bigquery":              "https://www.googleapis.com/auth/bigquery",
		"cloud-platform":        "https://www.googleapis.com/auth/cloud-platform",
		"cloud-source-repos":    "https://www.googleapis.com/auth/source.full_control",
		"cloud-source-repos-ro": "https://www.googleapis.com/auth/source.read_only",
		"compute-ro":            "https://www.googleapis.com/auth/compute.readonly",
		"compute-rw":            "https://www.googleapis.com/auth/compute",
		"datastore":             "https://www.googleapis.com/auth/datastore",
		"logging-write":         "https://www.googleapis.com/auth/logging.write",
		"monitoring":            "https://www.googleapis.com/auth/monitoring",
		"monitoring-read":       "https://www.googleapis.com/auth/monitoring.read",
		"monitoring-write":      "https://www.googleapis.com/auth/monitoring.write",
		"pubsub":                "https://www.googleapis.com/auth/pubsub",
		"service-control":       "https://www.googleapis.com/auth/servicecontrol",
		"service-management":    "https://www.googleapis.com/auth/service.management.readonly",
		"sql":                   "https://www.googleapis.com/auth/sqlservice",
		"sql-admin":             "https://www.googleapis.com/auth/sqlservice.admin",
		"storage-full":          "https://www.googleapis.com/auth/devstorage.full_control",
		"storage-ro":            "https://www.googleapis.com/auth/devstorage.read_only",
		"storage-rw":            "https://www.googleapis.com/auth/devstorage.read_write",
		"taskqueue":             "https://www.googleapis.com/auth/taskqueue",
		"trace-append":          "https://www.googleapis.com/auth/trace.append",
		"trace-ro":              "https://www.googleapis.com/auth/trace.readonly",
		"useraccounts-ro":       "https://www.googleapis.com/auth/cloud.useraccounts.readonly",
		"useraccounts-rw":       "https://www.googleapis.com/auth/cloud.useraccounts",
		"userinfo-email":        "https://www.googleapis.com/auth/userinfo.email",
	}

	if matchedURL, ok := scopeMap[scope]; ok {
		return matchedURL
	}

	return scope
}

func canonicalizeServiceScopes(scopes []string) []string {
	cs := make([]string, len(scopes))
	for i, scope := range scopes {
		cs[i] = canonicalizeServiceScope(scope)
	}
	return cs
}

func stringScopeHashcode(v interface{}) int {
	v = canonicalizeServiceScope(v.(string))
	return schema.HashString(v)
}
<|endoftext|>


<commit_before>package handlers

import (
	"errors"
	"fmt"
	"net/http"
	"strings"

	"appengine"
	"appengine/user"

	"code.google.com/p/xsrftoken"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type TagData struct {
	Posts   *[]models.Entry
	Tag     string
	Aliases []string
}

func TagHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	tag := r.Param("id")

	if tag == "" {
		http.Redirect(w, r.Request, "/tags", 301)
	}

	if tag != strings.ToLower(tag) {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", strings.ToLower(tag)), 301)
	}

	isAlias, alias := models.GetAlias(c, tag)
	if isAlias {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", alias), 301)
	}

	entries, err := models.PostsWithTag(c, tag)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	aliases := models.GetTagAliases(c, tag)
	data := &TagData{Posts: entries, Tag: tag, Aliases: *aliases}
	w.Render("tag", data)
}

type TagsData struct {
	Tags map[string]int
}

func TagsHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	w.Render("tags", &TagsData{Tags: models.AllTags(c)})
}

type AliasData struct {
	Aliases map[string]string
	Xsrf    string
	IsAdmin bool
}

func TagAliasGetHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		token := xsrftoken.Generate(models.GetFlagLogError(c, "SESSION_KEY"), u.String(), "/aliases")
		w.Render("aliases", &AliasData{
			Aliases: models.AliasMap(c),
			Xsrf:    token,
			IsAdmin: user.IsAdmin(c),
		})
		return
	}
}

func TagAliasPostHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		err := r.ParseForm()
		if err != nil {
			c.Warningf("Couldn't parse form: %v", r)
		}
		xsrf := r.Request.FormValue("xsrf")
		from := r.Request.FormValue("name")
		to := r.Request.FormValue("tag")

		if xsrftoken.Valid(xsrf, models.GetFlagLogError(c, "SESSION_KEY"), u.String(), r.Request.URL.Path) {
			c.Infof("Valid Token!")
			a := models.NewAlias(from, to)
			err = a.Save(c)
			if err != nil {
				http.Error(w, err.Error(), 500)
				return
			}
		} else {
			c.Infof("Invalid Token...")
			http.Error(w, errors.New("Invalid Token").Error(), 403)
			return
		}

		http.Redirect(w, r.Request, "/aliases", 302)
		return
	}
}
<commit_msg>maybe<commit_after>package handlers

import (
	"errors"
	"fmt"
	"net/http"
	"strings"

	"appengine"
	"appengine/user"

	"code.google.com/p/xsrftoken"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type TagData struct {
	Posts   *map[int64]models.Entry
	Tag     string
	Aliases []string
}

func TagHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	tag := r.Param("id")

	if tag == "" {
		http.Redirect(w, r.Request, "/tags", 301)
	}

	if tag != strings.ToLower(tag) {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", strings.ToLower(tag)), 301)
	}

	isAlias, alias := models.GetAlias(c, tag)
	if isAlias {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", alias), 301)
	}

	entries, err := models.PostsWithTag(c, tag)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	aliases := models.GetTagAliases(c, tag)
	data := &TagData{Posts: entries, Tag: tag, Aliases: *aliases}
	w.Render("tag", data)
}

type TagsData struct {
	Tags map[string]int
}

func TagsHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	w.Render("tags", &TagsData{Tags: models.AllTags(c)})
}

type AliasData struct {
	Aliases map[string]string
	Xsrf    string
	IsAdmin bool
}

func TagAliasGetHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		token := xsrftoken.Generate(models.GetFlagLogError(c, "SESSION_KEY"), u.String(), "/aliases")
		w.Render("aliases", &AliasData{
			Aliases: models.AliasMap(c),
			Xsrf:    token,
			IsAdmin: user.IsAdmin(c),
		})
		return
	}
}

func TagAliasPostHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		err := r.ParseForm()
		if err != nil {
			c.Warningf("Couldn't parse form: %v", r)
		}
		xsrf := r.Request.FormValue("xsrf")
		from := r.Request.FormValue("name")
		to := r.Request.FormValue("tag")

		if xsrftoken.Valid(xsrf, models.GetFlagLogError(c, "SESSION_KEY"), u.String(), r.Request.URL.Path) {
			c.Infof("Valid Token!")
			a := models.NewAlias(from, to)
			err = a.Save(c)
			if err != nil {
				http.Error(w, err.Error(), 500)
				return
			}
		} else {
			c.Infof("Invalid Token...")
			http.Error(w, errors.New("Invalid Token").Error(), 403)
			return
		}

		http.Redirect(w, r.Request, "/aliases", 302)
		return
	}
}
<|endoftext|>


<commit_before>package run

import (
	"github.com/workanator/go-floc.v2"
)

const locLoop = "Loop"

/*
Loop repeats running jobs forever. Jobs are run sequentially.

Summary:
	- Run jobs in goroutines : NO
	- Wait all jobs finish   : YES
	- Run order              : SEQUENCE

Diagram:
    +-------------------------+
    |                         |
    V                         |
  ----->[JOB_1]-...->[JOB_N]--+
*/
func Loop(jobs ...floc.Job) floc.Job {
	return func(ctx floc.Context, ctrl floc.Control) error {
		for {
			for _, job := range jobs {
				// Do not start the next job if the execution is finished
				if ctrl.IsFinished() {
					return nil
				}

				// Do the job
				err := job(ctx, ctrl)
				if handledErr := handleResult(ctrl, err, locLoop); handledErr != nil {
					return handledErr
				}
			}
		}
	}
}
<commit_msg>Loop takes only one job<commit_after>package run

import (
	"github.com/workanator/go-floc.v2"
)

const locLoop = "Loop"

/*
Loop repeats running jobs forever. Jobs are run sequentially.

Summary:
	- Run jobs in goroutines : NO
	- Wait all jobs finish   : YES
	- Run order              : SEQUENCE

Diagram:
    +-------------------------+
    |                         |
    V                         |
  ----->[JOB_1]-...->[JOB_N]--+
*/
func Loop(job floc.Job) floc.Job {
	return func(ctx floc.Context, ctrl floc.Control) error {
		for {
			// Do not start the job if the execution is finished
			if ctrl.IsFinished() {
				return nil
			}

			// Do the job
			err := job(ctx, ctrl)
			if handledErr := handleResult(ctrl, err, locLoop); handledErr != nil {
				return handledErr
			}
		}
	}
}
<|endoftext|>