<commit_before>package gobot

import (
	"fmt"
	"log"
	"math/rand"
	"time"
)

type JSONRobot struct {
	Name        string            `json:"name"`
	Commands    []string          `json:"commands"`
	Connections []*JSONConnection `json:"connections"`
	Devices     []*JSONDevice     `json:"devices"`
}

type Robot struct {
	Name        string                                              `json:"-"`
	Commands    map[string]func(map[string]interface{}) interface{} `json:"-"`
	Work        func()                                              `json:"-"`
	connections connections                                         `json:"-"`
	devices     devices                                             `json:"-"`
}

type Robots []*Robot

func (r Robots) Start() {
	for _, robot := range r {
		robot.Start()
	}
}

func (r Robots) Each(f func(*Robot)) {
	for _, robot := range r {
		f(robot)
	}
}

func NewRobot(name string, c []Connection, d []Device, work func()) *Robot {
	r := &Robot{
		Name:     name,
		Work:     work,
		Commands: make(map[string]func(map[string]interface{}) interface{}),
	}
	r.initName()
	log.Println("Initializing Robot", r.Name, "...")
	r.initConnections(c)
	r.initDevices(d)
	return r
}

func (r *Robot) AddCommand(name string, f func(map[string]interface{}) interface{}) {
	r.Commands[name] = f
}

func (r *Robot) Start() {
	log.Println("Starting Robot", r.Name, "...")
	if err := r.Connections().Start(); err != nil {
		panic("Could not start connections")
	}
	if err := r.Devices().Start(); err != nil {
		panic("Could not start devices")
	}
	if r.Work != nil {
		log.Println("Starting work...")
		r.Work()
	}
}

func (r *Robot) initName() {
	if r.Name == "" {
		rand.Seed(time.Now().UTC().UnixNano())
		i := rand.Int()
		r.Name = fmt.Sprintf("Robot%v", i)
	}
}

func (r *Robot) initConnections(c []Connection) {
	r.connections = make(connections, len(c))
	log.Println("Initializing connections...")
	for i, connection := range c {
		log.Println("Initializing connection", FieldByNamePtr(connection, "Name"), "...")
		r.connections[i] = NewConnection(connection, r)
	}
}

func (r *Robot) initDevices(d []Device) {
	r.devices = make([]*device, len(d))
	log.Println("Initializing devices...")
	for i, device := range d {
		log.Println("Initializing device", FieldByNamePtr(device, "Name"), "...")
		r.devices[i] = NewDevice(device, r)
	}
}

func (r *Robot) Devices() devices {
	return devices(r.devices)
}

func (r *Robot) Device(name string) *device {
	if r == nil {
		return nil
	}
	for _, device := range r.devices {
		if device.Name == name {
			return device
		}
	}
	return nil
}

func (r *Robot) Connections() connections {
	return connections(r.connections)
}

func (r *Robot) Connection(name string) *connection {
	if r == nil {
		return nil
	}
	for _, connection := range r.connections {
		if connection.Name == name {
			return connection
		}
	}
	return nil
}

func (r *Robot) ToJSON() *JSONRobot {
	jsonRobot := &JSONRobot{
		Name:        r.Name,
		Commands:    []string{},
		Connections: []*JSONConnection{},
		Devices:     []*JSONDevice{},
	}
	for command := range r.Commands {
		jsonRobot.Commands = append(jsonRobot.Commands, command)
	}
	for _, device := range r.Devices() {
		jsonDevice := device.ToJSON()
		jsonRobot.Connections = append(jsonRobot.Connections, jsonDevice.Connection)
		jsonRobot.Devices = append(jsonRobot.Devices, jsonDevice)
	}
	return jsonRobot
}
<commit_msg>NewRobot is now a variadic function<commit_after>package gobot

import (
	"fmt"
	"log"
	"math/rand"
	"time"
)

type JSONRobot struct {
	Name        string            `json:"name"`
	Commands    []string          `json:"commands"`
	Connections []*JSONConnection `json:"connections"`
	Devices     []*JSONDevice     `json:"devices"`
}

type Robot struct {
	Name        string                                              `json:"-"`
	Commands    map[string]func(map[string]interface{}) interface{} `json:"-"`
	Work        func()                                              `json:"-"`
	connections connections                                         `json:"-"`
	devices     devices                                             `json:"-"`
}

type Robots []*Robot

func (r Robots) Start() {
	for _, robot := range r {
		robot.Start()
	}
}

func (r Robots) Each(f func(*Robot)) {
	for _, robot := range r {
		f(robot)
	}
}

func NewRobot(name string, v ...interface{}) *Robot {
	r := &Robot{
		Name:     name,
		Commands: make(map[string]func(map[string]interface{}) interface{}),
	}
	r.initName()
	log.Println("Initializing Robot", r.Name, "...")
	if len(v) > 0 {
		if v[0] == nil {
			v[0] = []Connection{}
		}
		r.initConnections(v[0].([]Connection))
	}
	if len(v) > 1 {
		if v[1] == nil {
			v[1] = []Device{}
		}
		r.initDevices(v[1].([]Device))
	}
	if len(v) > 2 {
		if v[2] == nil {
			v[2] = func() {}
		}
		r.Work = v[2].(func())
	}
	return r
}

func (r *Robot) AddCommand(name string, f func(map[string]interface{}) interface{}) {
	r.Commands[name] = f
}

func (r *Robot) Start() {
	log.Println("Starting Robot", r.Name, "...")
	if err := r.Connections().Start(); err != nil {
		panic("Could not start connections")
	}
	if err := r.Devices().Start(); err != nil {
		panic("Could not start devices")
	}
	if r.Work != nil {
		log.Println("Starting work...")
		r.Work()
	}
}

func (r *Robot) initName() {
	if r.Name == "" {
		rand.Seed(time.Now().UTC().UnixNano())
		i := rand.Int()
		r.Name = fmt.Sprintf("Robot%v", i)
	}
}

func (r *Robot) initConnections(c []Connection) {
	r.connections = make(connections, len(c))
	log.Println("Initializing connections...")
	for i, connection := range c {
		log.Println("Initializing connection", FieldByNamePtr(connection, "Name"), "...")
		r.connections[i] = NewConnection(connection, r)
	}
}

func (r *Robot) initDevices(d []Device) {
	r.devices = make([]*device, len(d))
	log.Println("Initializing devices...")
	for i, device := range d {
		log.Println("Initializing device", FieldByNamePtr(device, "Name"), "...")
		r.devices[i] = NewDevice(device, r)
	}
}

func (r *Robot) Devices() devices {
	return devices(r.devices)
}

func (r *Robot) Device(name string) *device {
	if r == nil {
		return nil
	}
	for _, device := range r.devices {
		if device.Name == name {
			return device
		}
	}
	return nil
}

func (r *Robot) Connections() connections {
	return connections(r.connections)
}

func (r *Robot) Connection(name string) *connection {
	if r == nil {
		return nil
	}
	for _, connection := range r.connections {
		if connection.Name == name {
			return connection
		}
	}
	return nil
}

func (r *Robot) ToJSON() *JSONRobot {
	jsonRobot := &JSONRobot{
		Name:        r.Name,
		Commands:    []string{},
		Connections: []*JSONConnection{},
		Devices:     []*JSONDevice{},
	}
	for command := range r.Commands {
		jsonRobot.Commands = append(jsonRobot.Commands, command)
	}
	for _, device := range r.Devices() {
		jsonDevice := device.ToJSON()
		jsonRobot.Connections = append(jsonRobot.Connections, jsonDevice.Connection)
		jsonRobot.Devices = append(jsonRobot.Devices, jsonDevice)
	}
	return jsonRobot
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/client"
	"github.com/olorin/nagiosplugin"
	"golang.org/x/net/context"
	"gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"os"
	"strings"
	"text/template"
)

const VERSION = "1.0.0"

var (
	debug             = kingpin.Flag("debug", "Print debug prints to STDERR").Bool()
	format            = kingpin.Flag("format", "Format of output use go-templates like docker inspect").Default("Container {{.ID}} ({{.Config.Image}}) was killed by OOM killer").String()
	lastContainerFile = kingpin.Flag("last", "Path to file where is store last processed container").Short('l').String()
	level             = kingpin.Flag("level", "Report OOMKilled containers warning or critical").Default("warning").Enum("warning", "critical")
)

func main() {
	kingpin.Version(VERSION)
	kingpin.Parse()

	cli := createDockerClient()
	listOptions := prepareListOptions()
	addSinceFromFile(cli, &listOptions)

	containers, err := cli.ContainerList(context.Background(), listOptions)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("List docker containers: %s", err.Error()))
	}

	check := nagiosplugin.NewCheck()
	defer check.Finish()

	tmpl, err := template.New("format").Parse(*format)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Prepare template failed: %s", err.Error()))
	}

	var lastContainer types.Container
	for i := range containers {
		//becuase order is from newer to older
		c := containers[len(containers)-1-i]

		containerInfo, err := cli.ContainerInspect(context.Background(), c.ID)
		if err != nil {
			nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Container %s inspect error: %s", c.ID, err.Error()))
		}

		if containerInfo.State.OOMKilled {
			buf := new(bytes.Buffer)
			err := tmpl.Execute(buf, containerInfo)
			if err != nil {
				nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Execute template failed: %s", err.Error()))
			}

			buf.String()

			nagiosStatus := nagiosplugin.WARNING
			if *level == "critical" {
				nagiosStatus = nagiosplugin.CRITICAL
			}

			check.AddResult(nagiosStatus, buf.String())
		}

		lastContainer = c
	}

	writeSinceToFile(*lastContainerFile, lastContainer.ID)

	check.AddResult(nagiosplugin.OK, "No OOM killed container")
}

func createDockerClient() *client.Client {
	defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"}
	cli, err := client.NewClient("unix:///var/run/docker.sock", "v1.18", nil, defaultHeaders)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Connect to docker: %s", err.Error()))
	}

	return cli
}

func prepareListOptions() types.ContainerListOptions {
	filterOptions := filters.NewArgs()
	filterOptions.Add("status", "exited")
	filterOptions.Add("status", "dead")

	return types.ContainerListOptions{All: true, Filters: filterOptions}
}

func addSinceFromFile(cli *client.Client, listOptions *types.ContainerListOptions) {
	if *lastContainerFile != "" {
		if _, err := os.Stat(*lastContainerFile); err == nil {
			if *debug {
				fmt.Fprintf(os.Stderr, "Load from file %s\n", *lastContainerFile)
			}

			sinceContainerIdByte, err := ioutil.ReadFile(*lastContainerFile)
			if err != nil {
				nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Read file %s failed: %s", *lastContainerFile, err.Error()))
			}

			sinceContainerId := strings.TrimSpace((string)(sinceContainerIdByte))

			if len(sinceContainerId) == 64 {
				if *debug {
					fmt.Fprintf(os.Stderr, "Loaded container %s from file\n", sinceContainerId)
				}

				_, err := cli.ContainerInspect(context.Background(), sinceContainerId)

				if err == nil {
					//docker 1.10
					listOptions.Since = sinceContainerId
					//docker 1.12
					listOptions.Filters.Add("since", sinceContainerId)
				} else if *debug {
					fmt.Fprintf(os.Stderr, "Loaded container %s don't exists\n", sinceContainerId)
				}
			}
		}
	}
}

func writeSinceToFile(lastContainerFile, id string) {
	if lastContainerFile != "" && id != "" {
		err := ioutil.WriteFile(lastContainerFile, []byte(id), 0644)

		if err != nil {
			nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Write to file %s failed: %s", lastContainerFile, err.Error()))
		}
	}
}
<commit_msg>remove -l and use --store instead it<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/client"
	"github.com/olorin/nagiosplugin"
	"golang.org/x/net/context"
	"gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"os"
	"strings"
	"text/template"
)

