<commit_before>// net.go Copyright (c) 2016 Grant Brady
// Licensed under the MIT License
// See LICENSE.TXT
package gn2

import (
	"fmt"
	"math/rand"
)

//
// Base neuron type
// The slice consists of n weights. The n+1 element is the neuron bias
type neuron []float64

// Basic neuron factory. Creates a neuron with numInputs input with randomized
// input weights and neuron bias.
func newNeuron(numInputs int64) neuron {
	var n neuron
	// One extra for the bias
	for i := int64(0); i < numInputs+1; i++ {
		n = append(n, randWeight())
	}
	return n
}

// Get the bias of the neuron
func (n neuron) bias() float64 {
	return n[len(n)-1]
}

// Calculate the output of the neuron for a given set of inputs
func (n neuron) updateNeuron(inputs []float64) float64 {
	var output float64 = 0.0
	for i := 0; i < len(n)-1; i++ {
		output += n[i] * inputs[i]
	}
	output -= n.bias()
	return sigmoid(output)
}

//
// layer of neurons
// A simple list of neurons
type nLayer []neuron

// Basic neuron layer factory. Create numNeurons neurons each taking numInputs
// inputs
func newNeuronLayer(numNeurons, numInputs int64) nLayer {
	var layer nLayer
	for i := int64(0); i < numNeurons; i++ {
		layer = append(layer, newNeuron(numInputs))
	}
	return layer
}

// Calculate the output of each neuron in the layer for the given set of inputs
func (layer nLayer) updateLayer(inputs []float64) []float64 {
	var output []float64
	for _, n := range layer {
		output = append(output, n.updateNeuron(inputs))
	}
	return output
}

//
// a full neural net
// A simple list of neuron layers
type NeuralNet []nLayer

// Neural net factory. Creates a net that takes numInputs inputs, numOutputs
// outputs, with numHiddenLayers hidden layers, and numNeuronPerLayer neurons
// in the hidden layers
func NewNeuralNet(numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer int64) NeuralNet {
	var net NeuralNet
	if numHiddenLayers > 0 {
		net = append(net, newNeuronLayer(numNeuronsPerLayer, numInputs))
		for i := int64(0); i < numHiddenLayers-1; i++ {
			net = append(net, newNeuronLayer(numNeuronsPerLayer, numNeuronsPerLayer))
		}
		net = append(net, newNeuronLayer(numOutputs, numNeuronsPerLayer))
	} else {
		net = append(net, newNeuronLayer(numOutputs, numInputs))
	}
	return net
}

// Return a list containing all the edge weights and neuron biases based on a
// simple serializations of the nested lists. This does the opposite of
// SetWeights()
func (net NeuralNet) GetWeights() []float64 {
	weights := make([]float64, 0)

	for _, layer := range net {
		for _, neuron := range layer {
			for _, weight := range neuron {
				weights = append(weights, weight)
			}
		}
	}
	return weights
}

// Set the edge weights and neuron biases by a simple deserialization of a list
// weights to the nested list. This does the opposite of GetWeights()
func (net NeuralNet) SetWeights(newWeights []float64) {
	index := 0
	for l, _ := range net {
		for n, _ := range net[l] {
			for e, _ := range net[l][n] {
				net[l][n][e] = newWeights[index]
				index++
			}
		}
	}
}

// Print all the neuron layers, nerons, edge weights, and neuron biases
func (net NeuralNet) PrintNet() {
	for c, layer := range net {
		fmt.Printf("Layer: %d (%d neurons)\n", c, len(layer))
		for i, neuron := range layer {
			fmt.Printf("Neuron: %d\n", i)
			for i, weight := range neuron {
				if i == len(neuron)-1 {
					fmt.Printf("Bias: %f\n", weight)
				} else {
					fmt.Println(weight)
				}
			}
		}
	}
}

// Return the output of a network for a given input
func (net NeuralNet) Update(inputs []float64) []float64 {
	var outputs []float64

	for _, layer := range net {
		outputs = layer.updateLayer(inputs)
		inputs = outputs
	}

	return outputs
}

func (net NeuralNet) Mutate(mutationRate, maxPerturbation float64, numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer int64) NeuralNet {
	mutatedNet := NewNeuralNet(numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer)

	genome := net.GetWeights()

	for i, _ := range genome {
		if rand.Float64() < mutationRate {
			genome[i] += randWeight() * maxPerturbation
		}
	}
	mutatedNet.SetWeights(genome)

	return mutatedNet
}
<commit_msg>Comment<commit_after>// net.go Copyright (c) 2016 Grant Brady
// Licensed under the MIT License
// See LICENSE.TXT
package gn2

import (
	"fmt"
	"math/rand"
)

//
// Base neuron type
// The slice consists of n weights. The n+1 element is the neuron bias
type neuron []float64

// Basic neuron factory. Creates a neuron with numInputs input with randomized
// input weights and neuron bias.
func newNeuron(numInputs int64) neuron {
	var n neuron
	// One extra for the bias
	for i := int64(0); i < numInputs+1; i++ {
		n = append(n, randWeight())
	}
	return n
}

// Get the bias of the neuron
func (n neuron) bias() float64 {
	return n[len(n)-1]
}

// Calculate the output of the neuron for a given set of inputs
func (n neuron) updateNeuron(inputs []float64) float64 {
	var output float64 = 0.0
	for i := 0; i < len(n)-1; i++ {
		output += n[i] * inputs[i]
	}
	output -= n.bias()
	return sigmoid(output)
}

//
// layer of neurons
// A simple list of neurons
type nLayer []neuron

// Basic neuron layer factory. Create numNeurons neurons each taking numInputs
// inputs
func newNeuronLayer(numNeurons, numInputs int64) nLayer {
	var layer nLayer
	for i := int64(0); i < numNeurons; i++ {
		layer = append(layer, newNeuron(numInputs))
	}
	return layer
}

// Calculate the output of each neuron in the layer for the given set of inputs
func (layer nLayer) updateLayer(inputs []float64) []float64 {
	var output []float64
	for _, n := range layer {
		output = append(output, n.updateNeuron(inputs))
	}
	return output
}

//
// a full neural net
// A simple list of neuron layers
type NeuralNet []nLayer

// Neural net factory. Creates a net that takes numInputs inputs, numOutputs
// outputs, with numHiddenLayers hidden layers, and numNeuronPerLayer neurons
// in the hidden layers
func NewNeuralNet(numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer int64) NeuralNet {
	var net NeuralNet
	if numHiddenLayers > 0 {
		net = append(net, newNeuronLayer(numNeuronsPerLayer, numInputs))
		for i := int64(0); i < numHiddenLayers-1; i++ {
			net = append(net, newNeuronLayer(numNeuronsPerLayer, numNeuronsPerLayer))
		}
		net = append(net, newNeuronLayer(numOutputs, numNeuronsPerLayer))
	} else {
		net = append(net, newNeuronLayer(numOutputs, numInputs))
	}
	return net
}

// Return a list containing all the edge weights and neuron biases based on a
// simple serializations of the nested lists. This does the opposite of
// SetWeights()
func (net NeuralNet) GetWeights() []float64 {
	weights := make([]float64, 0)

	for _, layer := range net {
		for _, neuron := range layer {
			for _, weight := range neuron {
				weights = append(weights, weight)
			}
		}
	}
	return weights
}

// Set the edge weights and neuron biases by a simple deserialization of a list
// weights to the nested list. This does the opposite of GetWeights()
func (net NeuralNet) SetWeights(newWeights []float64) {
	index := 0
	for l, _ := range net {
		for n, _ := range net[l] {
			for e, _ := range net[l][n] {
				net[l][n][e] = newWeights[index]
				index++
			}
		}
	}
}

// Print all the neuron layers, nerons, edge weights, and neuron biases
func (net NeuralNet) PrintNet() {
	for c, layer := range net {
		fmt.Printf("Layer: %d (%d neurons)\n", c, len(layer))
		for i, neuron := range layer {
			fmt.Printf("Neuron: %d\n", i)
			for i, weight := range neuron {
				if i == len(neuron)-1 {
					fmt.Printf("Bias: %f\n", weight)
				} else {
					fmt.Println(weight)
				}
			}
		}
	}
}

// Return the output of a network for a given input
func (net NeuralNet) Update(inputs []float64) []float64 {
	var outputs []float64

	for _, layer := range net {
		outputs = layer.updateLayer(inputs)
		inputs = outputs
	}

	return outputs
}

// Make a copy of the neural net and mutate it according to the specified settings
func (net NeuralNet) Mutate(mutationRate, maxPerturbation float64, numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer int64) NeuralNet {
	mutatedNet := NewNeuralNet(numInputs, numOutputs, numHiddenLayers, numNeuronsPerLayer)

	genome := net.GetWeights()

	for i, _ := range genome {
		if rand.Float64() < mutationRate {
			genome[i] += randWeight() * maxPerturbation
		}
	}
	mutatedNet.SetWeights(genome)

	return mutatedNet
}
<|endoftext|>


<commit_before>package browsersafe

import (
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/authorization/authorizer"
)

const (
	proxyAction = "proxy"
	unsafeProxy = "unsafeproxy"
)

type browserSafeAuthorizer struct {
	delegate authorizer.Authorizer

	// list of groups, any of which indicate the request is authenticated
	authenticatedGroups sets.String
}

func NewBrowserSafeAuthorizer(delegate authorizer.Authorizer, authenticatedGroups ...string) authorizer.Authorizer {
	return &browserSafeAuthorizer{
		delegate:            delegate,
		authenticatedGroups: sets.NewString(authenticatedGroups...),
	}
}

func (a *browserSafeAuthorizer) Authorize(attributes authorizer.Attributes) (authorizer.Decision, string, error) {
	browserSafeAttributes := a.getBrowserSafeAttributes(attributes)
	return a.delegate.Authorize(browserSafeAttributes)
}

func (a *browserSafeAuthorizer) getBrowserSafeAttributes(attributes authorizer.Attributes) authorizer.Attributes {
	if !attributes.IsResourceRequest() {
		return attributes
	}

	isProxyVerb := attributes.GetVerb() == proxyAction
	isProxySubresource := attributes.GetSubresource() == proxyAction

	if !isProxyVerb && !isProxySubresource {
		// Requests to non-proxy resources don't expose HTML or HTTP-handling user content to browsers
		return attributes
	}

	if user := attributes.GetUser(); user != nil {
		if a.authenticatedGroups.HasAny(user.GetGroups()...) {
			// An authenticated request indicates this isn't a browser page load.
			// Browsers cannot make direct authenticated requests.
			// This depends on the API not enabling basic or cookie-based auth.
			return attributes
		}
	}

	return &browserSafeAttributes{
		Attributes:         attributes,
		isProxyVerb:        isProxyVerb,
		isProxySubresource: isProxySubresource,
	}
}

