<commit_before>// Mgmt
// Copyright (C) 2013-2016+ James Shubin and the project contributors
// Written by James Shubin <james@shubin.ca> and the project contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"log"
	"time"
)

//go:generate stringer -type=typeState -output=typestate_stringer.go
type typeState int

const (
	typeNil typeState = iota
	//typeConverged
	typeConvergedTimeout
)

type Type interface {
	Init()
	GetName() string // can't be named "Name()" because of struct field
	GetType() string
	Watch()
	StateOK() bool // TODO: can we rename this to something better?
	Apply() bool
	SetVertex(*Vertex)
	SetConvegedCallback(ctimeout int, converged chan bool)
	Compare(Type) bool
	SendEvent(eventName, bool)
	IsWatching() bool
	SetWatching(bool)
	GetState() typeState
	SetState(typeState)
	GetTimestamp() int64
	UpdateTimestamp() int64
	//Process()
}

type BaseType struct {
	Name      string `yaml:"name"`
	timestamp int64  // last updated timestamp ?
	events    chan Event
	vertex    *Vertex
	state     typeState
	watching  bool // is Watch() loop running ?
	ctimeout  int  // converged timeout
	converged chan bool
}

type NoopType struct {
	BaseType `yaml:",inline"`
	Comment  string `yaml:"comment"` // extra field for example purposes
}

func NewNoopType(name string) *NoopType {
	// FIXME: we could get rid of this New constructor and use raw object creation with a required Init()
	return &NoopType{
		BaseType: BaseType{
			Name:   name,
			events: make(chan Event), // unbuffered chan size to avoid stale events
			vertex: nil,
		},
		Comment: "",
	}
}

// initialize structures like channels if created without New constructor
func (obj *BaseType) Init() {
	obj.events = make(chan Event)
}

// this method gets used by all the types, if we have one of (obj NoopType) it would get overridden in that case!
func (obj *BaseType) GetName() string {
	return obj.Name
}

func (obj *BaseType) GetType() string {
	return "Base"
}

func (obj *BaseType) GetVertex() *Vertex {
	return obj.vertex
}

func (obj *BaseType) SetVertex(v *Vertex) {
	obj.vertex = v
}

func (obj *BaseType) SetConvegedCallback(ctimeout int, converged chan bool) {
	obj.ctimeout = ctimeout
	obj.converged = converged
}

// is the Watch() function running?
func (obj *BaseType) IsWatching() bool {
	return obj.watching
}

// store status of if the Watch() function is running
func (obj *BaseType) SetWatching(b bool) {
	obj.watching = b
}

func (obj *BaseType) GetState() typeState {
	return obj.state
}

func (obj *BaseType) SetState(state typeState) {
	obj.state = state
}

// get timestamp of a vertex
func (obj *BaseType) GetTimestamp() int64 {
	return obj.timestamp
}

// update timestamp of a vertex
func (obj *BaseType) UpdateTimestamp() int64 {
	obj.timestamp = time.Now().UnixNano() // update
	return obj.timestamp
}

// can this element run right now?
func (obj *BaseType) OKTimestamp() bool {
	v := obj.GetVertex()
	g := v.GetGraph()
	// these are all the vertices pointing TO v, eg: ??? -> v
	for _, n := range g.IncomingGraphEdges(v) {
		// if the vertex has a greater timestamp than any pre-req (n)
		// then we can't run right now...
		if obj.GetTimestamp() > n.Type.GetTimestamp() {
			return false
		}
	}
	return true
}

func (obj *BaseType) Poke() bool { // XXX: how can this ever fail and return false? eg: when is a poke not possible and should be rescheduled?
	v := obj.GetVertex()
	g := v.GetGraph()
	// these are all the vertices pointing AWAY FROM v, eg: v -> ???
	for _, n := range g.OutgoingGraphEdges(v) {
		n.SendEvent(eventPoke, false) // XXX: should this be sync or not? XXX: try it as async for now, but switch to sync and see if we deadlock -- maybe it's possible, i don't know for sure yet
	}
	return true
}

// push an event into the message queue for a particular type vertex
func (obj *BaseType) SendEvent(event eventName, sync bool) {
	if !sync {
		obj.events <- Event{event, nil, ""}
		return
	}

	resp := make(chan bool)
	obj.events <- Event{event, resp, ""}
	for {
		value := <-resp
		// wait until true value
		if value {
			return
		}
	}
}

// process events when a select gets one
// this handles the pause code too!
func (obj *BaseType) ReadEvent(event *Event) bool {

	event.ACK()
	switch event.Name {
	case eventStart:
		return true

	case eventPoke:
		return true

	case eventExit:
		return false

	case eventPause:
		// wait for next event to continue
		select {
		case e := <-obj.events:
			e.ACK()
			if e.Name == eventExit {
				return false
			} else if e.Name == eventStart { // eventContinue
				return true
			} else {
				log.Fatal("Unknown event: ", e)
			}
		}

	default:
		log.Fatal("Unknown event: ", event)
	}
	return false // required to keep the stupid go compiler happy
}

// XXX: rename this function
func (obj *BaseType) Process(typ Type) {
	var ok bool

	ok = true
	// is it okay to run dependency wise right now?
	// if not, that's okay because when the dependency runs, it will poke
	// us back and we will run if needed then!
	if obj.OKTimestamp() {
		// XXX XXX: why does this have to be typ instead of just obj! "obj.StateOK undefined (type *BaseType has no field or method StateOK)"

		if !typ.StateOK() { // TODO: can we rename this to something better?
			// throw an error if apply fails...
			// if this fails, don't UpdateTimestamp()
			if !typ.Apply() { // check for error
				ok = false
			}
		}

		if ok {
			// if poke fails, don't update timestamp
			// since we didn't propagate the pokes!
			if obj.Poke() {
				obj.UpdateTimestamp() // this was touched...
			}
		}
	}

}

func (obj *NoopType) GetType() string {
	return "Noop"
}

func (obj *NoopType) Watch() {
	if obj.IsWatching() {
		return
	}
	obj.SetWatching(true)
	defer obj.SetWatching(false)

	//vertex := obj.vertex // stored with SetVertex
	var send = false // send event?
	for {
		select {
		case event := <-obj.events:
			obj.SetState(typeNil)
			if ok := obj.ReadEvent(&event); !ok {
				return // exit
			}
			send = true

		case _ = <-TimeAfterOrBlock(obj.ctimeout):
			obj.SetState(typeConvergedTimeout)
			obj.converged <- true
			continue
		}

		// do all our event sending all together to avoid duplicate msgs
		if send {
			send = false

			obj.Process(obj) // XXX: rename this function
		}
	}
}

func (obj *NoopType) StateOK() bool {
	return true // never needs updating
}

func (obj *NoopType) Apply() bool {
	log.Printf("%v[%v]: Apply", obj.GetType(), obj.GetName())
	return true
}

func (obj *NoopType) Compare(typ Type) bool {
	switch typ.(type) {
	// we can only compare NoopType to others of the same type
	case *NoopType:
		typ := typ.(*NoopType)
		if obj.Name != typ.Name {
			return false
		}
	default:
		return false
	}
	return true
}
<commit_msg>Fix effective off-by-one error in dependency processing<commit_after>// Mgmt
// Copyright (C) 2013-2016+ James Shubin and the project contributors
// Written by James Shubin <james@shubin.ca> and the project contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"log"
	"time"
)

//go:generate stringer -type=typeState -output=typestate_stringer.go
type typeState int

const (
	typeNil typeState = iota
	//typeConverged
	typeConvergedTimeout
)

type Type interface {
	Init()
	GetName() string // can't be named "Name()" because of struct field
	GetType() string
	Watch()
	StateOK() bool // TODO: can we rename this to something better?
	Apply() bool
	SetVertex(*Vertex)
	SetConvegedCallback(ctimeout int, converged chan bool)
	Compare(Type) bool
	SendEvent(eventName, bool)
	IsWatching() bool
	SetWatching(bool)
	GetState() typeState
	SetState(typeState)
	GetTimestamp() int64
	UpdateTimestamp() int64
	//Process()
}

type BaseType struct {
	Name      string `yaml:"name"`
	timestamp int64  // last updated timestamp ?
	events    chan Event
	vertex    *Vertex
	state     typeState
	watching  bool // is Watch() loop running ?
	ctimeout  int  // converged timeout
	converged chan bool
}

type NoopType struct {
	BaseType `yaml:",inline"`
	Comment  string `yaml:"comment"` // extra field for example purposes
}

func NewNoopType(name string) *NoopType {
	// FIXME: we could get rid of this New constructor and use raw object creation with a required Init()
	return &NoopType{
		BaseType: BaseType{
			Name:   name,
			events: make(chan Event), // unbuffered chan size to avoid stale events
			vertex: nil,
		},
		Comment: "",
	}
}

// initialize structures like channels if created without New constructor
func (obj *BaseType) Init() {
	obj.events = make(chan Event)
}

// this method gets used by all the types, if we have one of (obj NoopType) it would get overridden in that case!
func (obj *BaseType) GetName() string {
	return obj.Name
}

func (obj *BaseType) GetType() string {
	return "Base"
}

func (obj *BaseType) GetVertex() *Vertex {
	return obj.vertex
}

func (obj *BaseType) SetVertex(v *Vertex) {
	obj.vertex = v
}

func (obj *BaseType) SetConvegedCallback(ctimeout int, converged chan bool) {
	obj.ctimeout = ctimeout
	obj.converged = converged
}

// is the Watch() function running?
func (obj *BaseType) IsWatching() bool {
	return obj.watching
}

// store status of if the Watch() function is running
func (obj *BaseType) SetWatching(b bool) {
	obj.watching = b
}

func (obj *BaseType) GetState() typeState {
	return obj.state
}

func (obj *BaseType) SetState(state typeState) {
	obj.state = state
}

// get timestamp of a vertex
func (obj *BaseType) GetTimestamp() int64 {
	return obj.timestamp
}

// update timestamp of a vertex
func (obj *BaseType) UpdateTimestamp() int64 {
	obj.timestamp = time.Now().UnixNano() // update
	return obj.timestamp
}

// can this element run right now?
func (obj *BaseType) OKTimestamp() bool {
	v := obj.GetVertex()
	g := v.GetGraph()
	// these are all the vertices pointing TO v, eg: ??? -> v
	for _, n := range g.IncomingGraphEdges(v) {
		// if the vertex has a greater timestamp than any pre-req (n)
		// then we can't run right now...
		// if they're equal (eg: on init of 0) then we also can't run
		// b/c we should let our pre-req's go first...
		if obj.GetTimestamp() >= n.Type.GetTimestamp() {
			return false
		}
	}
	return true
}

func (obj *BaseType) Poke() bool { // XXX: how can this ever fail and return false? eg: when is a poke not possible and should be rescheduled?
	v := obj.GetVertex()
	g := v.GetGraph()
	// these are all the vertices pointing AWAY FROM v, eg: v -> ???
	for _, n := range g.OutgoingGraphEdges(v) {
		n.SendEvent(eventPoke, false) // XXX: should this be sync or not? XXX: try it as async for now, but switch to sync and see if we deadlock -- maybe it's possible, i don't know for sure yet
	}
	return true
}

// push an event into the message queue for a particular type vertex
func (obj *BaseType) SendEvent(event eventName, sync bool) {
	if !sync {
		obj.events <- Event{event, nil, ""}
		return
	}

	resp := make(chan bool)
	obj.events <- Event{event, resp, ""}
	for {
		value := <-resp
		// wait until true value
		if value {
			return
		}
	}
}

// process events when a select gets one
// this handles the pause code too!
func (obj *BaseType) ReadEvent(event *Event) bool {

	event.ACK()
	switch event.Name {
	case eventStart:
		return true

	case eventPoke:
		return true

	case eventExit:
		return false

	case eventPause:
		// wait for next event to continue
		select {
		case e := <-obj.events:
			e.ACK()
			if e.Name == eventExit {
				return false
			} else if e.Name == eventStart { // eventContinue
				return true
			} else {
				log.Fatal("Unknown event: ", e)
			}
		}

	default:
		log.Fatal("Unknown event: ", event)
	}
	return false // required to keep the stupid go compiler happy
}

// XXX: rename this function
func (obj *BaseType) Process(typ Type) {
	if DEBUG {
		log.Printf("%v[%v]: Process()", obj.GetType(), obj.GetName())
	}
	var ok bool = true
	// is it okay to run dependency wise right now?
	// if not, that's okay because when the dependency runs, it will poke
	// us back and we will run if needed then!
	if obj.OKTimestamp() {
		if DEBUG {
			log.Printf("%v[%v]: OKTimestamp(%v)", obj.GetType(), obj.GetName(), obj.GetTimestamp())
		}
		// XXX XXX: why does this have to be typ instead of just obj! "obj.StateOK undefined (type *BaseType has no field or method StateOK)"
		if !typ.StateOK() { // TODO: can we rename this to something better?
			if DEBUG {
				log.Printf("%v[%v]: !StateOK()", obj.GetType(), obj.GetName())
			}
			// throw an error if apply fails...
			// if this fails, don't UpdateTimestamp()
			if !typ.Apply() { // check for error
				ok = false
			}
		}

		if ok {
			// if poke fails, don't update timestamp
			// since we didn't propagate the pokes!
			if obj.Poke() {
				obj.UpdateTimestamp() // this was touched...
			}
		}
	}

}