const VERSION = "1.0.0"

var (
	debug             = kingpin.Flag("debug", "Print debug prints to STDERR").Bool()
	format            = kingpin.Flag("format", "Format of output use go-templates like docker inspect").Default("Container {{.ID}} ({{.Config.Image}}) was killed by OOM killer").String()
	lastContainerFile = kingpin.Flag("store", "Path to file where is store last processed container").String()
	level             = kingpin.Flag("level", "Report OOMKilled containers warning or critical").Default("warning").Enum("warning", "critical")
)

func main() {
	kingpin.Version(VERSION)
	kingpin.Parse()

	cli := createDockerClient()
	listOptions := prepareListOptions()
	addSinceFromFile(cli, &listOptions)

	containers, err := cli.ContainerList(context.Background(), listOptions)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("List docker containers: %s", err.Error()))
	}

	check := nagiosplugin.NewCheck()
	defer check.Finish()

	tmpl, err := template.New("format").Parse(*format)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Prepare template failed: %s", err.Error()))
	}

	var lastContainer types.Container
	for i := range containers {
		//becuase order is from newer to older
		c := containers[len(containers)-1-i]

		containerInfo, err := cli.ContainerInspect(context.Background(), c.ID)
		if err != nil {
			nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Container %s inspect error: %s", c.ID, err.Error()))
		}

		if containerInfo.State.OOMKilled {
			buf := new(bytes.Buffer)
			err := tmpl.Execute(buf, containerInfo)
			if err != nil {
				nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Execute template failed: %s", err.Error()))
			}

			buf.String()

			nagiosStatus := nagiosplugin.WARNING
			if *level == "critical" {
				nagiosStatus = nagiosplugin.CRITICAL
			}

			check.AddResult(nagiosStatus, buf.String())
		}

		lastContainer = c
	}

	writeSinceToFile(*lastContainerFile, lastContainer.ID)

	check.AddResult(nagiosplugin.OK, "No OOM killed container")
}

func createDockerClient() *client.Client {
	defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"}
	cli, err := client.NewClient("unix:///var/run/docker.sock", "v1.18", nil, defaultHeaders)
	if err != nil {
		nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Connect to docker: %s", err.Error()))
	}

	return cli
}

func prepareListOptions() types.ContainerListOptions {
	filterOptions := filters.NewArgs()
	filterOptions.Add("status", "exited")
	filterOptions.Add("status", "dead")

	return types.ContainerListOptions{All: true, Filters: filterOptions}
}

func addSinceFromFile(cli *client.Client, listOptions *types.ContainerListOptions) {
	if *lastContainerFile != "" {
		if _, err := os.Stat(*lastContainerFile); err == nil {
			if *debug {
				fmt.Fprintf(os.Stderr, "Load from file %s\n", *lastContainerFile)
			}

			sinceContainerIdByte, err := ioutil.ReadFile(*lastContainerFile)
			if err != nil {
				nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Read file %s failed: %s", *lastContainerFile, err.Error()))
			}

			sinceContainerId := strings.TrimSpace((string)(sinceContainerIdByte))

			if len(sinceContainerId) == 64 {
				if *debug {
					fmt.Fprintf(os.Stderr, "Loaded container %s from file\n", sinceContainerId)
				}

				_, err := cli.ContainerInspect(context.Background(), sinceContainerId)

				if err == nil {
					//docker 1.10
					listOptions.Since = sinceContainerId
					//docker 1.12
					listOptions.Filters.Add("since", sinceContainerId)
				} else if *debug {
					fmt.Fprintf(os.Stderr, "Loaded container %s don't exists\n", sinceContainerId)
				}
			}
		}
	}
}

func writeSinceToFile(lastContainerFile, id string) {
	if lastContainerFile != "" && id != "" {
		err := ioutil.WriteFile(lastContainerFile, []byte(id), 0644)

		if err != nil {
			nagiosplugin.Exit(nagiosplugin.UNKNOWN, fmt.Sprintf("Write to file %s failed: %s", lastContainerFile, err.Error()))
		}
	}
}
<|endoftext|>


<commit_before>package similar

import (
	"fmt"
	"strings"
	"testing"

	"github.com/gyuho/stringx"
)

func TestCosine(t *testing.T) {
	// the bigger the return value is,
	// the more similar the two texts are.

	// very similar texts (0.8616404368553293)
	text1 := "This is a foo bar sentence."
	text2 := "This sentence is similar to a foo bar sentence."
	// very different texts (0.04879500364742665)
	text3 := "AppendFloat appends the string form of the floating-point number f, as generated by FormatFloat, to dst and returns the extended buffer."
	text4 := "There are very simple ways to use matlab in parallel, with GPU, multi-thread support."
	if Cosine(text1, text2) < Cosine(text3, text4) {
		t.Errorf("Error: text1, text2 should be more similar than text3, text4")
	}
	// less different texts (0.31980107453341566)
	text5 := "How is the product team at SEOmoz structured?"
	text6 := "Moz: How trustworthy is SEOMoz after what they did to DOZ?"

	// same texts (1)
	text7 := "I am a gopher."
	text8 := "I am a gopher."
	if Cosine(text5, text6) > Cosine(text7, text8) {
		t.Errorf("Error: text7, text8 should be more simliar than text3, text4")
	}

	// totally different text
	text9 := "I am a gopher."
	text0 := ""
	if Cosine(text9, text0) != 0.0001 {
		t.Error("Error: text9, text10 should return 0.0001 with smoothing")
	}
	if Cosine("intention", "execution") != 0.6917144638660746 {
		t.Error("Error: intention, execution, Cosine")
	}
	if fmt.Sprintf("%.5f", Cosine("i n t e n t i o n", "e x e c u t i o n")) != "0.93791" {
		t.Errorf("Error: intention, execution, Cosine returns %f", Cosine("i n t e n t i o n", "e x e c u t i o n"))
	}
	if Cosine("AGGCTATCACCTGACCTCCAGGCCGATGCC", "TAGCTATCACGACCGCGGTCGATTTGCCCGAC") != 0.9890107762526607 {
		t.Errorf("DNA, Cosine")
	}
	if Cosine("like", "lllikee") != 0.9036961141150639 {
		t.Error("like", "lllikee", "Cosine")
	}

	// you may want to delete the whitespace characters
	if fmt.Sprintf("%.5f", Cosine("love it", "go to the beach")) != "0.63168" {
		t.Errorf("love it , go to the beach return %.5f", Cosine("love it", "go to the beach"))
	}

	sim00 := Cosine("Spokesman confirms senior government adviser was shot.", "Spokesman said the senior adviser was shot dead.")
	csim00 := 0.900721
	if fmt.Sprintf("%.5f", sim00) != fmt.Sprintf("%.5f", csim00) {
		t.Errorf("%f != %f (%v)", sim00, csim00, sim00-csim00)
	}
}

func TestLevenshtein(t *testing.T) {
	// the bigger the return value is,
	// the more similar the two texts are.

	// insertion
	if Levenshtein(strings.ToLower("Hello"), strings.ToLower("Hellok")) != 1 {
		t.Errorf("'Hello', 'Hellok' = %v", Levenshtein(strings.ToLower("Hello"), strings.ToLower("Hellok")))
	}

	// deletion
	if Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Hello")) != 1 {
		t.Errorf("'Hellok', 'Hello' = %v", Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Hello")))
	}

	// substituition
	if Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Helloa")) != 1 {
		t.Errorf("'Hellok', 'Helloa' = %v", Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Helloa")))
	}

	// very similar texts
	text1 := "This is a foo bar sentence."
	text2 := "This sentence is similar to a foo bar sentence."
	text2 = stringx.ReplaceNonAlnum(text2, " ")
	text2 = stringx.ReplaceNonAlnum(text2, " ")
	if Levenshtein(strings.ToLower(text1), strings.ToLower(text2)) != 21 {
		t.Errorf("text1, text2 = %v", Levenshtein(strings.ToLower(text1), strings.ToLower(text2)))
	}

	// very different texts
	text3 := "AppendFloat appends the string form of the floating-point number f, as generated by FormatFloat, to dst and returns the extended buffer."
	text4 := "There are very simple ways to use matlab in parallel, with GPU, multi-thread support."
	text3 = stringx.ReplaceNonAlnum(text3, " ")
	text4 = stringx.ReplaceNonAlnum(text4, " ")
	if Levenshtein(strings.ToLower(text3), text4) != 98 {
		t.Errorf("text3, text4 = %v", Levenshtein(strings.ToLower(text3), text4))
	}

	// less different texts
	text5 := "How is the product team at SEOmoz structured?"
	text6 := "Moz: How trustworthy is SEOMoz after what they did to DOZ?"
	if Levenshtein(strings.ToLower(text5), strings.ToLower(text6)) != 41 {
		t.Errorf("text5, text6 = %v", Levenshtein(strings.ToLower(text5), strings.ToLower(text6)))
	}

	// same texts
	text7 := "I am a gopher."
	text8 := "I am a gopher."
	if Levenshtein(strings.ToLower(text7), strings.ToLower(text8)) != 0.0001 {
		t.Errorf("text7, text8 = %v", Levenshtein(strings.ToLower(text7), strings.ToLower(text8)))
	}

	// totally different text
	text9 := "I am a gopher."
	text0 := ""
	if Levenshtein(strings.ToLower(text9), text0) != 14 {
		t.Errorf("'I am a gopher', '' = %v", Levenshtein(strings.ToLower(text9), text0))
	}

	if Levenshtein(strings.ToLower("intention"), "execution") != 5 {
		t.Errorf("'intention', 'execution' = %v", Levenshtein(strings.ToLower("intention"), "execution"))
	}

	if Levenshtein(strings.ToLower("i n t e n t i o n"), "e x e c u t i o n") != 5 {
		t.Errorf("'i n t e n t i o n', 'e x e c u t i o n' = %v", Levenshtein(strings.ToLower("i n t e n t i o n"), "e x e c u t i o n"))
	}

	sim1 := Levenshtein(strings.ToLower("AGGCTATCACCTGACCTCCAGGCCGATGCC"), strings.ToLower("TAGCTATCACGACCGCGGTCGATTTGCCCGAC"))
	if sim1 != 14 {
		t.Errorf("DNA = %v", sim1)
	}

	if Levenshtein(strings.ToLower("like"), "lllikee") != 3 {
		t.Errorf("'like', 'lllikee' = %v", Levenshtein(strings.ToLower("like"), "lllikee"))
	}

	if Levenshtein(strings.ToLower("look at"), "google") != 5 {
		t.Errorf("'look at' , 'google' = %v", Levenshtein(strings.ToLower("look at"), "google"))
	}

	if Levenshtein(strings.ToLower("l"), "g") != 1 {
		t.Errorf("'l' , 'g' = %v", Levenshtein(strings.ToLower("l"), "g"))
	}

	if Levenshtein(strings.ToLower("love it"), "go to the beach") != 12 {
		t.Errorf("love it", "go to the beach = %v", Levenshtein(strings.ToLower("love it"), "go to the beach"))
	}

	sim := Levenshtein(strings.ToLower("Spokesman confirms senior government adviser was shot."), strings.ToLower("Spokesman said the senior adviser was shot dead."))
	if sim != 24 {
		t.Errorf("%v", sim)
	}
}