type browserSafeAttributes struct {
	authorizer.Attributes

	isProxyVerb, isProxySubresource bool
}

func (b *browserSafeAttributes) GetVerb() string {
	if b.isProxyVerb {
		return unsafeProxy
	}
	return b.Attributes.GetVerb()
}

func (b *browserSafeAttributes) GetSubresource() string {
	if b.isProxySubresource {
		return unsafeProxy
	}
	return b.Attributes.GetSubresource()
}
<commit_msg>browsersafe reason<commit_after>package browsersafe

import (
	"fmt"

	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/authorization/authorizer"
)

const (
	proxyAction = "proxy"
	unsafeProxy = "unsafeproxy"
)

type browserSafeAuthorizer struct {
	delegate authorizer.Authorizer

	// list of groups, any of which indicate the request is authenticated
	authenticatedGroups sets.String
}

func NewBrowserSafeAuthorizer(delegate authorizer.Authorizer, authenticatedGroups ...string) authorizer.Authorizer {
	return &browserSafeAuthorizer{
		delegate:            delegate,
		authenticatedGroups: sets.NewString(authenticatedGroups...),
	}
}

func (a *browserSafeAuthorizer) Authorize(attributes authorizer.Attributes) (authorizer.Decision, string, error) {
	attrs := a.getBrowserSafeAttributes(attributes)
	decision, reason, err := a.delegate.Authorize(attrs)
	safeAttributes, changed := attrs.(*browserSafeAttributes)

	// check if the request was not allowed and we changed the attributes
	if decision == authorizer.DecisionAllow || !changed {
		return decision, reason, err
	}

	// if so, use this information to update the reason
	return decision, safeAttributes.reason(reason), err
}

func (a *browserSafeAuthorizer) getBrowserSafeAttributes(attributes authorizer.Attributes) authorizer.Attributes {
	if !attributes.IsResourceRequest() {
		return attributes
	}

	isProxyVerb := attributes.GetVerb() == proxyAction
	isProxySubresource := attributes.GetSubresource() == proxyAction

	if !isProxyVerb && !isProxySubresource {
		// Requests to non-proxy resources don't expose HTML or HTTP-handling user content to browsers
		return attributes
	}

	if user := attributes.GetUser(); user != nil {
		if a.authenticatedGroups.HasAny(user.GetGroups()...) {
			// An authenticated request indicates this isn't a browser page load.
			// Browsers cannot make direct authenticated requests.
			// This depends on the API not enabling basic or cookie-based auth.
			return attributes
		}
	}

	return &browserSafeAttributes{
		Attributes:         attributes,
		isProxyVerb:        isProxyVerb,
		isProxySubresource: isProxySubresource,
	}
}

type browserSafeAttributes struct {
	authorizer.Attributes

	isProxyVerb, isProxySubresource bool
}

func (b *browserSafeAttributes) GetVerb() string {
	if b.isProxyVerb {
		return unsafeProxy
	}
	return b.Attributes.GetVerb()
}

func (b *browserSafeAttributes) GetSubresource() string {
	if b.isProxySubresource {
		return unsafeProxy
	}
	return b.Attributes.GetSubresource()
}

func (b *browserSafeAttributes) reason(reason string) string {
	if b.isProxyVerb {
		if len(reason) != 0 {
			reason += ", "
		}
		reason += fmt.Sprintf("%s verb changed to %s", proxyAction, unsafeProxy)
	}
	if b.isProxySubresource {
		if len(reason) != 0 {
			reason += ", "
		}
		reason += fmt.Sprintf("%s subresource changed to %s", proxyAction, unsafeProxy)
	}
	return reason
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Fredy Wijaya
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package goprops

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"regexp"
	"strings"
)

var (
	regex = regexp.MustCompile(`^([^=]+)=(.*)$`)
)

// Properties contains the list of properties
type Properties map[string]string

// Read reads properties from a reader.
func Read(in io.Reader) (Properties, error) {
	scanner := bufio.NewScanner(in)
	props := Properties{}
	lineNumber := 1
	for scanner.Scan() {
		line := scanner.Text()
		line = strings.TrimSpace(line)
		// Skip comment
		if len(line) == 0 || line[0] == '#' {
			lineNumber++
			continue
		}
		if groups := regex.FindStringSubmatch(line); groups != nil {
			key, value := groups[1], groups[2]
			props[strings.TrimSpace(key)] = strings.TrimSpace(value)
		} else {
			return nil, errors.New(fmt.Sprintf("Invalid syntax at line %d", lineNumber))
		}
		lineNumber++
	}
	err := scanner.Err()
	if err != nil {
		return nil, err
	}
	return props, nil
}

// ReadFile reads properties from a file.
func ReadFile(fileName string) (Properties, error) {
	file, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return Read(file)
}

// Write writes properties into a writer
func Write(out io.Writer, props Properties) {
	for key, value := range props {
		fmt.Fprintln(out, key, "=", value)
	}
	fmt.Fprintln(out)
}

// WriteFile writes properties into a file
func WriteFile(fileName string, props Properties) error {
	file, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer file.Close()
	Write(file, props)
	return nil
}
<commit_msg>Golint code<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Fredy Wijaya
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package goprops

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"regexp"
	"strings"
)

var (
	regex = regexp.MustCompile(`^([^=]+)=(.*)$`)
)

// Properties contains the list of properties
type Properties map[string]string

// Read reads properties from a reader.
func Read(in io.Reader) (Properties, error) {
	scanner := bufio.NewScanner(in)
	props := Properties{}
	lineNumber := 1
	for scanner.Scan() {
		line := scanner.Text()
		line = strings.TrimSpace(line)
		// Skip comment
		if len(line) == 0 || line[0] == '#' {
			lineNumber++
			continue
		}
		if groups := regex.FindStringSubmatch(line); groups != nil {
			key, value := groups[1], groups[2]
			props[strings.TrimSpace(key)] = strings.TrimSpace(value)
		} else {
			return nil, fmt.Errorf("Invalid syntax at line %d", lineNumber)
		}
		lineNumber++
	}
	err := scanner.Err()
	if err != nil {
		return nil, err
	}
	return props, nil
}

// ReadFile reads properties from a file.
func ReadFile(fileName string) (Properties, error) {
	file, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return Read(file)
}

// Write writes properties into a writer
func Write(out io.Writer, props Properties) {
	for key, value := range props {
		fmt.Fprintln(out, key, "=", value)
	}
	fmt.Fprintln(out)
}

// WriteFile writes properties into a file
func WriteFile(fileName string, props Properties) error {
	file, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer file.Close()
	Write(file, props)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/codegangsta/cli"
)

var (
	appDebug        = false
	appName         = "gosping"
	appHelpTemplate = `
NAME:
	{{.Name}} - {{.Usage}}

USAGE:
	{{.Name}} [options] x@y.z [@server]
	Where: x@y.z  is the address that will receive e-mail
	and server is the address to connect to (optional)

VERSION:
	{{.Version}}

OPTIONS:
	{{range .Flags}}{{.}}
	{{end}}

If no @server is specified, {{.Name}} will try to find
the recipient domain's MX record, falling back on A/AAAA records.
`
)

type Stats struct {
	min, max, sum, num float64
}

var connectStats, bannerStats, heloStats, mailfromStats,
	rcpttoStats, dataStats, datasentStats, quitStats Stats

func (st *Stats) add(number float64) {
	number = float64(int(number*100)) / 100
	switch {
	case st.min > number || st.min == 0.0:
		st.min = number
	case st.max < number:
		st.max = number
	}
	st.sum += number
	st.num++
}
func main() {
	cli.AppHelpTemplate = appHelpTemplate
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug,d", Usage: "Show more debugging"},
		cli.IntFlag{Name: "port,p", Usage: "Which TCP port to use [default: 25]", Value: 25},
		cli.IntFlag{Name: "wait,w", Usage: "Time to wait between PINGs [default: 1000] (ms)", Value: 1000},
		cli.IntFlag{Name: "count,c", Usage: "Number on messages [default: 10]", Value: 10},
		cli.IntFlag{Name: "parallel, P", Usage: "Number of parallel workers [default 1]", Value: 1},
		cli.IntFlag{Name: "size,s", Usage: "Message size in kilobytes [default: 10] (KiB)", Value: 10},
		cli.StringFlag{Name: "file,f", Usage: "Send message file (RFC 822)", Value: ""},
		cli.StringFlag{Name: "helo, H", Usage: "HELO domain [default: localhost.localdomain]",
			Value: "localhost.localdomain"},
		cli.StringFlag{Name: "sender, S", Usage: "sender; Sender address [default: empty]", Value: ""},
		cli.BoolFlag{Name: "rate,r", Usage: "rate; Show message rate per second"},
		cli.BoolTFlag{Name: "quiet,q", Usage: "quiet; Show less output"},
		cli.BoolFlag{Name: "J", Usage: "Run in jailed mode (forbid --file)"},
	}
	app.Name = "gosping"
	app.Version = "0.0.1"
	app.Usage = "Get some SMTP statistics"
	app.Action = run
	app.Run(os.Args)
}

func run(c *cli.Context) {
	appDebug = c.Bool("debug")
	targetAddress, mxServer, err := getdestination(c)
	if err != nil {
		fmt.Println(err)
		os.Exit(127)
	}
	jobs := c.Int("parallel")
	connecttarget := mxServer + ":" + strconv.Itoa(c.Int("port"))
	fmt.Printf("PING %s (%s) with %v sequence(s), waiting %v between, using %v gorutine(s). \n",
		targetAddress, connecttarget, c.Int("count"),
		(time.Duration(c.Int("wait")) * time.Millisecond), jobs)

	var wg sync.WaitGroup
	wg.Add(jobs)
	// let's go berserk
	for i := 0; i < jobs; i++ {
		go do(c, connecttarget, &wg)
	}
	wg.Wait()
	printStats("connect", connectStats)
	printStats("banner", bannerStats)
	printStats("helo", heloStats)

}