func (obj *NoopType) GetType() string {
	return "Noop"
}

func (obj *NoopType) Watch() {
	if obj.IsWatching() {
		return
	}
	obj.SetWatching(true)
	defer obj.SetWatching(false)

	//vertex := obj.vertex // stored with SetVertex
	var send = false // send event?
	for {
		select {
		case event := <-obj.events:
			obj.SetState(typeNil)
			if ok := obj.ReadEvent(&event); !ok {
				return // exit
			}
			send = true

		case _ = <-TimeAfterOrBlock(obj.ctimeout):
			obj.SetState(typeConvergedTimeout)
			obj.converged <- true
			continue
		}

		// do all our event sending all together to avoid duplicate msgs
		if send {
			send = false

			obj.Process(obj) // XXX: rename this function
		}
	}
}

func (obj *NoopType) StateOK() bool {
	return true // never needs updating
}

func (obj *NoopType) Apply() bool {
	log.Printf("%v[%v]: Apply", obj.GetType(), obj.GetName())
	return true
}

func (obj *NoopType) Compare(typ Type) bool {
	switch typ.(type) {
	// we can only compare NoopType to others of the same type
	case *NoopType:
		typ := typ.(*NoopType)
		if obj.Name != typ.Name {
			return false
		}
	default:
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package onecache

import (
	"errors"
	"time"
)

const (
	EXPIRES_DEFAULT = time.Duration(0)
	EXPIRES_FOREVER = time.Duration(-1)
)

var (
	ErrCacheMiss         = errors.New("Key not found")
	ErrCacheNotStored    = errors.New("Data not stored")
	ErrCacheNotSupported = errors.New("Operation not supported")
)

//identifes a cached piece of data
type Item struct {
	ExpiresAt time.Time
	Data      interface{}
}

//Interface for all onecache store implementations
type Store interface {
	Set(key string, data interface{}, expires time.Duration) error
	Get(key string) (interface{}, error)
	Delete(key string) error
	Flush() error
}
<commit_msg>Extended the store interface plus introduced error constants for the new methods<commit_after>package onecache

import (
	"errors"
	"time"
)

const (
	EXPIRES_DEFAULT = time.Duration(0)
	EXPIRES_FOREVER = time.Duration(-1)
)

var (
	ErrCacheMiss                  = errors.New("Key not found")
	ErrCacheNotStored             = errors.New("Data not stored")
	ErrCacheNotSupported          = errors.New("Operation not supported")
	errCacheDataIntegerOperation  = errors.New("Data isn't an integer type")
	ErrCacheDataCannotBeIncreased = errCacheDataIntegerOperation
	ErrCacheDataCannotBeDecreased = errCacheDataIntegerOperation
)

//identifes a cached piece of data
type Item struct {
	ExpiresAt time.Time
	Data      interface{}
}

//Interface for all onecache store implementations
type Store interface {
	Set(key string, data interface{}, expires time.Duration) error
	Get(key string) (interface{}, error)
	Delete(key string) error
	Flush() error
	Increment(key string, steps int) error
	Decrement(key string, steps int) error
}
<|endoftext|>


<commit_before>package gotetra

import (
	"github.com/phil-mansfield/gotetra/geom"
)

// Particle represents a single interpolation point on the Lagrangian
// submanifold which all the matter in the simulation is constrained to.
//
// float32s is used only for memory efficiency. All calculations should be done
// with float64s.
type Particle struct {
	Xs geom.Vec
	Vs geom.Vec
	Id int64
}

// Header describes meta-information about the current catalog.
type Header struct {
	Cosmo CosmologyHeader

	Mass       float64 // Mass of one particle
	Count      int64   // Number of particles in catalog
	TotalCount int64   // Number of particles in all catalogs
	CountWidth int64   // Number of particles "on one side": TotalCount^(1/3)

	Idx        int64   // Index of catalog: x-major ordering is used
	GridWidth  int64   // Number of gird cells "on one side"
	Width      float64 // Width of the catalog's bounding box
	TotalWidth float64 // Width of the sim's bounding box
}

type CosmologyHeader struct {
	Z      float64
	OmegaM float64
	OmegaL float64
	H100   float64
}
<commit_msg>Added note about which int and float types are used and why.<commit_after>/*Package gotetra implements a suite of algorithms for computing cosmic field
densities from particle catalogs.

It is worth discussing a quick note on the types used throughout this pacakge.
For storage efficiency purposes, all data structures store data as float32s.
However, whenever possible calculations are done with float64s to improve
accuracy. Additionally, any calculation which is expected to interact with the
fixed-width integers used in catalogs will use int64s, while all other
calculations will use ints.*/
package gotetra

import (
	"github.com/phil-mansfield/gotetra/geom"
)

// Particle represents a single interpolation point on the Lagrangian
// submanifold which all the matter in the simulation is constrained to.
//
// float32s is used only for memory efficiency. All calculations should be done
// with float64s.
type Particle struct {
	Xs geom.Vec
	Vs geom.Vec
	Id int64
}

// Header describes meta-information about the current catalog.
type Header struct {
	Cosmo CosmologyHeader

	Mass       float64 // Mass of one particle
	Count      int64   // Number of particles in catalog
	TotalCount int64   // Number of particles in all catalogs
	CountWidth int64   // Number of particles "on one side": TotalCount^(1/3)

	Idx        int64   // Index of catalog: x-major ordering is used
	GridWidth  int64   // Number of gird cells "on one side"
	Width      float64 // Width of the catalog's bounding box
	TotalWidth float64 // Width of the sim's bounding box
}

type CosmologyHeader struct {
	Z      float64
	OmegaM float64
	OmegaL float64
	H100   float64
}
<|endoftext|>


<commit_before>package main

import ()

type dnsRec struct {
	name string
	ttl int
	recType string
	priority int //priority
	protocol string
	service string
	weight string
	port string
	comment string
	value string // also commonly called target
}

type soaRec struct {
	name string
	ttl int
	const recTyep := "SOA"
	primary string
	contact string
	serial int
	refresh int
	retry int
	expire int
	minimum int
}

type fqdn struct {
	parentPart string
	localPart string
	records []dnsRec
	subdomains []fqdn
}

type zone struct {
	soa soaRec
	defaultTTL int
	tld fqdn
}

// Returns the DNS record in standard zone file format.
func (dnsRec) String() (string) {
	if dnsRec.ttl == 0 {
		switch dnsRec.recType {
		case "A", "AAAA", "NS", "CNAME":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					dnsRec.value
				}, "\t")
		case "MX":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					dnsRec.priority,
					dnsRec.value
				}, "\t")
		case "TXT":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					'"' + dnsRec.value + '"'
				}, "\t")
		}
	}
}

func (*zone) isRec(input []byte) err {

}<commit_msg>pushing changes down before migration<commit_after>package main

import ()

type dnsRec struct {
	name string
	ttl int
	recType string
	priority int //priority
	protocol string
	service string
	weight string
	port string
	comment string
	value string // also commonly called target
}

type soaRec struct {
	name string
	ttl int
	primary string
	contact string
	serial int
	refresh int
	retry int
	expire int
	minimum int
}

type fqdn struct {
	parentPart string
	localPart string
	records []dnsRec
	subdomains []fqdn
}

type zone struct {
	soa soaRec
	defaultTTL int
	tld fqdn
}

// Returns the DNS record in standard zone file format.
func (dnsRec) String() (string) {
	if dnsRec.ttl == 0 {
		switch dnsRec.recType {
		case "A", "AAAA", "NS", "CNAME":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					dnsRec.value
				}, "\t")
		case "MX":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					dnsRec.priority,
					dnsRec.value
				}, "\t")
		case "TXT":
			return strings.Join(
				[]string{
					dnsRec.name,
					"IN",
					dnsRec.type,
					'"' + dnsRec.value + '"'
				}, "\t")
		} else {
		case "A", "AAAA", "NS", "CNAME":
			return strings.Join(
				[]string{
					dnsRec.name,
					string(dnsRec.ttl),
					"IN",
					dnsRec.type,
					dnsRec.value
				}, "\t")
		case "MX":
			return strings.Join(
				[]string{
					dnsRec.name,
					string(dnsRec.ttl),
					"IN",
					dnsRec.type,
					dnsRec.priority,
					dnsRec.value
				}, "\t")
		case "TXT":
			return strings.Join(
				[]string{
					dnsRec.name,
					string(dnsRec.ttl),
					"IN",
					dnsRec.type,
					'"' + dnsRec.value + '"'
				}, "\t")

		}
	}
}

func (*zone) isRec(input []byte) err {

}<|endoftext|>


<commit_before>package tripeg

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

	"github.com/fatih/color"
)

//Hole struct that contains information
//about a hole in the board, its location
//and whether or not it has a peg in it.
type Hole struct {
	Row    int //max of 5
	Col    int //max of 9
	Peg    bool
	Status int
}

const (
	//Dormant short hand for a row/col location that's not involved in a jump move
	Dormant = iota
	//Source shorthand for the source peg row/col for a jump move
	Source
	//Target the empty row/col the source peg will land in for a jump move.
	Target
)

func (b Board) showMove(m, o, t Hole) Board {
	result := Board{}
	result.Rows = b.Rows
	for k, v := range b.Holes {
		b.Holes[k].Status = Dormant
		if v.Row == m.Row && v.Col == m.Col {
			b.Holes[k].Status = Source
		}
		if v.Row == t.Row && v.Col == t.Col {
			b.Holes[k].Status = Target
		}
	}
	result.MoveLog = b.MoveLog
	result.Holes = b.Holes
	return result

}

//Jump from the Board struct type
func (b Board) Jump(m, o Hole) (Board, Hole, error) {
	result := Board{}
	result.SolveMoves = b.SolveMoves
	result.Rows = b.Rows
	thole := Hole{}
	for _, r := range b.Holes {
		result.Holes = append(result.Holes, r)
	}
	if !m.Peg {
		//If there is no peg in the moveHole, no jump possible
		return result, thole, fmt.Errorf("No Peg in move hole %d,%d\n", o.Row, o.Col)
	}
	if !o.Peg {
		//If there is no peg in the overHole, no jump possible
		return result, thole, fmt.Errorf("No Peg in over hole %d,%d\n", o.Row, o.Col)
	}
	rDif := m.Row - o.Row
	cDif := o.Col - m.Col
	if cDif == 0 && rDif == 0 {
		//Holes are the same, not valid
		return result, thole, fmt.Errorf("Jump peg and over hole are the same\n")
	}
	if math.Abs(float64(rDif)) > 1 {
		//You can't jump over more than 1 row horizontally
		return result, thole, fmt.Errorf("Invalid horizonal movement %d\n", rDif)
	}
	if rDif > 0 && math.Abs(float64(cDif)) > 1 {
		//You can't jump over more than 1 col vertically
		return result, thole, fmt.Errorf("Invalid vertical movement %d\n", cDif)
	}
	if rDif == 0 && math.Abs(float64(cDif)) > 2 {
		return result, thole, fmt.Errorf("Invalid horizantal movement %d\n", rDif)
		//You can't jump more than 2 cols horizontally
	}
	targetR := 0
	targetC := 0
	if rDif == 0 {
		//This is a horizontal jump
		targetR = m.Row
	}
	if rDif > 0 {
		targetR = o.Row - 1
		//This is an up jump
	}
	if rDif < 0 {
		targetR = o.Row + 1
		//This is a jump down
	}
	if cDif < 0 {
		x := 1
		if rDif == 0 {
			x = 2
		}
		targetC = o.Col - x
		//This is a jump left
	}
	if cDif > 0 {
		x := 1
		if rDif == 0 {
			x = 2
		}
		targetC = o.Col + x
		//This is a jump right
	}
	targetHole, err := b.GetHole(targetR, targetC)
	if err != nil {
		return result, thole, fmt.Errorf("Target hole(%d,%d) does not exist\n", targetR, targetC)
	}
	if targetHole.Peg {
		return result, thole, fmt.Errorf("Target hole(%d,%d) has a peg in it\n", targetHole.Row, targetHole.Col)
	}
	for k, bh := range result.Holes {
		if bh.Row == m.Row && bh.Col == m.Col {
			result.Holes[k].Peg = false
		}
		if bh.Row == o.Row && bh.Col == o.Col {
			result.Holes[k].Peg = false
		}
		if bh.Row == targetHole.Row && bh.Col == targetHole.Col {
			result.Holes[k].Peg = true
		}
	}
	return result, targetHole, nil
}

//Board contains all the holes that contain the pegs
type Board struct {
	Holes      []Hole
	MoveLog    []string //TODO: Remove the movelog.
	MoveChart  []string
	SolveMoves int
	Rows       int
}