func TestGet(t *testing.T) {

	// similarly related (1538.2096034883082)
	str1 := "golang: read text file into string array (and write)"
	str2 := "writing to a text file gets cut short using java"

	// strongly similar (468.2115223342196)
	str3 := "Programming Interviews: What are some good resources to brush up on (or get better at) system designing interview questions? Specifically when you need to design a system all the way from the data center (and the machines in it) to picking the client-side architecture and framework."
	str4 := "I want to work on client side frameworks. For programming interview, I need to design a system from a data center or machines. What would be the good resource to prepare this interview?"
	if Get(str1, str2) < Get(str3, str4) {
		t.Errorf("%v\n%v\n", Get(str1, str2), Get(str3, str4))
	}

	// not similar at all
	str5 := "What's going on has to do with the pragmatics of conversation. In particular, you're flouting a conversational rule, called the Maxim of Quantity.This rule states that what a person contributes to a conversation should be neither more nor less than what is required in the context."
	str6 := "I think Go has a great future in Web development. For other applicative areas, I'm less certain as the development of the runtime is entirely focused on the problems associated with running stuff for the web: large static binaries, etc."
	if Get(str5, str6) != 215.9838472585061 {
		t.Errorf("%v", Get(str5, str6))
	}
}
<commit_msg>delete stringx<commit_after>package similar

import (
	"fmt"
	"regexp"
	"strings"
	"testing"
)

func replaceNonAlnum(str, replace string) string {
	// alphanumeric (== [0-9A-Za-z])
	// \s is a white space character
	validID := regexp.MustCompile(`[^[:alnum:]\s]`)
	return validID.ReplaceAllString(str, replace)
}

func TestCosine(t *testing.T) {
	// the bigger the return value is,
	// the more similar the two texts are.

	// very similar texts (0.8616404368553293)
	text1 := "This is a foo bar sentence."
	text2 := "This sentence is similar to a foo bar sentence."
	// very different texts (0.04879500364742665)
	text3 := "AppendFloat appends the string form of the floating-point number f, as generated by FormatFloat, to dst and returns the extended buffer."
	text4 := "There are very simple ways to use matlab in parallel, with GPU, multi-thread support."
	if Cosine(text1, text2) < Cosine(text3, text4) {
		t.Errorf("Error: text1, text2 should be more similar than text3, text4")
	}
	// less different texts (0.31980107453341566)
	text5 := "How is the product team at SEOmoz structured?"
	text6 := "Moz: How trustworthy is SEOMoz after what they did to DOZ?"

	// same texts (1)
	text7 := "I am a gopher."
	text8 := "I am a gopher."
	if Cosine(text5, text6) > Cosine(text7, text8) {
		t.Errorf("Error: text7, text8 should be more simliar than text3, text4")
	}

	// totally different text
	text9 := "I am a gopher."
	text0 := ""
	if Cosine(text9, text0) != 0.0001 {
		t.Error("Error: text9, text10 should return 0.0001 with smoothing")
	}
	if Cosine("intention", "execution") != 0.6917144638660746 {
		t.Error("Error: intention, execution, Cosine")
	}
	if fmt.Sprintf("%.5f", Cosine("i n t e n t i o n", "e x e c u t i o n")) != "0.93791" {
		t.Errorf("Error: intention, execution, Cosine returns %f", Cosine("i n t e n t i o n", "e x e c u t i o n"))
	}
	if Cosine("AGGCTATCACCTGACCTCCAGGCCGATGCC", "TAGCTATCACGACCGCGGTCGATTTGCCCGAC") != 0.9890107762526607 {
		t.Errorf("DNA, Cosine")
	}
	if Cosine("like", "lllikee") != 0.9036961141150639 {
		t.Error("like", "lllikee", "Cosine")
	}

	// you may want to delete the whitespace characters
	if fmt.Sprintf("%.5f", Cosine("love it", "go to the beach")) != "0.63168" {
		t.Errorf("love it , go to the beach return %.5f", Cosine("love it", "go to the beach"))
	}

	sim00 := Cosine("Spokesman confirms senior government adviser was shot.", "Spokesman said the senior adviser was shot dead.")
	csim00 := 0.900721
	if fmt.Sprintf("%.5f", sim00) != fmt.Sprintf("%.5f", csim00) {
		t.Errorf("%f != %f (%v)", sim00, csim00, sim00-csim00)
	}
}

func TestLevenshtein(t *testing.T) {
	// the bigger the return value is,
	// the more similar the two texts are.

	// insertion
	if Levenshtein(strings.ToLower("Hello"), strings.ToLower("Hellok")) != 1 {
		t.Errorf("'Hello', 'Hellok' = %v", Levenshtein(strings.ToLower("Hello"), strings.ToLower("Hellok")))
	}

	// deletion
	if Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Hello")) != 1 {
		t.Errorf("'Hellok', 'Hello' = %v", Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Hello")))
	}

	// substituition
	if Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Helloa")) != 1 {
		t.Errorf("'Hellok', 'Helloa' = %v", Levenshtein(strings.ToLower("Hellok"), strings.ToLower("Helloa")))
	}

	// very similar texts
	text1 := "This is a foo bar sentence."
	text2 := "This sentence is similar to a foo bar sentence."
	text2 = replaceNonAlnum(text2, " ")
	text2 = replaceNonAlnum(text2, " ")
	if Levenshtein(strings.ToLower(text1), strings.ToLower(text2)) != 21 {
		t.Errorf("text1, text2 = %v", Levenshtein(strings.ToLower(text1), strings.ToLower(text2)))
	}

	// very different texts
	text3 := "AppendFloat appends the string form of the floating-point number f, as generated by FormatFloat, to dst and returns the extended buffer."
	text4 := "There are very simple ways to use matlab in parallel, with GPU, multi-thread support."
	text3 = replaceNonAlnum(text3, " ")
	text4 = replaceNonAlnum(text4, " ")
	if Levenshtein(strings.ToLower(text3), text4) != 98 {
		t.Errorf("text3, text4 = %v", Levenshtein(strings.ToLower(text3), text4))
	}

	// less different texts
	text5 := "How is the product team at SEOmoz structured?"
	text6 := "Moz: How trustworthy is SEOMoz after what they did to DOZ?"
	if Levenshtein(strings.ToLower(text5), strings.ToLower(text6)) != 41 {
		t.Errorf("text5, text6 = %v", Levenshtein(strings.ToLower(text5), strings.ToLower(text6)))
	}

	// same texts
	text7 := "I am a gopher."
	text8 := "I am a gopher."
	if Levenshtein(strings.ToLower(text7), strings.ToLower(text8)) != 0.0001 {
		t.Errorf("text7, text8 = %v", Levenshtein(strings.ToLower(text7), strings.ToLower(text8)))
	}

	// totally different text
	text9 := "I am a gopher."
	text0 := ""
	if Levenshtein(strings.ToLower(text9), text0) != 14 {
		t.Errorf("'I am a gopher', '' = %v", Levenshtein(strings.ToLower(text9), text0))
	}

	if Levenshtein(strings.ToLower("intention"), "execution") != 5 {
		t.Errorf("'intention', 'execution' = %v", Levenshtein(strings.ToLower("intention"), "execution"))
	}

	if Levenshtein(strings.ToLower("i n t e n t i o n"), "e x e c u t i o n") != 5 {
		t.Errorf("'i n t e n t i o n', 'e x e c u t i o n' = %v", Levenshtein(strings.ToLower("i n t e n t i o n"), "e x e c u t i o n"))
	}

	sim1 := Levenshtein(strings.ToLower("AGGCTATCACCTGACCTCCAGGCCGATGCC"), strings.ToLower("TAGCTATCACGACCGCGGTCGATTTGCCCGAC"))
	if sim1 != 14 {
		t.Errorf("DNA = %v", sim1)
	}

	if Levenshtein(strings.ToLower("like"), "lllikee") != 3 {
		t.Errorf("'like', 'lllikee' = %v", Levenshtein(strings.ToLower("like"), "lllikee"))
	}

	if Levenshtein(strings.ToLower("look at"), "google") != 5 {
		t.Errorf("'look at' , 'google' = %v", Levenshtein(strings.ToLower("look at"), "google"))
	}

	if Levenshtein(strings.ToLower("l"), "g") != 1 {
		t.Errorf("'l' , 'g' = %v", Levenshtein(strings.ToLower("l"), "g"))
	}

	if Levenshtein(strings.ToLower("love it"), "go to the beach") != 12 {
		t.Errorf("love it", "go to the beach = %v", Levenshtein(strings.ToLower("love it"), "go to the beach"))
	}

	sim := Levenshtein(strings.ToLower("Spokesman confirms senior government adviser was shot."), strings.ToLower("Spokesman said the senior adviser was shot dead."))
	if sim != 24 {
		t.Errorf("%v", sim)
	}
}

func TestGet(t *testing.T) {

	// similarly related (1538.2096034883082)
	str1 := "golang: read text file into string array (and write)"
	str2 := "writing to a text file gets cut short using java"

	// strongly similar (468.2115223342196)
	str3 := "Programming Interviews: What are some good resources to brush up on (or get better at) system designing interview questions? Specifically when you need to design a system all the way from the data center (and the machines in it) to picking the client-side architecture and framework."
	str4 := "I want to work on client side frameworks. For programming interview, I need to design a system from a data center or machines. What would be the good resource to prepare this interview?"
	if Get(str1, str2) < Get(str3, str4) {
		t.Errorf("%v\n%v\n", Get(str1, str2), Get(str3, str4))
	}

	// not similar at all
	str5 := "What's going on has to do with the pragmatics of conversation. In particular, you're flouting a conversational rule, called the Maxim of Quantity.This rule states that what a person contributes to a conversation should be neither more nor less than what is required in the context."
	str6 := "I think Go has a great future in Web development. For other applicative areas, I'm less certain as the development of the runtime is entirely focused on the problems associated with running stuff for the web: large static binaries, etc."
	if Get(str5, str6) != 215.9838472585061 {
		t.Errorf("%v", Get(str5, str6))
	}
}
<|endoftext|>


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

package goserv

import (
	"net/http"
	"regexp"
)

type Route struct {
	middleware []Handler
	methods    map[string][]Handler
	matcher    *regexp.Regexp
	params     []string
}

func (r *Route) All(handlers ...Handler) *Route {
	r.middleware = append(r.middleware, handlers...)
	return r
}

func (r *Route) AllFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	for _, fn := range funcs {
		r.middleware = append(r.middleware, HandlerFunc(fn))
	}
	return r
}

func (r *Route) Method(method string, handlers ...Handler) *Route {
	r.addMethodHandlers(method, handlers...)
	return r
}

func (r *Route) MethodFunc(method string, funcs ...func(ResponseWriter, *Request)) *Route {
	for _, fn := range funcs {
		r.addMethodHandlers(method, HandlerFunc(fn))
	}
	return r
}

func (r *Route) Methods(methods []string, handlers ...Handler) *Route {
	for _, method := range methods {
		r.Method(method, handlers...)
	}
	return r
}

func (r *Route) MethodsFunc(methods []string, funcs ...func(ResponseWriter, *Request)) *Route {
	for _, method := range methods {
		r.MethodFunc(method, funcs...)
	}
	return r
}

func (r *Route) Get(handlers ...Handler) *Route {
	return r.Method(http.MethodGet, handlers...)
}

func (r *Route) GetFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodGet, funcs...)
}

func (r *Route) Post(handlers ...Handler) *Route {
	return r.Method(http.MethodPost, handlers...)
}

func (r *Route) PostFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPost, funcs...)
}

func (r *Route) Put(handlers ...Handler) *Route {
	return r.Method(http.MethodPut, handlers...)
}

func (r *Route) PutFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPut, funcs...)
}

func (r *Route) Delete(handlers ...Handler) *Route {
	return r.Method(http.MethodDelete, handlers...)
}

func (r *Route) DeleteFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodDelete, funcs...)
}

func (r *Route) Patch(handlers ...Handler) *Route {
	return r.Method(http.MethodPatch, handlers...)
}