func do(c *cli.Context, d string, wg *sync.WaitGroup) {
	//get the globals from context so we just parse them once
	sleep := time.Duration(c.Int("wait")) * time.Millisecond
	seqs := c.Int("count")

	for i := 0; i < seqs; i++ {
		smtp_init := time.Now().UnixNano()
		conn_duration := float64(0)
		ban_duration := float64(0)
		helo_duration := float64(0)

		//connection
		conn, conn_err := connect(d)
		conntime := time.Now().UnixNano()
		if conn_err == nil {
			conn_duration = float64((conntime - smtp_init) / int64(time.Millisecond))
		}
		//for seq x we have x+1 numbers in the stat
		connectStats.add(conn_duration)

		//baner
		ban_str, ban_err := readSMTPLine(conn)
		bantime := time.Now().UnixNano()
		if ban_err == nil && ban_str == "220" {
			ban_duration = float64((bantime - conntime) / int64(time.Millisecond))
		}
		bannerStats.add(ban_duration)

		//helo
		msg := "HELO " + c.String("helo") + "\r\n"
		ok, part, err := gossip(conn, msg, "250")
		if ok {
			helotime := time.Now().UnixNano()
			helo_duration = float64((helotime - bantime) / int64(time.Millisecond))
		} else {
			fmt.Printf("Error %v occured in gossip at %v part", err, part)
		}
		heloStats.add(helo_duration)
		conn.Close()
		time.Sleep(sleep)
	}
	wg.Done()
}

func getdestination(c *cli.Context) (string, string, error) {
	var mxServer string
	var targetAddress string
	var err error
	myArgs := c.Args()
	debugprint("Entering getdestination \n")
	if len(myArgs) > 1 {
		if myArgs[1][:1] != "@" {
			mxServer = ""
			targetAddress = ""
			err = fmt.Errorf("Server argument should be like \"@server\" %q provided", myArgs[1])
		} else {
			mxServer = myArgs[1][1:]
			targetAddress = myArgs[0]
		}
	} else {
		targetAddress = myArgs[0]
		mxServer, err = resolvmx(strings.SplitAfter(targetAddress, "@")[1])
		if err != nil {
			mxServer = ""
		}
	}
	debugprint(fmt.Sprintf("Target address is %s, mxServer is %s, error is %v \n",
		targetAddress, mxServer, err))

	return targetAddress, mxServer, err
}

func connect(target string) (net.Conn, error) {
	debugprint("Entering connect \n")

	conn, err := net.Dial("tcp", target)
	debugprint("We connected, or errored \n")
	return conn, err
}

func resolvmx(target string) (string, error) {
	mxRecord, err := net.LookupMX(target)
	// we don't want the last dot in the host (it does not hurt to have it though)
	return mxRecord[0].Host[0 : len(mxRecord[0].Host)-1], err
}

func readSMTPLine(conn net.Conn) (string, error) {
	message, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	return message[0:3], err
}

func writeSMTP(conn net.Conn, message string) error {
	// we just write the message and return the error, message content is not our job
	_, err := fmt.Fprintf(conn, message)
	return err
}

func printStats(name string, st Stats) error {
	_, err := fmt.Fprintf(os.Stdout, "%v min/avg/max = %.2f/%.2f/%.2f ms \n",
		name, st.min, st.sum/st.num, st.max)
	return err
}

func debugprint(str string) {
	if appDebug {
		fmt.Fprintf(os.Stdout, str)
	}
}

func gossip(conn net.Conn, say string, hear string) (status bool, part string, err error) {
	write_err := writeSMTP(conn, say)
	if err != nil {
		status := false
		part := "write"
		return status, part, write_err
	}
	ret, read_err := readSMTPLine(conn)
	if read_err != nil {
		status := false
		part := "read"
		return status, part, write_err
	}
	if ret == hear {
		return true, "", nil
	} else {
		return false, "", nil

	}
}
<commit_msg>implemented mailfromStats and connection error checking<commit_after>package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/codegangsta/cli"
)

var (
	appDebug        = false
	appName         = "gosping"
	appHelpTemplate = `
NAME:
	{{.Name}} - {{.Usage}}

USAGE:
	{{.Name}} [options] x@y.z [@server]
	Where: x@y.z  is the address that will receive e-mail
	and server is the address to connect to (optional)

VERSION:
	{{.Version}}

OPTIONS:
	{{range .Flags}}{{.}}
	{{end}}

If no @server is specified, {{.Name}} will try to find
the recipient domain's MX record, falling back on A/AAAA records.
`
)

type Stats struct {
	min, max, sum, num float64
}

var connectStats, bannerStats, heloStats, mailfromStats,
	rcpttoStats, dataStats, datasentStats, quitStats Stats

func (st *Stats) add(number float64) {
	number = float64(int(number*100)) / 100
	switch {
	case st.min > number || st.min == 0.0:
		st.min = number
	case st.max < number:
		st.max = number
	}
	st.sum += number
	st.num++
}
func main() {
	cli.AppHelpTemplate = appHelpTemplate
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug,d", Usage: "Show more debugging"},
		cli.IntFlag{Name: "port,p", Usage: "Which TCP port to use [default: 25]", Value: 25},
		cli.IntFlag{Name: "wait,w", Usage: "Time to wait between PINGs [default: 1000] (ms)", Value: 1000},
		cli.IntFlag{Name: "count,c", Usage: "Number on messages [default: 10]", Value: 10},
		cli.IntFlag{Name: "parallel, P", Usage: "Number of parallel workers [default 1]", Value: 1},
		cli.IntFlag{Name: "size,s", Usage: "Message size in kilobytes [default: 10] (KiB)", Value: 10},
		cli.StringFlag{Name: "file,f", Usage: "Send message file (RFC 822)", Value: ""},
		cli.StringFlag{Name: "helo, H", Usage: "HELO domain [default: localhost.localdomain]",
			Value: "localhost.localdomain"},
		cli.StringFlag{Name: "sender, S", Usage: "sender; Sender address [default: empty]", Value: ""},
		cli.BoolFlag{Name: "rate,r", Usage: "rate; Show message rate per second"},
		cli.BoolTFlag{Name: "quiet,q", Usage: "quiet; Show less output"},
		cli.BoolFlag{Name: "J", Usage: "Run in jailed mode (forbid --file)"},
	}
	app.Name = "gosping"
	app.Version = "0.0.1"
	app.Usage = "Get some SMTP statistics"
	app.Action = run
	app.Run(os.Args)
}

func run(c *cli.Context) {
	appDebug = c.Bool("debug")
	targetAddress, mxServer, err := getdestination(c)
	if err != nil {
		fmt.Println(err)
		os.Exit(127)
	}
	jobs := c.Int("parallel")

	connecttarget := mxServer + ":" + strconv.Itoa(c.Int("port"))
	fmt.Printf("PING %s (%s) with %v sequence(s), waiting %v between, using %v gorutine(s). \n",
		targetAddress, connecttarget, c.Int("count"),
		(time.Duration(c.Int("wait")) * time.Millisecond), jobs)

	var wg sync.WaitGroup
	wg.Add(jobs)
	// let's go berserk
	for i := 0; i < jobs; i++ {
		go do(c, connecttarget, &wg)
	}
	wg.Wait()
	printStats("connect", connectStats)
	printStats("banner", bannerStats)
	printStats("helo", heloStats)
	printStats("mailfrom", mailfromStats)

}

func do(c *cli.Context, d string, wg *sync.WaitGroup) {
	//get the globals from context so we just parse them once
	sleep := time.Duration(c.Int("wait")) * time.Millisecond
	seqs := c.Int("count")
	smtpFrom := c.String("sender")

	for i := 0; i < seqs; i++ {
		smtp_init := time.Now().UnixNano()
		conn_duration := float64(0)
		ban_duration := float64(0)
		helo_duration := float64(0)
		mailfrom_duration := float64(0)

		//connection
		conn, conn_err := connect(d)
		conntime := time.Now().UnixNano()
		if conn_err != nil {
			fmt.Println(conn_err)
			os.Exit(128)
		} else {
			conn_duration = float64((conntime - smtp_init) / int64(time.Millisecond))
		}
		//for seq x we have x+1 numbers in the stat
		connectStats.add(conn_duration)

		//baner
		ban_str, ban_err := readSMTPLine(conn)
		bantime := time.Now().UnixNano()
		if ban_err == nil && ban_str == "220" {
			ban_duration = float64((bantime - conntime) / int64(time.Millisecond))
		}
		bannerStats.add(ban_duration)

		//helo
		msg := "HELO " + c.String("helo") + "\r\n"
		ok, part, err := gossip(conn, msg, "250")
		helotime := time.Now().UnixNano()
		if ok {
			helo_duration = float64((helotime - bantime) / int64(time.Millisecond))
		} else {
			fmt.Printf("Error %v occured in gossip at %v part", err, part)
		}
		heloStats.add(helo_duration)

		//mail from: <address>
		msg = "MAIL FROM: <" + smtpFrom + ">\r\n"
		ok, part, err = gossip(conn, msg, "250")
		if ok {
			mailfromtime := time.Now().UnixNano()
			mailfrom_duration = float64((mailfromtime - helotime) / int64(time.Millisecond))
		} else {
			fmt.Printf("Error %v occured in gossip at %v part", err, part)
		}
		mailfromStats.add(mailfrom_duration)

		conn.Close()
		time.Sleep(sleep)
	}
	wg.Done()
}

func getdestination(c *cli.Context) (string, string, error) {
	var mxServer string
	var targetAddress string
	var err error
	myArgs := c.Args()
	debugprint("Entering getdestination \n")
	if len(myArgs) > 1 {
		if myArgs[1][:1] != "@" {
			mxServer = ""
			targetAddress = ""
			err = fmt.Errorf("Server argument should be like \"@server\" %q provided", myArgs[1])
		} else {
			mxServer = myArgs[1][1:]
			targetAddress = myArgs[0]
		}
	} else {
		targetAddress = myArgs[0]
		mxServer, err = resolvmx(strings.SplitAfter(targetAddress, "@")[1])
		if err != nil {
			mxServer = ""
		}
	}
	debugprint(fmt.Sprintf("Target address is %s, mxServer is %s, error is %v \n",
		targetAddress, mxServer, err))

	return targetAddress, mxServer, err
}

func connect(target string) (net.Conn, error) {
	debugprint("Entering connect \n")

	conn, err := net.Dial("tcp", target)
	debugprint("We connected, or errored \n")
	return conn, err
}

func resolvmx(target string) (string, error) {
	mxRecord, err := net.LookupMX(target)
	// we don't want the last dot in the host (it does not hurt to have it though)
	return mxRecord[0].Host[0 : len(mxRecord[0].Host)-1], err
}

func readSMTPLine(conn net.Conn) (string, error) {
	message, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	return message[0:3], err
}

func writeSMTP(conn net.Conn, message string) error {
	// we just write the message and return the error, message content is not our job
	_, err := fmt.Fprintf(conn, message)
	return err
}

func printStats(name string, st Stats) error {
	_, err := fmt.Fprintf(os.Stdout, "%v min/avg/max = %.2f/%.2f/%.2f ms \n",
		name, st.min, st.sum/st.num, st.max)
	return err
}

func debugprint(str string) {
	if appDebug {
		fmt.Fprintf(os.Stdout, str)
	}
}