//GetHole gets a pointer to a hole based on the row,col coordinates
func (b Board) GetHole(r, c int) (Hole, error) {
	if r < 0 || r > b.Rows+1 || c < 0 || c > b.Rows+(b.Rows-1) {
		return Hole{}, fmt.Errorf("Hole %d,%d does not exist\n", r, c)
	}
	for _, v := range b.Holes {
		if v.Col == c && v.Row == r {
			return v, nil
		}
	}
	return Hole{}, fmt.Errorf("Hole %d,%d does not exist\n", r, c)
}

//BuildBoard makes a board of peg holes.
//All holes have a peg except one.
func BuildBoard(rows, empty int) (Board, error) {
	var b Board
	if rows < 5 {
		return b, fmt.Errorf("Invalid rows valid %d, it must be greater than 4\n", rows)
	}
	if rows > 6 {
		return b, fmt.Errorf("We're going to need a better algorithm before we get to %d... rows\n", rows)
	}
	max := 0
	for i := 1; i < rows+1; i++ {
		max += i
	}
	b.SolveMoves = max - 2
	b.Rows = rows

	if empty < 0 || empty > max {
		return b, fmt.Errorf("1st parameter must be >=0 or <=%d, you supplied %d", empty, max)
	}
	s2 := rand.NewSource(time.Now().UnixNano())
	r2 := rand.New(s2)
	if empty == 0 {
		empty = r2.Intn(max)
	} else {
		empty--
	}
	for r := 1; r < rows+1; r++ {
		for c := 1; c < r+1; c++ {
			offset := 1
			col := rows + (c * 2) - offset - r
			h := Hole{Row: r, Col: col, Peg: true}
			if empty == len(b.Holes) {
				h.Peg = false
			}
			b.Holes = append(b.Holes, h)
		}
	}
	return b, nil
}

type move struct {
	H Hole
	O Hole
	T Hole
}

func (m move) String() string {
	return fmt.Sprintf("[%d,%d] over [%d,%d] to [%d,%d]", m.H.Row, m.H.Col, m.O.Row, m.O.Col, m.T.Row, m.T.Col)
}

//ErrorArray an array of errors that also implements the error interface
type ErrorArray struct {
	Errors []error
}

func (ea ErrorArray) Error() string {
	r := ""
	m := len(ea.Errors)
	c := m
	if m > 11 {
		m = 11
		ea.Errors[10] = fmt.Errorf("Too many errors! Count: %v", c-1)
	}
	for _, v := range ea.Errors[0:m] {
		r += v.Error() + "\n"
	}
	return r[0 : len(r)-1]
}

//Add takes an argument of the error interface and adds it to the array
func (ea *ErrorArray) Add(err error) {
	ea.Errors = append(ea.Errors, err)
}

//Solve does a brute force solving of the game
func (b *Board) Solve() []error {
	high := 0
	s2 := rand.NewSource(time.Now().UnixNano())
	r2 := rand.New(s2)
	var newBoard = b
	var solved = false
	var solveErrors = ErrorArray{}
	validMove := 0
	for {
		func() {
			aMoves := []move{}
			o := Hole{}
			var err error
			for _, v := range newBoard.Holes {
				/*
					Go through all of the holes on the board.
					If the hole doesn't have a peg, it can't
					have a legal move, so skip it.
					If it doesn't have a peg, just to see if it has
					a legal move by jumping left, right, up left, up right, down left or down right.
					If any of these moves are legal, add it to the array of available moves.
					Do this for each hole on the board.
					Randomly select a legal move, color the board and return the new color coded board.
					Keep doing this until we've done SolveMoves legal moves or we run out of availaable moves.
					If no legal moves left, start over and hope for the best.
					If SolveMoves legal moves, then we've solved it, return out of here.
				*/
				if v.Peg {
					//upleft
					o, err = newBoard.GetHole(v.Row-1, v.Col-1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//upright
					o, err = newBoard.GetHole(v.Row-1, v.Col+1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//left
					o, err = newBoard.GetHole(v.Row, v.Col-2)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}
					//right
					o, err = newBoard.GetHole(v.Row, v.Col+2)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//downleft
					o, err = newBoard.GetHole(v.Row+1, v.Col-1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//downright
					o, err = newBoard.GetHole(v.Row+1, v.Col+1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}
				}
			}
			if len(aMoves) == 0 {
				//No legal moves left
				newBoard = b
				validMove = 0
				b.MoveLog = []string{}
				b.MoveChart = []string{}
				return
			}
			available := r2.Intn(len(aMoves))
			avs := aMoves[available].H
			avo := aMoves[available].O
			cBoard, th, errN := newBoard.Jump(avs, avo)
			cBoard.Rows = b.Rows
			if errN != nil {
				solveErrors.Add(errN)
			}
			validMove++
			if validMove > high {
				high = validMove
				// fmt.Println(high)
			}
			b.MoveChart = append(b.MoveChart, fmt.Sprintf("%v", newBoard.showMove(avs, avo, th)))
			b.MoveLog = append(b.MoveLog, fmt.Sprintf("%v", aMoves[available]))

			newBoard = &cBoard
			if validMove == b.SolveMoves {
				solved = true
				return
			}
		}()
		if solved {
			break
		}
	}
	return nil
}

func (b Board) String() string {
	result := "\n"
	tar := color.New(color.FgRed).SprintFunc()
	src := color.New(color.FgGreen).SprintFunc()
	dor := color.New(color.FgWhite).SprintFunc()
	offset := 1
	for r := 1; r < b.Rows+1; r++ {
		for c := 1; c < b.Rows*2+offset; c++ {
			h, err := b.GetHole(r, c)
			mark := " "
			if err == nil {
				mark = "O"
				if h.Peg {
					mark = "*"
				}
			}
			switch h.Status {
			case Source:
				result += fmt.Sprintf("%s", src(mark))
			case Target:
				result += fmt.Sprintf("%s", tar(mark))
			case Dormant:
				result += fmt.Sprintf("%s", dor(mark))
			}
		}
		result += "\n"
	}
	return result
}
<commit_msg>we'll need this later for debug<commit_after>package tripeg

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

	"github.com/fatih/color"
)

//Hole struct that contains information
//about a hole in the board, its location
//and whether or not it has a peg in it.
type Hole struct {
	Row    int //max of 5
	Col    int //max of 9
	Peg    bool
	Status int
}

const (
	//Dormant short hand for a row/col location that's not involved in a jump move
	Dormant = iota
	//Source shorthand for the source peg row/col for a jump move
	Source
	//Target the empty row/col the source peg will land in for a jump move.
	Target
)

func (b Board) showMove(m, o, t Hole) Board {
	result := Board{}
	result.Rows = b.Rows
	for k, v := range b.Holes {
		b.Holes[k].Status = Dormant
		if v.Row == m.Row && v.Col == m.Col {
			b.Holes[k].Status = Source
		}
		if v.Row == t.Row && v.Col == t.Col {
			b.Holes[k].Status = Target
		}
	}
	result.MoveLog = b.MoveLog
	result.Holes = b.Holes
	return result

}

//Jump from the Board struct type
func (b Board) Jump(m, o Hole) (Board, Hole, error) {
	result := Board{}
	result.SolveMoves = b.SolveMoves
	result.Rows = b.Rows
	thole := Hole{}
	for _, r := range b.Holes {
		result.Holes = append(result.Holes, r)
	}
	if !m.Peg {
		//If there is no peg in the moveHole, no jump possible
		return result, thole, fmt.Errorf("No Peg in move hole %d,%d\n", o.Row, o.Col)
	}
	if !o.Peg {
		//If there is no peg in the overHole, no jump possible
		return result, thole, fmt.Errorf("No Peg in over hole %d,%d\n", o.Row, o.Col)
	}
	rDif := m.Row - o.Row
	cDif := o.Col - m.Col
	if cDif == 0 && rDif == 0 {
		//Holes are the same, not valid
		return result, thole, fmt.Errorf("Jump peg and over hole are the same\n")
	}
	if math.Abs(float64(rDif)) > 1 {
		//You can't jump over more than 1 row horizontally
		return result, thole, fmt.Errorf("Invalid horizonal movement %d\n", rDif)
	}
	if rDif > 0 && math.Abs(float64(cDif)) > 1 {
		//You can't jump over more than 1 col vertically
		return result, thole, fmt.Errorf("Invalid vertical movement %d\n", cDif)
	}
	if rDif == 0 && math.Abs(float64(cDif)) > 2 {
		return result, thole, fmt.Errorf("Invalid horizantal movement %d\n", rDif)
		//You can't jump more than 2 cols horizontally
	}
	targetR := 0
	targetC := 0
	if rDif == 0 {
		//This is a horizontal jump
		targetR = m.Row
	}
	if rDif > 0 {
		targetR = o.Row - 1
		//This is an up jump
	}
	if rDif < 0 {
		targetR = o.Row + 1
		//This is a jump down
	}
	if cDif < 0 {
		x := 1
		if rDif == 0 {
			x = 2
		}
		targetC = o.Col - x
		//This is a jump left
	}
	if cDif > 0 {
		x := 1
		if rDif == 0 {
			x = 2
		}
		targetC = o.Col + x
		//This is a jump right
	}
	targetHole, err := b.GetHole(targetR, targetC)
	if err != nil {
		return result, thole, fmt.Errorf("Target hole(%d,%d) does not exist\n", targetR, targetC)
	}
	if targetHole.Peg {
		return result, thole, fmt.Errorf("Target hole(%d,%d) has a peg in it\n", targetHole.Row, targetHole.Col)
	}
	for k, bh := range result.Holes {
		if bh.Row == m.Row && bh.Col == m.Col {
			result.Holes[k].Peg = false
		}
		if bh.Row == o.Row && bh.Col == o.Col {
			result.Holes[k].Peg = false
		}
		if bh.Row == targetHole.Row && bh.Col == targetHole.Col {
			result.Holes[k].Peg = true
		}
	}
	return result, targetHole, nil
}

//Board contains all the holes that contain the pegs
type Board struct {
	Holes      []Hole
	MoveLog    []string //TODO: Remove the movelog.
	MoveChart  []string
	SolveMoves int
	Rows       int
}

//GetHole gets a pointer to a hole based on the row,col coordinates
func (b Board) GetHole(r, c int) (Hole, error) {
	if r < 0 || r > b.Rows+1 || c < 0 || c > b.Rows+(b.Rows-1) {
		return Hole{}, fmt.Errorf("Hole %d,%d does not exist\n", r, c)
	}
	for _, v := range b.Holes {
		if v.Col == c && v.Row == r {
			return v, nil
		}
	}
	return Hole{}, fmt.Errorf("Hole %d,%d does not exist\n", r, c)
}

//BuildBoard makes a board of peg holes.
//All holes have a peg except one.
func BuildBoard(rows, empty int) (Board, error) {
	var b Board
	if rows < 5 {
		return b, fmt.Errorf("Invalid rows valid %d, it must be greater than 4\n", rows)
	}
	if rows > 6 {
		return b, fmt.Errorf("We're going to need a better algorithm before we get to %d... rows\n", rows)
	}
	max := 0
	for i := 1; i < rows+1; i++ {
		max += i
	}
	b.SolveMoves = max - 2
	b.Rows = rows

	if empty < 0 || empty > max {
		return b, fmt.Errorf("1st parameter must be >=0 or <=%d, you supplied %d", empty, max)
	}
	s2 := rand.NewSource(time.Now().UnixNano())
	r2 := rand.New(s2)
	if empty == 0 {
		empty = r2.Intn(max)
	} else {
		empty--
	}
	for r := 1; r < rows+1; r++ {
		for c := 1; c < r+1; c++ {
			offset := 1
			col := rows + (c * 2) - offset - r
			h := Hole{Row: r, Col: col, Peg: true}
			if empty == len(b.Holes) {
				h.Peg = false
			}
			b.Holes = append(b.Holes, h)
		}
	}
	return b, nil
}

type move struct {
	H Hole
	O Hole
	T Hole
}

func (m move) String() string {
	return fmt.Sprintf("[%d,%d] over [%d,%d] to [%d,%d]", m.H.Row, m.H.Col, m.O.Row, m.O.Col, m.T.Row, m.T.Col)
}

//ErrorArray an array of errors that also implements the error interface
type ErrorArray struct {
	Errors []error
}

func (ea ErrorArray) Error() string {
	r := ""
	m := len(ea.Errors)
	c := m
	if m > 11 {
		m = 11
		ea.Errors[10] = fmt.Errorf("Too many errors! Count: %v", c-1)
	}
	for _, v := range ea.Errors[0:m] {
		r += v.Error() + "\n"
	}
	return r[0 : len(r)-1]
}

//Add takes an argument of the error interface and adds it to the array
func (ea *ErrorArray) Add(err error) {
	ea.Errors = append(ea.Errors, err)
}

//Solve does a brute force solving of the game
func (b *Board) Solve() []error {
	high := 0
	s2 := rand.NewSource(time.Now().UnixNano())
	r2 := rand.New(s2)
	var newBoard = b
	var solved = false
	var solveErrors = ErrorArray{}
	validMove := 0
	for {
		func() {
			aMoves := []move{}
			o := Hole{}
			var err error
			for _, v := range newBoard.Holes {
				/*
					Go through all of the holes on the board.
					If the hole doesn't have a peg, it can't
					have a legal move, so skip it.
					If it doesn't have a peg, just to see if it has
					a legal move by jumping left, right, up left, up right, down left or down right.
					If any of these moves are legal, add it to the array of available moves.
					Do this for each hole on the board.
					Randomly select a legal move, color the board and return the new color coded board.
					Keep doing this until we've done SolveMoves legal moves or we run out of availaable moves.
					If no legal moves left, start over and hope for the best.
					If SolveMoves legal moves, then we've solved it, return out of here.
				*/
				if v.Peg {
					//upleft
					o, err = newBoard.GetHole(v.Row-1, v.Col-1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//upright
					o, err = newBoard.GetHole(v.Row-1, v.Col+1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//left
					o, err = newBoard.GetHole(v.Row, v.Col-2)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}
					//right
					o, err = newBoard.GetHole(v.Row, v.Col+2)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//downleft
					o, err = newBoard.GetHole(v.Row+1, v.Col-1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}

					//downright
					o, err = newBoard.GetHole(v.Row+1, v.Col+1)
					if err == nil {
						_, t, errJ := newBoard.Jump(v, o)
						if errJ == nil {
							aMoves = append(aMoves, move{H: v, O: o, T: t})
						}
					}
				}
			}
			if len(aMoves) == 0 {
				//No legal moves left
				newBoard = b
				validMove = 0
				b.MoveLog = []string{}
				b.MoveChart = []string{}
				return
			}
			available := r2.Intn(len(aMoves))
			avs := aMoves[available].H
			avo := aMoves[available].O
			cBoard, th, errN := newBoard.Jump(avs, avo)
			cBoard.Rows = b.Rows
			if errN != nil {
				solveErrors.Add(errN)
			}
			validMove++
			if validMove > high {
				high = validMove
				//fmt.Println(b.SolveMoves, high, b.SolveMoves-high)
			}
			b.MoveChart = append(b.MoveChart, fmt.Sprintf("%v", newBoard.showMove(avs, avo, th)))
			b.MoveLog = append(b.MoveLog, fmt.Sprintf("%v", aMoves[available]))

			newBoard = &cBoard
			if validMove == b.SolveMoves {
				solved = true
				return
			}
		}()
		if solved {
			break
		}
	}
	return nil
}

func (b Board) String() string {
	result := "\n"
	tar := color.New(color.FgRed).SprintFunc()
	src := color.New(color.FgGreen).SprintFunc()
	dor := color.New(color.FgWhite).SprintFunc()
	offset := 1
	for r := 1; r < b.Rows+1; r++ {
		for c := 1; c < b.Rows*2+offset; c++ {
			h, err := b.GetHole(r, c)
			mark := " "
			if err == nil {
				mark = "O"
				if h.Peg {
					mark = "*"
				}
			}
			switch h.Status {
			case Source:
				result += fmt.Sprintf("%s", src(mark))
			case Target:
				result += fmt.Sprintf("%s", tar(mark))
			case Dormant:
				result += fmt.Sprintf("%s", dor(mark))
			}
		}
		result += "\n"
	}
	return result
}
<|endoftext|>


<commit_before>package skiplist

import (
	"fmt"
	"math/rand"
	"runtime"
	"strings"
	"testing"
)

//
// Utility functions
//

func less(a, b interface{}) bool {
	return a.(int) < b.(int)
}

func shuffleRange(min, max int) []int {
	a := make ([]int, max - min + 1)
	for i := range(a) {
		a[i] = min+i
	}
	for i := range(a) {
		other := rand.Intn(max-min+1)
		a[i], a[other] = a[other], a[i]
	}
	return a
}

func skiplist(min, max int) *Skiplist {
	s := New(less, nil)
	for _, v := range shuffleRange(min,max) {
		s.Insert (v, 2*v)
	}
	return s
}

//
// Benchmarks, examples, and Tests
//

func TestSkiplist(t *testing.T) {
	s := skiplist(1, 20)
	i := 1
	for e := s.Front(); e != nil; e = e.Next() {
		if e.Key().(int) != i || e.Value.(int) != 2*i {
			t.Fail()
		}
		i++
	}
}

func TestElement_Key(t *testing.T) {
	e := skiplist(1,3).Front()
	for i := 1; i<=3; i++ {
		if e == nil || e.Key().(int) != i {
			t.Fail()
		}
		e = e.Next()
	}
}

func ExampleElement_Next() {
	s := New(less, nil).Insert(0, 0).Insert(1, 2).Insert(2, 4).Insert(3, 6)
	for e := s.Front(); e != nil; e = e.Next() {
		fmt.Print(e, " ")
	}
	// Output: 0:0 1:2 2:4 3:6
}

func TestElement_String(t *testing.T) {
	if fmt.Sprint(skiplist(1,2).Front()) != "1:2" {
		t.Fail()
	}
}

func TestNew(t *testing.T) {
	// Verify the injected random number generator is used.
	s := New(less, nil)
	s1 := New(less, rand.New(rand.NewSource(1)))
	s42 := New(less, rand.New(rand.NewSource(42)))
	for i:=0; i<32; i++ {
		s.Insert(i,i)
		s1.Insert(i,i)
		s42.Insert(i,i)
	}
	v := s.Visualization()
	v1 := s1.Visualization()
	v42 := s42.Visualization()
	if v == v1 {
		t.Error("Seed did not change behaviour")
	} else if v != v42 {
		t.Error("Default seed is not 42.")
	}
}

func TestSkiplist_Front(t *testing.T) {
	s := skiplist (1,3)
	if s.Front().Key().(int) != 1 {
		t.Fail()
	}
}

func TestSkiplist_Insert(t *testing.T) {
	if skiplist(1, 10).String() != "{1:2 2:4 3:6 4:8 5:10 6:12 7:14 8:16 9:18 10:20}" {
		t.Fail()
	}
}

func BenchmarkSkiplist_Insert(b *testing.B) {
	b.StopTimer()
	s := New(less, nil)
	runtime.GC()
	b.StartTimer()
	for i:=0; i<b.N; i++ {
		s.Insert(i,i)
	}
}

func TestSkiplist_Remove(t *testing.T) {
	s := skiplist(0,10)
	if s.Remove(-1) != nil || s.Remove(11) != nil {
		t.Error("Removing nonexistant key should fail.")
	}
	for i:= range shuffleRange(0,10) {
		e := s.Remove(i)
		if e == nil {
			t.Error("nil")
		}
		if e.Key().(int) != i {
			t.Error("bad key")
		}
		if e.Value.(int) != 2*i {
			t.Error("bad value")
		}
	}
	if s.Len() != 0 {
		t.Error("nonzero len")
	}
}

func BenchmarkSkiplist_Remove(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.Remove(key)
	}
}

func TestSkiplist_RemoveN(t *testing.T) {
	s := skiplist(0,10)
	keys := shuffleRange(0,10)
	cnt := 11
	for _,key := range(keys) {
		found, pos := s.Find(key)
		t.Logf("Removing key=%v at pos=%v", key, pos)
		t.Log(key, found, pos)
		t.Log("\n" + s.Visualization())
		e := s.RemoveN(pos)
		if e == nil {
			t.Error("nil returned")
		} else if found != e {
			t.Error("Wrong removed")
		} else if e.Key().(int) != key {
			t.Error("bad Key()")
		} else if e.Value.(int) != 2*key {
			t.Error("bad Value")
		}
		cnt--
		l := s.Len()
		if l != cnt {
			t.Error ("bad Len()=", l, "!=", cnt)
		}
	}
}

func BenchmarkSkiplist_RemoveN(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.RemoveN(key)
	}
}