func (r *Route) PatchFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPatch, funcs...)
}

func (r *Route) ServeHTTP(res ResponseWriter, req *Request) {
	if r.ContainsParams() && len(req.Params) == 0 {
		r.FillParams(req)
	}

	for _, handler := range append(r.middleware, r.methods[req.Method]...) {
		handler.ServeHTTP(res, req)

		if res.Error() != nil {
			return
		}

		if res.Written() {
			return
		}
	}
}

func (r *Route) Match(path string) bool {
	return r.matcher.MatchString(path)
}

func (r *Route) FillParams(req *Request) {
	if !r.ContainsParams() {
		return
	}

	matches := r.matcher.FindAllStringSubmatch(req.SanitizedPath(), -1)
	if len(matches) == 0 {
		return
	}

	// Iterate group matches only
	for index, value := range matches[0][1:] {
		name := r.params[index]
		req.Params[name] = value
	}
}

func (r *Route) ContainsParams() bool {
	return len(r.params) > 0
}

func (r *Route) addMethodHandlers(method string, handlers ...Handler) {
	r.methods[method] = append(r.methods[method], handlers...)
}

func newRoute(pattern string, strict, prefixOnly bool) *Route {
	matcher, params := pathComponents(pattern, strict, prefixOnly)

	return &Route{
		methods: make(map[string][]Handler),
		matcher: matcher,
		params:  params,
	}
}
<commit_msg>Add Params() getter to Route<commit_after>// Copyright 2016 Marcel Gotsch. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package goserv

import (
	"net/http"
	"regexp"
)

type Route struct {
	middleware []Handler
	methods    map[string][]Handler
	matcher    *regexp.Regexp
	params     []string
}

func (r *Route) All(handlers ...Handler) *Route {
	r.middleware = append(r.middleware, handlers...)
	return r
}

func (r *Route) AllFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	for _, fn := range funcs {
		r.middleware = append(r.middleware, HandlerFunc(fn))
	}
	return r
}

func (r *Route) Method(method string, handlers ...Handler) *Route {
	r.addMethodHandlers(method, handlers...)
	return r
}

func (r *Route) MethodFunc(method string, funcs ...func(ResponseWriter, *Request)) *Route {
	for _, fn := range funcs {
		r.addMethodHandlers(method, HandlerFunc(fn))
	}
	return r
}

func (r *Route) Methods(methods []string, handlers ...Handler) *Route {
	for _, method := range methods {
		r.Method(method, handlers...)
	}
	return r
}

func (r *Route) MethodsFunc(methods []string, funcs ...func(ResponseWriter, *Request)) *Route {
	for _, method := range methods {
		r.MethodFunc(method, funcs...)
	}
	return r
}

func (r *Route) Get(handlers ...Handler) *Route {
	return r.Method(http.MethodGet, handlers...)
}

func (r *Route) GetFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodGet, funcs...)
}

func (r *Route) Post(handlers ...Handler) *Route {
	return r.Method(http.MethodPost, handlers...)
}

func (r *Route) PostFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPost, funcs...)
}

func (r *Route) Put(handlers ...Handler) *Route {
	return r.Method(http.MethodPut, handlers...)
}

func (r *Route) PutFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPut, funcs...)
}

func (r *Route) Delete(handlers ...Handler) *Route {
	return r.Method(http.MethodDelete, handlers...)
}

func (r *Route) DeleteFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodDelete, funcs...)
}

func (r *Route) Patch(handlers ...Handler) *Route {
	return r.Method(http.MethodPatch, handlers...)
}

func (r *Route) PatchFunc(funcs ...func(ResponseWriter, *Request)) *Route {
	return r.MethodFunc(http.MethodPatch, funcs...)
}

func (r *Route) ServeHTTP(res ResponseWriter, req *Request) {
	if r.ContainsParams() && len(req.Params) == 0 {
		r.FillParams(req)
	}

	for _, handler := range append(r.middleware, r.methods[req.Method]...) {
		handler.ServeHTTP(res, req)

		if res.Error() != nil {
			return
		}

		if res.Written() {
			return
		}
	}
}

func (r *Route) Match(path string) bool {
	return r.matcher.MatchString(path)
}

func (r *Route) FillParams(req *Request) {
	if !r.ContainsParams() {
		return
	}

	matches := r.matcher.FindAllStringSubmatch(req.SanitizedPath(), -1)
	if len(matches) == 0 {
		return
	}

	// Iterate group matches only
	for index, value := range matches[0][1:] {
		name := r.params[index]
		req.Params[name] = value
	}
}

func (r *Route) ContainsParams() bool {
	return len(r.params) > 0
}

func (r *Route) Params() []string {
	return append([]string{}, r.params...) // return a copy
}

func (r *Route) addMethodHandlers(method string, handlers ...Handler) {
	r.methods[method] = append(r.methods[method], handlers...)
}

