<commit_before>/*
Copyright 2013 Andrew Medworth

This file is part of Gopoker, a set of miscellaneous poker-related functions
written in the Go programming language (http://golang.org).

Gopoker 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.

Gopoker 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 Gopoker.  If not, see <http://www.gnu.org/licenses/>.
*/
package poker

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

type PlayerOutcome struct {
	Player int
	Level  HandLevel
	Cards  []Card
}

type HandSorter struct {
	Outcomes []PlayerOutcome
}

func (hs HandSorter) Len() int {
	return len(hs.Outcomes)
}

func (hs HandSorter) Swap(i, j int) {
	hs.Outcomes[i], hs.Outcomes[j] = hs.Outcomes[j], hs.Outcomes[i]
}

func (hs HandSorter) Less(i, j int) bool {
	iBeatsJ := Beats(hs.Outcomes[i].Level, hs.Outcomes[j].Level)
	jBeatsI := Beats(hs.Outcomes[j].Level, hs.Outcomes[i].Level)
	if iBeatsJ && !jBeatsI {
		return true
	}
	if jBeatsI && !iBeatsJ {
		return false
	}
	return hs.Outcomes[i].Player < hs.Outcomes[j].Player
}

type Pack struct {
	Cards   [52]Card
	randGen *rand.Rand
}

func (p *Pack) initialise() {
	p.randGen = rand.New(rand.NewSource(time.Now().UnixNano()))

	i := 0
	for s := 0; s < 4; s++ {
		for r := 0; r < 13; r++ {
			p.Cards[i] = Card{Rank(r), Suit(s)}
			i++
		}
	}
}

// Shuffle the pack
func (p *Pack) Shuffle() {
	for i := 0; i < 52; i++ {
		j := p.randGen.Intn(52-i) + i
		p.Cards[i], p.Cards[j] = p.Cards[j], p.Cards[i]
	}
}

// Shuffle the pack, but fix certain cards in place. For use in simulations.
// It is assumed that there are no duplicate cards in (tableCards+yourCards).
func (p *Pack) shuffleFixing(tableCards, yourCards []Card) {
	if len(tableCards) > 5 {
		panic(fmt.Sprintf("Maximum of 5 table cards supported, found %v", len(tableCards)))
	}
	// Remove fixed cards from the pack, shuffle those, and fill them in
	nonFixedCards := make([]Card, 52-len(yourCards)-len(tableCards))

	indexOf := func(cards []Card, card Card) int {
		result := -1
		for i, c := range cards {
			if c == card {
				result = i
				break
			}
		}
		return result
	}

	i := 0
	for _, c := range p.Cards {
		if indexOf(yourCards, c) == -1 && indexOf(tableCards, c) == -1 {
			nonFixedCards[i] = c
			i++
		}
	}
	for i = 0; i < len(nonFixedCards); i++ {
		j := p.randGen.Intn(len(nonFixedCards)-i) + i
		nonFixedCards[i], nonFixedCards[j] = nonFixedCards[j], nonFixedCards[i]
	}

	copy(p.Cards[0:len(tableCards)], tableCards)

	// If not all table cards were supplied, fill in the gaps from the non-fixed cards
	for i = 0; i < 5-len(tableCards); i++ {
		p.Cards[i+len(tableCards)] = nonFixedCards[i]
	}
	copy(p.Cards[5:5+len(yourCards)], yourCards)
	copy(p.Cards[5+len(yourCards):52], nonFixedCards[i:len(nonFixedCards)])
}

func (p *Pack) Deal(players int) (onTable []Card, playerCards [][]Card) {
	if players < 1 {
		panic(fmt.Sprintf("At least one player required, found %v", players))
	}

	onTable = p.Cards[0:5]

	playerCards = make([][]Card, players)
	for player := 0; player < players; player++ {
		playerCards[player] = p.Cards[5+2*player : 7+2*player]
	}

	return onTable, playerCards
}

// Assess the hand each player holds and returna  sorted list of outcomes
// by hand strength (descending) then player number (ascending).
// Player numbers are in ascending order of playerCards entries, starting with 1.
func DealOutcomes(onTable []Card, playerCards [][]Card) []PlayerOutcome {
	outcomes := make([]PlayerOutcome, len(playerCards))
	for playerIdx, hand := range playerCards {
		// In Hold'em it is not mandatory to use the cards in your hand,
		// so they are all optional
		combinedCards := make([]Card, 7)
		copy(combinedCards[0:5], onTable)
		copy(combinedCards[5:7], hand)
		level, cards := Classify([]Card{}, combinedCards)
		outcomes[playerIdx] = PlayerOutcome{playerIdx + 1, level, cards}
	}
	sort.Sort(HandSorter{outcomes})
	return outcomes
}

type SimulationResult struct {
	Won, OpponentWon                                 bool
	OurLevel, BestOpponentLevel, RandomOpponentLevel HandLevel
}

// Play out one hand of Texas Hold'em and return whether or not player 1 won,
// plus player 1's hand level, plus the best hand level of any of player 1's opponents.
func (p *Pack) SimulateOneHoldemHand(players int) SimulationResult {
	onTable, playerCards := p.Deal(players)
	outcomes := DealOutcomes(onTable, playerCards)

	// This works even if player 1 was equal first, since equal hands are sorted by player
	won := outcomes[0].Player == 1

	var ourOutcome PlayerOutcome
	opponentOutcomes := make([]PlayerOutcome, players-1)
	i := 0
	for _, o := range outcomes {
		if o.Player == 1 {
			ourOutcome = o
		} else {
			opponentOutcomes[i] = o
			i++
		}
	}

	opponentWon := !Beats(ourOutcome.Level, opponentOutcomes[0].Level)

	randomOpponentLevel := opponentOutcomes[p.randGen.Intn(len(opponentOutcomes))].Level

	return SimulationResult{won, opponentWon, ourOutcome.Level, opponentOutcomes[0].Level, randomOpponentLevel}
}