func TestSkiplist_Find(t *testing.T) {
	s := skiplist(0, 9)
	for i := s.Len()-1; i>=0; i-- {
		e, pos := s.Find(i)
		if e == nil {
			t.Error("nil")
		} else if e != s.FindN(pos) {
			t.Error("bad pos")
		} else if e.Key().(int) != i {
			t.Error("bad Key")
		} else if e.Value.(int) != 2*i {
			t.Error ("bad Value")
		}
	}
}

func TestSkiplist_Len(t *testing.T) {
	s := skiplist(0, 4)
	if s.Len() != 5 {
		t.Fail()
	}
}

func TestSkiplist_FindN(t *testing.T) {
	s := skiplist(0, 9)
	for i := s.Len()-1; i>=0; i-- {
		e := s.FindN(i)
		if e == nil {
			t.Error("nil")
		} else if e.Key().(int) != i {
			t.Error("bad Key")
		} else if e.Value.(int) != 2*i {
			t.Error ("bad Value")
		}
	}
}

func ExampleSkiplist_String() {
	skip := New(less, nil).Insert(1, 10).Insert(2, 20).Insert(3, 30)
	fmt.Println(skip)
	// Output: {1:10 2:20 3:30}
}

func ExampleVisualization() {
	s := New(less, nil)
	for i := 0; i < 64; i++ {
		s.Insert(i, i)
	}
	fmt.Println(s.Visualization())
	// Output:
	// L6 ---------------------------------------------------------------->
	// L5 ---------------------------------------------------->----------->
	// L4 -------------------------->------------------------->----------->
	// L3 -------------->----------->---->---->---------->---->->--------->
	// L2 --->--->--->-->----->->--->>->->->-->-->----->->---->->--------->
	// L1 --->--->--->>->>>>-->>>>-->>->->>>>->>>>>>--->>>--->>->>>--->-->>
	// L0 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
	//    0000000000000000111111111111111122222222222222223333333333333333
	//    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
}

func arrow(cnt int) (s string) {
	switch {
	case cnt > 1:
		return strings.Repeat("-", cnt-1) + ">"
	case cnt == 1:
		return ">"
	}
	return "X"
}

func (l *Skiplist) Visualization() (s string) {
	for level := len(l.links) - 1; level >= 0; level-- {
		s += fmt.Sprintf("L%d ", level)
		w := l.links[level].width
		s += arrow(w)
		for n := l.links[level].to; n != nil; n = n.links[level].to {
			w = n.links[level].width
			s += arrow(w)
		}
		s += "\n"
	}
	s += "   "
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s += fmt.Sprintf("%x", n.key.(int)>>4&0xf)
	}
	s += "\n   "
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s += fmt.Sprintf("%x", n.key.(int)&0xf)
	}
	return string(s)
}
<commit_msg>Add Benchmarks for Find (2754 ns/op) and FindN (1592 ns/op)<commit_after>package skiplist

import (
	"fmt"
	"math/rand"
	"runtime"
	"strings"
	"testing"
)

//
// Utility functions
//

func less(a, b interface{}) bool {
	return a.(int) < b.(int)
}

func shuffleRange(min, max int) []int {
	a := make ([]int, max - min + 1)
	for i := range(a) {
		a[i] = min+i
	}
	for i := range(a) {
		other := rand.Intn(max-min+1)
		a[i], a[other] = a[other], a[i]
	}
	return a
}

func skiplist(min, max int) *Skiplist {
	s := New(less, nil)
	for _, v := range shuffleRange(min,max) {
		s.Insert (v, 2*v)
	}
	return s
}

//
// Benchmarks, examples, and Tests
//

func TestSkiplist(t *testing.T) {
	s := skiplist(1, 20)
	i := 1
	for e := s.Front(); e != nil; e = e.Next() {
		if e.Key().(int) != i || e.Value.(int) != 2*i {
			t.Fail()
		}
		i++
	}
}

func TestElement_Key(t *testing.T) {
	e := skiplist(1,3).Front()
	for i := 1; i<=3; i++ {
		if e == nil || e.Key().(int) != i {
			t.Fail()
		}
		e = e.Next()
	}
}

func ExampleElement_Next() {
	s := New(less, nil).Insert(0, 0).Insert(1, 2).Insert(2, 4).Insert(3, 6)
	for e := s.Front(); e != nil; e = e.Next() {
		fmt.Print(e, " ")
	}
	// Output: 0:0 1:2 2:4 3:6
}

func TestElement_String(t *testing.T) {
	if fmt.Sprint(skiplist(1,2).Front()) != "1:2" {
		t.Fail()
	}
}

func TestNew(t *testing.T) {
	// Verify the injected random number generator is used.
	s := New(less, nil)
	s1 := New(less, rand.New(rand.NewSource(1)))
	s42 := New(less, rand.New(rand.NewSource(42)))
	for i:=0; i<32; i++ {
		s.Insert(i,i)
		s1.Insert(i,i)
		s42.Insert(i,i)
	}
	v := s.Visualization()
	v1 := s1.Visualization()
	v42 := s42.Visualization()
	if v == v1 {
		t.Error("Seed did not change behaviour")
	} else if v != v42 {
		t.Error("Default seed is not 42.")
	}
}

func TestSkiplist_Front(t *testing.T) {
	s := skiplist (1,3)
	if s.Front().Key().(int) != 1 {
		t.Fail()
	}
}

func TestSkiplist_Insert(t *testing.T) {
	if skiplist(1, 10).String() != "{1:2 2:4 3:6 4:8 5:10 6:12 7:14 8:16 9:18 10:20}" {
		t.Fail()
	}
}

func BenchmarkSkiplist_Insert(b *testing.B) {
	b.StopTimer()
	s := New(less, nil)
	runtime.GC()
	b.StartTimer()
	for i:=0; i<b.N; i++ {
		s.Insert(i,i)
	}
}