func newRoute(pattern string, strict, prefixOnly bool) *Route {
	matcher, params := pathComponents(pattern, strict, prefixOnly)

	return &Route{
		methods: make(map[string][]Handler),
		matcher: matcher,
		params:  params,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

var (
	num = flag.Int(
		"n", 20,
		"Number of tasks per batch.",
	)
	restartDuration = flag.Duration(
		"restart-duration", time.Minute,
		"Duration of a rolling restart.",
	)
	runDuration = flag.Duration(
		"run-duration", time.Minute,
		"Duration between restarts (and initial time before the first restart).",
	)
	qps = flag.Float64(
		"qps", 10,
		"Average queries per second per task.",
	)
	jitter = flag.Float64(
		"jitter", 0,
		"How much the wait time between queries is randomly changed. The wait time between queries is normal-distributed with the given jitter value equaling σ/μ.",
	)
	addr = flag.String(
		"addr", ":8080",
		"The address to bind to (for exposition of the /metric HTTP endpoint).",
	)
)

func waitDuration() time.Duration {
	waitNs := 1e9 * (rand.NormFloat64()**jitter + 1) / *qps
	return time.Duration(waitNs)
}

func runTask(id, batch int, duration time.Duration) {
	log.Printf("Starting task %d of batch %d.\n", id, batch)
	defer log.Printf("Stopping task %d of batch %d.\n", id, batch)

	cnt := prometheus.NewCounter(prometheus.CounterOpts{
		Name: "queries_total",
		Help: "Number of (simulated) queries the task has served.",
		ConstLabels: prometheus.Labels{
			"batch": fmt.Sprint(batch),
			"task":  fmt.Sprint(id),
		},
	})
	prometheus.MustRegister(cnt)
	defer prometheus.Unregister(cnt)

	stopTimer := time.NewTimer(duration)
	queryTimer := time.NewTimer(waitDuration() / 2)
	for {
		select {
		case <-stopTimer.C:
			return
		case <-queryTimer.C:
			cnt.Inc()
			queryTimer.Reset(waitDuration())
		}
	}
}

func main() {
	flag.Parse()

	http.Handle("/metrics", prometheus.Handler())
	go http.ListenAndServe(*addr, nil)

	batch := 0

	// First start one batch of already running tasks.
	for i := 0; i < *num; i++ {
		go runTask(i, batch, *runDuration+*restartDuration*time.Duration(i)/time.Duration(*num))
	}

	for {
		time.Sleep(*runDuration)
		batch++
		log.Printf("Initiating restart batch %d.\n", batch)
		for i := 0; i < *num; i++ {
			go runTask(i, batch, *runDuration+*restartDuration)
			time.Sleep(*restartDuration / time.Duration(*num))
		}
		log.Printf("Restart batch %d complete.\n", batch)
	}
}
<commit_msg>Randomize start time<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

var (
	num = flag.Int(
		"n", 20,
		"Number of tasks per batch.",
	)
	restartDuration = flag.Duration(
		"restart-duration", time.Minute,
		"Duration of a rolling restart.",
	)
	runDuration = flag.Duration(
		"run-duration", time.Minute,
		"Duration between restarts (and initial time before the first restart).",
	)
	qps = flag.Float64(
		"qps", 10,
		"Average queries per second per task.",
	)
	jitter = flag.Float64(
		"jitter", 0,
		"How much the wait time between queries is randomly changed. The wait time between queries is normal-distributed with the given jitter value equaling σ/μ.",
	)
	addr = flag.String(
		"addr", ":8080",
		"The address to bind to (for exposition of the /metric HTTP endpoint).",
	)
)

func waitDurationNs() float64 {
	return 1e9 * (rand.NormFloat64()**jitter + 1) / *qps
}

func runTask(id, batch int, duration time.Duration) {
	log.Printf("Starting task %d of batch %d.\n", id, batch)
	defer log.Printf("Stopping task %d of batch %d.\n", id, batch)

	cnt := prometheus.NewCounter(prometheus.CounterOpts{
		Name: "queries_total",
		Help: "Number of (simulated) queries the task has served.",
		ConstLabels: prometheus.Labels{
			"batch": fmt.Sprint(batch),
			"task":  fmt.Sprint(id),
		},
	})
	prometheus.MustRegister(cnt)
	defer prometheus.Unregister(cnt)

	stopTimer := time.NewTimer(duration)
	queryTimer := time.NewTimer(time.Duration(waitDurationNs() * rand.Float64()))
	for {
		select {
		case <-stopTimer.C:
			return
		case <-queryTimer.C:
			cnt.Inc()
			queryTimer.Reset(time.Duration(waitDurationNs()))
		}
	}
}

func main() {
	flag.Parse()

	http.Handle("/metrics", prometheus.Handler())
	go http.ListenAndServe(*addr, nil)

	batch := 0

	// First start one batch of already running tasks.
	for i := 0; i < *num; i++ {
		go runTask(i, batch, *runDuration+*restartDuration*time.Duration(i)/time.Duration(*num))
	}

	for {
		time.Sleep(*runDuration)
		batch++
		log.Printf("Initiating restart batch %d.\n", batch)
		for i := 0; i < *num; i++ {
			go runTask(i, batch, *runDuration+*restartDuration)
			time.Sleep(*restartDuration / time.Duration(*num))
		}
		log.Printf("Restart batch %d complete.\n", batch)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"strings"
)

type count map[string]uint

// RandomKey returns a random key from the count map, weighted by the counts
func (c *count) RandomKey() string {
	var arr []string
	for key, val := range *c {
		for ; val > 0; val-- {
			arr = append(arr, key)
		}
	}
	if len(arr) == 0 {
		return ""
	}
	if len(arr) == 1 {
		return arr[0]
	}
	return arr[rand.Intn(len(arr)-1)]
}

// NGram builds an ngram list of character groupings from a string
func NGram(name string, size int) (ret []string) {
	tmp := ""
	for index, chr := range []rune(name) {
		tmp = tmp + string(chr)
		if index > 0 && (index+1)%size == 0 {
			ret = append(ret, tmp)
			tmp = ""
		}
	}
	return
}

// FillGrams makes a map of which gram leads to another, weighted by occurence
func FillGrams(gramList []string, gramMap map[string]count) {
	start := ""
	for _, gram := range gramList {
		if _, ok := gramMap[start]; !ok {
			gramMap[start] = make(count)
		}
		if _, ok := gramMap[start][gram]; !ok {
			gramMap[start][gram] = 0
		}
		gramMap[start][gram] = gramMap[start][gram] + 1
		start = gram
	}
}

// SplitOnVowelGroups breaks a string into a chunks on the start of every
// contiguous group of vowels
func SplitOnVowelGroups(name string, bugged bool) (ret []string) {
	vg := regexp.MustCompile("[AEIOUYaeiouy]+")
	indexes := vg.FindAllStringIndex(name, -1)
	start := 0
	for _, index := range indexes {
		if index[0] > 0 {
			ret = append(ret, name[start:index[1]])
			if bugged {
				start = index[1] + 1
			} else {
				start = index[1]
			}
		}
	}
	if len(ret) == 0 {
		ret = append(ret, name)
	}
	if bugged && start <= len(name) && start > 0 {
		if start == len(name) {
			start--
		}
		if len(ret) == 1 {
			ret[0] += name[start:]
		} else {
			ret[len(ret)-1] += name[start:]
		}
	} else if start < len(name) && start > 0 {
		if len(ret) < 2 {
			ret = append(ret, name[start:])
		} else {
			ret[len(ret)-1] += name[start:]
		}
	}
	return
}

func main() {
	min := 0
	flag.IntVar(&min, "m", 0, "minimum size required for a name fragment")
	gen := 0
	flag.IntVar(&gen, "g", 0, "generate given number of names")
	write := false
	flag.BoolVar(&write, "w", false, "write out analysis to json files")
	bugged := false
	flag.BoolVar(&bugged, "b", false, "use bugged implementation of vowel grou splitting")
	stats := false
	flag.BoolVar(&stats, "s", false, "print out analysis stats")
	raw := false
	flag.BoolVar(&raw, "r", false, "print out name parts individually")
	algorithm := "vg3"
	flag.StringVar(&algorithm, "a", "vg3", "generation algorithm [vg3, vg3b, 2gr, 3gr, pt2, pt3]")
	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		return
	}

	file, err := os.Open(flag.Arg(0)) // For read access.
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	twograms := make(map[string]count)
	threegrams := make(map[string]count)
	prefixes := make(count)
	joins := make(count)
	suffixes := make(count)
	vowelgroups := make(map[string]count)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		name := strings.TrimSpace(scanner.Text())
		if len(name) == 0 {
			continue
		}
		FillGrams(NGram(name, 2), twograms)
		FillGrams(NGram(name, 3), threegrams)
		vgs := SplitOnVowelGroups(name, bugged)
		// Skip processing names that only have a prefix
		if len(vgs) < 2 {
			continue
		}

		FillGrams(vgs, vowelgroups)

		suffix := vgs[len(vgs)-1]
		vgs = vgs[:len(vgs)-1]

		if _, ok := suffixes[suffix]; !ok {
			suffixes[suffix] = 1
		} else {
			suffixes[suffix] = suffixes[suffix] + 1
		}

		for len(vgs) > 1 {
			join := vgs[len(vgs)-1]
			vgs = vgs[:len(vgs)-1]
			if _, ok := joins[join]; !ok {
				joins[join] = 1
			} else {
				joins[join] = joins[join] + 1
			}
		}

		prefix := vgs[len(vgs)-1]
		if _, ok := prefixes[prefix]; !ok {
			prefixes[prefix] = 1
		} else {
			prefixes[prefix] = prefixes[prefix] + 1
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}

	if write {
		// output 2-grams
		b, err := json.Marshal(twograms)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("twograms.json", b, 0755)

		// output 3-grams
		b, err = json.Marshal(threegrams)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("threegrams.json", b, 0755)

		// output prefixes
		b, err = json.Marshal(prefixes)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("prefixes.json", b, 0755)

		// output joins
		b, err = json.Marshal(joins)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("joins.json", b, 0755)

		// output suffixes
		b, err = json.Marshal(suffixes)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("suffixes.json", b, 0755)

		// output vowel groups
		b, err = json.Marshal(vowelgroups)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("vowelgroups.json", b, 0755)
	}

	if stats {
		fmt.Println("Analysis stats:")
		fmt.Printf("  twograms: %d\n", len(twograms))
		fmt.Printf("  threegrams: %d\n", len(threegrams))
		fmt.Printf("  prefixes: %d\n", len(prefixes))
		fmt.Printf("  joins: %d\n", len(joins))
		fmt.Printf("  suffixes: %d\n", len(suffixes))
		fmt.Printf("  vowelgroups: %d\n\n", len(vowelgroups))
	}

	var algFunc func() []string
	switch algorithm {
	case "vg3", "vg3b":
		algFunc = func() []string {
			return GenerateMarkovName(min, vowelgroups, 3)
		}
	case "2gr":
		algFunc = func() []string {
			return GenerateMarkovName(0, twograms, 6)
		}
	case "3gr":
		algFunc = func() []string {
			return GenerateMarkovName(0, threegrams, 4)
		}
	case "pt2":
		algFunc = func() []string {
			return GeneratePartsName(min, prefixes, suffixes)
		}
	case "pt3":
		algFunc = func() []string {
			return GeneratePartsName(min, prefixes, joins, suffixes)
		}
	default:
		log.Fatal("Unknown name algorithm specified")
	}

	for i := 0; i < gen; i++ {
		if raw {
			fmt.Println(strings.Join(algFunc(), " "))
		} else {
			fmt.Println(strings.Join(algFunc(), ""))
		}
	}
}

// GenerateMarkovName makes a name by traversing the map randomly.
// It limits the name length to the given maxlen and returns immediately on a
// dead end.
func GenerateMarkovName(min int, markov map[string]count, maxiter int) (ret []string) {
	key := ""
	if val, ok := markov[""]; ok {
		for i := 0; i < len(markov); i++ {
			key = val.RandomKey()
			if len(key) >= min {
				break
			}
		}
	}
	ret = append(ret, key)
	for i := 0; i < maxiter; i++ {
		if val, ok := markov[key]; ok {
			for i := 0; i < len(markov); i++ {
				key = val.RandomKey()
				if len(key) >= min {
					break
				}
			}
			ret = append(ret, key)
		} else {
			return
		}
	}
	return
}

// GeneratePartsName makes a name by picking a random item from each list and
// appending it
func GeneratePartsName(min int, lists ...count) (ret []string) {
	for idx, list := range lists {
		if len(list) == 0 {
			continue
		}
		var keys []string
		for key := range list {
			keys = append(keys, key)
		}
		for i := 0; i < len(keys); i++ {
			j := 0
			if len(keys) > 1 {
				j = rand.Intn(len(keys) - 1)
			}
			key := keys[j]
			if len(key) >= min {
				ret = append(ret, key)
				if idx == len(lists)-1 {
					return
				}
				break
			}
		}
	}
	return
}
<commit_msg>Better help when providing wrong algorithm<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"strings"
)

type count map[string]uint

// RandomKey returns a random key from the count map, weighted by the counts
func (c *count) RandomKey() string {
	var arr []string
	for key, val := range *c {
		for ; val > 0; val-- {
			arr = append(arr, key)
		}
	}
	if len(arr) == 0 {
		return ""
	}
	if len(arr) == 1 {
		return arr[0]
	}
	return arr[rand.Intn(len(arr)-1)]
}

// NGram builds an ngram list of character groupings from a string
func NGram(name string, size int) (ret []string) {
	tmp := ""
	for index, chr := range []rune(name) {
		tmp = tmp + string(chr)
		if index > 0 && (index+1)%size == 0 {
			ret = append(ret, tmp)
			tmp = ""
		}
	}
	return
}

// FillGrams makes a map of which gram leads to another, weighted by occurence
func FillGrams(gramList []string, gramMap map[string]count) {
	start := ""
	for _, gram := range gramList {
		if _, ok := gramMap[start]; !ok {
			gramMap[start] = make(count)
		}
		if _, ok := gramMap[start][gram]; !ok {
			gramMap[start][gram] = 0
		}
		gramMap[start][gram] = gramMap[start][gram] + 1
		start = gram
	}
}

// SplitOnVowelGroups breaks a string into a chunks on the start of every
// contiguous group of vowels
func SplitOnVowelGroups(name string, bugged bool) (ret []string) {
	vg := regexp.MustCompile("[AEIOUYaeiouy]+")
	indexes := vg.FindAllStringIndex(name, -1)
	start := 0
	for _, index := range indexes {
		if index[0] > 0 {
			ret = append(ret, name[start:index[1]])
			if bugged {
				start = index[1] + 1
			} else {
				start = index[1]
			}
		}
	}
	if len(ret) == 0 {
		ret = append(ret, name)
	}
	if bugged && start <= len(name) && start > 0 {
		if start == len(name) {
			start--
		}
		if len(ret) == 1 {
			ret[0] += name[start:]
		} else {
			ret[len(ret)-1] += name[start:]
		}
	} else if start < len(name) && start > 0 {
		if len(ret) < 2 {
			ret = append(ret, name[start:])
		} else {
			ret[len(ret)-1] += name[start:]
		}
	}
	return
}

func main() {
	min := 0
	flag.IntVar(&min, "m", 0, "minimum size required for a name fragment")
	gen := 0
	flag.IntVar(&gen, "g", 0, "generate given number of names")
	write := false
	flag.BoolVar(&write, "w", false, "write out analysis to json files")
	bugged := false
	flag.BoolVar(&bugged, "b", false, "use bugged implementation of vowel grou splitting")
	stats := false
	flag.BoolVar(&stats, "s", false, "print out analysis stats")
	raw := false
	flag.BoolVar(&raw, "r", false, "print out name parts individually")
	algorithm := "vg3"
	flag.StringVar(&algorithm, "a", "vg3", "generation algorithm [vg3, vg3b, 2gr, 3gr, pt2, pt3]")
	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		return
	}

	file, err := os.Open(flag.Arg(0)) // For read access.
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	twograms := make(map[string]count)
	threegrams := make(map[string]count)
	prefixes := make(count)
	joins := make(count)
	suffixes := make(count)
	vowelgroups := make(map[string]count)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		name := strings.TrimSpace(scanner.Text())
		if len(name) == 0 {
			continue
		}
		FillGrams(NGram(name, 2), twograms)
		FillGrams(NGram(name, 3), threegrams)
		vgs := SplitOnVowelGroups(name, bugged)
		// Skip processing names that only have a prefix
		if len(vgs) < 2 {
			continue
		}

		FillGrams(vgs, vowelgroups)

		suffix := vgs[len(vgs)-1]
		vgs = vgs[:len(vgs)-1]

		if _, ok := suffixes[suffix]; !ok {
			suffixes[suffix] = 1
		} else {
			suffixes[suffix] = suffixes[suffix] + 1
		}

		for len(vgs) > 1 {
			join := vgs[len(vgs)-1]
			vgs = vgs[:len(vgs)-1]
			if _, ok := joins[join]; !ok {
				joins[join] = 1
			} else {
				joins[join] = joins[join] + 1
			}
		}

		prefix := vgs[len(vgs)-1]
		if _, ok := prefixes[prefix]; !ok {
			prefixes[prefix] = 1
		} else {
			prefixes[prefix] = prefixes[prefix] + 1
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}

	if write {
		// output 2-grams
		b, err := json.Marshal(twograms)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("twograms.json", b, 0755)

		// output 3-grams
		b, err = json.Marshal(threegrams)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("threegrams.json", b, 0755)

		// output prefixes
		b, err = json.Marshal(prefixes)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("prefixes.json", b, 0755)

		// output joins
		b, err = json.Marshal(joins)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("joins.json", b, 0755)

		// output suffixes
		b, err = json.Marshal(suffixes)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("suffixes.json", b, 0755)

		// output vowel groups
		b, err = json.Marshal(vowelgroups)
		if err != nil {
			fmt.Println("error:", err)
		}
		ioutil.WriteFile("vowelgroups.json", b, 0755)
	}

	if stats {
		fmt.Println("Analysis stats:")
		fmt.Printf("  twograms: %d\n", len(twograms))
		fmt.Printf("  threegrams: %d\n", len(threegrams))
		fmt.Printf("  prefixes: %d\n", len(prefixes))
		fmt.Printf("  joins: %d\n", len(joins))
		fmt.Printf("  suffixes: %d\n", len(suffixes))
		fmt.Printf("  vowelgroups: %d\n\n", len(vowelgroups))
	}

	var algFunc func() []string
	switch algorithm {
	case "vg3", "vg3b":
		algFunc = func() []string {
			return GenerateMarkovName(min, vowelgroups, 3)
		}
	case "2gr":
		algFunc = func() []string {
			return GenerateMarkovName(0, twograms, 6)
		}
	case "3gr":
		algFunc = func() []string {
			return GenerateMarkovName(0, threegrams, 4)
		}
	case "pt2":
		algFunc = func() []string {
			return GeneratePartsName(min, prefixes, suffixes)
		}
	case "pt3":
		algFunc = func() []string {
			return GeneratePartsName(min, prefixes, joins, suffixes)
		}
	default:
		log.Fatal("Unknown name algorithm specified. Valid algorithms are: vg3, vg3b, 2gr, 3gr, pt2, pt3")
	}

	for i := 0; i < gen; i++ {
		if raw {
			fmt.Println(strings.Join(algFunc(), " "))
		} else {
			fmt.Println(strings.Join(algFunc(), ""))
		}
	}
}