func gossip(conn net.Conn, say string, hear string) (status bool, part string, err error) {
	write_err := writeSMTP(conn, say)
	if err != nil {
		return false, "write", write_err
	}
	ret, read_err := readSMTPLine(conn)
	if read_err != nil {
		return false, "read", read_err
	}
	if ret == hear {
		return true, "", nil
	} else {
		return false, "", nil

	}
}
<|endoftext|>


<commit_before>package validator

//go:generate mockery -name Validator -output mock_validator

import (
	"regexp"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/onedaycat/errors"

	"fmt"
)

var (
	emptyStr          = ""
	emailPatern       = regexp.MustCompile(".+@.+\\..+")
	dateiso8601Patern = regexp.MustCompile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(Z|(\\+|-)\\d{2}(:?\\d{2})?)$")
)

type ValidateError struct {
	Name string
	Err  error
}

type Validator interface {
	HasError() bool
	Messages() map[string]string
	GetError() errors.Error
	GetMsg() string
	AddError(name string, err errors.Error)
	AddErrorMsg(name, format string, args ...interface{})
	RequiredString(val string, name string, err ...errors.Error)
	RequiredBytes(val []byte, name string, err ...errors.Error)
	RequiredInt(val int, name string, err ...errors.Error)
	RequiredInt32(val int32, name string, err ...errors.Error)
	RequiredInt64(val int64, name string, err ...errors.Error)
	RequiredFloat64(val float64, name string, err ...errors.Error)
	RequiredBool(val bool, name string, err ...errors.Error)
	RequiredEmail(val string, name string, err ...errors.Error)
	NotNil(val interface{}, name string, err ...errors.Error)
	RequiredTime(val time.Time, name string, err ...errors.Error)
	MinInt(val int, n int, name string, err ...errors.Error)
	MaxInt(val int, n int, name string, err ...errors.Error)
	MinInt64(val int64, n int64, name string, err ...errors.Error)
	MaxInt64(val int64, n int64, name string, err ...errors.Error)
	MinFloat64(val float64, n float64, name string, err ...errors.Error)
	MaxFloat64(val float64, n float64, name string, err ...errors.Error)
	MinChar(val string, n int, name string, err ...errors.Error)
	MaxChar(val string, n int, name string, err ...errors.Error)
	Email(val string, name string, err ...errors.Error)
	Gender(val string, name string, err ...errors.Error)
	Confirm(val, confirm string, name string, confirmName string, err ...errors.Error)
	ISO8601DataTime(val string, name string, err ...errors.Error)
	InString(val string, in []string, name string, err ...errors.Error)
	RangeInt(val, min, max int, name string, err ...errors.Error)
	RangeInt32(val, min, max int32, name string, err ...errors.Error)
	RangeInt64(val, min, max int64, name string, err ...errors.Error)
}

type validator struct {
	errs []ValidateError
}

func New() Validator {
	return &validator{
		errs: []ValidateError{},
	}
}

func (v *validator) HasError() bool {
	if len(v.errs) > 0 {
		return true
	}

	return false
}

func (v *validator) Messages() map[string]string {
	msgs := make(map[string]string)
	for i := 0; i < len(v.errs); i++ {
		if v.errs[i].Name != "" {
			msgs[v.errs[i].Name] = v.errs[i].Err.Error()
		}
	}

	return msgs
}

func (v *validator) GetError() errors.Error {
	if len(v.errs) > 0 {
		return errors.BadRequest(emptyStr, v.errs[0].Err.Error())
	}

	return nil
}

func (v *validator) GetMsg() string {
	if len(v.errs) > 0 {
		return v.errs[0].Err.Error()
	}

	return emptyStr
}

func (v *validator) add(name string, err error, errs []errors.Error) {
	if len(errs) > 0 {
		err = errs[0]
	}

	v.errs = append(v.errs, ValidateError{name, err})
}

func (v *validator) AddError(name string, err errors.Error) {
	v.errs = append(v.errs, ValidateError{name, err})
}

func (v *validator) AddErrorMsg(name, format string, args ...interface{}) {
	v.errs = append(v.errs, ValidateError{name, fmt.Errorf(format, args...)})
}