func TestSkiplist_Remove(t *testing.T) {
	s := skiplist(0,10)
	if s.Remove(-1) != nil || s.Remove(11) != nil {
		t.Error("Removing nonexistant key should fail.")
	}
	for i:= range shuffleRange(0,10) {
		e := s.Remove(i)
		if e == nil {
			t.Error("nil")
		}
		if e.Key().(int) != i {
			t.Error("bad key")
		}
		if e.Value.(int) != 2*i {
			t.Error("bad value")
		}
	}
	if s.Len() != 0 {
		t.Error("nonzero len")
	}
}

func BenchmarkSkiplist_Remove(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.Remove(key)
	}
}

func TestSkiplist_RemoveN(t *testing.T) {
	s := skiplist(0,10)
	keys := shuffleRange(0,10)
	cnt := 11
	for _,key := range(keys) {
		found, pos := s.Find(key)
		t.Logf("Removing key=%v at pos=%v", key, pos)
		t.Log(key, found, pos)
		t.Log("\n" + s.Visualization())
		e := s.RemoveN(pos)
		if e == nil {
			t.Error("nil returned")
		} else if found != e {
			t.Error("Wrong removed")
		} else if e.Key().(int) != key {
			t.Error("bad Key()")
		} else if e.Value.(int) != 2*key {
			t.Error("bad Value")
		}
		cnt--
		l := s.Len()
		if l != cnt {
			t.Error ("bad Len()=", l, "!=", cnt)
		}
	}
}

func BenchmarkSkiplist_RemoveN(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.RemoveN(key)
	}
}

func TestSkiplist_Find(t *testing.T) {
	s := skiplist(0, 9)
	for i := s.Len()-1; i>=0; i-- {
		e, pos := s.Find(i)
		if e == nil {
			t.Error("nil")
		} else if e != s.FindN(pos) {
			t.Error("bad pos")
		} else if e.Key().(int) != i {
			t.Error("bad Key")
		} else if e.Value.(int) != 2*i {
			t.Error ("bad Value")
		}
	}
}

func BenchmarkSkiplist_FindN(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.FindN(key)
	}
}

func TestSkiplist_Len(t *testing.T) {
	s := skiplist(0, 4)
	if s.Len() != 5 {
		t.Fail()
	}
}

func TestSkiplist_FindN(t *testing.T) {
	s := skiplist(0, 9)
	for i := s.Len()-1; i>=0; i-- {
		e := s.FindN(i)
		if e == nil {
			t.Error("nil")
		} else if e.Key().(int) != i {
			t.Error("bad Key")
		} else if e.Value.(int) != 2*i {
			t.Error ("bad Value")
		}
	}
}

func BenchmarkSkiplist_Find(b *testing.B) {
	b.StopTimer()
	a := shuffleRange (0, b.N-1)
	s := skiplist(0, b.N-1)
	runtime.GC()
	b.StartTimer()
	for _, key := range a {
		s.Find(key)
	}
}

func ExampleSkiplist_String() {
	skip := New(less, nil).Insert(1, 10).Insert(2, 20).Insert(3, 30)
	fmt.Println(skip)
	// Output: {1:10 2:20 3:30}
}

func ExampleVisualization() {
	s := New(less, nil)
	for i := 0; i < 64; i++ {
		s.Insert(i, i)
	}
	fmt.Println(s.Visualization())
	// Output:
	// L6 ---------------------------------------------------------------->
	// L5 ---------------------------------------------------->----------->
	// L4 -------------------------->------------------------->----------->
	// L3 -------------->----------->---->---->---------->---->->--------->
	// L2 --->--->--->-->----->->--->>->->->-->-->----->->---->->--------->
	// L1 --->--->--->>->>>>-->>>>-->>->->>>>->>>>>>--->>>--->>->>>--->-->>
	// L0 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
	//    0000000000000000111111111111111122222222222222223333333333333333
	//    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
}

func arrow(cnt int) (s string) {
	switch {
	case cnt > 1:
		return strings.Repeat("-", cnt-1) + ">"
	case cnt == 1:
		return ">"
	}
	return "X"
}

func (l *Skiplist) Visualization() (s string) {
	for level := len(l.links) - 1; level >= 0; level-- {
		s += fmt.Sprintf("L%d ", level)
		w := l.links[level].width
		s += arrow(w)
		for n := l.links[level].to; n != nil; n = n.links[level].to {
			w = n.links[level].width
			s += arrow(w)
		}
		s += "\n"
	}
	s += "   "
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s += fmt.Sprintf("%x", n.key.(int)>>4&0xf)
	}
	s += "\n   "
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s += fmt.Sprintf("%x", n.key.(int)&0xf)
	}
	return string(s)
}
<|endoftext|>


<commit_before><commit_msg>use generated names for all resources in GFR ILB test (#841)<commit_after><|endoftext|>


<commit_before>package slackapi

import (
	"encoding/json"
	"testing"
)

func CheckResponse(t *testing.T, x interface{}, y string) {
	out, err := json.Marshal(x)
	if err != nil {
		t.Fatal("json fromat;", err)
	}
	if string(out) != y {
		t.Fatalf("invalid json response;\n- %s\n+ %s\n", y, out)
	}
}

func TestAPITest(t *testing.T) {
	s := New()
	x := s.APITest()
	y := `{"ok":true}`
	CheckResponse(t, x, y)
}

func TestAppsList(t *testing.T) {
	s := New()
	x := s.AppsList()
	y := `{"ok":false,"error":"not_authed","apps":null,"cache_ts":""}`
	CheckResponse(t, x, y)
}

func TestAuthRevoke(t *testing.T) {
	s := New()
	x := s.AuthRevoke()
	y := `{"ok":false,"error":"not_authed","revoked":false}`
	CheckResponse(t, x, y)
}

func TestAuthTest(t *testing.T) {
	s := New()
	x, err := s.AuthTest()
	if err != nil {
		t.Fatal(err)
	}
	y := `{"ok":false,"error":"not_authed","team":"","team_id":"","url":"","user":"","user_id":""}`
	CheckResponse(t, x, y)
}

func TestBotsInfo(t *testing.T) {
	s := New()
	x := s.BotsInfo("user")
	y := `{"ok":false,"error":"not_authed","bot":{"id":"","deleted":false,"name":"","icons":null}}`
	CheckResponse(t, x, y)
}

func TestChannelsID(t *testing.T) {
	s := New()
	x := s.ChannelsID("channel")
	y := `"channel"`
	CheckResponse(t, x, y)
}

func TestChannelsMyHistory(t *testing.T) {
	s := New()
	x := s.ChannelsMyHistory("channel", "1234567890")
	y := `{"Filtered":0,"Latest":"","Messages":null,"Oldest":"","Total":0,"Username":""}`
	CheckResponse(t, x, y)
}

func TestChannelsPurgeHistory(t *testing.T) {
	s := New()
	x := s.ChannelsPurgeHistory("channel", "1234567890", true)
	y := `{"Deleted":0,"NotDeleted":0,"Messages":null}`
	CheckResponse(t, x, y)
}

func TestChannelsSetRetention(t *testing.T) {
	s := New()
	x := s.ChannelsSetRetention("channel", 1)
	y := `{"ok":false,"error":"not_authed"}`
	CheckResponse(t, x, y)
}

func TestChannelsSuggestions(t *testing.T) {
	s := New()
	x := s.ChannelsSuggestions()
	y := `{"ok":false,"error":"not_authed","status":{"ok":false},"suggestion_types_tried":null}`
	CheckResponse(t, x, y)
}

func TestChatDelete(t *testing.T) {
	s := New()
	x := s.ChatDelete(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","text":"","ts":""}`
	CheckResponse(t, x, y)
}

func TestChatMeMessage(t *testing.T) {
	s := New()
	x := s.ChatMeMessage(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","text":"","ts":""}`
	CheckResponse(t, x, y)
}

func TestChatPostMessage(t *testing.T) {
	s := New()
	x := s.ChatPostMessage(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","ts":"","message":{"display_as_bot":false}}`
	CheckResponse(t, x, y)
}

func TestChatUpdate(t *testing.T) {
	s := New()
	x := s.ChatUpdate(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","ts":"","message":{"display_as_bot":false}}`
	CheckResponse(t, x, y)
}
<commit_msg>Remove chat.update unit test due to API uncertanties<commit_after>package slackapi

import (
	"encoding/json"
	"testing"
)

func CheckResponse(t *testing.T, x interface{}, y string) {
	out, err := json.Marshal(x)
	if err != nil {
		t.Fatal("json fromat;", err)
	}
	if string(out) != y {
		t.Fatalf("invalid json response;\n- %s\n+ %s\n", y, out)
	}
}

func TestAPITest(t *testing.T) {
	s := New()
	x := s.APITest()
	y := `{"ok":true}`
	CheckResponse(t, x, y)
}

func TestAppsList(t *testing.T) {
	s := New()
	x := s.AppsList()
	y := `{"ok":false,"error":"not_authed","apps":null,"cache_ts":""}`
	CheckResponse(t, x, y)
}

func TestAuthRevoke(t *testing.T) {
	s := New()
	x := s.AuthRevoke()
	y := `{"ok":false,"error":"not_authed","revoked":false}`
	CheckResponse(t, x, y)
}

func TestAuthTest(t *testing.T) {
	s := New()
	x, err := s.AuthTest()
	if err != nil {
		t.Fatal(err)
	}
	y := `{"ok":false,"error":"not_authed","team":"","team_id":"","url":"","user":"","user_id":""}`
	CheckResponse(t, x, y)
}

func TestBotsInfo(t *testing.T) {
	s := New()
	x := s.BotsInfo("user")
	y := `{"ok":false,"error":"not_authed","bot":{"id":"","deleted":false,"name":"","icons":null}}`
	CheckResponse(t, x, y)
}

func TestChannelsID(t *testing.T) {
	s := New()
	x := s.ChannelsID("channel")
	y := `"channel"`
	CheckResponse(t, x, y)
}

func TestChannelsMyHistory(t *testing.T) {
	s := New()
	x := s.ChannelsMyHistory("channel", "1234567890")
	y := `{"Filtered":0,"Latest":"","Messages":null,"Oldest":"","Total":0,"Username":""}`
	CheckResponse(t, x, y)
}

func TestChannelsPurgeHistory(t *testing.T) {
	s := New()
	x := s.ChannelsPurgeHistory("channel", "1234567890", true)
	y := `{"Deleted":0,"NotDeleted":0,"Messages":null}`
	CheckResponse(t, x, y)
}

func TestChannelsSetRetention(t *testing.T) {
	s := New()
	x := s.ChannelsSetRetention("channel", 1)
	y := `{"ok":false,"error":"not_authed"}`
	CheckResponse(t, x, y)
}

func TestChannelsSuggestions(t *testing.T) {
	s := New()
	x := s.ChannelsSuggestions()
	y := `{"ok":false,"error":"not_authed","status":{"ok":false},"suggestion_types_tried":null}`
	CheckResponse(t, x, y)
}

func TestChatDelete(t *testing.T) {
	s := New()
	x := s.ChatDelete(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","text":"","ts":""}`
	CheckResponse(t, x, y)
}

func TestChatMeMessage(t *testing.T) {
	s := New()
	x := s.ChatMeMessage(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","text":"","ts":""}`
	CheckResponse(t, x, y)
}

func TestChatPostMessage(t *testing.T) {
	s := New()
	x := s.ChatPostMessage(MessageArgs{})
	y := `{"ok":false,"error":"not_authed","channel":"","ts":"","message":{"display_as_bot":false}}`
	CheckResponse(t, x, y)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"net"
	"strconv"
	"time"
)

const (
	SERVER_PORT = 1080
)

const (
	READ_DEADLINE  = time.Minute
	WRITE_DEADLINE = 2 * time.Minute
)

func handleRequest(conn net.Conn) {
	if conn == nil {
		return
	}
	defer conn.Close()
	conn.SetReadDeadline(time.Now().Add(READ_DEADLINE))
	conn.SetWriteDeadline(time.Now().Add(WRITE_DEADLINE))

	var b [1024]byte
	if _, err := conn.Read(b[:]); err != nil {
		log.Println("conn read err:", err.Error())
		return
	}

	// only handle socks5 protocol
	if b[0] != 0x05 {
		log.Println("server do not support client version:", b[0])
		return
	}

	if _, err := conn.Write([]byte{0x05, 0x00}); err != nil {
		log.Println("client cannot arrived, err:", err.Error())
		return
	}

	n, err := conn.Read(b[:])
	if err != nil {
		log.Println("conn read err:", err.Error())
		return
	}
	if b[0] != 0x05 || b[1] != 0x01 || b[2] != 0x00 {
		log.Println("client cmd param is not supported:", b[0], b[1], b[2])
		return
	}

	var targetHost, targetPort string
	switch b[3] {
	case 0x01: // ipv4
		targetHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
	case 0x03:
		targetHost = string(b[5 : n-2])
	case 0x04:
		targetHost = net.IP(b[4:20]).String()
	}
	targetPort = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))

	targetConn, err := net.Dial("tcp", net.JoinHostPort(targetHost, targetPort))
	if err != nil {
		log.Printf("net dial host:%v, port:%v, err:%v\n", targetHost, targetPort, err)
		return
	}
	defer targetConn.Close()

	if _, err := conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); err != nil {
		log.Println("client cannot arrived, err:", err.Error())
		return
	}

	go io.Copy(targetConn, conn)
	io.Copy(conn, targetConn)
}

func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", SERVER_PORT))
	if err != nil {
		log.Panic(err)
	}
	log.Println("socks5 server listen on:", SERVER_PORT)

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Println("accept conn err:", err.Error())
			continue
		}

		go handleRequest(conn)
	}
}
<commit_msg>update socks5<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"net"
	"strconv"
	"time"
)