// GenerateMarkovName makes a name by traversing the map randomly.
// It limits the name length to the given maxlen and returns immediately on a
// dead end.
func GenerateMarkovName(min int, markov map[string]count, maxiter int) (ret []string) {
	key := ""
	if val, ok := markov[""]; ok {
		for i := 0; i < len(markov); i++ {
			key = val.RandomKey()
			if len(key) >= min {
				break
			}
		}
	}
	ret = append(ret, key)
	for i := 0; i < maxiter; i++ {
		if val, ok := markov[key]; ok {
			for i := 0; i < len(markov); i++ {
				key = val.RandomKey()
				if len(key) >= min {
					break
				}
			}
			ret = append(ret, key)
		} else {
			return
		}
	}
	return
}

// GeneratePartsName makes a name by picking a random item from each list and
// appending it
func GeneratePartsName(min int, lists ...count) (ret []string) {
	for idx, list := range lists {
		if len(list) == 0 {
			continue
		}
		var keys []string
		for key := range list {
			keys = append(keys, key)
		}
		for i := 0; i < len(keys); i++ {
			j := 0
			if len(keys) > 1 {
				j = rand.Intn(len(keys) - 1)
			}
			key := keys[j]
			if len(key) >= min {
				ret = append(ret, key)
				if idx == len(lists)-1 {
					return
				}
				break
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"

	"io/ioutil"
	"net/http"
	"net/url"

	"strconv"
	"strings"

	"github.com/rawoke083/ColorPrint"
	"log"
	"os"

	"errors"
)

type TestCase struct {
	HttpMethod       string
	Url              string
	HttpReturnCode   string
	ResponseTXTCheck string
	Pass             bool
}

func (test *TestCase) runATest(mparams map[string]string) bool {

	for i, k := range mparams {
		test.Url = strings.Replace(test.Url, i, k, -1)
	}

	ColorPrint.ColWrite("\n\nTEST:"+ColorPrint.ToColor(test.HttpMethod, ColorPrint.CL_LIGHT_CYAN)+" "+test.Url, ColorPrint.CL_WHITE)

	err := errors.New("")
	resp := new(http.Response)

	if test.HttpMethod == "POST" {
		u, _ := url.Parse(test.Url)
		ColorPrint.ColWrite("  ::: ARGS:"+u.RawQuery, ColorPrint.CL_WHITE)
		q, _ := url.ParseQuery(u.RawQuery)
		resp, err = http.PostForm(test.Url, q)
	} else {
		resp, err = http.Get(test.Url)
	}
	if err != nil {
		// handle error
		ColorPrint.ColWrite(fmt.Sprintf("\n\n=====>HTTP-ERROR:%s", test.Url), ColorPrint.CL_RED)
		return false
	}
	defer resp.Body.Close()

	test.Pass = true

	http_code := strconv.Itoa(resp.StatusCode)

	body, _ := ioutil.ReadAll(resp.Body)
	s := string(body)

	if strings.TrimSpace(test.HttpReturnCode) != http_code {

		test.Pass = false
		//ColorPrint.ColWrite("\n=>FAILED  - HttpCode Excepted |"+test.HttpReturnCode+"| but got |"+http_code+"|"+s, ColorPrint.CL_RED)
		ColorPrint.ColWrite("\n=>FAILED  - HttpCode Excepted |"+test.HttpReturnCode+"| but got |"+http_code+"|", ColorPrint.CL_RED)
		return false
	}

	if len(test.ResponseTXTCheck) > 1 {

		if !strings.Contains(s, test.ResponseTXTCheck) {
			test.Pass = false

			ColorPrint.ColWrite("\n=>FAILED  - ResponseText ("+test.ResponseTXTCheck+") not found. "+s, ColorPrint.CL_RED)
			return false

		}

	}

	return true
}

func runTestSuite(testCases []TestCase, mparams map[string]string) int {

	var testRunCount int
	var testOKCount int

	for _, test := range testCases {

		testRunCount++
		if test.runATest(mparams) {
			testOKCount++
		}

	} //end for

	s_total_test := fmt.Sprintf("\n\nTotal Test %d", testRunCount)
	s_total_test_ok := fmt.Sprintf("\nTest(s) OK %d", testOKCount)
	s_total_test_failed := fmt.Sprintf("\nTest(s) Failed %d\n", int(testRunCount-testOKCount))

	ColorPrint.ColWrite(s_total_test, ColorPrint.CL_LIGHT_BLUE)
	ColorPrint.ColWrite(s_total_test_ok, ColorPrint.CL_LIGHT_GREEN)
	ColorPrint.ColWrite(s_total_test_failed, ColorPrint.CL_RED)

	return (testRunCount - testOKCount)

}

func LoadTest(filename string) []TestCase {

	//	valid_http_methods := []string{"GET", "POST", "PUT", "DELETE"}

	f, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}

	//max of 64 test for now...
	testCaseList := [64]TestCase{}
	testCount := 0

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {

		fields := strings.Split(scanner.Text(), "|")
		field_count := len(fields)

		if field_count < 2 {
			continue
		}

		testCaseList[testCount].HttpMethod = fields[0]
		testCaseList[testCount].Url = fields[1]
		testCaseList[testCount].HttpReturnCode = fields[2]
		if field_count > 3 {

			testCaseList[testCount].ResponseTXTCheck = fields[3]
		}
		testCount++

	} //for scanner

	return testCaseList[0:testCount]

}

func printUsage() {

	ColorPrint.ColWrite("Usage:\n", ColorPrint.CL_WHITE)
	ColorPrint.ColWrite("\nrtest filename=<url-list-file> [-DStringToReplace=NewString] [-DMoreStringToReplace=MoreNewString]\n\n", ColorPrint.CL_WHITE)
}

func main() {
	ColorPrint.ColWrite("\n###### REST Test ########\n", ColorPrint.CL_YELLOW)

	var mparams = make(map[string]string)

	var fileName string

	for i := range os.Args {

		if strings.Contains(os.Args[i], "-D") {

			fields := strings.Split(strings.Replace(os.Args[i], "-D", "", -1), "=")
			mparams[fields[0]] = fields[1]
		}

		if strings.Contains(os.Args[i], "filename=") {
			fields := strings.Split(os.Args[i], "=")
			fileName = fields[1]
		}

	}

	if len(fileName) < 1 {

		fmt.Println("\nError:No filename\n")
		printUsage()
		os.Exit(1)
	}

	os.Exit(runTestSuite(LoadTest(fileName), mparams))
}
<commit_msg>Added comment skip<commit_after>package main

import (
	"bufio"
	"fmt"

	"io/ioutil"
	"net/http"
	"net/url"

	"strconv"
	"strings"

	"github.com/rawoke083/ColorPrint"
	"log"
	"os"

	"errors"
)

type TestCase struct {
	HttpMethod       string
	Url              string
	HttpReturnCode   string
	ResponseTXTCheck string
	Pass             bool
}

func (test *TestCase) runATest(mparams map[string]string) bool {

	for i, k := range mparams {
		test.Url = strings.Replace(test.Url, i, k, -1)
	}

	ColorPrint.ColWrite("\n\nTEST:"+ColorPrint.ToColor(test.HttpMethod, ColorPrint.CL_LIGHT_CYAN)+" "+test.Url, ColorPrint.CL_WHITE)

	err := errors.New("")
	resp := new(http.Response)

	if test.HttpMethod == "POST" {
		u, _ := url.Parse(test.Url)
		ColorPrint.ColWrite("  ::: ARGS:"+u.RawQuery, ColorPrint.CL_WHITE)
		q, _ := url.ParseQuery(u.RawQuery)
		resp, err = http.PostForm(test.Url, q)
	} else {
		resp, err = http.Get(test.Url)
	}
	if err != nil {
		// handle error
		ColorPrint.ColWrite(fmt.Sprintf("\n\n=====>HTTP-ERROR:%s", test.Url), ColorPrint.CL_RED)
		return false
	}
	defer resp.Body.Close()

	test.Pass = true

	http_code := strconv.Itoa(resp.StatusCode)

	body, _ := ioutil.ReadAll(resp.Body)
	s := string(body)

	if strings.TrimSpace(test.HttpReturnCode) != http_code {

		test.Pass = false
		//ColorPrint.ColWrite("\n=>FAILED  - HttpCode Excepted |"+test.HttpReturnCode+"| but got |"+http_code+"|"+s, ColorPrint.CL_RED)
		ColorPrint.ColWrite("\n=>FAILED  - HttpCode Excepted |"+test.HttpReturnCode+"| but got |"+http_code+"|", ColorPrint.CL_RED)
		return false
	}

	if len(test.ResponseTXTCheck) > 1 {

		if !strings.Contains(s, test.ResponseTXTCheck) {
			test.Pass = false

			ColorPrint.ColWrite("\n=>FAILED  - ResponseText ("+test.ResponseTXTCheck+") not found. "+s, ColorPrint.CL_RED)
			return false

		}

	}

	return true
}

func runTestSuite(testCases []TestCase, mparams map[string]string) int {

	var testRunCount int
	var testOKCount int

	for _, test := range testCases {

		testRunCount++
		if test.runATest(mparams) {
			testOKCount++
		}

	} //end for

	s_total_test := fmt.Sprintf("\n\nTotal Test %d", testRunCount)
	s_total_test_ok := fmt.Sprintf("\nTest(s) OK %d", testOKCount)
	s_total_test_failed := fmt.Sprintf("\nTest(s) Failed %d\n", int(testRunCount-testOKCount))

	ColorPrint.ColWrite(s_total_test, ColorPrint.CL_LIGHT_BLUE)
	ColorPrint.ColWrite(s_total_test_ok, ColorPrint.CL_LIGHT_GREEN)
	ColorPrint.ColWrite(s_total_test_failed, ColorPrint.CL_RED)

	return (testRunCount - testOKCount)

}

func LoadTest(filename string) []TestCase {

	//	valid_http_methods := []string{"GET", "POST", "PUT", "DELETE"}

	f, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}

	//max of 64 test for now...
	testCaseList := [64]TestCase{}
	testCount := 0

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {

		if strings.HasPrefix(scanner.Text(), "#") {
			continue
		}

		fields := strings.Split(scanner.Text(), "|")
		field_count := len(fields)

		if field_count < 2 {
			continue
		}

		testCaseList[testCount].HttpMethod = fields[0]
		testCaseList[testCount].Url = fields[1]
		testCaseList[testCount].HttpReturnCode = fields[2]
		if field_count > 3 {

			testCaseList[testCount].ResponseTXTCheck = fields[3]
		}
		testCount++

	} //for scanner

	return testCaseList[0:testCount]

}

func printUsage() {

	ColorPrint.ColWrite("Usage:\n", ColorPrint.CL_WHITE)
	ColorPrint.ColWrite("\nrtest filename=<url-list-file> [-DStringToReplace=NewString] [-DMoreStringToReplace=MoreNewString]\n\n", ColorPrint.CL_WHITE)
}

func main() {
	ColorPrint.ColWrite("\n###### REST Test ########\n", ColorPrint.CL_YELLOW)

	var mparams = make(map[string]string)

	var fileName string

	for i := range os.Args {

		if strings.Contains(os.Args[i], "-D") {

			fields := strings.Split(strings.Replace(os.Args[i], "-D", "", -1), "=")
			mparams[fields[0]] = fields[1]
		}

		if strings.Contains(os.Args[i], "filename=") {
			fields := strings.Split(os.Args[i], "=")
			fileName = fields[1]
		}

	}

	if len(fileName) < 1 {

		fmt.Println("\nError:No filename\n")
		printUsage()
		os.Exit(1)
	}

	os.Exit(runTestSuite(LoadTest(fileName), mparams))
}
<|endoftext|>


<commit_before>package hitcounter

import (
	"sync"
	"time"
)

type Clock struct {
	lock   sync.Mutex
	ticks  int32
	ticker <-chan time.Time
}

func NewClock() *Clock {
	result := &Clock{
		ticker: time.Tick(time.Second),
	}

	// Start a goroutine to capture the ticks
	go func() {
		for {
			<-result.ticker
			result.lock.Lock()
			result.ticks++
			result.lock.Unlock()
		}
	}()

	return result
}

func (c *Clock) GetTime() int32 {
	var result int32
	c.lock.Lock()
	result = c.ticks
	c.lock.Unlock()
	return result
}
<commit_msg>Changed clock to use sync.RWMutex<commit_after>package hitcounter

import (
	"sync"
	"time"
)

type Clock struct {
	lock   sync.RWMutex
	ticks  int32
	ticker <-chan time.Time
}

func NewClock() *Clock {
	result := &Clock{
		ticker: time.Tick(time.Second),
	}

	// Start a goroutine to capture the ticks
	go func() {
		for {
			<-result.ticker
			result.lock.Lock()
			result.ticks++
			result.lock.Unlock()
		}
	}()

	return result
}

func (c *Clock) GetTime() int32 {
	var result int32
	c.lock.RLock()
	result = c.ticks
	c.lock.RUnlock()
	return result
}
<|endoftext|>


<commit_before>// This parses raw golang stack traces ([]byte) to a slice of well formated structs.

// As this package will need to evolve with the development of go's stack trace
// format, this is the stack format the package currently works with:
//
//  1: goroutine x [running]:                           <-- ignore this line
//  2: path/to/package.functionName()
//  3: path/to/responsible/file:lineNumber +0xdeadbeef  <-- memory address optional
//  ... repeat 2 + 3 for each stack trace element
//
// To work with this, you need a type satisfying the interface
//
//  type stackTrace interface {
//    AddEntry(lineNumber int, packageName string, fileName string, methodName string)
//  }
//
// and from there you can do whatever you like with the accumulated data.
package raygun4go

import (
	"fmt"
	"runtime"
	"strconv"
	"strings"
)

// stackTrace is the interface a target stack has to satisfy.
type stackTrace interface {
	AddEntry(lineNumber int, packageName string, fileName string, methodName string)
}

// Current loads the current stacktrace into a given stack
func Current(stack stackTrace) {
	rawStack := make([]byte, 1<<16)
	rawStack = rawStack[:runtime.Stack(rawStack, false)]
	Parse(rawStack, stack)
}

// Parse loads the stack trace (given as trace) into the given stack.
// See Current() on how to obtain a stack trace.
func Parse(trace []byte, stack stackTrace) {
	lines := strings.Split(string(trace), "\n")

	var lineNumber int
	var fileName, packageName, methodName string

	for index, line := range lines[1:] {
		if len(line) == 0 {
			continue
		}
		if index%2 == 0 {
			packageName, methodName = extractPackageName(line)
		} else {
			lineNumber, fileName = extractLineNumberAndFile(line)
			stack.AddEntry(lineNumber, packageName, fileName, methodName)
		}
	}
}

// extractPageName receives a trace line and extracts packageName and
// methodName.
func extractPackageName(line string) (packageName, methodName string) {
	packagePath, packageNameAndFunction := splitAtLastSlash(line)
	parts := strings.Split(packageNameAndFunction, ".")

	if len(parts) > 1 {
		packageName = parts[0]
		if len(packagePath) > 0 {
			packageName = fmt.Sprintf("%s/%s", packagePath, packageName)
		}
		methodName = strings.Join(parts[1:], ".")
	} else {
		methodName = parts[0]
	}

	return
}

// extractLineNumberAndFile receives a trace line and extracts lineNumber and
// fileName.
func extractLineNumberAndFile(line string) (lineNumber int, fileName string) {
	_, fileAndLine := splitAtLastSlash(line)
	fileAndLine = removeSpaceAndSuffix(fileAndLine)
	parts := strings.Split(fileAndLine, ":")

    lineNumber = 0

    if len(parts) >= 2 {
	    numberAsString := parts[1]
	    number, _ := strconv.ParseUint(numberAsString, 10, 32)
	    lineNumber = int(number)
    }

	fileName = parts[0]
	return lineNumber, fileName
}

// splitAtLastSlash splits a string at the last found slash and returns the
// respective strings left and right of the slash.
func splitAtLastSlash(line string) (left, right string) {
	parts := strings.Split(line, "/")
	right = parts[len(parts)-1]
	left = strings.Join(parts[:len(parts)-1], "/")
	return
}

// removeSpaceAndSuffix splits the given string at ' ' and cuts off the part
// found after the last space.
func removeSpaceAndSuffix(line string) string {
	parts := strings.Split(line, " ")
	if len(parts) <= 1 {
	    return line
	}
	return strings.Join(parts[:len(parts)-1], " ")
}
<commit_msg>Attempt to detach the stack2struct docs from the raygun4go package docs<commit_after>// This parses raw golang stack traces ([]byte) to a slice of well formated structs.

// As this package will need to evolve with the development of go's stack trace
// format, this is the stack format the package currently works with:
//
//  1: goroutine x [running]:                           <-- ignore this line
//  2: path/to/package.functionName()
//  3: path/to/responsible/file:lineNumber +0xdeadbeef  <-- memory address optional
//  ... repeat 2 + 3 for each stack trace element
//
// To work with this, you need a type satisfying the interface
//
//  type stackTrace interface {
//    AddEntry(lineNumber int, packageName string, fileName string, methodName string)
//  }
//
// and from there you can do whatever you like with the accumulated data.

package raygun4go

import (
	"fmt"
	"runtime"
	"strconv"
	"strings"
)

// stackTrace is the interface a target stack has to satisfy.
type stackTrace interface {
	AddEntry(lineNumber int, packageName string, fileName string, methodName string)
}

// Current loads the current stacktrace into a given stack
func Current(stack stackTrace) {
	rawStack := make([]byte, 1<<16)
	rawStack = rawStack[:runtime.Stack(rawStack, false)]
	Parse(rawStack, stack)
}

// Parse loads the stack trace (given as trace) into the given stack.
// See Current() on how to obtain a stack trace.
func Parse(trace []byte, stack stackTrace) {
	lines := strings.Split(string(trace), "\n")

	var lineNumber int
	var fileName, packageName, methodName string

	for index, line := range lines[1:] {
		if len(line) == 0 {
			continue
		}
		if index%2 == 0 {
			packageName, methodName = extractPackageName(line)
		} else {
			lineNumber, fileName = extractLineNumberAndFile(line)
			stack.AddEntry(lineNumber, packageName, fileName, methodName)
		}
	}
}

// extractPageName receives a trace line and extracts packageName and
// methodName.
func extractPackageName(line string) (packageName, methodName string) {
	packagePath, packageNameAndFunction := splitAtLastSlash(line)
	parts := strings.Split(packageNameAndFunction, ".")

	if len(parts) > 1 {
		packageName = parts[0]
		if len(packagePath) > 0 {
			packageName = fmt.Sprintf("%s/%s", packagePath, packageName)
		}
		methodName = strings.Join(parts[1:], ".")
	} else {
		methodName = parts[0]
	}

	return
}

// extractLineNumberAndFile receives a trace line and extracts lineNumber and
// fileName.
func extractLineNumberAndFile(line string) (lineNumber int, fileName string) {
	_, fileAndLine := splitAtLastSlash(line)
	fileAndLine = removeSpaceAndSuffix(fileAndLine)
	parts := strings.Split(fileAndLine, ":")

    lineNumber = 0

    if len(parts) >= 2 {
	    numberAsString := parts[1]
	    number, _ := strconv.ParseUint(numberAsString, 10, 32)
	    lineNumber = int(number)
    }

	fileName = parts[0]
	return lineNumber, fileName
}

// splitAtLastSlash splits a string at the last found slash and returns the
// respective strings left and right of the slash.
func splitAtLastSlash(line string) (left, right string) {
	parts := strings.Split(line, "/")
	right = parts[len(parts)-1]
	left = strings.Join(parts[:len(parts)-1], "/")
	return
}

// removeSpaceAndSuffix splits the given string at ' ' and cuts off the part
// found after the last space.
func removeSpaceAndSuffix(line string) string {
	parts := strings.Split(line, " ")
	if len(parts) <= 1 {
	    return line
	}
	return strings.Join(parts[:len(parts)-1], " ")
}
<|endoftext|>


<commit_before>// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//+build linux

package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"syscall"

	"github.com/appc/spec/schema/types"
	"github.com/hashicorp/errwrap"

	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/common/cgroup"
	"github.com/coreos/rkt/networking"
	rktlog "github.com/coreos/rkt/pkg/log"
)