func (v *validator) RequiredString(val string, name string, err ...errors.Error) {
	if len(strings.TrimSpace(val)) == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredBytes(val []byte, name string, err ...errors.Error) {
	if len(val) == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt(val int, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt32(val int32, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt64(val int64, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredFloat64(val float64, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredBool(val bool, name string, err ...errors.Error) {
	if !val {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredEmail(val string, name string, err ...errors.Error) {
	if val == "" {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}

	v.Email(val, name, err...)
}

func (v *validator) NotNil(val interface{}, name string, err ...errors.Error) {
	if val == nil {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredTime(val time.Time, name string, err ...errors.Error) {
	if val.IsZero() {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinInt(val int, n int, name string, err ...errors.Error) {
	if val > n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %d", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxInt(val int, n int, name string, err ...errors.Error) {
	if val > n {
		defaultErr := fmt.Errorf("%s should not greater than %d", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinInt64(val int64, n int64, name string, err ...errors.Error) {
	if val > n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %d", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxInt64(val int64, n int64, name string, err ...errors.Error) {
	if val > n {
		defaultErr := fmt.Errorf("%s should not greater than %d", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinFloat64(val float64, n float64, name string, err ...errors.Error) {
	if val < n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %v", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxFloat64(val float64, n float64, name string, err ...errors.Error) {
	if val > n {
		return
	}
	defaultErr := fmt.Errorf("%s should not greater than %v", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MinChar(val string, n int, name string, err ...errors.Error) {
	if utf8.RuneCountInString(val) < n {
		defaultErr := fmt.Errorf("%s should be atleast %d character", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MaxChar(val string, n int, name string, err ...errors.Error) {
	if utf8.RuneCountInString(val) > n {
		defaultErr := fmt.Errorf("%s should not greater than %d character", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Email(val string, name string, err ...errors.Error) {
	if val == "" {
		return
	}
	if !emailPatern.MatchString(val) {
		defaultErr := fmt.Errorf("%s invalid email format", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Gender(val string, name string, err ...errors.Error) {
	if val != `male` && val != `female` {
		defaultErr := fmt.Errorf("%s should be male or female", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Confirm(val, confirm string, name string, confirmName string, err ...errors.Error) {
	if val != confirm {
		defaultErr := fmt.Errorf("%s is not matched %s", name, confirmName)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) ISO8601DataTime(val string, name string, err ...errors.Error) {
	if val == "" {
		return
	}
	if !dateiso8601Patern.MatchString(val) {
		defaultErr := fmt.Errorf("%s is invalid date format", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) InString(val string, in []string, name string, err ...errors.Error) {
	for _, k := range in {
		if k == val {
			return
		}
	}

	defaultErr := fmt.Errorf("%s is not in", strings.Join(in, ","))
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt(val, min, max int, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt32(val, min, max int32, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt64(val, min, max int64, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}
<commit_msg>update<commit_after>package validator

//go:generate mockery -name Validator -output mock_validator

import (
	"regexp"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/onedaycat/errors"

	"fmt"
)

var (
	emptyStr          = ""
	emailPatern       = regexp.MustCompile(".+@.+\\..+")
	dateiso8601Patern = regexp.MustCompile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(Z|(\\+|-)\\d{2}(:?\\d{2})?)$")
)

type ValidateError struct {
	Name string
	Err  error
}

type Validator interface {
	HasError() bool
	Messages() map[string]string
	GetError() errors.Error
	GetMsg() string
	Wrap(errors.Error) errors.Error
	AddError(name string, err errors.Error)
	AddErrorMsg(name, format string, args ...interface{})
	RequiredString(val string, name string, err ...errors.Error)
	RequiredBytes(val []byte, name string, err ...errors.Error)
	RequiredInt(val int, name string, err ...errors.Error)
	RequiredInt32(val int32, name string, err ...errors.Error)
	RequiredInt64(val int64, name string, err ...errors.Error)
	RequiredFloat64(val float64, name string, err ...errors.Error)
	RequiredBool(val bool, name string, err ...errors.Error)
	RequiredEmail(val string, name string, err ...errors.Error)
	NotNil(val interface{}, name string, err ...errors.Error)
	RequiredTime(val time.Time, name string, err ...errors.Error)
	MinInt(val int, n int, name string, err ...errors.Error)
	MaxInt(val int, n int, name string, err ...errors.Error)
	MinInt64(val int64, n int64, name string, err ...errors.Error)
	MaxInt64(val int64, n int64, name string, err ...errors.Error)
	MinFloat64(val float64, n float64, name string, err ...errors.Error)
	MaxFloat64(val float64, n float64, name string, err ...errors.Error)
	MinChar(val string, n int, name string, err ...errors.Error)
	MaxChar(val string, n int, name string, err ...errors.Error)
	Email(val string, name string, err ...errors.Error)
	Gender(val string, name string, err ...errors.Error)
	Confirm(val, confirm string, name string, confirmName string, err ...errors.Error)
	ISO8601DataTime(val string, name string, err ...errors.Error)
	InString(val string, in []string, name string, err ...errors.Error)
	RangeInt(val, min, max int, name string, err ...errors.Error)
	RangeInt32(val, min, max int32, name string, err ...errors.Error)
	RangeInt64(val, min, max int64, name string, err ...errors.Error)
}

type validator struct {
	errs []ValidateError
}

func New() Validator {
	return &validator{
		errs: []ValidateError{},
	}
}

func (v *validator) HasError() bool {
	if len(v.errs) > 0 {
		return true
	}

	return false
}

func (v *validator) Messages() map[string]string {
	msgs := make(map[string]string)
	for i := 0; i < len(v.errs); i++ {
		if v.errs[i].Name != "" {
			msgs[v.errs[i].Name] = v.errs[i].Err.Error()
		}
	}

	return msgs
}

func (v *validator) GetError() errors.Error {
	if len(v.errs) > 0 {
		return errors.BadRequest(emptyStr, v.errs[0].Err.Error())
	}

	return nil
}

func (v *validator) GetMsg() string {
	if len(v.errs) > 0 {
		return v.errs[0].Err.Error()
	}

	return emptyStr
}

func (v *validator) Wrap(err errors.Error) errors.Error {
	if len(v.errs) > 0 {
		return err.WithMessage(v.errs[0].Err.Error())
	}

	return nil
}

func (v *validator) add(name string, err error, errs []errors.Error) {
	if len(errs) > 0 {
		err = errs[0]
	}

	v.errs = append(v.errs, ValidateError{name, err})
}

func (v *validator) AddError(name string, err errors.Error) {
	v.errs = append(v.errs, ValidateError{name, err})
}

func (v *validator) AddErrorMsg(name, format string, args ...interface{}) {
	v.errs = append(v.errs, ValidateError{name, fmt.Errorf(format, args...)})
}

func (v *validator) RequiredString(val string, name string, err ...errors.Error) {
	if len(strings.TrimSpace(val)) == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredBytes(val []byte, name string, err ...errors.Error) {
	if len(val) == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt(val int, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt32(val int32, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredInt64(val int64, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredFloat64(val float64, name string, err ...errors.Error) {
	if val == 0 {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredBool(val bool, name string, err ...errors.Error) {
	if !val {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredEmail(val string, name string, err ...errors.Error) {
	if val == "" {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}

	v.Email(val, name, err...)
}

func (v *validator) NotNil(val interface{}, name string, err ...errors.Error) {
	if val == nil {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) RequiredTime(val time.Time, name string, err ...errors.Error) {
	if val.IsZero() {
		defaultErr := fmt.Errorf("%s is required", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinInt(val int, n int, name string, err ...errors.Error) {
	if val > n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %d", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxInt(val int, n int, name string, err ...errors.Error) {
	if val > n {
		defaultErr := fmt.Errorf("%s should not greater than %d", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinInt64(val int64, n int64, name string, err ...errors.Error) {
	if val > n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %d", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxInt64(val int64, n int64, name string, err ...errors.Error) {
	if val > n {
		defaultErr := fmt.Errorf("%s should not greater than %d", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MinFloat64(val float64, n float64, name string, err ...errors.Error) {
	if val < n {
		return
	}

	defaultErr := fmt.Errorf("%s should be atleast %v", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MaxFloat64(val float64, n float64, name string, err ...errors.Error) {
	if val > n {
		return
	}
	defaultErr := fmt.Errorf("%s should not greater than %v", name, n)
	v.add(name, defaultErr, err)
}

func (v *validator) MinChar(val string, n int, name string, err ...errors.Error) {
	if utf8.RuneCountInString(val) < n {
		defaultErr := fmt.Errorf("%s should be atleast %d character", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) MaxChar(val string, n int, name string, err ...errors.Error) {
	if utf8.RuneCountInString(val) > n {
		defaultErr := fmt.Errorf("%s should not greater than %d character", name, n)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Email(val string, name string, err ...errors.Error) {
	if val == "" {
		return
	}
	if !emailPatern.MatchString(val) {
		defaultErr := fmt.Errorf("%s invalid email format", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Gender(val string, name string, err ...errors.Error) {
	if val != `male` && val != `female` {
		defaultErr := fmt.Errorf("%s should be male or female", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) Confirm(val, confirm string, name string, confirmName string, err ...errors.Error) {
	if val != confirm {
		defaultErr := fmt.Errorf("%s is not matched %s", name, confirmName)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) ISO8601DataTime(val string, name string, err ...errors.Error) {
	if val == "" {
		return
	}
	if !dateiso8601Patern.MatchString(val) {
		defaultErr := fmt.Errorf("%s is invalid date format", name)
		v.add(name, defaultErr, err)
	}
}

func (v *validator) InString(val string, in []string, name string, err ...errors.Error) {
	for _, k := range in {
		if k == val {
			return
		}
	}

	defaultErr := fmt.Errorf("%s is not in", strings.Join(in, ","))
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt(val, min, max int, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt32(val, min, max int32, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}

func (v *validator) RangeInt64(val, min, max int64, name string, err ...errors.Error) {
	if val >= min && val <= max {
		return
	}

	defaultErr := fmt.Errorf("%s is out of range", name)
	v.add(name, defaultErr, err)
}
<|endoftext|>


<commit_before>package depot

import (
	"fmt"
	"log"
	"os"

	git "github.com/libgit2/git2go"
)

const (
	filePerm = 0644
)

// CreateNewRepo if repo doesn't already exist will create a new
// repo in depot
func CreateNewRepo(author string, repo string, ref string) error {
	log.Printf("Creating New Repo on depot %s/%s@%s \n", author, repo, ref)
	folderName := fmt.Sprintf("%s.git", BuildHashedRepoName(author, repo, ref))

	// First check if repo folder exists on depot volume
	if err := checkIfRepoFolderExists(folderName); err == nil {
		return nil
	}

	// Create repo folder on depot volume
	err := os.Mkdir(
		fmt.Sprintf("%s/%s", depotReposPath, folderName),
		filePerm,
	)

	// Check to make sure we properly created folder
	if err != nil {
		// If we couldn't make the folder, and the foler exists now return error. Someone else is
		// Already versioning this package
		if checkFolderErr := checkIfRepoFolderExists(folderName); checkFolderErr == nil {
			return fmt.Errorf("Error, folder already exists, package is in process of being versioned already. %v %v", checkFolderErr, err)
		}
	}

	// Initialize the new bare git repository
	_, err = git.InitRepository(fmt.Sprintf("%s/%s", depotReposPath, folderName), true)
	if err != nil {
		return fmt.Errorf("Error, could not initialize new repository. %v", err)
	}

	return err
}

func checkIfRepoFolderExists(folderName string) error {
	_, err := os.Stat(fmt.Sprintf("%s/%s", depotReposPath, folderName))
	return err
}
<commit_msg>rename ref to SHA<commit_after>package depot

import (
	"fmt"
	"log"
	"os"

	git "github.com/libgit2/git2go"
)

const (
	filePerm = 0644
)

// CreateNewRepo if repo doesn't already exist will create a new
// repo in depot
func CreateNewRepo(author string, repo string, sha string) error {
	log.Printf("Creating New Repo on depot %s/%s@%s \n", author, repo, sha)
	folderName := fmt.Sprintf("%s.git", BuildHashedRepoName(author, repo, sha))

	// First check if repo folder exists on depot volume
	if err := checkIfRepoFolderExists(folderName); err == nil {
		return nil
	}

	// Create repo folder on depot volume
	err := os.Mkdir(
		fmt.Sprintf("%s/%s", depotReposPath, folderName),
		filePerm,
	)

	// Check to make sure we properly created folder
	if err != nil {
		// If we couldn't make the folder, and the foler exists now return error. Someone else is
		// Already versioning this package
		if checkFolderErr := checkIfRepoFolderExists(folderName); checkFolderErr == nil {
			return fmt.Errorf("Error, folder already exists, package is in process of being versioned already. %v %v", checkFolderErr, err)
		}
	}

	// Initialize the new bare git repository
	_, err = git.InitRepository(fmt.Sprintf("%s/%s", depotReposPath, folderName), true)
	if err != nil {
		return fmt.Errorf("Error, could not initialize new repository. %v", err)
	}

	return err
}

func checkIfRepoFolderExists(folderName string) error {
	_, err := os.Stat(fmt.Sprintf("%s/%s", depotReposPath, folderName))
	return err
}
<|endoftext|>


<commit_before>package provision

import (
	"bytes"
	"fmt"
	"text/template"

	"github.com/docker/machine/drivers"
	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/provision/pkgaction"
	"github.com/docker/machine/libmachine/provision/serviceaction"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/docker/machine/log"
	"github.com/docker/machine/utils"
)

func init() {
	Register("Debian", &RegisteredProvisioner{
		New: NewDebianProvisioner,
	})
}

func NewDebianProvisioner(d drivers.Driver) Provisioner {
	return &DebianProvisioner{
		GenericProvisioner{
			DockerOptionsDir:  "/etc/docker",
			DaemonOptionsFile: "/etc/systemd/system/docker.service",
			OsReleaseId:       "debian",
			Packages: []string{
				"curl",
			},
			Driver: d,
		},
	}
}

type DebianProvisioner struct {
	GenericProvisioner
}

func (provisioner *DebianProvisioner) Service(name string, action serviceaction.ServiceAction) error {
	// daemon-reload to catch config updates; systemd -- ugh
	if _, err := provisioner.SSHCommand("sudo systemctl daemon-reload"); err != nil {
		return err
	}

	command := fmt.Sprintf("sudo systemctl %s %s", action.String(), name)

	if _, err := provisioner.SSHCommand(command); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) Package(name string, action pkgaction.PackageAction) error {
	var packageAction string

	updateMetadata := true

	switch action {
	case pkgaction.Install, pkgaction.Upgrade:
		packageAction = "install"
	case pkgaction.Remove:
		packageAction = "remove"
		updateMetadata = false
	}

	switch name {
	case "docker":
		name = "docker-engine"
	}

	if updateMetadata {
		if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil {
			return err
		}
	}

	// handle the new docker-engine package; we can probably remove this
	// after we have a few versions
	if action == pkgaction.Upgrade && name == "docker-engine" {
		// run the force remove on the existing lxc-docker package
		// and remove the existing apt source list
		// also re-run the get.docker.com script to properly setup
		// the system again

		commands := []string{
			"rm /etc/apt/sources.list.d/docker.list || true",
			"apt-get remove -y lxc-docker || true",
			"curl -sSL https://get.docker.com | sh",
		}

		for _, cmd := range commands {
			command := fmt.Sprintf("sudo DEBIAN_FRONTEND=noninteractive %s", cmd)
			if _, err := provisioner.SSHCommand(command); err != nil {
				return err
			}
		}
	}

	command := fmt.Sprintf("DEBIAN_FRONTEND=noninteractive sudo -E apt-get %s -y  %s", packageAction, name)

	log.Debugf("package: action=%s name=%s", action.String(), name)

	if _, err := provisioner.SSHCommand(command); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) dockerDaemonResponding() bool {
	if _, err := provisioner.SSHCommand("sudo docker version"); err != nil {
		log.Warnf("Error getting SSH command to check if the daemon is up: %s", err)
		return false
	}

	// The daemon is up if the command worked.  Carry on.
	return true
}

func (provisioner *DebianProvisioner) Provision(swarmOptions swarm.SwarmOptions, authOptions auth.AuthOptions, engineOptions engine.EngineOptions) error {
	provisioner.SwarmOptions = swarmOptions
	provisioner.AuthOptions = authOptions
	provisioner.EngineOptions = engineOptions

	if provisioner.EngineOptions.StorageDriver == "" {
		provisioner.EngineOptions.StorageDriver = "aufs"
	}

	// HACK: since debian does not come with sudo by default we install
	log.Debug("installing sudo")
	if _, err := provisioner.SSHCommand("if ! type sudo; then apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y sudo; fi"); err != nil {
		return err
	}

	log.Debug("setting hostname")
	if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil {
		return err
	}

	log.Debug("installing base packages")
	for _, pkg := range provisioner.Packages {
		if err := provisioner.Package(pkg, pkgaction.Install); err != nil {
			return err
		}
	}

	log.Debug("installing docker")
	if err := installDockerGeneric(provisioner, engineOptions.InstallURL); err != nil {
		return err
	}

	log.Debug("waiting for docker daemon")
	if err := utils.WaitFor(provisioner.dockerDaemonResponding); err != nil {
		return err
	}

	provisioner.AuthOptions = setRemoteAuthOptions(provisioner)

	log.Debug("configuring auth")
	if err := ConfigureAuth(provisioner); err != nil {
		return err
	}

	log.Debug("configuring swarm")
	if err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions); err != nil {
		return err
	}

	// enable in systemd
	log.Debug("enabling docker in systemd")
	if err := provisioner.Service("docker", serviceaction.Enable); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) GenerateDockerOptions(dockerPort int) (*DockerOptions, error) {
	var (
		engineCfg bytes.Buffer
	)

	driverNameLabel := fmt.Sprintf("provider=%s", provisioner.Driver.DriverName())
	provisioner.EngineOptions.Labels = append(provisioner.EngineOptions.Labels, driverNameLabel)

	engineConfigTmpl := `[Service]
ExecStart=/usr/bin/docker -d -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}

[Install]
WantedBy=multi-user.target
`
	t, err := template.New("engineConfig").Parse(engineConfigTmpl)
	if err != nil {
		return nil, err
	}

	engineConfigContext := EngineConfigContext{
		DockerPort:    dockerPort,
		AuthOptions:   provisioner.AuthOptions,
		EngineOptions: provisioner.EngineOptions,
	}

	t.Execute(&engineCfg, engineConfigContext)

	return &DockerOptions{
		EngineOptions:     engineCfg.String(),
		EngineOptionsPath: provisioner.DaemonOptionsFile,
	}, nil
}
<commit_msg>fix debian provisioning bug with systemd<commit_after>package provision

import (
	"bytes"
	"fmt"
	"text/template"

	"github.com/docker/machine/drivers"
	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/provision/pkgaction"
	"github.com/docker/machine/libmachine/provision/serviceaction"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/docker/machine/log"
	"github.com/docker/machine/utils"
)

func init() {
	Register("Debian", &RegisteredProvisioner{
		New: NewDebianProvisioner,
	})
}

func NewDebianProvisioner(d drivers.Driver) Provisioner {
	return &DebianProvisioner{
		GenericProvisioner{
			DockerOptionsDir:  "/etc/docker",
			DaemonOptionsFile: "/etc/systemd/system/docker.service",
			OsReleaseId:       "debian",
			Packages: []string{
				"curl",
			},
			Driver: d,
		},
	}
}

type DebianProvisioner struct {
	GenericProvisioner
}

func (provisioner *DebianProvisioner) Service(name string, action serviceaction.ServiceAction) error {
	// daemon-reload to catch config updates; systemd -- ugh
	if _, err := provisioner.SSHCommand("sudo systemctl daemon-reload"); err != nil {
		return err
	}

	command := fmt.Sprintf("sudo systemctl -f %s %s", action.String(), name)

	if _, err := provisioner.SSHCommand(command); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) Package(name string, action pkgaction.PackageAction) error {
	var packageAction string

	updateMetadata := true

	switch action {
	case pkgaction.Install, pkgaction.Upgrade:
		packageAction = "install"
	case pkgaction.Remove:
		packageAction = "remove"
		updateMetadata = false
	}

	switch name {
	case "docker":
		name = "docker-engine"
	}

	if updateMetadata {
		if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil {
			return err
		}
	}

	// handle the new docker-engine package; we can probably remove this
	// after we have a few versions
	if action == pkgaction.Upgrade && name == "docker-engine" {
		// run the force remove on the existing lxc-docker package
		// and remove the existing apt source list
		// also re-run the get.docker.com script to properly setup
		// the system again

		commands := []string{
			"rm /etc/apt/sources.list.d/docker.list || true",
			"apt-get remove -y lxc-docker || true",
			"curl -sSL https://get.docker.com | sh",
		}

		for _, cmd := range commands {
			command := fmt.Sprintf("sudo DEBIAN_FRONTEND=noninteractive %s", cmd)
			if _, err := provisioner.SSHCommand(command); err != nil {
				return err
			}
		}
	}

	command := fmt.Sprintf("DEBIAN_FRONTEND=noninteractive sudo -E apt-get %s -y  %s", packageAction, name)

	log.Debugf("package: action=%s name=%s", action.String(), name)

	if _, err := provisioner.SSHCommand(command); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) dockerDaemonResponding() bool {
	if _, err := provisioner.SSHCommand("sudo docker version"); err != nil {
		log.Warnf("Error getting SSH command to check if the daemon is up: %s", err)
		return false
	}

	// The daemon is up if the command worked.  Carry on.
	return true
}

func (provisioner *DebianProvisioner) Provision(swarmOptions swarm.SwarmOptions, authOptions auth.AuthOptions, engineOptions engine.EngineOptions) error {
	provisioner.SwarmOptions = swarmOptions
	provisioner.AuthOptions = authOptions
	provisioner.EngineOptions = engineOptions

	if provisioner.EngineOptions.StorageDriver == "" {
		provisioner.EngineOptions.StorageDriver = "aufs"
	}

	// HACK: since debian does not come with sudo by default we install
	log.Debug("installing sudo")
	if _, err := provisioner.SSHCommand("if ! type sudo; then apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y sudo; fi"); err != nil {
		return err
	}

	log.Debug("setting hostname")
	if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil {
		return err
	}

	log.Debug("installing base packages")
	for _, pkg := range provisioner.Packages {
		if err := provisioner.Package(pkg, pkgaction.Install); err != nil {
			return err
		}
	}

	log.Debug("installing docker")
	if err := installDockerGeneric(provisioner, engineOptions.InstallURL); err != nil {
		return err
	}

	log.Debug("waiting for docker daemon")
	if err := utils.WaitFor(provisioner.dockerDaemonResponding); err != nil {
		return err
	}

	provisioner.AuthOptions = setRemoteAuthOptions(provisioner)

	log.Debug("configuring auth")
	if err := ConfigureAuth(provisioner); err != nil {
		return err
	}

	log.Debug("configuring swarm")
	if err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions); err != nil {
		return err
	}

	// enable in systemd
	log.Debug("enabling docker in systemd")
	if err := provisioner.Service("docker", serviceaction.Enable); err != nil {
		return err
	}

	return nil
}

func (provisioner *DebianProvisioner) GenerateDockerOptions(dockerPort int) (*DockerOptions, error) {
	var (
		engineCfg bytes.Buffer
	)

	driverNameLabel := fmt.Sprintf("provider=%s", provisioner.Driver.DriverName())
	provisioner.EngineOptions.Labels = append(provisioner.EngineOptions.Labels, driverNameLabel)

	engineConfigTmpl := `[Service]
ExecStart=/usr/bin/docker -d -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}

[Install]
WantedBy=multi-user.target
`
	t, err := template.New("engineConfig").Parse(engineConfigTmpl)
	if err != nil {
		return nil, err
	}

	engineConfigContext := EngineConfigContext{
		DockerPort:    dockerPort,
		AuthOptions:   provisioner.AuthOptions,
		EngineOptions: provisioner.EngineOptions,
	}

	t.Execute(&engineCfg, engineConfigContext)

	return &DockerOptions{
		EngineOptions:     engineCfg.String(),
		EngineOptionsPath: provisioner.DaemonOptionsFile,
	}, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
package elasticsearch

import (
	"k8s.io/heapster/metrics/core"
	"strings"
)

func MetricFamilyTimestamp(metricFamily core.MetricFamily) string {
	return strings.Title(string(metricFamily)) + "MetricsTimestamp"
}
func metricFamilySchema(metricFamily core.MetricFamily) string {
	metricSchemas := []string{}
	for _, metric := range core.MetricFamilies[metricFamily] {
		metricSchemas = append(metricSchemas,
			`"`+metric.Name+`": {
  "properties": {
    "value": {
      "type": "long"
    }
  }
}`,
		)
	}

	return customMetricTypeSchema(string(metricFamily),
		`"`+MetricFamilyTimestamp(metricFamily)+`": {
  "type": "date",
  "format": "strict_date_optional_time||epoch_millis"
},
"Metrics": {
  "properties": {
  `+strings.Join(metricSchemas, ",\r\n")+`
  }
}
`,
	)
}

func customMetricTypeSchema(typeName string, customSchema string) string {
	return `"` + typeName + `": {
  "properties": {
    "MetricsTags": {
      "properties": {
        "container_base_image": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "container_name": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "host_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "hostname": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "labels": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "namespace_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "namespace_name": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "nodename": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "pod_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "pod_name": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "pod_namespace": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "resource_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "type": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    },
    ` + customSchema + `
  }
}`
}

var mapping = `{
  "mappings": {
    "_default_": {
      "_all": {
        "enabled": false
      }
    },
    ` + metricFamilySchema(core.MetricFamilyCpu) + `,
    ` + metricFamilySchema(core.MetricFamilyFilesystem) + `,
    ` + metricFamilySchema(core.MetricFamilyMemory) + `,
    ` + metricFamilySchema(core.MetricFamilyNetwork) + `,
    ` + customMetricTypeSchema(core.MetricFamilyGeneral,
	`"MetricsName": {
  "type": "string",
  "index": "analyzed",
  "fields": {
    "raw": {
      "type": "string",
      "index": "not_analyzed"
    }
  }
},
"GeneralMetricsTimestamp": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"MetricsValue": {
  "properties": {
    "value": {
      "type": "long"
    }
  }
}`) + `,

    "events": {
      "properties": {
        "EventTags": {
          "properties": {
            "eventID": {
              "type": "string",
              "index": "not_analyzed"
            },
            "hostname": {
              "type": "string",
              "index": "analyzed",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "pod_id": {
              "type": "string",
              "index": "not_analyzed"
            },
            "pod_name": {
              "type": "string",
              "index": "analyzed",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            }
          }
        },
        "InvolvedObject": {
          "properties": {
            "apiVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "fieldPath": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "kind": {
              "type": "string",
              "index": "not_analyzed"
            },
            "name": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "namespace": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "resourceVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "uid": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "FirstOccurrenceTimestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        },
        "LastOccurrenceTimestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        },
        "Type": {
          "type": "string",
          "index": "not_analyzed"
        },
        "Message": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "Reason": {
          "type": "string",
          "index": "not_analyzed"
        },

        "Count": {
          "type": "long"
        },
        "Metadata": {
          "properties": {
            "creationTimestamp": {
              "type": "date",
              "format": "strict_date_optional_time||epoch_millis"
            },
            "name": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "namespace": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "resourceVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "selfLink": {
              "type": "string",
              "index": "not_analyzed"
            },
            "uid": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "Source": {
          "properties": {
            "component": {
              "type": "string",
              "index": "not_analyzed"
            },
            "host": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            }
          }
        }
      }
    }
  }
}`
<commit_msg>HOTFIX: change value to be double<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
package elasticsearch

import (
	"k8s.io/heapster/metrics/core"
	"strings"
)

func MetricFamilyTimestamp(metricFamily core.MetricFamily) string {
	return strings.Title(string(metricFamily)) + "MetricsTimestamp"
}
func metricFamilySchema(metricFamily core.MetricFamily) string {
	metricSchemas := []string{}
	for _, metric := range core.MetricFamilies[metricFamily] {
		metricSchemas = append(metricSchemas,
			`"`+metric.Name+`": {
  "properties": {
    "value": {
      "type": "double"
    }
  }
}`,
		)
	}

	return customMetricTypeSchema(string(metricFamily),
		`"`+MetricFamilyTimestamp(metricFamily)+`": {
  "type": "date",
  "format": "strict_date_optional_time||epoch_millis"
},
"Metrics": {
  "properties": {
  `+strings.Join(metricSchemas, ",\r\n")+`
  }
}
`,
	)
}

func customMetricTypeSchema(typeName string, customSchema string) string {
	return `"` + typeName + `": {
  "properties": {
    "MetricsTags": {
      "properties": {
        "container_base_image": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "container_name": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "host_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "hostname": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "labels": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "namespace_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "namespace_name": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "nodename": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "pod_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "pod_name": {
          "type": "string",
          "index": "analyzed",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "pod_namespace": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "resource_id": {
          "type": "string",
          "index": "not_analyzed"
        },
        "type": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    },
    ` + customSchema + `
  }
}`
}

var mapping = `{
  "mappings": {
    "_default_": {
      "_all": {
        "enabled": false
      }
    },
    ` + metricFamilySchema(core.MetricFamilyCpu) + `,
    ` + metricFamilySchema(core.MetricFamilyFilesystem) + `,
    ` + metricFamilySchema(core.MetricFamilyMemory) + `,
    ` + metricFamilySchema(core.MetricFamilyNetwork) + `,
    ` + customMetricTypeSchema(core.MetricFamilyGeneral,
	`"MetricsName": {
  "type": "string",
  "index": "analyzed",
  "fields": {
    "raw": {
      "type": "string",
      "index": "not_analyzed"
    }
  }
},
"GeneralMetricsTimestamp": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"MetricsValue": {
  "properties": {
    "value": {
      "type": "double"
    }
  }
}`) + `,

    "events": {
      "properties": {
        "EventTags": {
          "properties": {
            "eventID": {
              "type": "string",
              "index": "not_analyzed"
            },
            "hostname": {
              "type": "string",
              "index": "analyzed",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "pod_id": {
              "type": "string",
              "index": "not_analyzed"
            },
            "pod_name": {
              "type": "string",
              "index": "analyzed",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            }
          }
        },
        "InvolvedObject": {
          "properties": {
            "apiVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "fieldPath": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "kind": {
              "type": "string",
              "index": "not_analyzed"
            },
            "name": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "namespace": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "resourceVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "uid": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "FirstOccurrenceTimestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        },
        "LastOccurrenceTimestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        },
        "Type": {
          "type": "string",
          "index": "not_analyzed"
        },
        "Message": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "Reason": {
          "type": "string",
          "index": "not_analyzed"
        },

        "Count": {
          "type": "long"
        },
        "Metadata": {
          "properties": {
            "creationTimestamp": {
              "type": "date",
              "format": "strict_date_optional_time||epoch_millis"
            },
            "name": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "namespace": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            },
            "resourceVersion": {
              "type": "string",
              "index": "not_analyzed"
            },
            "selfLink": {
              "type": "string",
              "index": "not_analyzed"
            },
            "uid": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "Source": {
          "properties": {
            "component": {
              "type": "string",
              "index": "not_analyzed"
            },
            "host": {
              "type": "string",
              "fields": {
                "raw": {
                  "type": "string",
                  "index": "not_analyzed"
                }
              }
            }
          }
        }
      }
    }
  }
}`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"github.com/nsf/termbox-go"
	"github.com/simulatedsimian/neo"
	"os"
	"path/filepath"
	"unicode/utf8"
)

func printAt(x, y int, s string, fg, bg termbox.Attribute) {
	for len(s) > 0 {
		r, rlen := utf8.DecodeRuneInString(s)
		termbox.SetCell(x, y, r, fg, bg)
		s = s[rlen:]
		x++
	}
}

func printAtDef(x, y int, s string) {
	printAt(x, y, s, termbox.ColorDefault, termbox.ColorDefault)
}

type treeNode struct {
	path     string
	info     os.FileInfo
	children []*treeNode
	parent   *treeNode
	expanded bool
	index    int
}

func (n *treeNode) isLast() bool {
	if n.parent == nil {
		return true
	} else {
		sibcount := len(n.parent.children)
		return m.index == sibcount-1
	}
}

func createNodes(rootPath string, parent *treeNode) ([]*treeNode, error) {

	var res []*treeNode
	err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {

		if err == nil && path != rootPath {
			res = append(res, &treeNode{path, info, nil, parent, false, len(res)})
			if info.IsDir() {
				return filepath.SkipDir
			}
		}
		return nil
	})

	return res, err
}

func populateChildren(node *treeNode) error {

	if node.info.IsDir() {
		children, err := createNodes(node.path, node)
		neo.PanicOnError(err)
		node.children = children
		node.expanded = true
	}
	return nil
}

func drawNode(node *treeNode) {

	preamble := ""
	for n := node; n.parent != nil; n = n.parent {
		if n.parent.last {
			preamble = "   " + preamble
		} else {
			preamble = "│  " + preamble
		}
	}
	fmt.Print(preamble)

	if node.last {
		fmt.Print("└─")
	} else {
		fmt.Print("├─")
	}

	if node.info.IsDir() {
		if node.expanded {
			fmt.Print("[-]")
		} else {
			fmt.Print("[+]")
		}
	} else {
		fmt.Print("── ")
	}

	fmt.Println(node.info.Name())
}

func drawNodes(nodes []*treeNode) {

	for _, node := range nodes {
		drawNode(node)
		if node.expanded && len(node.children) > 0 {
			drawNodes(node.children)
		}
	}
}

func nextNode(node *treeNode) *treeNode {
	return nil
}

func prevNode(node *treeNode) *treeNode {
	return nil
}

func drawNodesFrom(node *treeNode, count int) {
	siblings := node.parent.children
	for i, max := node.index, len(siblings); i < max; i++ {
		drawNode(siblings[i])
	}
}

func filltree(nodes []*treeNode) {

	for _, node := range nodes {
		populateChildren(node)
		if len(node.children) > 0 {
			filltree(node.children)
		}
	}
}

func test() {
	rootpath := "."
	if len(os.Args) > 1 {
		rootpath = os.Args[1]
	}

	rootInfo, err := os.Stat(rootpath)
	neo.PanicOnError(err)

	rootNode := &treeNode{rootpath, rootInfo, nil, nil, true, 0}

	nodes, err := createNodes(rootpath, rootNode)
	neo.PanicOnError(err)
	filltree(nodes)
	rootNode.children = nodes

	var root []*treeNode
	root = append(root, rootNode)

	//	nodes[0].expanded = false

	drawNodes(root)

	spew.Dump(err)
	fmt.Println(err)
}

func termtest() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()

	termbox.HideCursor()

	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			printAt(0, 1, fmt.Sprint(ev), termbox.ColorDefault, termbox.ColorDefault)
			termbox.Flush()

			switch ev.Key {
			case termbox.KeyEsc:
				return
			case termbox.KeyArrowUp:
			case termbox.KeyArrowDown:
			}

			termbox.Flush()

		case termbox.EventResize:
			x, y := ev.Width, ev.Height
			printAt(0, 0, fmt.Sprintf("[%d, %d] ", x, y), termbox.ColorDefault, termbox.ColorDefault)
			termbox.Flush()
		}
	}

	termbox.Flush()
}

func main() {
	test()
}
<commit_msg>treeNode.isLast<commit_after>package main

import (
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"github.com/nsf/termbox-go"
	"github.com/simulatedsimian/neo"
	"os"
	"path/filepath"
	"unicode/utf8"
)

func printAt(x, y int, s string, fg, bg termbox.Attribute) {
	for len(s) > 0 {
		r, rlen := utf8.DecodeRuneInString(s)
		termbox.SetCell(x, y, r, fg, bg)
		s = s[rlen:]
		x++
	}
}

func printAtDef(x, y int, s string) {
	printAt(x, y, s, termbox.ColorDefault, termbox.ColorDefault)
}

type treeNode struct {
	path     string
	info     os.FileInfo
	children []*treeNode
	parent   *treeNode
	expanded bool
	index    int
}

func (n *treeNode) isLast() bool {
	if n.parent == nil {
		return true
	} else {
		return n.index == len(n.parent.children)-1
	}
}

func createNodes(rootPath string, parent *treeNode) ([]*treeNode, error) {

	var res []*treeNode
	err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {

		if err == nil && path != rootPath {
			res = append(res, &treeNode{path, info, nil, parent, false, len(res)})
			if info.IsDir() {
				return filepath.SkipDir
			}
		}
		return nil
	})

	return res, err
}

func populateChildren(node *treeNode) error {

	if node.info.IsDir() {
		children, err := createNodes(node.path, node)
		neo.PanicOnError(err)
		node.children = children
		node.expanded = true
	}
	return nil
}

func drawNode(node *treeNode) {

	preamble := ""
	for n := node; n.parent != nil; n = n.parent {
		if n.isLast() {
			preamble = "   " + preamble
		} else {
			preamble = "│  " + preamble
		}
	}
	fmt.Print(preamble)

	if node.isLast() {
		fmt.Print("└─")
	} else {
		fmt.Print("├─")
	}

	if node.info.IsDir() {
		if node.expanded {
			fmt.Print("[-]")
		} else {
			fmt.Print("[+]")
		}
	} else {
		fmt.Print("── ")
	}

	fmt.Println(node.info.Name())
}

func drawNodes(nodes []*treeNode) {

	for _, node := range nodes {
		drawNode(node)
		if node.expanded && len(node.children) > 0 {
			drawNodes(node.children)
		}
	}
}

func nextNode(node *treeNode) *treeNode {
	return nil
}

func prevNode(node *treeNode) *treeNode {
	return nil
}

func drawNodesFrom(node *treeNode, count int) {
	siblings := node.parent.children
	for i, max := node.index, len(siblings); i < max; i++ {
		drawNode(siblings[i])
	}
}

func filltree(nodes []*treeNode) {

	for _, node := range nodes {
		populateChildren(node)
		if len(node.children) > 0 {
			filltree(node.children)
		}
	}
}

func test() {
	rootpath := "."
	if len(os.Args) > 1 {
		rootpath = os.Args[1]
	}

	rootInfo, err := os.Stat(rootpath)
	neo.PanicOnError(err)

	rootNode := &treeNode{rootpath, rootInfo, nil, nil, true, 0}

	nodes, err := createNodes(rootpath, rootNode)
	neo.PanicOnError(err)
	filltree(nodes)
	rootNode.children = nodes

	var root []*treeNode
	root = append(root, rootNode)

	//	nodes[0].expanded = false

	drawNodes(root)

	spew.Dump(err)
	fmt.Println(err)
}

func termtest() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()

	termbox.HideCursor()

	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			printAt(0, 1, fmt.Sprint(ev), termbox.ColorDefault, termbox.ColorDefault)
			termbox.Flush()

			switch ev.Key {
			case termbox.KeyEsc:
				return
			case termbox.KeyArrowUp:
			case termbox.KeyArrowDown:
			}

			termbox.Flush()

		case termbox.EventResize:
			x, y := ev.Width, ev.Height
			printAt(0, 0, fmt.Sprintf("[%d, %d] ", x, y), termbox.ColorDefault, termbox.ColorDefault)
			termbox.Flush()
		}
	}

	termbox.Flush()
}

func main() {
	test()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"
	"sort"

	"github.com/zagrodzki/goscope/dummy"
	"github.com/zagrodzki/goscope/scope"
)

type AggrPoint struct {
	x     int
	sumY  int
	sizeY int
}

func (p AggrPoint) add(x, y int) AggrPoint {
	p.x = x
	p.sumY += y
	p.sizeY++
	return p
}

func (p AggrPoint) toPoint() image.Point {
	return image.Point{p.x, p.sumY / p.sizeY}
}

func SamplesToPoints(s []scope.Sample, start, end image.Point) []image.Point {
	if len(s) == 0 {
		return nil
	}
	minY := s[0]
	maxY := s[0]
	for _, y := range s {
		if minY > y {
			minY = y
		}
		if maxY < y {
			maxY = y
		}
	}

	rangeX := float64(len(s) - 1)
	rangeY := float64(maxY - minY)
	aggrPoints := make(map[int]AggrPoint)
	for i, y := range s {
		mapX := int(float64(start.X) + float64(i)/rangeX*float64(end.X-start.X))
		mapY := int(float64(end.Y) - float64(y-minY)/rangeY*float64(end.Y-start.Y))
		aggrPoints[mapX] = aggrPoints[mapX].add(mapX, mapY)
	}
	fmt.Println(aggrPoints)
	var points []image.Point
	for _, p := range aggrPoints {
		points = append(points, p.toPoint())
	}

	return points
}

type Plot struct {
	*image.RGBA
}

func (plot Plot) Fill(col color.RGBA) {
	bounds := plot.Bounds()
	for i := bounds.Min.X; i < bounds.Max.X; i++ {
		for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
			plot.Set(i, j, col)
		}
	}
}

func (plot Plot) DrawLine(p1, p2 image.Point, col color.RGBA) {
	if p1.X == p2.X {
		for i := Min(p1.Y, p2.Y); i <= Max(p1.Y, p2.Y); i++ {
			plot.Set(p1.X, i, col)
		}
		return
	}
	a := float64(p1.Y-p2.Y) / float64(p1.X-p2.X)
	b := float64(p1.Y) - float64(p1.X)*a

	if Abs(p1.X-p2.X) >= Abs(p1.Y-p2.Y) {
		for i := Min(p1.X, p2.X); i <= Max(p1.X, p2.X); i++ {
			plot.Set(i, int(a*float64(i)+b), col)
		}
	} else {
		for i := Min(p1.Y, p2.Y); i <= Max(p1.Y, p2.Y); i++ {
			plot.Set(int((float64(i)-b)/a), i, col)
		}
	}
}

func (plot Plot) DrawSamples(start, end image.Point, s []scope.Sample, col color.RGBA) {
	points := SamplesToPoints(s, start, end)
	sort.Sort(XSorter(points))
	for i := 1; i < len(points); i++ {
		plot.DrawLine(points[i-1], points[i], col)
	}
}

func (plot Plot) DrawAll(samples map[scope.ChanID][]scope.Sample, cols map[scope.ChanID]color.RGBA) {
	b := plot.Bounds()
	x1 := b.Min.X + 10
	x2 := b.Max.X - 10
	y1 := b.Min.Y + 10
	y2 := b.Min.Y + 10 + int((b.Max.Y-b.Min.Y-10*(len(samples)+1))/len(samples))
	step := y2 - b.Min.Y
	for id, v := range samples {
		plot.DrawSamples(image.Point{x1, y1}, image.Point{x2, y2}, v, cols[id])
		y1 = y1 + step
		y2 = y2 + step
	}
}

type XSorter []image.Point

func (a XSorter) Len() int {
	return len(a)
}

func (a XSorter) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a XSorter) Less(i, j int) bool {
	return a[i].X < a[j].X
}

func Min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func Max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func Abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func main() {
	dum, _ := dummy.Open("")
	data, stop, _ := dum.StartSampling()

	samples := (<-data).Samples
	fmt.Println(samples)
	stop()

	plot := Plot{image.NewRGBA(image.Rect(0, 0, 800, 600))}
	colWhite := color.RGBA{255, 255, 255, 255}

	colRed := color.RGBA{255, 0, 0, 255}
	colGreen := color.RGBA{0, 255, 0, 255}
	colBlue := color.RGBA{0, 0, 255, 255}
	colBlack := color.RGBA{0, 0, 0, 255}
	chanCols := [4]color.RGBA{colRed, colGreen, colBlue, colBlack}

	plot.Fill(colWhite)
	cols := make(map[scope.ChanID]color.RGBA)
	next := 0
	for _, id := range dum.Channels() {
		cols[id] = chanCols[next]
		next = (next + 1) % 4
	}
	plot.DrawAll(samples, cols)

	f, err := os.Create("draw.png")
	if err != nil {
		panic(err)
	}
	defer f.Close()
	png.Encode(f, plot)
}
<commit_msg>structs and functions made private<commit_after>package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"
	"sort"

	"github.com/zagrodzki/goscope/dummy"
	"github.com/zagrodzki/goscope/scope"
)

type aggrPoint struct {
	x     int
	sumY  int
	sizeY int
}

func (p aggrPoint) add(x, y int) aggrPoint {
	p.x = x
	p.sumY += y
	p.sizeY++
	return p
}

func (p aggrPoint) toPoint() image.Point {
	return image.Point{p.x, p.sumY / p.sizeY}
}

func SamplesToPoints(s []scope.Sample, start, end image.Point) []image.Point {
	if len(s) == 0 {
		return nil
	}
	minY := s[0]
	maxY := s[0]
	for _, y := range s {
		if minY > y {
			minY = y
		}
		if maxY < y {
			maxY = y
		}
	}

	rangeX := float64(len(s) - 1)
	rangeY := float64(maxY - minY)
	aggrPoints := make(map[int]aggrPoint)
	for i, y := range s {
		mapX := int(float64(start.X) + float64(i)/rangeX*float64(end.X-start.X))
		mapY := int(float64(end.Y) - float64(y-minY)/rangeY*float64(end.Y-start.Y))
		aggrPoints[mapX] = aggrPoints[mapX].add(mapX, mapY)
	}
	fmt.Println(aggrPoints)
	var points []image.Point
	for _, p := range aggrPoints {
		points = append(points, p.toPoint())
	}

	return points
}

type Plot struct {
	*image.RGBA
}

func (plot Plot) Fill(col color.RGBA) {
	bounds := plot.Bounds()
	for i := bounds.Min.X; i < bounds.Max.X; i++ {
		for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
			plot.Set(i, j, col)
		}
	}
}

func (plot Plot) DrawLine(p1, p2 image.Point, col color.RGBA) {
	if p1.X == p2.X {
		for i := min(p1.Y, p2.Y); i <= max(p1.Y, p2.Y); i++ {
			plot.Set(p1.X, i, col)
		}
		return
	}
	a := float64(p1.Y-p2.Y) / float64(p1.X-p2.X)
	b := float64(p1.Y) - float64(p1.X)*a

	if abs(p1.X-p2.X) >= abs(p1.Y-p2.Y) {
		for i := min(p1.X, p2.X); i <= max(p1.X, p2.X); i++ {
			plot.Set(i, int(a*float64(i)+b), col)
		}
	} else {
		for i := min(p1.Y, p2.Y); i <= max(p1.Y, p2.Y); i++ {
			plot.Set(int((float64(i)-b)/a), i, col)
		}
	}
}

func (plot Plot) DrawSamples(start, end image.Point, s []scope.Sample, col color.RGBA) {
	points := SamplesToPoints(s, start, end)
	sort.Sort(xSorter(points))
	for i := 1; i < len(points); i++ {
		plot.DrawLine(points[i-1], points[i], col)
	}
}

func (plot Plot) DrawAll(samples map[scope.ChanID][]scope.Sample, cols map[scope.ChanID]color.RGBA) {
	b := plot.Bounds()
	x1 := b.Min.X + 10
	x2 := b.Max.X - 10
	y1 := b.Min.Y + 10
	y2 := b.Min.Y + 10 + int((b.Max.Y-b.Min.Y-10*(len(samples)+1))/len(samples))
	step := y2 - b.Min.Y
	for id, v := range samples {
		plot.DrawSamples(image.Point{x1, y1}, image.Point{x2, y2}, v, cols[id])
		y1 = y1 + step
		y2 = y2 + step
	}
}

type xSorter []image.Point

func (a xSorter) Len() int {
	return len(a)
}

func (a xSorter) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a xSorter) Less(i, j int) bool {
	return a[i].X < a[j].X
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func main() {
	dum, _ := dummy.Open("")
	data, stop, _ := dum.StartSampling()

	samples := (<-data).Samples
	fmt.Println(samples)
	stop()

	plot := Plot{image.NewRGBA(image.Rect(0, 0, 800, 600))}
	colWhite := color.RGBA{255, 255, 255, 255}

	colRed := color.RGBA{255, 0, 0, 255}
	colGreen := color.RGBA{0, 255, 0, 255}
	colBlue := color.RGBA{0, 0, 255, 255}
	colBlack := color.RGBA{0, 0, 0, 255}
	chanCols := [4]color.RGBA{colRed, colGreen, colBlue, colBlack}

	plot.Fill(colWhite)
	cols := make(map[scope.ChanID]color.RGBA)
	next := 0
	for _, id := range dum.Channels() {
		cols[id] = chanCols[next]
		next = (next + 1) % 4
	}
	plot.DrawAll(samples, cols)

	f, err := os.Create("draw.png")
	if err != nil {
		panic(err)
	}
	defer f.Close()
	png.Encode(f, plot)
}
<|endoftext|>