const (
	SERVER_PORT = 1080
	SERVER_ADDR = "nange.me"
)

const (
	READ_DEADLINE  = time.Minute
	WRITE_DEADLINE = 2 * time.Minute
)

func handleRequest(conn net.Conn) {
	if conn == nil {
		return
	}
	defer conn.Close()
	conn.SetReadDeadline(time.Now().Add(READ_DEADLINE))
	conn.SetWriteDeadline(time.Now().Add(WRITE_DEADLINE))

	var b [1024]byte
	if _, err := conn.Read(b[:]); err != nil {
		log.Println("conn read err:", err.Error())
		return
	}

	// only handle socks5 protocol
	if b[0] != 0x05 {
		log.Println("server do not support client version:", b[0])
		return
	}

	if _, err := conn.Write([]byte{0x05, 0x00}); err != nil {
		log.Println("client cannot arrived, err:", err.Error())
		return
	}

	n, err := conn.Read(b[:])
	if err != nil {
		log.Println("conn read err:", err.Error())
		return
	}
	if b[0] != 0x05 || b[1] != 0x01 || b[2] != 0x00 {
		log.Println("client cmd param is not supported:", b[0], b[1], b[2])
		return
	}

	var targetHost, targetPort string
	switch b[3] {
	case 0x01: // ipv4
		targetHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
	case 0x03:
		targetHost = string(b[5 : n-2])
	case 0x04:
		targetHost = net.IP(b[4:20]).String()
	}
	targetPort = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))
	log.Printf("targetHost:%v, targetPort:%v, b[n-2]:%v, b[n-1]:%v\n", targetHost, targetHost, b[n-2], b[n-1])

	targetConn, err := net.Dial("tcp", net.JoinHostPort(targetHost, targetPort))
	if err != nil {
		log.Printf("net dial host:%v, port:%v, err:%v\n", targetHost, targetPort, err)
		return
	}
	defer targetConn.Close()

	var succ = []byte{0x05, 0x00, 0x00, 0x03, byte(len(SERVER_ADDR))}
	succ = append(succ, SERVER_ADDR[:]...)
	succ = append(succ, b[n-2], b[n-1])
	if _, err := conn.Write(succ); err != nil {
		log.Println("client cannot arrived, err:", err.Error())
		return
	}

	go io.Copy(targetConn, conn)
	io.Copy(conn, targetConn)
}

func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", SERVER_PORT))
	if err != nil {
		log.Panic(err)
	}
	log.Println("socks5 server listen on:", SERVER_PORT)

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Println("accept conn err:", err.Error())
			continue
		}

		go handleRequest(conn)
	}
}
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"unicode"

	"appengine"
	"appengine/datastore"
)

// type ApiResponse is a generic API response struct
type ApiResponse struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Result  interface{} `json:"result"`
}

func GenerateUniqueSlug(ctx appengine.Context, kind string, s string) (slug string) {
	slug = GenerateSlug(s)
	others, err := datastore.NewQuery(kind).
		Filter("Slug = ", slug).
		Count(ctx)
	if err != nil {
		ctx.Errorf("[utils/GenerateUniqueSlug] %v", err.Error())
		return ""
	}
	if others == 0 {
		return slug
	}
	counter := 2
	baseSlug := slug
	for others > 0 {
		slug = fmt.Sprintf("%v-%d", baseSlug, counter)
		others, err = datastore.NewQuery(kind).
			Filter("Slug = ", slug).
			Count(ctx)
		if err != nil {
			ctx.Errorf("[utils/GenerateUniqueSlug] %v", err.Error())
			return ""
		}
		counter = counter + 1
	}
	return slug
}

func GenerateSlug(s string) (slug string) {
	return strings.Map(func(r rune) rune {
		switch {
		case r == ' ', r == '-':
			return '-'
		case r == '_', unicode.IsLetter(r), unicode.IsDigit(r):
			return r
		default:
			return -1
		}
		return -1
	}, strings.ToLower(strings.TrimSpace(s)))
}

func Save(ctx appengine.Context, obj interface{}) (key *datastore.Key, err error) {
	kind, val := reflect.TypeOf(obj), reflect.ValueOf(obj)
	str := val
	if val.Kind().String() == "ptr" {
		kind, str = kind.Elem(), val.Elem()
	}
	if str.Kind().String() != "struct" {
		return nil, errors.New("Must pass a valid object to struct")
	}
	dsKind := getDatastoreKind(kind)
	if bsMethod := val.MethodByName("BeforeSave"); bsMethod.IsValid() {
		bsMethod.Call([]reflect.Value{reflect.ValueOf(ctx)})
	}
	//check for key field first
	keyField := str.FieldByName("Key")
	if keyField.IsValid() {
		keyInterface := keyField.Interface()
		key, _ = keyInterface.(*datastore.Key)
	}
	idField := str.FieldByName("ID")
	if key == nil {
		if idField.IsValid() && idField.Int() != 0 {
			key = datastore.NewKey(ctx, dsKind, "", idField.Int(), nil)
		} else {
			newId, _, err := datastore.AllocateIDs(ctx, dsKind, nil, 1)
			if err == nil {
				idField.SetInt(newId)
				key = datastore.NewKey(ctx, dsKind, "", newId, nil)
			} else {
				ctx.Errorf("Failed to allocate new ID for this user: %v", err.Error())
				key = datastore.NewIncompleteKey(ctx, dsKind, nil)
			}
		}
	}
	//Store in memcache
	key, err = datastore.Put(ctx, key, obj)
	if err != nil {
		ctx.Errorf("[utils/Save]: %v", err.Error())
	} else {
		if keyField.IsValid() {
			keyField.Set(reflect.ValueOf(key))
		}
		if idField.IsValid() {
			idField.SetInt(key.IntID())
		}
		if asMethod := val.MethodByName("AfterSave"); asMethod.IsValid() {
			asMethod.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(key)})
		}
	}
	return
}

// func ExistsInDatastore takes an appengine Context and an interface checks if that interface already exists in datastore
// Will call any 'BeforeSave' method as appropriate, in case that method sets up a 'Key' field, otherwise checks for an ID field
// and assumes that's the datastore IntID
func ExistsInDatastore(ctx appengine.Context, obj interface{}) bool {
	kind, val := reflect.TypeOf(obj), reflect.ValueOf(obj)
	str := val
	if val.Kind().String() == "ptr" {
		kind, str = kind.Elem(), val.Elem()
	}
	if str.Kind().String() != "struct" {
		return false
	}
	dsKind := getDatastoreKind(kind)
	if bsMethod := val.MethodByName("BeforeSave"); bsMethod.IsValid() {
		bsMethod.Call([]reflect.Value{reflect.ValueOf(ctx)})
	}
	var key *datastore.Key
	//check for key field first
	keyField := str.FieldByName("Key")
	if keyField.IsValid() {
		keyInterface := keyField.Interface()
		key, _ = keyInterface.(*datastore.Key)
	}
	idField := str.FieldByName("ID")
	if key == nil {
		if idField.IsValid() && idField.Int() != 0 {
			key = datastore.NewKey(ctx, dsKind, "", idField.Int(), nil)
		}
	}
	if key == nil {
		return false
	}
	err := datastore.Get(ctx, key, obj)
	if err != nil {
		return false
	}
	return true
}

// Takes a reflect kind and returns a valid string value matching that kind
// Strips off any package namespacing, so 'accounts.Account' becomes just 'Account'
func getDatastoreKind(kind reflect.Type) (dsKind string) {
	dsKind = kind.String()
	if li := strings.LastIndex(dsKind, "."); li >= 0 {
		//Format kind to be in a standard format used for datastore
		dsKind = dsKind[li+1:]
	}
	return
}

func InChain(needle string, haystack []string) bool {
	if haystack == nil {
		return false
	}
	for _, straw := range haystack {
		if needle == straw {
			return true
		}
	}
	return false
}
<commit_msg>Hotfix for saving models without ID fields<commit_after>package utils

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"unicode"

	"appengine"
	"appengine/datastore"
)

// type ApiResponse is a generic API response struct
type ApiResponse struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Result  interface{} `json:"result"`
}

func GenerateUniqueSlug(ctx appengine.Context, kind string, s string) (slug string) {
	slug = GenerateSlug(s)
	others, err := datastore.NewQuery(kind).
		Filter("Slug = ", slug).
		Count(ctx)
	if err != nil {
		ctx.Errorf("[utils/GenerateUniqueSlug] %v", err.Error())
		return ""
	}
	if others == 0 {
		return slug
	}
	counter := 2
	baseSlug := slug
	for others > 0 {
		slug = fmt.Sprintf("%v-%d", baseSlug, counter)
		others, err = datastore.NewQuery(kind).
			Filter("Slug = ", slug).
			Count(ctx)
		if err != nil {
			ctx.Errorf("[utils/GenerateUniqueSlug] %v", err.Error())
			return ""
		}
		counter = counter + 1
	}
	return slug
}

func GenerateSlug(s string) (slug string) {
	return strings.Map(func(r rune) rune {
		switch {
		case r == ' ', r == '-':
			return '-'
		case r == '_', unicode.IsLetter(r), unicode.IsDigit(r):
			return r
		default:
			return -1
		}
		return -1
	}, strings.ToLower(strings.TrimSpace(s)))
}

func Save(ctx appengine.Context, obj interface{}) (key *datastore.Key, err error) {
	kind, val := reflect.TypeOf(obj), reflect.ValueOf(obj)
	str := val
	if val.Kind().String() == "ptr" {
		kind, str = kind.Elem(), val.Elem()
	}
	if str.Kind().String() != "struct" {
		return nil, errors.New("Must pass a valid object to struct")
	}
	dsKind := getDatastoreKind(kind)
	if bsMethod := val.MethodByName("BeforeSave"); bsMethod.IsValid() {
		bsMethod.Call([]reflect.Value{reflect.ValueOf(ctx)})
	}
	//check for key field first
	keyField := str.FieldByName("Key")
	if keyField.IsValid() {
		keyInterface := keyField.Interface()
		key, _ = keyInterface.(*datastore.Key)
	}
	idField := str.FieldByName("ID")
	if key == nil {
		if idField.IsValid() && idField.Int() != 0 {
			key = datastore.NewKey(ctx, dsKind, "", idField.Int(), nil)
		} else {
			newId, _, err := datastore.AllocateIDs(ctx, dsKind, nil, 1)
			if err == nil {
				if idField.IsValid() {
					idField.SetInt(newId)
				}
				key = datastore.NewKey(ctx, dsKind, "", newId, nil)
			} else {
				ctx.Errorf("Failed to allocate new ID for this user: %v", err.Error())
				key = datastore.NewIncompleteKey(ctx, dsKind, nil)
			}
		}
	}
	//Store in memcache
	key, err = datastore.Put(ctx, key, obj)
	if err != nil {
		ctx.Errorf("[utils/Save]: %v", err.Error())
	} else {
		if keyField.IsValid() {
			keyField.Set(reflect.ValueOf(key))
		}
		if idField.IsValid() {
			idField.SetInt(key.IntID())
		}
		if asMethod := val.MethodByName("AfterSave"); asMethod.IsValid() {
			asMethod.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(key)})
		}
	}
	return
}

// func ExistsInDatastore takes an appengine Context and an interface checks if that interface already exists in datastore
// Will call any 'BeforeSave' method as appropriate, in case that method sets up a 'Key' field, otherwise checks for an ID field
// and assumes that's the datastore IntID
func ExistsInDatastore(ctx appengine.Context, obj interface{}) bool {
	kind, val := reflect.TypeOf(obj), reflect.ValueOf(obj)
	str := val
	if val.Kind().String() == "ptr" {
		kind, str = kind.Elem(), val.Elem()
	}
	if str.Kind().String() != "struct" {
		return false
	}
	dsKind := getDatastoreKind(kind)
	if bsMethod := val.MethodByName("BeforeSave"); bsMethod.IsValid() {
		bsMethod.Call([]reflect.Value{reflect.ValueOf(ctx)})
	}
	var key *datastore.Key
	//check for key field first
	keyField := str.FieldByName("Key")
	if keyField.IsValid() {
		keyInterface := keyField.Interface()
		key, _ = keyInterface.(*datastore.Key)
	}
	idField := str.FieldByName("ID")
	if key == nil {
		if idField.IsValid() && idField.Int() != 0 {
			key = datastore.NewKey(ctx, dsKind, "", idField.Int(), nil)
		}
	}
	if key == nil {
		return false
	}
	err := datastore.Get(ctx, key, obj)
	if err != nil {
		return false
	}
	return true
}