const (
	cgroupFsPath = "/sys/fs/cgroup"
)

var (
	debug bool
	log   *rktlog.Logger = rktlog.New(os.Stderr, "stage1 gc", debug)
)

func init() {
	flag.BoolVar(&debug, "debug", false, "Run in debug mode")

	// this ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

func main() {
	flag.Parse()

	podID, err := types.NewUUID(flag.Arg(0))
	if err != nil {
		log.Fatal("UUID is missing or malformed")
	}

	if err := removeJournalLink(podID); err != nil {
		log.PrintE("error removing journal link", err)
	}

	if err := cleanupCgroups(); err != nil {
		log.PrintE("error cleaning up cgroups", err)
	}

	if err := gcNetworking(podID); err != nil {
		log.FatalE("", err)
	}
}

func gcNetworking(podID *types.UUID) error {
	var flavor string
	// we first try to read the flavor from stage1 for backwards compatibility
	flavor, err := os.Readlink(filepath.Join(common.Stage1RootfsPath("."), "flavor"))
	if err != nil {
		// if we couldn't read the flavor from stage1 it could mean the overlay
		// filesystem is already unmounted (e.g. the system has been rebooted).
		// In that case we try to read it from the pod's root directory
		flavor, err = os.Readlink("flavor")
		if err != nil {
			return errwrap.Wrap(errors.New("failed to get stage1 flavor"), err)
		}
	}

	n, err := networking.Load(".", podID)
	switch {
	case err == nil:
		n.Teardown(flavor, debug)
	case os.IsNotExist(err):
		// probably ran with --net=host
	default:
		return errwrap.Wrap(errors.New("failed loading networking state"), err)
	}

	return nil
}

func removeJournalLink(uuid *types.UUID) error {
	// if the host runs systemd, we link the journal and set pod's machine-id
	// as pod's UUID without the dashes in init.go:
	// https://github.com/coreos/rkt/blob/95e6bc/stage1/init/init.go#L382
	machineID := strings.Replace(uuid.String(), "-", "", -1)
	journalLink := filepath.Join("/var/log/journal", machineID)
	err := os.Remove(journalLink)
	if err != nil && err.(*os.PathError).Err == syscall.ENOENT {
		err = nil
	}
	return err
}

type dirsByLength []string

func (c dirsByLength) Len() int           { return len(c) }
func (c dirsByLength) Less(i, j int) bool { return len(c[i]) < len(c[j]) }
func (c dirsByLength) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func cleanupCgroups() error {
	b, err := ioutil.ReadFile("subcgroup")
	if err != nil {
		return errwrap.Wrap(errors.New("error reading subcgroup file"), err)
	}
	subcgroup := string(b)

	// if we're trying to clean up our own cgroup it means we're running in the
	// same unit file as the rkt pod. We don't have to do anything, systemd
	// will do the cleanup for us
	ourCgroupPath, err := cgroup.GetOwnLegacyCgroupPath("name=systemd")
	if err == nil {
		if strings.HasPrefix(ourCgroupPath, "/"+subcgroup) {
			return nil
		}
	}

	f, err := os.Open(cgroupFsPath)
	if err != nil {
		return err
	}
	defer f.Close()
	ns, err := f.Readdirnames(0)
	if err != nil {
		return err
	}
	var cgroupDirs []string
	for _, c := range ns {
		scPath := filepath.Join(cgroupFsPath, c, subcgroup)
		walkCgroupDirs := func(path string, info os.FileInfo, err error) error {
			// if the subcgroup is already removed, we're fine
			if os.IsNotExist(err) {
				return nil
			}
			if err != nil {
				return err
			}
			mode := info.Mode()
			if mode.IsDir() {
				cgroupDirs = append(cgroupDirs, path)
			}
			return nil
		}
		if err := filepath.Walk(scPath, walkCgroupDirs); err != nil {
			log.PrintE(fmt.Sprintf("error walking subcgroup %q", scPath), err)
			continue
		}
	}

	// remove descendants before ancestors
	sort.Sort(sort.Reverse(dirsByLength(cgroupDirs)))
	for _, d := range cgroupDirs {
		if err := os.RemoveAll(d); err != nil {
			log.PrintE(fmt.Sprintf("error removing subcgroup %q", d), err)
		}
	}

	return nil
}
<commit_msg>gc: do not clean up cgroups with cgroup-v2<commit_after>// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//+build linux

package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"syscall"

	"github.com/appc/spec/schema/types"
	"github.com/hashicorp/errwrap"

	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/common/cgroup"
	"github.com/coreos/rkt/networking"
	rktlog "github.com/coreos/rkt/pkg/log"
)