func NewPack() Pack {
	var result Pack
	result.initialise()
	return result
}
<commit_msg>Simplify fixed shuffle implementation (closes #18)<commit_after>/*
Copyright 2013 Andrew Medworth

This file is part of Gopoker, a set of miscellaneous poker-related functions
written in the Go programming language (http://golang.org).

Gopoker 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.

Gopoker 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 Gopoker.  If not, see <http://www.gnu.org/licenses/>.
*/
package poker

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

type PlayerOutcome struct {
	Player int
	Level  HandLevel
	Cards  []Card
}

type HandSorter struct {
	Outcomes []PlayerOutcome
}

func (hs HandSorter) Len() int {
	return len(hs.Outcomes)
}

func (hs HandSorter) Swap(i, j int) {
	hs.Outcomes[i], hs.Outcomes[j] = hs.Outcomes[j], hs.Outcomes[i]
}

func (hs HandSorter) Less(i, j int) bool {
	iBeatsJ := Beats(hs.Outcomes[i].Level, hs.Outcomes[j].Level)
	jBeatsI := Beats(hs.Outcomes[j].Level, hs.Outcomes[i].Level)
	if iBeatsJ && !jBeatsI {
		return true
	}
	if jBeatsI && !iBeatsJ {
		return false
	}
	return hs.Outcomes[i].Player < hs.Outcomes[j].Player
}

type Pack struct {
	Cards   [52]Card
	randGen *rand.Rand
}

func (p *Pack) initialise() {
	// Not cryptographically secure, but fine for simulation, where performance is more important
	p.randGen = rand.New(rand.NewSource(time.Now().UnixNano()))

	i := 0
	for s := 0; s < 4; s++ {
		for r := 0; r < 13; r++ {
			p.Cards[i] = Card{Rank(r), Suit(s)}
			i++
		}
	}
}

// Shuffle the pack
func (p *Pack) Shuffle() {
	for i := 0; i < 52; i++ {
		j := p.randGen.Intn(52-i) + i
		p.Cards[i], p.Cards[j] = p.Cards[j], p.Cards[i]
	}
}

// Shuffle the pack, but fix certain cards in place. For use in simulations.
// It is assumed that there are no duplicate cards in (tableCards+yourCards).
func (p *Pack) shuffleFixing(tableCards, yourCards []Card) {
	if len(tableCards) > 5 || len(yourCards) > 2 {
		panic(fmt.Sprintf("Maximum of 5 table cards and 2 hole cards supported, found %v and %v", len(tableCards), len(yourCards)))
	}

	indexOf := func(cards [52]Card, card Card) int {
		result := -1
		for i, c := range cards {
			if c == card {
				result = i
				break
			}
		}
		return result
	}

	// Just shuffle the pack and then swap the fixed cards into place from wherever they are in the deck
	p.Shuffle()
	for i := 0; i < len(tableCards); i++ {
		swapIdx := indexOf(p.Cards, tableCards[i])
		p.Cards[i], p.Cards[swapIdx] = p.Cards[swapIdx], p.Cards[i]
	}
	for i := 0; i < len(yourCards); i++ {
		swapIdx := indexOf(p.Cards, yourCards[i])
		targetIdx := i + 5
		p.Cards[targetIdx], p.Cards[swapIdx] = p.Cards[swapIdx], p.Cards[targetIdx]
	}
}

func (p *Pack) Deal(players int) (onTable []Card, playerCards [][]Card) {
	if players < 1 {
		panic(fmt.Sprintf("At least one player required, found %v", players))
	}

	onTable = p.Cards[0:5]

	playerCards = make([][]Card, players)
	for player := 0; player < players; player++ {
		playerCards[player] = p.Cards[5+2*player : 7+2*player]
	}

	return onTable, playerCards
}

// Assess the hand each player holds and returna  sorted list of outcomes
// by hand strength (descending) then player number (ascending).
// Player numbers are in ascending order of playerCards entries, starting with 1.
func DealOutcomes(onTable []Card, playerCards [][]Card) []PlayerOutcome {
	outcomes := make([]PlayerOutcome, len(playerCards))
	for playerIdx, hand := range playerCards {
		// In Hold'em it is not mandatory to use the cards in your hand,
		// so they are all optional
		combinedCards := make([]Card, 7)
		copy(combinedCards[0:5], onTable)
		copy(combinedCards[5:7], hand)
		level, cards := Classify([]Card{}, combinedCards)
		outcomes[playerIdx] = PlayerOutcome{playerIdx + 1, level, cards}
	}
	sort.Sort(HandSorter{outcomes})
	return outcomes
}

type SimulationResult struct {
	Won, OpponentWon                                 bool
	OurLevel, BestOpponentLevel, RandomOpponentLevel HandLevel
}

// Play out one hand of Texas Hold'em and return whether or not player 1 won,
// plus player 1's hand level, plus the best hand level of any of player 1's opponents.
func (p *Pack) SimulateOneHoldemHand(players int) SimulationResult {
	onTable, playerCards := p.Deal(players)
	outcomes := DealOutcomes(onTable, playerCards)

	// This works even if player 1 was equal first, since equal hands are sorted by player
	won := outcomes[0].Player == 1

	var ourOutcome PlayerOutcome
	opponentOutcomes := make([]PlayerOutcome, players-1)
	i := 0
	for _, o := range outcomes {
		if o.Player == 1 {
			ourOutcome = o
		} else {
			opponentOutcomes[i] = o
			i++
		}
	}

	opponentWon := !Beats(ourOutcome.Level, opponentOutcomes[0].Level)

	randomOpponentLevel := opponentOutcomes[p.randGen.Intn(len(opponentOutcomes))].Level

	return SimulationResult{won, opponentWon, ourOutcome.Level, opponentOutcomes[0].Level, randomOpponentLevel}
}

func NewPack() Pack {
	var result Pack
	result.initialise()
	return result
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Tuenti Technologies S.L. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"log"

	api "k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	"k8s.io/kubernetes/pkg/watch"
)

type KubernetesClient struct {
	client *client.Client

	notifiers []Notifier
	templates []*Template

	domain string
}

func getClientConfig(kubecfg, apiserver string) (*client.Config, error) {
	if apiserver == "" && kubecfg == "" {
		if config, err := client.InClusterConfig(); err == nil {
			return config, nil
		} else {
			return nil, err
		}
	}
	if apiserver != "" && kubecfg == "" {
		return &client.Config{Host: apiserver}, nil
	}
	overrides := &clientcmd.ConfigOverrides{}
	overrides.ClusterInfo.Server = apiserver
	rules := clientcmd.NewDefaultClientConfigLoadingRules()
	rules.ExplicitPath = kubecfg
	return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig()
}

func NewKubernetesClient(kubecfg, apiserver, domain string) (*KubernetesClient, error) {
	var (
		config *client.Config
		err    error
	)

	if config, err = getClientConfig(kubecfg, apiserver); err != nil {
		return nil, err
	}

	log.Printf("Using %s for kubernetes master", config.Host)
	if c, err := client.New(config); err != nil {
		return nil, err
	} else {
		return &KubernetesClient{
			client:    c,
			notifiers: make([]Notifier, 0, 10),
			templates: make([]*Template, 0, 10),
			domain:    domain,
		}, nil
	}
}

func (c *KubernetesClient) AddNotifier(n Notifier) {
	c.notifiers = append(c.notifiers, n)
}

func (c *KubernetesClient) Notify() {
	for _, n := range c.notifiers {
		if err := n.Notify(); err != nil {
			log.Printf("Couldn't notify: %s\n", err)
		}
	}
}

func (c *KubernetesClient) AddTemplate(t *Template) {
	c.templates = append(c.templates, t)
}

func (c *KubernetesClient) ExecuteTemplates(info *ClusterInformation) {
	for _, t := range c.templates {
		if err := t.Execute(info); err != nil {
			log.Printf("Couldn't write template: %s\n", err)
		}
	}
}

func (c *KubernetesClient) getNodeNames() ([]string, error) {
	options := api.ListOptions{}
	ni := c.client.Nodes()
	nodes, err := ni.List(options.LabelSelector, options.FieldSelector)
	if err != nil {
		return nil, err
	}
	nodeNames := make([]string, len(nodes.Items))
	for i, n := range nodes.Items {
		nodeNames[i] = n.Name
	}
	return nodeNames, nil
}

func (c *KubernetesClient) getServices(namespace string) ([]ServiceInformation, error) {
	options := api.ListOptions{}
	si := c.client.Services(api.NamespaceAll)
	services, err := si.List(options.LabelSelector)
	if err != nil {
		return nil, fmt.Errorf("Couldn't get services: ", err)
	}
	servicesInformation := make([]ServiceInformation, 0, len(services.Items))
	for _, s := range services.Items {
		switch s.Spec.Type {
		case api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer:
			for _, port := range s.Spec.Ports {
				servicesInformation = append(servicesInformation,
					ServiceInformation{
						Name:      s.Name,
						Namespace: s.Namespace,
						Port:      port.Port,
						NodePort:  port.NodePort,
					},
				)
			}
		}
	}
	return servicesInformation, nil
}

func (c *KubernetesClient) Update() error {

	nodeNames, err := c.getNodeNames()
	if err != nil {
		return fmt.Errorf("Couldn't get nodes: ", err)
	}

	services, err := c.getServices(api.NamespaceAll)
	if err != nil {
		return fmt.Errorf("Couldn't get services: ", err)
	}

	info := &ClusterInformation{
		Nodes:    nodeNames,
		Services: services,
		Domain:   c.domain,
	}
	c.ExecuteTemplates(info)
	c.Notify()

	return nil
}

func (c *KubernetesClient) Watch() error {
	options := api.ListOptions{}
	ni := c.client.Nodes()
	si := c.client.Services(api.NamespaceAll)

	nodeWatcher, err := ni.Watch(options.LabelSelector, options.FieldSelector, "")
	if err != nil {
		return fmt.Errorf("Couldn't watch events on nodes: %v", err)
	}

	serviceWatcher, err := si.Watch(options.LabelSelector, options.FieldSelector, "")
	if err != nil {
		return fmt.Errorf("Couldn't watch events on nodes: %v", err)
	}

	isFirstUpdate := true
	updater := NewUpdater(func() {
		var err error
		if err = c.Update(); err != nil {
			log.Printf("Couldn't update state: ", err)
		}
		if isFirstUpdate {
			if err != nil {
				log.Fatalf("Failing on first update, check configuration: ", err)
			}
			isFirstUpdate = false
		}
	})
	go updater.Run()

	for {
		select {
		case e := <-nodeWatcher.ResultChan():
			if e.Type == watch.Added || e.Type == watch.Deleted {
				updater.Signal()
			}
		case <-serviceWatcher.ResultChan():
			updater.Signal()
		}
	}
}
<commit_msg>Don't write error twice when failing to notify<commit_after>/*
Copyright 2016 Tuenti Technologies S.L. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"log"

	api "k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	"k8s.io/kubernetes/pkg/watch"
)

type KubernetesClient struct {
	client *client.Client

	notifiers []Notifier
	templates []*Template

	domain string
}

func getClientConfig(kubecfg, apiserver string) (*client.Config, error) {
	if apiserver == "" && kubecfg == "" {
		if config, err := client.InClusterConfig(); err == nil {
			return config, nil
		} else {
			return nil, err
		}
	}
	if apiserver != "" && kubecfg == "" {
		return &client.Config{Host: apiserver}, nil
	}
	overrides := &clientcmd.ConfigOverrides{}
	overrides.ClusterInfo.Server = apiserver
	rules := clientcmd.NewDefaultClientConfigLoadingRules()
	rules.ExplicitPath = kubecfg
	return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig()
}

func NewKubernetesClient(kubecfg, apiserver, domain string) (*KubernetesClient, error) {
	var (
		config *client.Config
		err    error
	)

	if config, err = getClientConfig(kubecfg, apiserver); err != nil {
		return nil, err
	}

	log.Printf("Using %s for kubernetes master", config.Host)
	if c, err := client.New(config); err != nil {
		return nil, err
	} else {
		return &KubernetesClient{
			client:    c,
			notifiers: make([]Notifier, 0, 10),
			templates: make([]*Template, 0, 10),
			domain:    domain,
		}, nil
	}
}

func (c *KubernetesClient) AddNotifier(n Notifier) {
	c.notifiers = append(c.notifiers, n)
}

func (c *KubernetesClient) Notify() {
	for _, n := range c.notifiers {
		if err := n.Notify(); err != nil {
			log.Printf("Couldn't notify: %s\n", err)
		}
	}
}

func (c *KubernetesClient) AddTemplate(t *Template) {
	c.templates = append(c.templates, t)
}

func (c *KubernetesClient) ExecuteTemplates(info *ClusterInformation) {
	for _, t := range c.templates {
		if err := t.Execute(info); err != nil {
			log.Printf("Couldn't write template: %s\n", err)
		}
	}
}

func (c *KubernetesClient) getNodeNames() ([]string, error) {
	options := api.ListOptions{}
	ni := c.client.Nodes()
	nodes, err := ni.List(options.LabelSelector, options.FieldSelector)
	if err != nil {
		return nil, err
	}
	nodeNames := make([]string, len(nodes.Items))
	for i, n := range nodes.Items {
		nodeNames[i] = n.Name
	}
	return nodeNames, nil
}

func (c *KubernetesClient) getServices(namespace string) ([]ServiceInformation, error) {
	options := api.ListOptions{}
	si := c.client.Services(api.NamespaceAll)
	services, err := si.List(options.LabelSelector)
	if err != nil {
		return nil, fmt.Errorf("Couldn't get services: ", err)
	}
	servicesInformation := make([]ServiceInformation, 0, len(services.Items))
	for _, s := range services.Items {
		switch s.Spec.Type {
		case api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer:
			for _, port := range s.Spec.Ports {
				servicesInformation = append(servicesInformation,
					ServiceInformation{
						Name:      s.Name,
						Namespace: s.Namespace,
						Port:      port.Port,
						NodePort:  port.NodePort,
					},
				)
			}
		}
	}
	return servicesInformation, nil
}

func (c *KubernetesClient) Update() error {
	nodeNames, err := c.getNodeNames()
	if err != nil {
		return fmt.Errorf("Couldn't get nodes: ", err)
	}

	services, err := c.getServices(api.NamespaceAll)
	if err != nil {
		return fmt.Errorf("Couldn't get services: ", err)
	}

	info := &ClusterInformation{
		Nodes:    nodeNames,
		Services: services,
		Domain:   c.domain,
	}
	c.ExecuteTemplates(info)
	c.Notify()

	return nil
}

func (c *KubernetesClient) Watch() error {
	options := api.ListOptions{}
	ni := c.client.Nodes()
	si := c.client.Services(api.NamespaceAll)

	nodeWatcher, err := ni.Watch(options.LabelSelector, options.FieldSelector, "")
	if err != nil {
		return fmt.Errorf("Couldn't watch events on nodes: %v", err)
	}

	serviceWatcher, err := si.Watch(options.LabelSelector, options.FieldSelector, "")
	if err != nil {
		return fmt.Errorf("Couldn't watch events on nodes: %v", err)
	}

	isFirstUpdate := true
	updater := NewUpdater(func() {
		var err error
		if err = c.Update(); err != nil {
			log.Printf("Couldn't update state: ", err)
		}
		if isFirstUpdate {
			if err != nil {
				log.Fatalf("Failing on first update, check configuration.")
			}
			isFirstUpdate = false
		}
	})
	go updater.Run()

	for {
		select {
		case e := <-nodeWatcher.ResultChan():
			if e.Type == watch.Added || e.Type == watch.Deleted {
				updater.Signal()
			}
		case <-serviceWatcher.ResultChan():
			updater.Signal()
		}
	}
}
<|endoftext|>


<commit_before>package polynomial

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

// Data structure for a polynomial
// Just an array in reverse
// f(x) = 3x^3 + 2x + 1 => [1 2 0 3]
type Poly []*big.Int

// Helper function for generating a polynomial with given integers
func NewPolyInts(coeffs ...int) (p Poly) {
	p = make([]*big.Int, len(coeffs))
	for i := 0; i < len(coeffs); i++ {
		p[i] = big.NewInt(int64(coeffs[i]))
	}
	p.trim()
	return
}

// Returns a polynomial with random coefficients
// You can give the degree of the polynomial
// A random coefficients have a [0, 2^bits) integer
func RandomPoly(degree, bits int64) (p Poly) {
	p = make(Poly, degree+1)
	rr := rand.New(rand.NewSource(time.Now().UnixNano()))
	exp := big.NewInt(2)
	exp.Exp(exp, big.NewInt(bits), nil)
	for i := 0; i <= p.GetDegree(); i++ {
		p[i] = new(big.Int)
		p[i].Rand(rr, exp)
	}
	p.trim()
	return
}

// trim() makes sure that the highest coefficient never has zero value
// when you add or subtract two polynomials, sometimes the highest coefficient goes zero
// if you don't remove the highest and zero coefficient, GetDegree() returns the wrong result
func (p *Poly) trim() {
	var last int = 0
	for i := p.GetDegree(); i > 0; i-- { // why i > 0, not i >=0? do not remove the constant
		if (*p)[i].Sign() != 0 {
			last = i
			break
		}
	}
	*p = (*p)[:(last + 1)]
}

// isZero() checks if P = 0
func (p *Poly) isZero() bool {
	if p.GetDegree() == 0 && (*p)[0].Cmp(big.NewInt(0)) == 0 {
		return true
	}
	return false
}

// returns the degree
// if p = x^3 + 2x^2 + 5, GetDegree() returns 3
func (p Poly) GetDegree() int {
	return len(p) - 1
}

// pretty print
func (p Poly) String() (s string) {
	s = "["
	for i := len(p) - 1; i >= 0; i-- {
		switch p[i].Sign() {
		case -1:
			if i == len(p)-1 {
				s += "-"
			} else {
				s += " - "
			}
			if i == 0 || p[i].Int64() != -1 {
				s += p[i].String()[1:]
			}
		case 0:
			continue
		case 1:
			if i < len(p)-1 {
				s += " + "
			}
			if i == 0 || p[i].Int64() != 1 {
				s += p[i].String()
			}
		}
		if i > 0 {
			s += "x"
			if i > 1 {
				s += "^" + fmt.Sprintf("%d", i)
			}
		}
	}
	if s == "[" {
		s += "0"
	}
	s += "]"
	return
}

// Compare 함수는 두 개의 다항식을 비교한다.
// 현 다항식을 복사할 필요는 없으므로 포인터로 받으며,
// 비교 대상 다항식도 효율성을 위해 포인터로 받는다.
// 두 디항식이 동일하면 0,
// 인자로 넘겨준 다항식이 더 크면 1,
// 그렇지 않으면 -1을 반환한다.
// 알고리즘은 간단하다.
// 차수가 크면 무조건 큰 다항식이며, 차수가 같을 시에는 계수값을 비교한다.
func (p *Poly) Compare(q *Poly) int {
	switch {
	case p.GetDegree() > q.GetDegree():
		return 1
	case p.GetDegree() < q.GetDegree():
		return -1
	}
	for i := 0; i <= p.GetDegree(); i++ {
		switch (*p)[i].Cmp((*q)[i]) {
		case 1:
			return 1
		case -1:
			return -1
		}
	}
	return 0
}

// Add()는 두 다항식을 더하는 함수다.
// 추가 인자로는 modulo를 줄 수 있으며,
// modulo 연산을 하고 싶지 않을 경우에는 nil을 주면 된다.
func (p Poly) Add(q Poly, m *big.Int) Poly {
	if p.Compare(&q) < 0 {
		return q.Add(p, m)
	}
	var r Poly = make([]*big.Int, len(p))
	for i := 0; i < len(q); i++ {
		a := new(big.Int)
		a.Add(p[i], q[i])
		r[i] = a
	}
	for i := len(q); i < len(p); i++ {
		a := new(big.Int)
		a.Set(p[i])
		r[i] = a
	}
	if m != nil {
		for i := 0; i < len(p); i++ {
			r[i].Mod(r[i], m)
		}
	}
	r.trim()
	return r
}

// 주어진 다항식의 계수에 모두 -1를 곱한다.
func (p *Poly) NegSelf() {
	for i := 0; i < len(*p); i++ {
		(*p)[i].Neg((*p)[i])
	}
}

// 주어진 다항식예 계수에 모두 마이너스를 취한 다항식을 새로 만들어서 반환한다.
func (p *Poly) Neg() Poly {
	var q Poly = make([]*big.Int, len(*p))
	for i := 0; i < len(*p); i++ {
		b := new(big.Int)
		b.Neg((*p)[i])
		q[i] = b
	}
	return q
}

// Clone()은 주어진 다항식을 deep copy하여 새로운 다항식을 만들어주는 함수.
// 인자로 주어지는 adjust 정수값은 복사를 하면서 차수 변경을 할 때 이용한다.
// adjust는 음수값을 가질 수 없으며 이 경우에는 다항식 0를 반환한다.
// adjust값만큼 차수가 높아진 상태로 반환된다.
// 예를 들어, x + 1 다항식에 adjust값을 2를 주면 x^3 + x^2가 반환된다.
// 동일한 다항식을 복사하고 싶으면 adjust에 0을 넘겨주면 된다.
func (p Poly) Clone(adjust int) Poly {
	var q Poly = make([]*big.Int, len(p)+adjust)
	if adjust < 0 {
		return NewPolyInts(0)
	}
	for i := 0; i < adjust; i++ {
		q[i] = big.NewInt(0)
	}
	for i := adjust; i < len(p)+adjust; i++ {
		b := new(big.Int)
		b.Set(p[i-adjust])
		q[i] = b
	}
	return q
}

// sanitize() 함수는 주어진 modulo 값을 이용하여,
// 현재 다항식의 계수 전체에 modulo 연산을 적용한다.
func (p *Poly) sanitize(m *big.Int) {
	if m == nil {
		return
	}
	for i := 0; i <= (*p).GetDegree(); i++ {
		(*p)[i].Mod((*p)[i], m)
	}
}

// 두 다항식을 빼는 함수. 미리 만들어둔 Add 함수를 활용하기 위해 A + (-B)로 계산한다.
func (p Poly) Sub(q Poly, m *big.Int) Poly {
	r := q.Neg()
	return p.Add(r, m)
}

// 두 다항식을 곱하는 함수.
func (p Poly) Mul(q Poly, m *big.Int) Poly {
	if m != nil {
		p.sanitize(m)
		q.sanitize(m)
	}
	var r Poly = make([]*big.Int, p.GetDegree()+q.GetDegree()+1)
	for i := 0; i < len(r); i++ {
		r[i] = big.NewInt(0)
	}
	for i := 0; i < len(p); i++ {
		for j := 0; j < len(q); j++ {
			a := new(big.Int)
			a.Mul(p[i], q[j])
			a.Add(a, r[i+j])
			if m != nil {
				a.Mod(a, m)
			}
			r[i+j] = a
		}
	}
	r.trim()
	return r
}

//	현 다항식을 주어진 다항식으로 나누고 몫과 나머지를 반환하는 함수.
//	modulo값을 줄 수 있고, 원하지 않을 경우 nil을 주면 된다.
//	계수를 정수만 사용할 수 있어서 계수가 정확히 정수로 나눠지지 않을 경우는
//	나눗셈을 수행할 수 없다. 따라서 이 경우에는 아래의 설명과 같이 나눗셈을 수행하지 않는다.
func (p Poly) Div(q Poly, m *big.Int) (quo, rem Poly) {
	if m != nil {
		p.sanitize(m)
		q.sanitize(m)
	}
	if p.GetDegree() < q.GetDegree() || q.isZero() {
		quo = NewPolyInts(0)
		rem = p.Clone(0)
		return
	}
	quo = make([]*big.Int, p.GetDegree()-q.GetDegree()+1)
	rem = p.Clone(0)
	for i := 0; i < len(quo); i++ {
		quo[i] = big.NewInt(0)
	}
	t := p.Clone(0)
	qd := q.GetDegree()
	for {
		td := t.GetDegree()
		rd := td - qd
		if rd < 0 || t.isZero() {
			rem = t
			break
		}
		r := new(big.Int)
		if m != nil {
			r.ModInverse(q[qd], m)
			r.Mul(r, t[td])
			r.Mod(r, m)
		} else {
			r.Div(t[td], q[qd])
		}
		// r의 값이 0이 된다는 것은 (modulo 연산을 하지 않을 때) 최고차 항이 배수 관계
		// 아닌 경우다. 이 경우에는 결과가 실수(분수)로 나오게 되는데, 본 다항식 라이브러리
		// 암호화를 위한 BigInt 다항식 계산을 위한 것으로 실수 결과가 필요 없다.
		// 따라서 처리하지 않고 몫은 0, 나머지는 나누려했던 값으로 반환한다.
		if r.Cmp(big.NewInt(0)) == 0 {
			quo = NewPolyInts(0)
			rem = p.Clone(0)
			return
		}
		u := q.Clone(rd)
		for i := rd; i < len(u); i++ { // rd 밑으로는 어차피 모두 0므로 곱셈을 할 필요 없음
			u[i].Mul(u[i], r)
			if m != nil {
				u[i].Mod(u[i], m)
			}
		}
		t = t.Sub(u, m)
		t.trim()
		quo[rd] = r
	}
	quo.trim()
	rem.trim()
	return
}

// 유클리드 알고리즘을 이용하여 최대공약 다항식을 계산하는 함수.
// 다항식 나눗셈, 나머지 연산이 구현되어 있으므로 그것을 활용
func (p Poly) Gcd(q Poly, m *big.Int) Poly {
	// fmt.Println("p:", p, ", q:", q)
	if p.Compare(&q) < 0 {
		return q.Gcd(p, m)
	}
	if q.isZero() {
		// fmt.Println("Found:", p)
		return p
	} else {
		_, rem := p.Div(q, m)
		// fmt.Println("rem:", rem)
		return q.Gcd(rem, m)
	}
}

// Eval()은 주어진 함수 p(x)에 x값을 넣었을 때 어떤 값이 나오는지 계산하는 함수.
// modulo값 m을 줄 수 있다.
func (p Poly) Eval(x *big.Int, m *big.Int) (y *big.Int) {
	y = big.NewInt(0)
	accx := big.NewInt(1)
	xd := new(big.Int)
	for i := 0; i <= p.GetDegree(); i++ {
		xd.Mul(accx, p[i])
		y.Add(y, xd)
		accx.Mul(accx, x)
		if m != nil {
			y.Mod(y, m)
			accx.Mod(accx, m)
		}
	}
	return y
}
<commit_msg>deletes NegSelf()<commit_after>package polynomial

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

// Data structure for a polynomial
// Just an array in reverse
// f(x) = 3x^3 + 2x + 1 => [1 2 0 3]
type Poly []*big.Int

// Helper function for generating a polynomial with given integers
func NewPolyInts(coeffs ...int) (p Poly) {
	p = make([]*big.Int, len(coeffs))
	for i := 0; i < len(coeffs); i++ {
		p[i] = big.NewInt(int64(coeffs[i]))
	}
	p.trim()
	return
}

// Returns a polynomial with random coefficients
// You can give the degree of the polynomial
// A random coefficients have a [0, 2^bits) integer
func RandomPoly(degree, bits int64) (p Poly) {
	p = make(Poly, degree+1)
	rr := rand.New(rand.NewSource(time.Now().UnixNano()))
	exp := big.NewInt(2)
	exp.Exp(exp, big.NewInt(bits), nil)
	for i := 0; i <= p.GetDegree(); i++ {
		p[i] = new(big.Int)
		p[i].Rand(rr, exp)
	}
	p.trim()
	return
}

// trim() makes sure that the highest coefficient never has zero value
// when you add or subtract two polynomials, sometimes the highest coefficient goes zero
// if you don't remove the highest and zero coefficient, GetDegree() returns the wrong result
func (p *Poly) trim() {
	var last int = 0
	for i := p.GetDegree(); i > 0; i-- { // why i > 0, not i >=0? do not remove the constant
		if (*p)[i].Sign() != 0 {
			last = i
			break
		}
	}
	*p = (*p)[:(last + 1)]
}

// isZero() checks if P = 0
func (p *Poly) isZero() bool {
	if p.GetDegree() == 0 && (*p)[0].Cmp(big.NewInt(0)) == 0 {
		return true
	}
	return false
}

// returns the degree
// if p = x^3 + 2x^2 + 5, GetDegree() returns 3
func (p Poly) GetDegree() int {
	return len(p) - 1
}

// pretty print
func (p Poly) String() (s string) {
	s = "["
	for i := len(p) - 1; i >= 0; i-- {
		switch p[i].Sign() {
		case -1:
			if i == len(p)-1 {
				s += "-"
			} else {
				s += " - "
			}
			if i == 0 || p[i].Int64() != -1 {
				s += p[i].String()[1:]
			}
		case 0:
			continue
		case 1:
			if i < len(p)-1 {
				s += " + "
			}
			if i == 0 || p[i].Int64() != 1 {
				s += p[i].String()
			}
		}
		if i > 0 {
			s += "x"
			if i > 1 {
				s += "^" + fmt.Sprintf("%d", i)
			}
		}
	}
	if s == "[" {
		s += "0"
	}
	s += "]"
	return
}

// Compare 함수는 두 개의 다항식을 비교한다.
// 현 다항식을 복사할 필요는 없으므로 포인터로 받으며,
// 비교 대상 다항식도 효율성을 위해 포인터로 받는다.
// 두 디항식이 동일하면 0,
// 인자로 넘겨준 다항식이 더 크면 1,
// 그렇지 않으면 -1을 반환한다.
// 알고리즘은 간단하다.
// 차수가 크면 무조건 큰 다항식이며, 차수가 같을 시에는 계수값을 비교한다.
func (p *Poly) Compare(q *Poly) int {
	switch {
	case p.GetDegree() > q.GetDegree():
		return 1
	case p.GetDegree() < q.GetDegree():
		return -1
	}
	for i := 0; i <= p.GetDegree(); i++ {
		switch (*p)[i].Cmp((*q)[i]) {
		case 1:
			return 1
		case -1:
			return -1
		}
	}
	return 0
}

// Add()는 두 다항식을 더하는 함수다.
// 추가 인자로는 modulo를 줄 수 있으며,
// modulo 연산을 하고 싶지 않을 경우에는 nil을 주면 된다.
func (p Poly) Add(q Poly, m *big.Int) Poly {
	if p.Compare(&q) < 0 {
		return q.Add(p, m)
	}
	var r Poly = make([]*big.Int, len(p))
	for i := 0; i < len(q); i++ {
		a := new(big.Int)
		a.Add(p[i], q[i])
		r[i] = a
	}
	for i := len(q); i < len(p); i++ {
		a := new(big.Int)
		a.Set(p[i])
		r[i] = a
	}
	if m != nil {
		for i := 0; i < len(p); i++ {
			r[i].Mod(r[i], m)
		}
	}
	r.trim()
	return r
}

// 주어진 다항식예 계수에 모두 마이너스를 취한 다항식을 새로 만들어서 반환한다.
func (p *Poly) Neg() Poly {
	var q Poly = make([]*big.Int, len(*p))
	for i := 0; i < len(*p); i++ {
		b := new(big.Int)
		b.Neg((*p)[i])
		q[i] = b
	}
	return q
}

// Clone()은 주어진 다항식을 deep copy하여 새로운 다항식을 만들어주는 함수.
// 인자로 주어지는 adjust 정수값은 복사를 하면서 차수 변경을 할 때 이용한다.
// adjust는 음수값을 가질 수 없으며 이 경우에는 다항식 0를 반환한다.
// adjust값만큼 차수가 높아진 상태로 반환된다.
// 예를 들어, x + 1 다항식에 adjust값을 2를 주면 x^3 + x^2가 반환된다.
// 동일한 다항식을 복사하고 싶으면 adjust에 0을 넘겨주면 된다.
func (p Poly) Clone(adjust int) Poly {
	var q Poly = make([]*big.Int, len(p)+adjust)
	if adjust < 0 {
		return NewPolyInts(0)
	}
	for i := 0; i < adjust; i++ {
		q[i] = big.NewInt(0)
	}
	for i := adjust; i < len(p)+adjust; i++ {
		b := new(big.Int)
		b.Set(p[i-adjust])
		q[i] = b
	}
	return q
}

// sanitize() 함수는 주어진 modulo 값을 이용하여,
// 현재 다항식의 계수 전체에 modulo 연산을 적용한다.
func (p *Poly) sanitize(m *big.Int) {
	if m == nil {
		return
	}
	for i := 0; i <= (*p).GetDegree(); i++ {
		(*p)[i].Mod((*p)[i], m)
	}
}

// 두 다항식을 빼는 함수. 미리 만들어둔 Add 함수를 활용하기 위해 A + (-B)로 계산한다.
func (p Poly) Sub(q Poly, m *big.Int) Poly {
	r := q.Neg()
	return p.Add(r, m)
}

// 두 다항식을 곱하는 함수.
func (p Poly) Mul(q Poly, m *big.Int) Poly {
	if m != nil {
		p.sanitize(m)
		q.sanitize(m)
	}
	var r Poly = make([]*big.Int, p.GetDegree()+q.GetDegree()+1)
	for i := 0; i < len(r); i++ {
		r[i] = big.NewInt(0)
	}
	for i := 0; i < len(p); i++ {
		for j := 0; j < len(q); j++ {
			a := new(big.Int)
			a.Mul(p[i], q[j])
			a.Add(a, r[i+j])
			if m != nil {
				a.Mod(a, m)
			}
			r[i+j] = a
		}
	}
	r.trim()
	return r
}

//	현 다항식을 주어진 다항식으로 나누고 몫과 나머지를 반환하는 함수.
//	modulo값을 줄 수 있고, 원하지 않을 경우 nil을 주면 된다.
//	계수를 정수만 사용할 수 있어서 계수가 정확히 정수로 나눠지지 않을 경우는
//	나눗셈을 수행할 수 없다. 따라서 이 경우에는 아래의 설명과 같이 나눗셈을 수행하지 않는다.
func (p Poly) Div(q Poly, m *big.Int) (quo, rem Poly) {
	if m != nil {
		p.sanitize(m)
		q.sanitize(m)
	}
	if p.GetDegree() < q.GetDegree() || q.isZero() {
		quo = NewPolyInts(0)
		rem = p.Clone(0)
		return
	}
	quo = make([]*big.Int, p.GetDegree()-q.GetDegree()+1)
	rem = p.Clone(0)
	for i := 0; i < len(quo); i++ {
		quo[i] = big.NewInt(0)
	}
	t := p.Clone(0)
	qd := q.GetDegree()
	for {
		td := t.GetDegree()
		rd := td - qd
		if rd < 0 || t.isZero() {
			rem = t
			break
		}
		r := new(big.Int)
		if m != nil {
			r.ModInverse(q[qd], m)
			r.Mul(r, t[td])
			r.Mod(r, m)
		} else {
			r.Div(t[td], q[qd])
		}
		// r의 값이 0이 된다는 것은 (modulo 연산을 하지 않을 때) 최고차 항이 배수 관계
		// 아닌 경우다. 이 경우에는 결과가 실수(분수)로 나오게 되는데, 본 다항식 라이브러리
		// 암호화를 위한 BigInt 다항식 계산을 위한 것으로 실수 결과가 필요 없다.
		// 따라서 처리하지 않고 몫은 0, 나머지는 나누려했던 값으로 반환한다.
		if r.Cmp(big.NewInt(0)) == 0 {
			quo = NewPolyInts(0)
			rem = p.Clone(0)
			return
		}
		u := q.Clone(rd)
		for i := rd; i < len(u); i++ { // rd 밑으로는 어차피 모두 0므로 곱셈을 할 필요 없음
			u[i].Mul(u[i], r)
			if m != nil {
				u[i].Mod(u[i], m)
			}
		}
		t = t.Sub(u, m)
		t.trim()
		quo[rd] = r
	}
	quo.trim()
	rem.trim()
	return
}

// 유클리드 알고리즘을 이용하여 최대공약 다항식을 계산하는 함수.
// 다항식 나눗셈, 나머지 연산이 구현되어 있으므로 그것을 활용
func (p Poly) Gcd(q Poly, m *big.Int) Poly {
	// fmt.Println("p:", p, ", q:", q)
	if p.Compare(&q) < 0 {
		return q.Gcd(p, m)
	}
	if q.isZero() {
		// fmt.Println("Found:", p)
		return p
	} else {
		_, rem := p.Div(q, m)
		// fmt.Println("rem:", rem)
		return q.Gcd(rem, m)
	}
}

// Eval()은 주어진 함수 p(x)에 x값을 넣었을 때 어떤 값이 나오는지 계산하는 함수.
// modulo값 m을 줄 수 있다.
func (p Poly) Eval(x *big.Int, m *big.Int) (y *big.Int) {
	y = big.NewInt(0)
	accx := big.NewInt(1)
	xd := new(big.Int)
	for i := 0; i <= p.GetDegree(); i++ {
		xd.Mul(accx, p[i])
		y.Add(y, xd)
		accx.Mul(accx, x)
		if m != nil {
			y.Mod(y, m)
			accx.Mod(accx, m)
		}
	}
	return y
}
<|endoftext|>


<commit_before>package websocket

import (
	"encoding/json"
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"github.com/go-martini/martini"
	"github.com/gorilla/websocket"
)

type Message struct {
	Type string          `json:"type"`
	Data json.RawMessage `json:"data"`
	To   string          `json:"to"`
}
type Clients struct {
	sync.Mutex
	clients []*Client
	Router  *Router `inject:""`
}
type Client struct {
	Name       string
	in         <-chan *Message
	out        chan<- *Message
	done       <-chan bool
	err        <-chan error
	disconnect chan<- int
}

// Add a client to a room
func (r *Clients) appendClient(client *Client) {
	r.Lock()
	r.clients = append(r.clients, client)
	r.Unlock()

	msgs := r.Router.RunOnClientConnectHandlers()
	for _, msg := range msgs {
		client.out <- msg
	}
}

// Message all the other clients
func (r *Clients) SendToAll(t string, data interface{}) {

	out, err := json.Marshal(data)
	if err != nil {
		log.Error(err)
		return
	}
	msg := &Message{Type: t, Data: out}

	r.Lock()
	defer r.Unlock()
	for _, c := range r.clients {
		select {
		case c.out <- msg:
			// Everything went well :)
		case <-time.After(time.Second):
			log.Warn("Failed writing to websocket: timeout (", c.Name, ")")
		}
	}
}

// Remove a client
func (r *Clients) removeClient(client *Client) {
	r.Lock()
	defer r.Unlock()

	for index, c := range r.clients {
		if c == client {
			r.clients = append(r.clients[:index], r.clients[(index+1):]...)
		}
	}
}

// Disconnect all clients
func (r *Clients) disconnectAll() {
	r.Lock()
	defer r.Unlock()

	for _, c := range r.clients {
		c.disconnect <- websocket.CloseGoingAway
	}
}

func newClients() *Clients {
	return &Clients{sync.Mutex{}, make([]*Client, 0), nil}
}
func (clients *Clients) WebsocketRoute(params martini.Params, receiver <-chan *Message, sender chan<- *Message, done <-chan bool, disconnect chan<- int, err <-chan error) (int, string) {
	client := &Client{params["clientname"], receiver, sender, done, err, disconnect}
	clients.appendClient(client)

	// A single select can be used to do all the messaging
	for {
		select {
		case <-client.err:
			// Don't try to do this:
			// client.out <- &Message{"system", "system", "There has been an error with your connection"}
			// The socket connection is already long gone.
			// Use the error for statistics etc
		case msg := <-client.in:
			//TODO implement command from websocket here. using same process as WebHandlerCommandToNode

			log.Info("incoming message from webui on websocket", string(msg.Data))
			clients.Router.Run(msg)
		case <-client.done:
			clients.removeClient(client)
			return 200, "OK"
		}
	}
}
<commit_msg>Possible fix for bug #17<commit_after>package websocket

import (
	"encoding/json"
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"github.com/go-martini/martini"
	"github.com/gorilla/websocket"
)

type Message struct {
	Type string          `json:"type"`
	Data json.RawMessage `json:"data"`
	To   string          `json:"to"`
}
type Clients struct {
	sync.Mutex
	clients []*Client
	Router  *Router `inject:""`
}
type Client struct {
	Name       string
	in         <-chan *Message
	out        chan<- *Message
	done       <-chan bool
	err        <-chan error
	disconnect chan<- int
}

// Add a client to a room
func (r *Clients) appendClient(client *Client) {
	r.Lock()
	r.clients = append(r.clients, client)
	r.Unlock()

	msgs := r.Router.RunOnClientConnectHandlers()
	for _, msg := range msgs {
		client.out <- msg
	}
}

// Message all the other clients
func (r *Clients) SendToAll(t string, data interface{}) {

	out, err := json.Marshal(data)
	if err != nil {
		log.Error(err)
		return
	}
	msg := &Message{Type: t, Data: out}

	r.Lock()
	defer r.Unlock()
	clientsToRemove := make([]*Client, 0)

	for _, c := range r.clients {
		select {
		case c.out <- msg:
			// Everything went well :)
		case <-time.After(time.Second):
			log.Warn("Failed writing to websocket: timeout (", c.Name, ")")
			clientsToRemove = append(clientsToRemove, c)
		}
	}

	go func() {
		for _, c := range clientsToRemove {
			r.removeClient(c)
		}
	}()
}

// Remove a client
func (r *Clients) removeClient(client *Client) {
	r.Lock()
	defer r.Unlock()

	for index, c := range r.clients {
		if c == client {
			c.disconnect <- websocket.CloseInternalServerErr
			r.clients = append(r.clients[:index], r.clients[(index+1):]...)
		}
	}
}

// Disconnect all clients
func (r *Clients) disconnectAll() {
	r.Lock()
	defer r.Unlock()

	for _, c := range r.clients {
		c.disconnect <- websocket.CloseGoingAway
	}
}

func newClients() *Clients {
	return &Clients{sync.Mutex{}, make([]*Client, 0), nil}
}
func (clients *Clients) WebsocketRoute(params martini.Params, receiver <-chan *Message, sender chan<- *Message, done <-chan bool, disconnect chan<- int, err <-chan error) (int, string) {
	client := &Client{params["clientname"], receiver, sender, done, err, disconnect}
	clients.appendClient(client)

	// A single select can be used to do all the messaging
	for {
		select {
		case <-client.err:
			// Don't try to do this:
			// client.out <- &Message{"system", "system", "There has been an error with your connection"}
			// The socket connection is already long gone.
			// Use the error for statistics etc
		case msg := <-client.in:
			//TODO implement command from websocket here. using same process as WebHandlerCommandToNode

			log.Info("incoming message from webui on websocket", string(msg.Data))
			clients.Router.Run(msg)
		case <-client.done:
			clients.removeClient(client)
			return 200, "OK"
		}
	}
}
<|endoftext|>


<commit_before>package manifest_test

import (
	. "cf/manifest"
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"path/filepath"
)

var _ = Describe("ManifestDiskRepository", func() {
	var repo ManifestRepository

	BeforeEach(func() {
		repo = NewManifestDiskRepository()
	})

	Describe("given a directory containing a file called 'manifest.yml'", func() {
		It("reads that file", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests")

			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/manifest.yml")))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a directory that doesn't contain a file called 'manifest.yml", func() {
		It("returns an error", func() {
			m, errs := repo.ReadManifest("../../fixtures")

			Expect(errs).NotTo(BeEmpty())
			Expect(m.Path).To(BeEmpty())
		})
	})

	Describe("given a directory that contains a file called 'manifest.yaml'", func() {
		It("reads that file", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests/only_yaml")

			fmt.Printf("\n errors: %v", errs)
			//Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/only_yaml/manifest.yaml")))

			applications, errs := m.Applications()
			//Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a directory contains files called 'manifest.yml' and 'manifest.yaml'", func() {
		It("reads the file named 'manifest.yml'", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests/both_yaml_yml")

			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/both_yaml_yml/manifest.yml")))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a path to a file", func() {
		var (
			inputPath string
			m         *Manifest
			errs      ManifestErrors
		)

		BeforeEach(func() {
			inputPath = filepath.Clean("../../fixtures/manifests/different-manifest.yml")
			m, errs = repo.ReadManifest(inputPath)
		})

		It("reads the file at that path", func() {
			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(inputPath))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-different-manifest"))
		})

		It("passes the base directory to the manifest file", func() {
			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(len(applications)).To(Equal(1))
			Expect(*applications[0].Name).To(Equal("from-different-manifest"))

			appPath := filepath.Clean("../../fixtures/manifests")
			Expect(*applications[0].Path).To(Equal(appPath))
		})
	})

	Describe("given a path to a file that doesn't exist", func() {
		It("returns an error", func() {
			_, errs := repo.ReadManifest("some/path/that/doesnt/exist/manifest.yml")
			Expect(errs).NotTo(BeEmpty())
		})

		It("returns empty string for the manifest path", func() {
			m, _ := repo.ReadManifest("some/path/that/doesnt/exist/manifest.yml")
			Expect(m.Path).To(Equal(""))
		})
	})

	Describe("when the manifest is not valid", func() {
		It("returns an error", func() {
			_, errs := repo.ReadManifest("../../fixtures/manifests/empty-manifest.yml")

			fmt.Printf("\n errors: %v", errs)

			Expect(errs).NotTo(BeEmpty())
		})

		It("returns the path to the manifest", func() {
			inputPath := filepath.Clean("../../fixtures/manifests/empty-manifest.yml")
			m, _ := repo.ReadManifest(inputPath)
			Expect(m.Path).To(Equal(inputPath))
		})
	})

	It("converts nested maps to generic maps", func() {
		m, errs := repo.ReadManifest("../../fixtures/manifests/different-manifest.yml")
		Expect(errs).To(BeEmpty())

		applications, errs := m.Applications()
		Expect(errs).To(BeEmpty())
		Expect(*applications[0].EnvironmentVars).To(Equal(map[string]string{
			"LD_LIBRARY_PATH": "/usr/lib/somewhere",
		}))
	})

	It("merges manifests with their 'inherited' manifests", func() {
		m, errs := repo.ReadManifest("../../fixtures/manifests/inherited-manifest.yml")
		Expect(errs).To(BeEmpty())

		applications, errs := m.Applications()
		Expect(errs).To(BeEmpty())
		Expect(*applications[0].Name).To(Equal("base-app"))
		Expect(*applications[0].ServicesToBind).To(Equal([]string{"base-service"}))
		Expect(*applications[0].EnvironmentVars).To(Equal(map[string]string{
			"foo":                "bar",
			"will-be-overridden": "my-value",
		}))

		Expect(*applications[1].Name).To(Equal("my-app"))

		env := *applications[1].EnvironmentVars
		Expect(env["will-be-overridden"]).To(Equal("my-value"))
		Expect(env["foo"]).To(Equal("bar"))

		services := *applications[1].ServicesToBind
		Expect(services).To(Equal([]string{"base-service", "foo-service"}))
	})
})
<commit_msg>Fix test description<commit_after>package manifest_test

import (
	. "cf/manifest"
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"path/filepath"
)

var _ = Describe("ManifestDiskRepository", func() {
	var repo ManifestRepository

	BeforeEach(func() {
		repo = NewManifestDiskRepository()
	})

	Describe("given a directory containing a file called 'manifest.yml'", func() {
		It("reads that file", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests")

			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/manifest.yml")))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a directory that doesn't contain a file called 'manifest.y{a}ml'", func() {
		It("returns an error", func() {
			m, errs := repo.ReadManifest("../../fixtures")

			Expect(errs).NotTo(BeEmpty())
			Expect(m.Path).To(BeEmpty())
		})
	})

	Describe("given a directory that contains a file called 'manifest.yaml'", func() {
		It("reads that file", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests/only_yaml")

			fmt.Printf("\n errors: %v", errs)
			//Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/only_yaml/manifest.yaml")))

			applications, errs := m.Applications()
			//Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a directory contains files called 'manifest.yml' and 'manifest.yaml'", func() {
		It("reads the file named 'manifest.yml'", func() {
			m, errs := repo.ReadManifest("../../fixtures/manifests/both_yaml_yml")

			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(filepath.Clean("../../fixtures/manifests/both_yaml_yml/manifest.yml")))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-default-manifest"))
		})
	})

	Describe("given a path to a file", func() {
		var (
			inputPath string
			m         *Manifest
			errs      ManifestErrors
		)

		BeforeEach(func() {
			inputPath = filepath.Clean("../../fixtures/manifests/different-manifest.yml")
			m, errs = repo.ReadManifest(inputPath)
		})

		It("reads the file at that path", func() {
			Expect(errs).To(BeEmpty())
			Expect(m.Path).To(Equal(inputPath))

			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(*applications[0].Name).To(Equal("from-different-manifest"))
		})

		It("passes the base directory to the manifest file", func() {
			applications, errs := m.Applications()
			Expect(errs).To(BeEmpty())
			Expect(len(applications)).To(Equal(1))
			Expect(*applications[0].Name).To(Equal("from-different-manifest"))

			appPath := filepath.Clean("../../fixtures/manifests")
			Expect(*applications[0].Path).To(Equal(appPath))
		})
	})

	Describe("given a path to a file that doesn't exist", func() {
		It("returns an error", func() {
			_, errs := repo.ReadManifest("some/path/that/doesnt/exist/manifest.yml")
			Expect(errs).NotTo(BeEmpty())
		})

		It("returns empty string for the manifest path", func() {
			m, _ := repo.ReadManifest("some/path/that/doesnt/exist/manifest.yml")
			Expect(m.Path).To(Equal(""))
		})
	})

	Describe("when the manifest is not valid", func() {
		It("returns an error", func() {
			_, errs := repo.ReadManifest("../../fixtures/manifests/empty-manifest.yml")

			fmt.Printf("\n errors: %v", errs)

			Expect(errs).NotTo(BeEmpty())
		})

		It("returns the path to the manifest", func() {
			inputPath := filepath.Clean("../../fixtures/manifests/empty-manifest.yml")
			m, _ := repo.ReadManifest(inputPath)
			Expect(m.Path).To(Equal(inputPath))
		})
	})

	It("converts nested maps to generic maps", func() {
		m, errs := repo.ReadManifest("../../fixtures/manifests/different-manifest.yml")
		Expect(errs).To(BeEmpty())

		applications, errs := m.Applications()
		Expect(errs).To(BeEmpty())
		Expect(*applications[0].EnvironmentVars).To(Equal(map[string]string{
			"LD_LIBRARY_PATH": "/usr/lib/somewhere",
		}))
	})

	It("merges manifests with their 'inherited' manifests", func() {
		m, errs := repo.ReadManifest("../../fixtures/manifests/inherited-manifest.yml")
		Expect(errs).To(BeEmpty())

		applications, errs := m.Applications()
		Expect(errs).To(BeEmpty())
		Expect(*applications[0].Name).To(Equal("base-app"))
		Expect(*applications[0].ServicesToBind).To(Equal([]string{"base-service"}))
		Expect(*applications[0].EnvironmentVars).To(Equal(map[string]string{
			"foo":                "bar",
			"will-be-overridden": "my-value",
		}))

		Expect(*applications[1].Name).To(Equal("my-app"))

		env := *applications[1].EnvironmentVars
		Expect(env["will-be-overridden"]).To(Equal("my-value"))
		Expect(env["foo"]).To(Equal("bar"))

		services := *applications[1].ServicesToBind
		Expect(services).To(Equal([]string{"base-service", "foo-service"}))
	})
})
<|endoftext|>


<commit_before>package pinboard

import (
	"fmt"
	"log"
	"testing"
	"time"
)

// Test TestPostsAdd first as almost all subsequent tests rely on
// adding a post.
//
// go test -v -failfast
func TestPostsAdd(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Error(err)
	}

	err = PostsAdd(&PostsAddOptions{
		Description: "This should fail",
	})
	if err == nil {
		t.Error("error: expected missing url error")
	}

	err = PostsAdd(&PostsAddOptions{
		URL: "https://github.com/imwally/pinboard",
	})
	if err == nil {
		t.Error("error: expected must provide title error")
	}
}

func ExamplePostsAdd() {
	opt := &PostsAddOptions{
		URL:         "https://github.com/imwally/pinboard",
		Description: "Testing Pinboard Go Package",
	}

	err := PostsAdd(opt)
	if err != nil {
		log.Println("error adding post:", err)
	}
}

// Next, make sure PostsDelete works so we can remove test posts
// created in subsequent tests. This will delete the post that was
// created with TestPostsAdd.
func TestPostsDelete(t *testing.T) {
	err := PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: failed to delete test post: %s", err)
	}

	url := "https://thisisjustatest.com"
	err = PostsDelete(url)
	if err == nil {
		t.Error("error: expected item not found error")
	}
}

func TestPostsUpdate(t *testing.T) {
	timeBeforeAdd := time.Now()

	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	timeAfterAdd := time.Now()

	timeUpdate, err := PostsUpdate()
	if err != nil {
		t.Error(err)
	}

	if timeUpdate.After(timeAfterAdd) && timeUpdate.Before(timeBeforeAdd) {
		t.Errorf("error: expected %s to be between %s and %s",
			timeUpdate,
			timeBeforeAdd,
			timeAfterAdd,
		)
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}
}

func TestPostsGet(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	// Test PostsGet by URL
	posts, err := PostsGet(&PostsGetOptions{
		URL: optAdd.URL,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) > 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Test PostsGet by tag
	dt, _ := time.Parse("2006-01-02", "2010-12-11")

	posts, err = PostsGet(&PostsGetOptions{
		Dt:  dt,
		Tag: []string{"pinboard", "testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Test PostsGet by Dt
	posts, err = PostsGet(&PostsGetOptions{
		Dt: dt,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Did we get the meta signature?
	if posts[0].Meta == nil {
		t.Error("error: PostsGet: expected meta signature")
	}

	posts, err = PostsGet(&PostsGetOptions{
		Tag: []string{"sadklfjsldkfjsdlkfj"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 0 {
		t.Error("error: PostsGet: expected zero posts")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}
}

func ExamplePostsGet() {
	dt, err := time.Parse("2006-01-02", "2010-12-11")
	if err != nil {
		log.Println(err)
	}

	posts, err := PostsGet(&PostsGetOptions{Dt: dt})
	if err != nil {
		log.Println("error getting posts:", err)
	}

	for _, post := range posts {
		fmt.Println(post.Description)
		fmt.Println(post.Href)
		fmt.Println(post.Time)
	}

	// Output:
	// Testing Pinboard Go Package
	// https://github.com/imwally/pinboard
	// 2010-12-11 19:48:02 +0000 UTC
}

func TestPostsRecent(t *testing.T) {
	// Test Count
	posts, err := PostsRecent(&PostsRecentOptions{
		Count: 100,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 100 {
		t.Error("error: expected 100 posts")
	}

	err = PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	posts, err = PostsRecent(&PostsRecentOptions{
		Tag: []string{"pinboard_testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: expected 1 post")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

}

func TestPostsDates(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	dates, err := PostsDates(nil)
	if err != nil {
		t.Error(err)
	}

	expected := "2010-12-11"
	if _, ok := dates[expected]; !ok {
		t.Errorf("error: expected at least 1 post on %s", expected)
	}

	// Test with tags
	dates, err = PostsDates(&PostsDatesOptions{
		Tag: []string{"pinboard_testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(dates) != 1 {
		t.Error("error: expected only 1 post")
	}

	if _, ok := dates[expected]; !ok {
		t.Errorf("error: expected at least 1 post on %s", expected)
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

	// Make sure that date no longer appears
	dates, err = PostsDates(nil)
	if err != nil {
		t.Error(err)
	}

	if _, ok := dates[expected]; ok {
		t.Errorf("error: expected no posts on %s", expected)
	}
}

func TestPostsAll(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	posts, err := PostsAll(&PostsAllOptions{
		Results: 1,
		Fromdt:  optAdd.Dt.Add(time.Duration(-1) * time.Second),
		Todt:    optAdd.Dt.Add(time.Second),
		Tag:     []string{"pinboard", "testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Errorf("error: PostsAll: expected only 1 post")
	}

	posts, err = PostsAll(&PostsAllOptions{
		Results: 1,
		Fromdt:  optAdd.Dt.Add(time.Duration(-1) * time.Second),
		Todt:    optAdd.Dt.Add(time.Second),
		Tag:     []string{"this should fail"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 0 {
		t.Errorf("error: PostsAll: expected 0 posts")
	}

	posts, err = PostsAll(nil)
	if err != nil {
		t.Error(err)
	}

	if len(posts) < 200 {
		t.Errorf("error: PostsAll: expected more than 200 posts")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

}

// The following two tests don't require posting a bookmark to get
// suggested tags.
func TestPostsSuggestPopular(t *testing.T) {
	got, err := PostsSuggestPopular(optAdd.URL)
	if err != nil {
		t.Error(err)
	}

	if len(got) > 1 || got[0] != "code" {
		t.Error("error: expected single tag code")
	}
}

func TestPostsSuggestRecommended(t *testing.T) {
	got, err := PostsSuggestRecommended(optAdd.URL)
	if err != nil {
		t.Error(err)
	}

	if len(got) != 3 {
		t.Error("error: expected 3 tags")
	}

	if got[0] != "code" {
		t.Error("error: expected code tag")
	}

	if got[1] != "github" {
		t.Error("error: expected github tag")
	}

	if got[2] != "IFTTT" {
		t.Error("error: expected IFTTT tag")
	}
}
<commit_msg>Test posts/dates count int<commit_after>package pinboard

import (
	"fmt"
	"log"
	"testing"
	"time"
)

// Test TestPostsAdd first as almost all subsequent tests rely on
// adding a post.
//
// go test -v -failfast
func TestPostsAdd(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Error(err)
	}

	err = PostsAdd(&PostsAddOptions{
		Description: "This should fail",
	})
	if err == nil {
		t.Error("error: expected missing url error")
	}

	err = PostsAdd(&PostsAddOptions{
		URL: "https://github.com/imwally/pinboard",
	})
	if err == nil {
		t.Error("error: expected must provide title error")
	}
}

func ExamplePostsAdd() {
	opt := &PostsAddOptions{
		URL:         "https://github.com/imwally/pinboard",
		Description: "Testing Pinboard Go Package",
	}

	err := PostsAdd(opt)
	if err != nil {
		log.Println("error adding post:", err)
	}
}

// Next, make sure PostsDelete works so we can remove test posts
// created in subsequent tests. This will delete the post that was
// created with TestPostsAdd.
func TestPostsDelete(t *testing.T) {
	err := PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: failed to delete test post: %s", err)
	}

	url := "https://thisisjustatest.com"
	err = PostsDelete(url)
	if err == nil {
		t.Error("error: expected item not found error")
	}
}

func TestPostsUpdate(t *testing.T) {
	timeBeforeAdd := time.Now()

	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	timeAfterAdd := time.Now()

	timeUpdate, err := PostsUpdate()
	if err != nil {
		t.Error(err)
	}

	if timeUpdate.After(timeAfterAdd) && timeUpdate.Before(timeBeforeAdd) {
		t.Errorf("error: expected %s to be between %s and %s",
			timeUpdate,
			timeBeforeAdd,
			timeAfterAdd,
		)
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}
}

func TestPostsGet(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	// Test PostsGet by URL
	posts, err := PostsGet(&PostsGetOptions{
		URL: optAdd.URL,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) > 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Test PostsGet by tag
	dt, _ := time.Parse("2006-01-02", "2010-12-11")

	posts, err = PostsGet(&PostsGetOptions{
		Dt:  dt,
		Tag: []string{"pinboard", "testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Test PostsGet by Dt
	posts, err = PostsGet(&PostsGetOptions{
		Dt: dt,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: PostsGet: expected only 1 post")
	}

	// Did we get the meta signature?
	if posts[0].Meta == nil {
		t.Error("error: PostsGet: expected meta signature")
	}

	posts, err = PostsGet(&PostsGetOptions{
		Tag: []string{"sadklfjsldkfjsdlkfj"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 0 {
		t.Error("error: PostsGet: expected zero posts")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}
}

func ExamplePostsGet() {
	dt, err := time.Parse("2006-01-02", "2010-12-11")
	if err != nil {
		log.Println(err)
	}

	posts, err := PostsGet(&PostsGetOptions{Dt: dt})
	if err != nil {
		log.Println("error getting posts:", err)
	}

	for _, post := range posts {
		fmt.Println(post.Description)
		fmt.Println(post.Href)
		fmt.Println(post.Time)
	}

	// Output:
	// Testing Pinboard Go Package
	// https://github.com/imwally/pinboard
	// 2010-12-11 19:48:02 +0000 UTC
}

func TestPostsRecent(t *testing.T) {
	// Test Count
	posts, err := PostsRecent(&PostsRecentOptions{
		Count: 100,
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 100 {
		t.Error("error: expected 100 posts")
	}

	err = PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	posts, err = PostsRecent(&PostsRecentOptions{
		Tag: []string{"pinboard_testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Error("error: expected 1 post")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

}

func TestPostsDates(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	dates, err := PostsDates(nil)
	if err != nil {
		t.Error(err)
	}

	expected := "2010-12-11"
	if _, ok := dates[expected]; !ok {
		t.Errorf("error: expected at least 1 post on %s", expected)
	}

	// Test with tags
	dates, err = PostsDates(&PostsDatesOptions{
		Tag: []string{"pinboard_testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(dates) != 1 {
		t.Error("error: expected only 1 post")
	}

	if _, ok := dates[expected]; !ok {
		t.Errorf("error: expected at least 1 post on %s", expected)
	}

	// Test count
	if dates[expected] != 1 {
		t.Errorf("error: expected count to be 1, got %v", dates[expected])
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

	// Make sure that date no longer appears
	dates, err = PostsDates(nil)
	if err != nil {
		t.Error(err)
	}

	if _, ok := dates[expected]; ok {
		t.Errorf("error: expected no posts on %s", expected)
	}
}

func TestPostsAll(t *testing.T) {
	err := PostsAdd(optAdd)
	if err != nil {
		t.Errorf("error: failed to create test post: %s", err)
	}

	posts, err := PostsAll(&PostsAllOptions{
		Results: 1,
		Fromdt:  optAdd.Dt.Add(time.Duration(-1) * time.Second),
		Todt:    optAdd.Dt.Add(time.Second),
		Tag:     []string{"pinboard", "testing"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 1 {
		t.Errorf("error: PostsAll: expected only 1 post")
	}

	posts, err = PostsAll(&PostsAllOptions{
		Results: 1,
		Fromdt:  optAdd.Dt.Add(time.Duration(-1) * time.Second),
		Todt:    optAdd.Dt.Add(time.Second),
		Tag:     []string{"this should fail"},
	})
	if err != nil {
		t.Error(err)
	}

	if len(posts) != 0 {
		t.Errorf("error: PostsAll: expected 0 posts")
	}

	posts, err = PostsAll(nil)
	if err != nil {
		t.Error(err)
	}

	if len(posts) < 200 {
		t.Errorf("error: PostsAll: expected more than 200 posts")
	}

	// Clean up by removing test post
	err = PostsDelete(optAdd.URL)
	if err != nil {
		t.Errorf("error: clean up failed: %s", err)
	}

}

// The following two tests don't require posting a bookmark to get
// suggested tags.
func TestPostsSuggestPopular(t *testing.T) {
	got, err := PostsSuggestPopular(optAdd.URL)
	if err != nil {
		t.Error(err)
	}

	if len(got) > 1 || got[0] != "code" {
		t.Error("error: expected single tag code")
	}
}

func TestPostsSuggestRecommended(t *testing.T) {
	got, err := PostsSuggestRecommended(optAdd.URL)
	if err != nil {
		t.Error(err)
	}

	if len(got) != 3 {
		t.Error("error: expected 3 tags")
	}

	if got[0] != "code" {
		t.Error("error: expected code tag")
	}

	if got[1] != "github" {
		t.Error("error: expected github tag")
	}

	if got[2] != "IFTTT" {
		t.Error("error: expected IFTTT tag")
	}
}
<|endoftext|>


<commit_before>package totp

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
  "strings"
  time "time"
	"fmt"
  "errors"
  "hash"
	"strconv"
	"log"
	big "math/big"
)

/*
 * This is an implementation of the OATH TOTP algorithm based on RFC 6238 and RFC 4226
 * Visit www.openauthentication.org for more information.
 *
 * @author Pietro Tollot, Zero12 s.r.l
 */

 /*
  * This function uses the crypto package to provide the crypto algorithm.
  * HMAC computes a Hashed Message Authentication Code with the
  * crypto hash algorithm as a parameter.
  *
  * @param crypto: the crypto algorithm [HmacSHA1 | HmacSHA256 | HmacSHA512]
  * @param keyBytes: the bytes to use for the HMAC key
  * @param text: the message or text to be authenticated
  */

func hmac_sha(crypto string, keyBytes []byte, text []byte) ([]byte, error) {

  var mac hash.Hash
  var hashed_text []byte

  switch crypto {
    default: return nil, errors.New("crypto: algorithm not found")
    case "HmacSHA1": mac = hmac.New(sha1.New, keyBytes)
    case "HmacSHA256": mac = hmac.New(sha256.New, keyBytes)
    case "HmacSHA512": mac = hmac.New(sha512.New, keyBytes)
  }

  mac.Write(text)
  hashed_text = mac.Sum(nil)

  return hashed_text, nil
}

func hexStr2Bytes(hex string) []byte{
		// Adding one byte to get the right conversion
		// Values starting with "0" can be converted
		var bArray []byte
		temp := big.NewInt(0)
		temp, _ = temp.SetString("10" + hex, 16)
		bArray = temp.Bytes()

		// Copy all the REAL bytes, not the "first"
		ret := bArray[1:]
		return ret;
}

 var DIGITS_POWER = [9]int{1,10,100,1000,10000,100000,1000000,10000000,100000000}

/*
 * These funtions generates a TOTP value for the given set of parameters.
 *
 * @param key: the shared secret, HEX encoded
 * @param time: a value that reflects a time
 * @param returnDigits: number of digits to return
 *
 * @return: a numeric String in base 10 that includes
 *              {@link truncationDigits} digits
 */

func generateTOTP1(key, time, returnDigits string) (string, error){
		hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA1")
		if err != nil {
				return "", err
		}
    return hashCode, nil
}

func generateTOTP256(key, time, returnDigits string) (string, error){
	hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA256")
	if err != nil {
			return "", err
	}
	return hashCode, nil
}

func generateTOTP512(key, time, returnDigits string) (string, error){
	hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA512")
	if err != nil {
			return "", err
	}
	return hashCode, nil
}

/*
 * This function generates a TOTP value for the given
 * set of parameters.
 *
 * @param key: the shared secret, HEX encoded
 * @param time: a value that reflects a time
 * @param returnDigits: number of digits to return
 * @param crypto: the crypto function to use
 *
 * @return: a numeric String in base 10 that includes
 *              {@link truncationDigits} digits
 */

 func generateTOTP(key, time, returnDigits, crypto string) (string, error){

  codeDigits, err := strconv.Atoi(returnDigits)
	if err != nil {
		return "", err
	}

  keyBytes := hexStr2Bytes(key)  // Get the HEX in a Byte[]
  if err != nil {
    return "", err
  }

  for len(time) < 16 {
      time = "0" + time
		}

  msg := hexStr2Bytes(time)  // Get the HEX in a Byte[]
  if err != nil {
    return "", err
  }

	var hash []byte

  hash, err = hmac_sha(crypto, keyBytes, msg)
	if err != nil {
    return "", err
  }

	// truncate the hashed value
  off := hash[len(hash) - 1] & 0xf;
	offset := int64(off)

	var binar [4]byte

	binar[0] = (hash[offset] & 0x7f)
	binar[1] = (hash[offset + 1])
	binar[2] = (hash[offset + 2])
	binar[3] = (hash[offset + 3])

	binarSlice := binar[:]

	// see array byte as integer
	temp := big.NewInt(0)
	binary := temp.SetBytes(binarSlice)

  otp := binary.Uint64() % uint64(DIGITS_POWER[codeDigits])

	result := strconv.FormatInt(int64(otp), 10)

	// limit digits
  for len(result) < codeDigits {
      result = "0" + result;
  }

  return result, nil
}

//===============
//=== singleton
//===============
// a singleton implementation of a totp verifier that uses
// the procedures defined above

var TotpReference *TotpServer

func init(){
	initObj, err := totpFactory("HmacSHA1", 30, 0)
	TotpReference = initObj
	if err != nil {
		log.Fatal(err)
	}
}

type TotpServer struct {
	seeds 		map[string] string
	method 		string
	interval 	int64
	T0 				int64
}

// factory of a TotpServer with:
// @method:    [HmacSHA1 | HmacSHA256 | HmacSHA512]
// @interval:  interval after wich totp change
// @T0:				 time offset from Unix time

func totpFactory(method string, interval, T0 int64) (*TotpServer, error){

	if method != "HmacSHA1" && method != "Hmac256" && method != "Hmac512" {
		return nil, fmt.Errorf("unkonwn method")
	}

	var totpObj *TotpServer = &TotpServer{}
	totpObj.method = method
	totpObj.interval = interval
	totpObj.T0 = T0

	totpObj.seeds = map[string]string{}

	return totpObj, nil
}

// associate user with seed
func (this *TotpServer) Register(username string, seed string) {
	this.seeds[username] = seed
}

func (this *TotpServer) Delete(username string) {
	delete(this.seeds, username)
}

// get list of users registered
func (this *TotpServer) GetUsernames() []string {
		var keys []string
    for k := range this.seeds {
        keys = append(keys, k)
    }
		return keys
}

// verify if a user is in the struct
func (this *TotpServer) UserVerify(username string) bool{
	_, present := this.seeds[username]
	return present
}

// verify if the passcode is correct for the user passed
func (this *TotpServer) Verify(username, passcode string) (bool, error){
	now := time.Now()
	seconds := now.Unix()
	var counter int64 = ((seconds - this.T0)/this.interval)

	steps := strconv.FormatInt(counter, 16)
	steps = strings.ToUpper(steps)
	for len(steps) < 16 {
		 steps = "0" + steps
	 }

	code, err:= generateTOTP(this.seeds[username], steps, "8", this.method)
	if err != nil {
		 return false, err
	 }

	 if code == passcode {
		 return true, nil
	 }else{
		 return false, nil
	 }

}
<commit_msg>Removed comment<commit_after>package totp

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
  "strings"
  time "time"
	"fmt"
  "errors"
  "hash"
	"strconv"
	"log"
	big "math/big"
)

/*
 * This is an implementation of the OATH TOTP algorithm based on RFC 6238 and RFC 4226
 * Visit www.openauthentication.org for more information.
 *
 * @author Pietro Tollot, Zero12 s.r.l
 */

 /*
  * This function uses the crypto package to provide the crypto algorithm.
  * HMAC computes a Hashed Message Authentication Code with the
  * crypto hash algorithm as a parameter.
  *
  * @param crypto: the crypto algorithm [HmacSHA1 | HmacSHA256 | HmacSHA512]
  * @param keyBytes: the bytes to use for the HMAC key
  * @param text: the message or text to be authenticated
  */

func hmac_sha(crypto string, keyBytes []byte, text []byte) ([]byte, error) {

  var mac hash.Hash
  var hashed_text []byte

  switch crypto {
    default: return nil, errors.New("crypto: algorithm not found")
    case "HmacSHA1": mac = hmac.New(sha1.New, keyBytes)
    case "HmacSHA256": mac = hmac.New(sha256.New, keyBytes)
    case "HmacSHA512": mac = hmac.New(sha512.New, keyBytes)
  }

  mac.Write(text)
  hashed_text = mac.Sum(nil)

  return hashed_text, nil
}

func hexStr2Bytes(hex string) []byte{
		// Adding one byte to get the right conversion
		// Values starting with "0" can be converted
		var bArray []byte
		temp := big.NewInt(0)
		temp, _ = temp.SetString("10" + hex, 16)
		bArray = temp.Bytes()

		// Copy all the REAL bytes, not the "first"
		ret := bArray[1:]
		return ret;
}

 var DIGITS_POWER = [9]int{1,10,100,1000,10000,100000,1000000,10000000,100000000}

/*
 * These funtions generates a TOTP value for the given set of parameters.
 *
 * @param key: the shared secret, HEX encoded
 * @param time: a value that reflects a time
 * @param returnDigits: number of digits to return
 *
 * @return: a numeric String in base 10 that includes
 *              {@link truncationDigits} digits
 */

func generateTOTP1(key, time, returnDigits string) (string, error){
		hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA1")
		if err != nil {
				return "", err
		}
    return hashCode, nil
}

func generateTOTP256(key, time, returnDigits string) (string, error){
	hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA256")
	if err != nil {
			return "", err
	}
	return hashCode, nil
}

func generateTOTP512(key, time, returnDigits string) (string, error){
	hashCode, err := generateTOTP(key, time, returnDigits, "HmacSHA512")
	if err != nil {
			return "", err
	}
	return hashCode, nil
}

/*
 * This function generates a TOTP value for the given
 * set of parameters.
 *
 * @param key: the shared secret, HEX encoded
 * @param time: a value that reflects a time
 * @param returnDigits: number of digits to return
 * @param crypto: the crypto function to use
 *
 * @return: a numeric String in base 10 that includes
 *              {@link truncationDigits} digits
 */

 func generateTOTP(key, time, returnDigits, crypto string) (string, error){

  codeDigits, err := strconv.Atoi(returnDigits)
	if err != nil {
		return "", err
	}

  keyBytes := hexStr2Bytes(key)  // Get the HEX in a Byte[]
  if err != nil {
    return "", err
  }

  for len(time) < 16 {
      time = "0" + time
		}

  msg := hexStr2Bytes(time)  // Get the HEX in a Byte[]
  if err != nil {
    return "", err
  }

	var hash []byte

  hash, err = hmac_sha(crypto, keyBytes, msg)
	if err != nil {
    return "", err
  }

	// truncate the hashed value
  off := hash[len(hash) - 1] & 0xf;
	offset := int64(off)

	var binar [4]byte

	binar[0] = (hash[offset] & 0x7f)
	binar[1] = (hash[offset + 1])
	binar[2] = (hash[offset + 2])
	binar[3] = (hash[offset + 3])

	binarSlice := binar[:]

	// see array byte as integer
	temp := big.NewInt(0)
	binary := temp.SetBytes(binarSlice)

  otp := binary.Uint64() % uint64(DIGITS_POWER[codeDigits])

	result := strconv.FormatInt(int64(otp), 10)

	// limit digits
  for len(result) < codeDigits {
      result = "0" + result;
  }

  return result, nil
}

var TotpReference *TotpServer

func init(){
	initObj, err := totpFactory("HmacSHA1", 30, 0)
	TotpReference = initObj
	if err != nil {
		log.Fatal(err)
	}
}

type TotpServer struct {
	seeds 		map[string] string
	method 		string
	interval 	int64
	T0 				int64
}

// factory of a TotpServer with:
// @method:    [HmacSHA1 | HmacSHA256 | HmacSHA512]
// @interval:  interval after wich totp change
// @T0:				 time offset from Unix time

func totpFactory(method string, interval, T0 int64) (*TotpServer, error){

	if method != "HmacSHA1" && method != "Hmac256" && method != "Hmac512" {
		return nil, fmt.Errorf("unkonwn method")
	}

	var totpObj *TotpServer = &TotpServer{}
	totpObj.method = method
	totpObj.interval = interval
	totpObj.T0 = T0

	totpObj.seeds = map[string]string{}

	return totpObj, nil
}

// associate user with seed
func (this *TotpServer) Register(username string, seed string) {
	this.seeds[username] = seed
}

func (this *TotpServer) Delete(username string) {
	delete(this.seeds, username)
}

// get list of users registered
func (this *TotpServer) GetUsernames() []string {
		var keys []string
    for k := range this.seeds {
        keys = append(keys, k)
    }
		return keys
}

// verify if a user is in the struct
func (this *TotpServer) UserVerify(username string) bool{
	_, present := this.seeds[username]
	return present
}

// verify if the passcode is correct for the user passed
func (this *TotpServer) Verify(username, passcode string) (bool, error){
	now := time.Now()
	seconds := now.Unix()
	var counter int64 = ((seconds - this.T0)/this.interval)

	steps := strconv.FormatInt(counter, 16)
	steps = strings.ToUpper(steps)
	for len(steps) < 16 {
		 steps = "0" + steps
	 }

	code, err:= generateTOTP(this.seeds[username], steps, "8", this.method)
	if err != nil {
		 return false, err
	 }

	 if code == passcode {
		 return true, nil
	 }else{
		 return false, nil
	 }

}
<|endoftext|>


<commit_before>package totp

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/binary"
	"math"
	"time"
)

// TOTP struct where K is a byte array of user key, Digit how long the token and Window the time window in seconds
type TOTP struct {
	K          []byte
	Digit      int
	Window     uint64
	WindowSize int
}

// Validate check if the code is correct, return true or false and a map with its correspondent timestamp and PIN value.
func (t *TOTP) Validate(code uint64) (map[uint64]uint64, bool) {

	//Verify all possible PINs inside the window and compare with each PIN.
	codes := make(map[uint64]uint64)
	ok := false

	for count := 0; count <= t.WindowSize-1; count++ {
		tryNum := -(t.WindowSize-1)/2 + count
		timestamp := time.Now().Unix() + (int64(t.Window) * int64(tryNum))

		//Verify reuse case based on stored timestamps.
		// clock := uint64(time.Now().Unix() / t.Window)
		clock := uint64(timestamp) / t.Window
		C := make([]byte, 8)
		binary.BigEndian.PutUint64(C, clock)

		mac := hmac.New(sha512.New, t.K)
		mac.Write(C)

		truncate := Truncate(mac.Sum(nil), t.Digit)
		if truncate == code {
			codes[clock] = code
			ok = true
			break
		}
	}

	return codes, ok
}

// Truncate trunc hmac as the RFC says so
func Truncate(hmacres []byte, digits int) uint64 {
	offset := uint64(hmacres[19] & 0xf)
	binCode := uint64(int(hmacres[offset]&0x7f)<<24 | int(hmacres[offset+1]&0xff)<<16 | int(hmacres[offset+2]&0xff)<<8 | int(hmacres[offset+3]&0xff))
	return uint64(binCode % uint64(math.Pow10(digits)))
}

// StdTOTP Standard TOTP
var StdTOTP = TOTP{
	Window:     30,
	Digit:      6,
	WindowSize: 17,
}
<commit_msg>algorithm option on the defatul struct<commit_after>package totp

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"math"
	"time"
)

// TOTP struct where K is a byte array of user key, Digit how long the token and Window the time window in seconds
type TOTP struct {
	K          []byte
	Digit      int
	Window     uint64
	WindowSize int
	Algorithm  string
}

// Validate check if the code is correct, return true or false and a map with its correspondent timestamp and PIN value.
func (t *TOTP) Validate(code uint64) (map[uint64]uint64, bool) {

	//Verify all possible PINs inside the window and compare with each PIN.
	codes := make(map[uint64]uint64)
	ok := false

	for count := 0; count <= t.WindowSize-1; count++ {
		tryNum := -(t.WindowSize-1)/2 + count
		timestamp := time.Now().Unix() + (int64(t.Window) * int64(tryNum))

		//Verify reuse case based on stored timestamps.
		// clock := uint64(time.Now().Unix() / t.Window)
		clock := uint64(timestamp) / t.Window
		C := make([]byte, 8)
		binary.BigEndian.PutUint64(C, clock)

		alg := sha1.New
		switch t.Algorithm {
		case "SHA256":
			alg = sha256.New
		case "SHA512":
			alg = sha512.New
		}
		mac := hmac.New(alg, t.K)
		mac.Write(C)

		truncate := Truncate(mac.Sum(nil), t.Digit)
		if truncate == code {
			codes[clock] = code
			ok = true
			break
		}
	}

	return codes, ok
}

// Truncate trunc hmac as the RFC says so
func Truncate(hmacres []byte, digits int) uint64 {
	offset := uint64(hmacres[19] & 0xf)
	binCode := uint64(int(hmacres[offset]&0x7f)<<24 | int(hmacres[offset+1]&0xff)<<16 | int(hmacres[offset+2]&0xff)<<8 | int(hmacres[offset+3]&0xff))
	return uint64(binCode % uint64(math.Pow10(digits)))
}

// StdTOTP Standard TOTP
var StdTOTP = TOTP{
	Window:     30,
	Digit:      6,
	WindowSize: 17,
	Algorithm:  "SHA1",
}
<|endoftext|>


<commit_before>package probstruct

import (
  "fmt"
  "log"
)

func main() {
  bloom, err := NewBloomWithEstimate(300000, 0.01, 1)
  countminsketch, err := InitMinSketchWithEstimate(0.01, 0.01, 1)
  //bloom, err := NewBloomWithEstimate(300000000, 0.01, -1)
  fmt.Println("Initiated bloom filter with m:", bloom.m, "k:", bloom.k, "hash method:", bloom.hash)
  if err != nil { log.Fatal(err) }
  fmt.Println(len(bloom.bits))
  //fmt.Println(genBaseHashes([]byte("test1m3")))
  bloom.AddString("test1m3")
  bloom.Add([]byte("test1m2"))
  bloom.Add([]byte("lalala"))
  //for bit := range bloom.bits {
  //  if bloom.bits[bit] == true {
  //    fmt.Println(bit)
  //  }
  //}
  fmt.Println( bloom.QueryString("test1m3") )
  fmt.Println( bloom.QueryString("test3m3") )
  fmt.Println( "----------------------" )
  fmt.Println(countminsketch.width)
  fmt.Println(countminsketch.depth)
  countminsketch.AddString("test1m3")
  fmt.Println( countminsketch.QueryString("test1m3") )
  //asd := genRandomIntegers(10)
  //fmt.Println(asd)
}
<commit_msg>remove debug stuff<commit_after>package probstruct

//import (
//  "fmt"
//  "log"
//)
//
//func main() {
//  bloom, err := NewBloomWithEstimate(300000, 0.01, 1)
//  countminsketch, err := InitMinSketchWithEstimate(0.01, 0.01, 1)
//  //bloom, err := NewBloomWithEstimate(300000000, 0.01, -1)
//  fmt.Println("Initiated bloom filter with m:", bloom.m, "k:", bloom.k, "hash method:", bloom.hash)
//  if err != nil { log.Fatal(err) }
//  fmt.Println(len(bloom.bits))
//  //fmt.Println(genBaseHashes([]byte("test1m3")))
//  bloom.AddString("test1m3")
//  bloom.Add([]byte("test1m2"))
//  bloom.Add([]byte("lalala"))
//  //for bit := range bloom.bits {
//  //  if bloom.bits[bit] == true {
//  //    fmt.Println(bit)
//  //  }
//  //}
//  fmt.Println( bloom.QueryString("test1m3") )
//  fmt.Println( bloom.QueryString("test3m3") )
//  fmt.Println( "----------------------" )
//  fmt.Println(countminsketch.width)
//  fmt.Println(countminsketch.depth)
//  countminsketch.AddString("test1m3")
//  fmt.Println( countminsketch.QueryString("test1m3") )
//  //asd := genRandomIntegers(10)
//  //fmt.Println(asd)
//}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	"github.com/scgolang/sc"
)

func (c *controller) writeTree(w io.Writer, d *sc.Synthdef) error {
	buf := &bytes.Buffer{}

	if err := d.WriteJSON(buf); err != nil {
		return err
	}
	s := synthdef{}

	if err := json.NewDecoder(buf).Decode(&s); err != nil {
		return err
	}
	return tree(s, s.root(), "")
}

func tree(s synthdef, ugenIndex int, prefix string) error {
	u := s.Ugens[ugenIndex]

	fmt.Printf("%s(%d)\n", u.Name, ugenIndex)

	for i, in := range u.Inputs {
		fmt.Printf(prefix + "|- ")
		if isConstant(in) {
			fmt.Printf("%f\n", s.Constants[in.OutputIndex])
			continue
		}
		if i == len(u.Inputs)-1 {
			tree(s, in.UgenIndex, prefix+"   ")
		} else {
			tree(s, in.UgenIndex, prefix+"|  ")
		}
	}
	return nil
}
<commit_msg>use box characters in tree output<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	"github.com/scgolang/sc"
)

func (c *controller) writeTree(w io.Writer, d *sc.Synthdef) error {
	buf := &bytes.Buffer{}

	if err := d.WriteJSON(buf); err != nil {
		return err
	}
	s := synthdef{}

	if err := json.NewDecoder(buf).Decode(&s); err != nil {
		return err
	}
	return tree(s, s.root(), "")
}

func tree(s synthdef, ugenIndex int, prefix string) error {
	u := s.Ugens[ugenIndex]

	fmt.Printf("%s(%d)\n", u.Name, ugenIndex)

	for i, in := range u.Inputs {
		if i == len(u.Inputs)-1 {
			fmt.Printf(prefix + "\u2514\u2500\u2500 ")
		} else {
			fmt.Printf(prefix + "\u251c\u2500\u2500 ")
		}
		if isConstant(in) {
			fmt.Printf("%f\n", s.Constants[in.OutputIndex])
			continue
		}
		if i == len(u.Inputs)-1 {
			tree(s, in.UgenIndex, prefix+"    ")
		} else {
			tree(s, in.UgenIndex, prefix+"\u2502   ")
		}
	}
	return nil
}
<|endoftext|>