// Takes a reflect kind and returns a valid string value matching that kind
// Strips off any package namespacing, so 'accounts.Account' becomes just 'Account'
func getDatastoreKind(kind reflect.Type) (dsKind string) {
	dsKind = kind.String()
	if li := strings.LastIndex(dsKind, "."); li >= 0 {
		//Format kind to be in a standard format used for datastore
		dsKind = dsKind[li+1:]
	}
	return
}

func InChain(needle string, haystack []string) bool {
	if haystack == nil {
		return false
	}
	for _, straw := range haystack {
		if needle == straw {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package scipipe

import (
	// "github.com/go-errors/errors"
	//"os"
	"os/exec"
)

func ExecCmd(cmd string) {
	Info.Println("Executing command: ", cmd)
	_, err := exec.Command("bash", "-lc", cmd).Output()
	Check(err)
}

func Check(err error) {
	if err != nil {
		panic(err)
	}
}

// Short-hand function to create a slice of strings
func SS(ss ...string) []string {
	sslice := []string{}
	for _, s := range ss {
		sslice = append(sslice, s)
	}
	return sslice
}

func copyMapStrStr(m map[string]string) (nm map[string]string) {
	nm = make(map[string]string)
	for k, v := range m {
		nm[k] = v
	}
	return nm
}
<commit_msg>Provide output from failed command, on fail<commit_after>package scipipe

import (
	// "github.com/go-errors/errors"
	//"os"
	"os/exec"
)

func ExecCmd(cmd string) {
	Info.Println("Executing command: ", cmd)
	combOutput, err := exec.Command("bash", "-lc", cmd).CombinedOutput()
	if err != nil {
		Error.Println("Could not execute command `" + cmd + "`: " + string(combOutput))
	}
}

func Check(err error) {
	if err != nil {
		panic(err)
	}
}

// Short-hand function to create a slice of strings
func SS(ss ...string) []string {
	sslice := []string{}
	for _, s := range ss {
		sslice = append(sslice, s)
	}
	return sslice
}

func copyMapStrStr(m map[string]string) (nm map[string]string) {
	nm = make(map[string]string)
	for k, v := range m {
		nm[k] = v
	}
	return nm
}
<|endoftext|>


<commit_before>package goutils

import (
	"github.com/yosssi/gocmd"
	"os/exec"
	"reflect"
	"strings"
)

const (
	urlPrefixHttp  string = "http://"
	urlPrefixHttps string = "https://"
)

func StructToMap(data interface{}) map[string]interface{} {
	m := make(map[string]interface{})
	elem := reflect.ValueOf(data).Elem()
	size := elem.NumField()

	for i := 0; i < size; i++ {
		field := elem.Type().Field(i).Name
		value := elem.Field(i).Interface()
		m[field] = value
	}

	return m
}

func GetUrls(s string) []string {
	urls := make([]string, 0)
	tokens := strings.Split(s, " ")
	for _, t := range tokens {
		if strings.HasPrefix(t, urlPrefixHttp) || strings.HasPrefix(t, urlPrefixHttps) {
			urls = append(urls, t)
		}
	}
	return urls
}

func NormalUrl(s string) string {
	output, err := gocmd.Pipe(exec.Command("curl", "-sLI", s), exec.Command("grep", "-E", "Location:|location:"), exec.Command("tail", "-1"))
	if err != nil {
		panic(err)
	}
	result := string(output)
	if result == "" {
		result = s
	} else {
		result = strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(result, "location: "), "Location: "))
	}
	return result
}
<commit_msg>Updated "NormalUrl" method.<commit_after>package goutils

import (
	"fmt"
	"github.com/yosssi/gocmd"
	"os/exec"
	"reflect"
	"strings"
)

const (
	urlPrefixHttp  string = "http://"
	urlPrefixHttps string = "https://"
)

func StructToMap(data interface{}) map[string]interface{} {
	m := make(map[string]interface{})
	elem := reflect.ValueOf(data).Elem()
	size := elem.NumField()

	for i := 0; i < size; i++ {
		field := elem.Type().Field(i).Name
		value := elem.Field(i).Interface()
		m[field] = value
	}

	return m
}

func GetUrls(s string) []string {
	urls := make([]string, 0)
	tokens := strings.Split(s, " ")
	for _, t := range tokens {
		if strings.HasPrefix(t, urlPrefixHttp) || strings.HasPrefix(t, urlPrefixHttps) {
			urls = append(urls, t)
		}
	}
	return urls
}

func NormalUrl(s string) string {
	output, err := gocmd.Pipe(exec.Command("curl", "-sLI", s), exec.Command("grep", "-E", "Location:|location:"), exec.Command("tail", "-1"))
	if err != nil {
		fmt.Println(err.Error())
		return ""
	}
	result := string(output)
	if result == "" {
		result = s
	} else {
		result = strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(result, "location: "), "Location: "))
	}
	return result
}
<|endoftext|>


<commit_before>package bamstats

import (
	"encoding/json"
	"os"

	log "github.com/Sirupsen/logrus"
)

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func max(a, b uint32) uint32 {
	if a < b {
		return b
	}
	return a
}

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

func OutputJson(stats interface{}) {
	b, err := json.MarshalIndent(stats, "", "\t")
	check(err)
	os.Stdout.Write(b)
}
<commit_msg>Add functions to output stats to file<commit_after>package bamstats

import (
	"bufio"
	"encoding/json"
	"io"
	"os"

	log "github.com/Sirupsen/logrus"
)

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func max(a, b uint32) uint32 {
	if a < b {
		return b
	}
	return a
}

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

func OutputJson(writer io.Writer, stats interface{}) {
	b, err := json.MarshalIndent(stats, "", "\t")
	check(err)
	writer.Write(b)
	if w, ok := writer.(*bufio.Writer); ok {
		w.Flush()
	}
}

func NewOutput(output string) io.Writer {
	switch output {
	case "-":
		return os.Stdout
	default:
		f, err := os.Create(output)
		check(err)
		return bufio.NewWriter(f)
	}
}
<|endoftext|>


<commit_before>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	bf "github.com/russross/blackfriday"
	"log"
	"os"
	"fmt"
)

func errhandle(err error) {
	if err == nil {
		return
	}
	panic(err)
	log.Fatalf("ERR %s\n", err)
	os.Exit(1)
}

func out(format string, args... interface{}) {
	fmt.Printf(format, args...)
}

func debug(format string, args...  interface{}) {
	if !*verbose {
		return
	}
	fmt.Printf(format, args...)
}

func SliceStringIndexOf(haystack []string, needle string) int {
	for i, elem := range haystack {
		if elem == needle {
			return i
		}
	}
	return -1
}

func Markdown(source string) string {
	// set up the HTML renderer
	flags := 0
	flags |= bf.HTML_USE_SMARTYPANTS
	flags |= bf.HTML_SMARTYPANTS_FRACTIONS
	renderer := bf.HtmlRenderer(flags, "", "")

	// set up the parser
	ext := 0
	ext |= bf.EXTENSION_NO_INTRA_EMPHASIS
	ext |= bf.EXTENSION_TABLES
	ext |= bf.EXTENSION_FENCED_CODE
	ext |= bf.EXTENSION_AUTOLINK
	ext |= bf.EXTENSION_STRIKETHROUGH
	ext |= bf.EXTENSION_LAX_HTML_BLOCKS
	ext |= bf.EXTENSION_SPACE_HEADERS

	return string(bf.Markdown([]byte(source), renderer, ext))
}
<commit_msg>in the end, parsing markdown inside of html blocks is just too weird<commit_after>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	bf "github.com/russross/blackfriday"
	"log"
	"os"
	"fmt"
)

func errhandle(err error) {
	if err == nil {
		return
	}
	panic(err)
	log.Fatalf("ERR %s\n", err)
	os.Exit(1)
}

func out(format string, args... interface{}) {
	fmt.Printf(format, args...)
}

func debug(format string, args...  interface{}) {
	if !*verbose {
		return
	}
	fmt.Printf(format, args...)
}

func SliceStringIndexOf(haystack []string, needle string) int {
	for i, elem := range haystack {
		if elem == needle {
			return i
		}
	}
	return -1
}

func Markdown(source string) string {
	// set up the HTML renderer
	flags := 0
	flags |= bf.HTML_USE_SMARTYPANTS
	flags |= bf.HTML_SMARTYPANTS_FRACTIONS
	renderer := bf.HtmlRenderer(flags, "", "")

	// set up the parser
	ext := 0
	ext |= bf.EXTENSION_NO_INTRA_EMPHASIS
	ext |= bf.EXTENSION_TABLES
	ext |= bf.EXTENSION_FENCED_CODE
	ext |= bf.EXTENSION_AUTOLINK
	ext |= bf.EXTENSION_STRIKETHROUGH
	ext |= bf.EXTENSION_SPACE_HEADERS

	return string(bf.Markdown([]byte(source), renderer, ext))
}
<|endoftext|>


<commit_before>package godns

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"runtime"
	"strings"

	"golang.org/x/net/proxy"
)

const (
	// PanicMax is the max allowed panic times
	PanicMax = 5
	// INTERVAL is minute
	INTERVAL = 5
	// DNSPOD for dnspod.cn
	DNSPOD = "DNSPod"
	// HE for he.net
	HE = "HE"
)

// GetCurrentIP gets public IP from internet
func GetCurrentIP(configuration *Settings) (string, error) {
	client := &http.Client{}

	if configuration.Socks5Proxy != "" {

		log.Println("use socks5 proxy:" + configuration.Socks5Proxy)

		dialer, err := proxy.SOCKS5("tcp", configuration.Socks5Proxy, nil, proxy.Direct)
		if err != nil {
			fmt.Println("can't connect to the proxy:", err)
			return "", err
		}

		httpTransport := &http.Transport{}
		client.Transport = httpTransport
		httpTransport.Dial = dialer.Dial
	}

	response, err := client.Get(configuration.IPUrl)

	if err != nil {
		log.Println("Cannot get IP...")
		return "", err
	}

	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)
	return string(body), nil
}

// IdentifyPanic identifies panic and output the detailed panic infomation
func IdentifyPanic() string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}

// Usage prints the usage of GoDNS
func Usage() {
	log.Println("[command] -c=[config file path]")
	flag.PrintDefaults()
}

// CheckSettings check the format of settings
func CheckSettings(config *Settings) error {
	if config.Provider == DNSPOD {
		if (config.Email == "" || config.Password == "") && config.LoginToken == "" {
			return errors.New("email/password or login token cannot be empty")
		}
	} else if config.Provider == HE {
		if config.Password == "" {
			return errors.New("password cannot be empty")
		}
	} else {
		return errors.New("please provide supported DNS provider: DNSPod/HE")
	}

	return nil
}
<commit_msg>fix golint warnings<commit_after>package godns

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"runtime"
	"strings"

	"golang.org/x/net/proxy"
)

const (
	// PanicMax is the max allowed panic times
	PanicMax = 5
	// INTERVAL is minute
	INTERVAL = 5
	// DNSPOD for dnspod.cn
	DNSPOD = "DNSPod"
	// HE for he.net
	HE = "HE"
)

// GetCurrentIP gets public IP from internet
func GetCurrentIP(configuration *Settings) (string, error) {
	client := &http.Client{}

	if configuration.Socks5Proxy != "" {

		log.Println("use socks5 proxy:" + configuration.Socks5Proxy)

		dialer, err := proxy.SOCKS5("tcp", configuration.Socks5Proxy, nil, proxy.Direct)
		if err != nil {
			fmt.Println("can't connect to the proxy:", err)
			return "", err
		}

		httpTransport := &http.Transport{}
		client.Transport = httpTransport
		httpTransport.Dial = dialer.Dial
	}

	response, err := client.Get(configuration.IPUrl)

	if err != nil {
		log.Println("Cannot get IP...")
		return "", err
	}

	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)
	return string(body), nil
}

// IdentifyPanic identifies panic and output the detailed panic information
func IdentifyPanic() string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}

// Usage prints the usage of GoDNS
func Usage() {
	log.Println("[command] -c=[config file path]")
	flag.PrintDefaults()
}