const (
	cgroupFsPath = "/sys/fs/cgroup"
)

var (
	debug bool
	log   *rktlog.Logger = rktlog.New(os.Stderr, "stage1 gc", debug)
)

func init() {
	flag.BoolVar(&debug, "debug", false, "Run in debug mode")

	// this ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

func main() {
	flag.Parse()

	podID, err := types.NewUUID(flag.Arg(0))
	if err != nil {
		log.Fatal("UUID is missing or malformed")
	}

	if err := removeJournalLink(podID); err != nil {
		log.PrintE("error removing journal link", err)
	}

	if err := cleanupCgroups(); err != nil {
		log.PrintE("error cleaning up cgroups", err)
	}

	if err := gcNetworking(podID); err != nil {
		log.FatalE("", err)
	}
}

func gcNetworking(podID *types.UUID) error {
	var flavor string
	// we first try to read the flavor from stage1 for backwards compatibility
	flavor, err := os.Readlink(filepath.Join(common.Stage1RootfsPath("."), "flavor"))
	if err != nil {
		// if we couldn't read the flavor from stage1 it could mean the overlay
		// filesystem is already unmounted (e.g. the system has been rebooted).
		// In that case we try to read it from the pod's root directory
		flavor, err = os.Readlink("flavor")
		if err != nil {
			return errwrap.Wrap(errors.New("failed to get stage1 flavor"), err)
		}
	}

	n, err := networking.Load(".", podID)
	switch {
	case err == nil:
		n.Teardown(flavor, debug)
	case os.IsNotExist(err):
		// probably ran with --net=host
	default:
		return errwrap.Wrap(errors.New("failed loading networking state"), err)
	}

	return nil
}

func removeJournalLink(uuid *types.UUID) error {
	// if the host runs systemd, we link the journal and set pod's machine-id
	// as pod's UUID without the dashes in init.go:
	// https://github.com/coreos/rkt/blob/95e6bc/stage1/init/init.go#L382
	machineID := strings.Replace(uuid.String(), "-", "", -1)
	journalLink := filepath.Join("/var/log/journal", machineID)
	err := os.Remove(journalLink)
	if err != nil && err.(*os.PathError).Err == syscall.ENOENT {
		err = nil
	}
	return err
}

type dirsByLength []string

func (c dirsByLength) Len() int           { return len(c) }
func (c dirsByLength) Less(i, j int) bool { return len(c[i]) < len(c[j]) }
func (c dirsByLength) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func cleanupCgroups() error {
	isUnified, err := cgroup.IsCgroupUnified("/")
	if err != nil {
		return errwrap.Wrap(errors.New("failed to determine the cgroup version"), err)
	}
	if isUnified {
		return nil
	}

	b, err := ioutil.ReadFile("subcgroup")
	if err != nil {
		return errwrap.Wrap(errors.New("error reading subcgroup file"), err)
	}
	subcgroup := string(b)

	// if we're trying to clean up our own cgroup it means we're running in the
	// same unit file as the rkt pod. We don't have to do anything, systemd
	// will do the cleanup for us
	ourCgroupPath, err := cgroup.GetOwnLegacyCgroupPath("name=systemd")
	if err == nil {
		if strings.HasPrefix(ourCgroupPath, "/"+subcgroup) {
			return nil
		}
	}

	f, err := os.Open(cgroupFsPath)
	if err != nil {
		return err
	}
	defer f.Close()
	ns, err := f.Readdirnames(0)
	if err != nil {
		return err
	}
	var cgroupDirs []string
	for _, c := range ns {
		scPath := filepath.Join(cgroupFsPath, c, subcgroup)
		walkCgroupDirs := func(path string, info os.FileInfo, err error) error {
			// if the subcgroup is already removed, we're fine
			if os.IsNotExist(err) {
				return nil
			}
			if err != nil {
				return err
			}
			mode := info.Mode()
			if mode.IsDir() {
				cgroupDirs = append(cgroupDirs, path)
			}
			return nil
		}
		if err := filepath.Walk(scPath, walkCgroupDirs); err != nil {
			log.PrintE(fmt.Sprintf("error walking subcgroup %q", scPath), err)
			continue
		}
	}

	// remove descendants before ancestors
	sort.Sort(sort.Reverse(dirsByLength(cgroupDirs)))
	for _, d := range cgroupDirs {
		if err := os.RemoveAll(d); err != nil {
			log.PrintE(fmt.Sprintf("error removing subcgroup %q", d), err)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>//@author: Parag Patel
//this is the first version of nequeens, it has not been optimized yet. Hasn't been fully tested.

package main

import (
	"fmt"
	"os"
	"strconv"
)

var boardsize int = 3

func printBoard(board [][]bool) {
	fmt.Println("<==SOLUTION==>")
	for i, _ := range board {
		for j, _ := range board[i] {
			if board[i][j] == false {
				fmt.Printf("B ")
			} else {
				fmt.Printf("Q ")
			}
		}
		fmt.Printf("\n")
	}
}

func validatePosition(board [][]bool, x int, y int) bool {

	//check left
	for i := x - 1; i >= 0; i-- {
		if board[i][y] == true {
			return false
		}
	}

	//check right
	for i := x + 1; i < boardsize; i++ {
		if board[i][y] == true {
			return false
		}
	}

	//check leftdiagonalup
	for i, j := x-1, y-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
		if board[i][j] == true {
			return false
		}
	}

	//check rightdiagonalup
	for i, j := x+1, y-1; i < boardsize && j >= 0; i, j = i+1, j-1 {
		if board[i][j] == true {
			return false
		}
	}

	//check leftdiagonaldown
	for i, j := x-1, y+1; i >= 0 && j < boardsize; i, j = i-1, j+1 {
		if board[i][j] == true {
			return false
		}
	}

	return true
}

func newboard(board [][]bool) [][]bool {
	nboard := make([][]bool, boardsize)
	for i, _ := range nboard {
		nboard[i] = make([]bool, boardsize)
	}

	if board != nil {
		copy(nboard, board)
	}

	return nboard
}

func nxnboardandqueensolution(n int) {
	boardsize = n
	fmt.Println(n, "x", n, " board with ", n, " queens, has the following solutions")
	fmt.Println("total of ", nqueens(newboard(nil), 0), " solutions")
}

func nqueens(board [][]bool, n int) int {
	if n == boardsize {
		return 1
	}

	counter := 0

	for j := 0; j < boardsize; j++ {
		if board[n][j] == false && validatePosition(board, n, j) {
			board[n][j] = true
			nboard := newboard(board)
			counter += nqueens(nboard, n+1)
			board[n][j] = false
		}

	}

	return counter
}

func main() {

	n, _ := strconv.Atoi(os.Args[1])

	//for i := 1; i <= n; i++ {
	nxnboardandqueensolution(n)
	//}

}
<commit_msg>cleaned up some comments and got ride of uncessary validations<commit_after>//@author: Parag Patel
//this is the first version of nequeens, it has not been optimized yet. Hasn't been fully tested.

package main

import (
	"fmt"
	"os"
	"strconv"
)

var boardsize int = 3

func printBoard(board [][]bool) {
	fmt.Println("<==SOLUTION==>")
	for i, _ := range board {
		for j, _ := range board[i] {
			if board[i][j] == false {
				fmt.Printf("B ")
			} else {
				fmt.Printf("Q ")
			}
		}
		fmt.Printf("\n")
	}
}

func validatePosition(board [][]bool, x int, y int) bool {

	//check up
	for i := x - 1; i >= 0; i-- {
		if board[i][y] == true {
			return false
		}
	}

	//check leftdiagonalup
	for i, j := x-1, y-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
		if board[i][j] == true {
			return false
		}
	}

	//check rightdiagonalup
	for i, j := x-1, y+1; i >= 0 && j < boardsize; i, j = i-1, j+1 {
		if board[i][j] == true {
			return false
		}
	}

	return true
}

func newboard(board [][]bool) [][]bool {
	nboard := make([][]bool, boardsize)
	for i, _ := range nboard {
		nboard[i] = make([]bool, boardsize)
	}

	if board != nil {
		copy(nboard, board)
	}

	return nboard
}

func nxnboardandqueensolution(n int) {
	boardsize = n
	fmt.Println(n, "x", n, " board with ", n, " queens, has the following solutions")
	fmt.Println("total of ", nqueens(newboard(nil), 0, 0), " solutions")
}

func nqueens(board [][]bool, n int, i int) int {
	if n == boardsize {
		return 1
	}

	counter := 0

	for j := i; j < boardsize; j++ {
		if board[n][j] == false && validatePosition(board, n, j) {
			board[n][j] = true
			nboard := newboard(board)
			counter += nqueens(nboard, n+1, 0)
			board[n][j] = false
		}

	}

	return counter
}

func main() {

	n, _ := strconv.Atoi(os.Args[1])

	//for i := 1; i <= n; i++ {
	nxnboardandqueensolution(n)
	//}

}
<|endoftext|>