// CheckSettings check the format of settings
func CheckSettings(config *Settings) error {
	if config.Provider == DNSPOD {
		if (config.Email == "" || config.Password == "") && config.LoginToken == "" {
			return errors.New("email/password or login token cannot be empty")
		}
	} else if config.Provider == HE {
		if config.Password == "" {
			return errors.New("password cannot be empty")
		}
	} else {
		return errors.New("please provide supported DNS provider: DNSPod/HE")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

// CODE_BYTES_LENGTH - length of random code in bytes
const CODE_BYTES_LENGTH = 15

// exec shell commands with text to STDIN
func execShell(shellCmd, input string, varsNames []string, userID, chatID int, userName, userDisplayName string) (result []byte) {
	shell, params := "sh", []string{"-c", shellCmd}
	if runtime.GOOS == "windows" {
		shell, params = "cmd", []string{"/C", shellCmd}
	}
	osExecCommand := exec.Command(shell, params...)
	osExecCommand.Stderr = os.Stderr

	// copy variables from parent process
	for _, envRaw := range os.Environ() {
		osExecCommand.Env = append(osExecCommand.Env, envRaw)
	}

	if input != "" {
		if len(varsNames) > 0 {
			// set user input to shell vars
			arguments := regexp.MustCompile(`\s+`).Split(input, len(varsNames))
			for i, arg := range arguments {
				osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", varsNames[i], arg))
			}
		} else {
			// write user input to STDIN
			stdin, err := osExecCommand.StdinPipe()
			if err == nil {
				io.WriteString(stdin, input)
				stdin.Close()
			} else {
				log.Print("get STDIN error: ", err)
			}
		}
	}

	// set S2T_* env vars
	s2tVariables := [...]struct{ name, value string }{
		{"S2T_LOGIN", userName},
		{"S2T_USERID", strconv.Itoa(userID)},
		{"S2T_USERNAME", userDisplayName},
		{"S2T_CHATID", strconv.Itoa(userID)},
	}
	for _, row := range s2tVariables {
		osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", row.name, row.value))
	}

	shellOut, err := osExecCommand.Output()
	if err != nil {
		log.Print("exec error: ", err)
		result = []byte(fmt.Sprintf("exec error: %s", err))
	} else {
		result = shellOut
	}

	return result
}

// return 2 strings, second="" if string dont contain space
func splitStringHalfBySpace(str string) (one, two string) {
	array := regexp.MustCompile(`\s+`).Split(str, 2)
	one, two = array[0], ""
	if len(array) > 1 {
		two = array[1]
	}

	return one, two
}

// cleanUserName - remove @ from telegram username
func cleanUserName(in string) string {
	return regexp.MustCompile("@").ReplaceAllLiteralString(in, "")
}

// getRandomCode - generate random code for authorize user
func getRandomCode() string {
	buffer := make([]byte, CODE_BYTES_LENGTH)
	_, err := rand.Read(buffer)
	if err != nil {
		log.Print("Get code error: ", err)
		return ""
	}

	return base64.URLEncoding.EncodeToString(buffer)
}

// parseBotCommand - parse command-line arguments for one bot command
func parseBotCommand(pathRaw, shellCmd string) (path string, command Command, err error) {
	if len(pathRaw) == 0 || pathRaw[0] != '/' {
		return "", command, fmt.Errorf("error: path %s dont starts with /", pathRaw)
	}
	if stringIsEmpty(shellCmd) {
		return "", command, fmt.Errorf("error: shell command cannot be empty")
	}

	_parseVars := func(varsParts []string) (desc string, vars []string, err error) {
		for _, oneVar := range varsParts {
			oneVarParts := regexp.MustCompile("=").Split(oneVar, 2)
			if len(oneVarParts) != 2 {
				err = fmt.Errorf("error: parse command modificators: %s", oneVar)
				return
			} else if oneVarParts[0] == "desc" {
				desc = oneVarParts[1]
				if desc == "" {
					err = fmt.Errorf("error: command description cannot be empty")
					return
				}
			} else if oneVarParts[0] == "vars" {
				vars = regexp.MustCompile(",").Split(oneVarParts[1], -1)
				for _, oneVarName := range vars {
					if oneVarName == "" {
						err = fmt.Errorf("error: var name cannot be empty")
						return
					}
				}
			} else if oneVarParts[0] == "image_out" {
				log.Print("Not implemented")
			} else {
				err = fmt.Errorf("error: parse command modificators, not found %s", oneVarParts[0])
				return
			}
		}

		return desc, vars, nil
	}

	pathParts := regexp.MustCompile(":").Split(pathRaw, -1)
	desc, vars := "", []string{}
	switch {
	case len(pathParts) == 1:
		// /, /cmd
		path = pathParts[0]
	case pathParts[0] == "/" && regexp.MustCompile("^(plain_text|image)$").MatchString(pathParts[1]):
		// /:plain_text, /:image, /:plain_text:desc=name
		path = "/:" + pathParts[1]
		if pathParts[1] == "image" {
			log.Print("/:image not implemented")
		}
		if len(pathParts) > 2 {
			desc, vars, err = _parseVars(pathParts[2:])
		}
	case len(pathParts) > 1:
		// commands with modificators :desc, :vars
		path = pathParts[0]
		desc, vars, err = _parseVars(pathParts[1:])
	}
	if err != nil {
		return "", command, err
	}

	command = Command{
		shellCmd:    shellCmd,
		description: desc,
		vars:        vars,
	}

	// pp.Println(path, command)
	return path, command, nil
}

// stringIsEmpty - check string is empty
func stringIsEmpty(str string) bool {
	isEmpty, _ := regexp.MatchString(`^\s*$`, str)
	return isEmpty
}

// split string by chunks less maxSize size (whole rows)
func splitStringLinesBySize(input string, maxSize int) []string {
	result := []string{}
	parts := regexp.MustCompile("\n").Split(input, -1)
	chunks := []string{parts[0]}
	chunkSize := len(parts[0])

	for _, part := range parts[1:] {
		// current + "\n" + next > maxSize
		if chunkSize+1+len(part) > maxSize {
			result = append(result, strings.Join(chunks, "\n"))
			chunks = []string{part}
			chunkSize = len(part)
		} else {
			chunks = append(chunks, part)
			chunkSize += 1 + len(part)
		}
	}
	if len(chunks) > 0 {
		result = append(result, strings.Join(chunks, "\n"))
	}

	return result
}

// create dir if it is not exists
func createDirIfNeed(dir string) {
	if _, err := os.Stat(dir); err != nil {
		err = os.MkdirAll(dir, 0755)
		if err != nil {
			log.Fatal("create dir error:", dir)
		}
	}
}

// get home dir
func getOsUserHomeDir() string {
	homeDir := os.Getenv("HOME")
	if runtime.GOOS == "windows" {
		homeDir = os.Getenv("APPDATA")
	}
	return homeDir
}

// read default or user db file name
func getDBFilePath(usersDBFile string, needCreateDir bool) string {
	fileName := ""
	if usersDBFile == "" {
		dirName := getOsUserHomeDir() + string(os.PathSeparator) + ".config"
		if needCreateDir {
			createDirIfNeed(dirName)
		}
		fileName = dirName + string(os.PathSeparator) + DB_FILE_NAME
	} else {
		fileName = usersDBFile
	}

	return fileName
}
<commit_msg>Removed :image_out obsolete attribute<commit_after>package main

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

// CODE_BYTES_LENGTH - length of random code in bytes
const CODE_BYTES_LENGTH = 15

// exec shell commands with text to STDIN
func execShell(shellCmd, input string, varsNames []string, userID, chatID int, userName, userDisplayName string) (result []byte) {
	shell, params := "sh", []string{"-c", shellCmd}
	if runtime.GOOS == "windows" {
		shell, params = "cmd", []string{"/C", shellCmd}
	}
	osExecCommand := exec.Command(shell, params...)
	osExecCommand.Stderr = os.Stderr

	// copy variables from parent process
	for _, envRaw := range os.Environ() {
		osExecCommand.Env = append(osExecCommand.Env, envRaw)
	}

	if input != "" {
		if len(varsNames) > 0 {
			// set user input to shell vars
			arguments := regexp.MustCompile(`\s+`).Split(input, len(varsNames))
			for i, arg := range arguments {
				osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", varsNames[i], arg))
			}
		} else {
			// write user input to STDIN
			stdin, err := osExecCommand.StdinPipe()
			if err == nil {
				io.WriteString(stdin, input)
				stdin.Close()
			} else {
				log.Print("get STDIN error: ", err)
			}
		}
	}

	// set S2T_* env vars
	s2tVariables := [...]struct{ name, value string }{
		{"S2T_LOGIN", userName},
		{"S2T_USERID", strconv.Itoa(userID)},
		{"S2T_USERNAME", userDisplayName},
		{"S2T_CHATID", strconv.Itoa(userID)},
	}
	for _, row := range s2tVariables {
		osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", row.name, row.value))
	}

	shellOut, err := osExecCommand.Output()
	if err != nil {
		log.Print("exec error: ", err)
		result = []byte(fmt.Sprintf("exec error: %s", err))
	} else {
		result = shellOut
	}

	return result
}

// return 2 strings, second="" if string dont contain space
func splitStringHalfBySpace(str string) (one, two string) {
	array := regexp.MustCompile(`\s+`).Split(str, 2)
	one, two = array[0], ""
	if len(array) > 1 {
		two = array[1]
	}

	return one, two
}

// cleanUserName - remove @ from telegram username
func cleanUserName(in string) string {
	return regexp.MustCompile("@").ReplaceAllLiteralString(in, "")
}

// getRandomCode - generate random code for authorize user
func getRandomCode() string {
	buffer := make([]byte, CODE_BYTES_LENGTH)
	_, err := rand.Read(buffer)
	if err != nil {
		log.Print("Get code error: ", err)
		return ""
	}

	return base64.URLEncoding.EncodeToString(buffer)
}

// parseBotCommand - parse command-line arguments for one bot command
func parseBotCommand(pathRaw, shellCmd string) (path string, command Command, err error) {
	if len(pathRaw) == 0 || pathRaw[0] != '/' {
		return "", command, fmt.Errorf("error: path %s dont starts with /", pathRaw)
	}
	if stringIsEmpty(shellCmd) {
		return "", command, fmt.Errorf("error: shell command cannot be empty")
	}

	_parseVars := func(varsParts []string) (desc string, vars []string, err error) {
		for _, oneVar := range varsParts {
			oneVarParts := regexp.MustCompile("=").Split(oneVar, 2)
			if len(oneVarParts) != 2 {
				err = fmt.Errorf("error: parse command modificators: %s", oneVar)
				return
			} else if oneVarParts[0] == "desc" {
				desc = oneVarParts[1]
				if desc == "" {
					err = fmt.Errorf("error: command description cannot be empty")
					return
				}
			} else if oneVarParts[0] == "vars" {
				vars = regexp.MustCompile(",").Split(oneVarParts[1], -1)
				for _, oneVarName := range vars {
					if oneVarName == "" {
						err = fmt.Errorf("error: var name cannot be empty")
						return
					}
				}
			} else {
				err = fmt.Errorf("error: parse command modificators, not found %s", oneVarParts[0])
				return
			}
		}

		return desc, vars, nil
	}

	pathParts := regexp.MustCompile(":").Split(pathRaw, -1)
	desc, vars := "", []string{}
	switch {
	case len(pathParts) == 1:
		// /, /cmd
		path = pathParts[0]
	case pathParts[0] == "/" && regexp.MustCompile("^(plain_text|image)$").MatchString(pathParts[1]):
		// /:plain_text, /:image, /:plain_text:desc=name
		path = "/:" + pathParts[1]
		if pathParts[1] == "image" {
			log.Print("/:image not implemented")
		}
		if len(pathParts) > 2 {
			desc, vars, err = _parseVars(pathParts[2:])
		}
	case len(pathParts) > 1:
		// commands with modificators :desc, :vars
		path = pathParts[0]
		desc, vars, err = _parseVars(pathParts[1:])
	}
	if err != nil {
		return "", command, err
	}

	command = Command{
		shellCmd:    shellCmd,
		description: desc,
		vars:        vars,
	}

	// pp.Println(path, command)
	return path, command, nil
}

// stringIsEmpty - check string is empty
func stringIsEmpty(str string) bool {
	isEmpty, _ := regexp.MatchString(`^\s*$`, str)
	return isEmpty
}

// split string by chunks less maxSize size (whole rows)
func splitStringLinesBySize(input string, maxSize int) []string {
	result := []string{}
	parts := regexp.MustCompile("\n").Split(input, -1)
	chunks := []string{parts[0]}
	chunkSize := len(parts[0])

	for _, part := range parts[1:] {
		// current + "\n" + next > maxSize
		if chunkSize+1+len(part) > maxSize {
			result = append(result, strings.Join(chunks, "\n"))
			chunks = []string{part}
			chunkSize = len(part)
		} else {
			chunks = append(chunks, part)
			chunkSize += 1 + len(part)
		}
	}
	if len(chunks) > 0 {
		result = append(result, strings.Join(chunks, "\n"))
	}

	return result
}

// create dir if it is not exists
func createDirIfNeed(dir string) {
	if _, err := os.Stat(dir); err != nil {
		err = os.MkdirAll(dir, 0755)
		if err != nil {
			log.Fatal("create dir error:", dir)
		}
	}
}

// get home dir
func getOsUserHomeDir() string {
	homeDir := os.Getenv("HOME")
	if runtime.GOOS == "windows" {
		homeDir = os.Getenv("APPDATA")
	}
	return homeDir
}

// read default or user db file name
func getDBFilePath(usersDBFile string, needCreateDir bool) string {
	fileName := ""
	if usersDBFile == "" {
		dirName := getOsUserHomeDir() + string(os.PathSeparator) + ".config"
		if needCreateDir {
			createDirIfNeed(dirName)
		}
		fileName = dirName + string(os.PathSeparator) + DB_FILE_NAME
	} else {
		fileName = usersDBFile
	}

	return fileName
}
<|endoftext|>