<commit_before>package dejavu

import (
	"crypto/sha256"
	"github.com/willf/bloom"
	"sync"
)

// DejaVu witnesses data and recalls if seen before.
type DejaVu interface {

	// Witness data and add to memory. Returns true if previously seen.
	Witness(data []byte) bool

	// WitnessDigest is equivalent to the Winness method but bypasses hashing
	// the data. Use this to improve performance if you already happen
	// to have the sha256 digest.
	WitnessDigest(digest [sha256.Size]byte) bool
}

//////////////////////////////////
// DETERMINISTIC IMPLEMENTATION //
//////////////////////////////////

type deterministic struct {
	buffer [][sha256.Size]byte       // ring buffer
	size   int                       // ring buffer size
	index  int                       // current ring buffer index
	lookup map[[sha256.Size]byte]int // digest -> newest index (optimization)
	mutex  *sync.Mutex
}

// NewDeterministic creates a deterministic DejaVu memory. Will remember
// most recent entries within given entrie limit and forget older entries.
func NewDeterministic(entrieLimit uint32) DejaVu {
	return &deterministic{
		buffer: make([][sha256.Size]byte, entrieLimit),
		size:   int(entrieLimit),
		index:  0,
		lookup: make(map[[sha256.Size]byte]int),
		mutex:  new(sync.Mutex),
	}
}

func (d *deterministic) WitnessDigest(digest [sha256.Size]byte) bool {
	d.mutex.Lock()

	_, familiar := d.lookup[digest] // check if previously seen

	// rm oldest lookup key if no newer entry
	maxed := len(d.buffer) == d.size // overwriting oldest entry
	if maxed && (d.lookup[d.buffer[d.index]] == d.index) {
		delete(d.lookup, d.buffer[d.index]) // no newer entries
	}

	// add entry and update index/lookup
	d.buffer[d.index] = digest
	d.lookup[digest] = d.index
	d.index = (d.index + 1) % d.size

	d.mutex.Unlock()
	return familiar
}

func (d *deterministic) Witness(data []byte) bool {
	return d.WitnessDigest(sha256.Sum256(data))
}

//////////////////////////////////
// PROBABILISTIC IMPLEMENTATION //
//////////////////////////////////

type probabilistic struct {
	filters            [2]*bloom.BloomFilter // alternatingly replaced when maxed
	entrieLimit        uint32                // filter size
	falsePositiveRatio float64               // remember for buffer switch
	index              int                   // current filter index
	entries            uint32                // entries in currently indexed filter
	mutex              *sync.Mutex
}

// NewProbabilistic creates a probabilistic DejaVu memory. Probably remembers
// most recent entries within given entrie limit and false positive ratio.
// False positive ratio should be between 0.0 and 1.0.
func NewProbabilistic(entrieLimit uint32, falsePositiveRatio float64) DejaVu {
	a := bloom.NewWithEstimates(uint(entrieLimit), falsePositiveRatio)
	b := bloom.NewWithEstimates(uint(entrieLimit), falsePositiveRatio)
	return &probabilistic{
		filters:            [2]*bloom.BloomFilter{a, b},
		entrieLimit:        entrieLimit,
		falsePositiveRatio: falsePositiveRatio,
		index:              0,
		entries:            0,
		mutex:              new(sync.Mutex),
	}
}

func (p *probabilistic) WitnessDigest(digest [sha256.Size]byte) bool {
	p.mutex.Lock()

	// check if exists
	d := digest[:]
	familiar := p.filters[0].Test(d) || p.filters[1].Test(d)

	// always add in case its from the old buffer
	p.filters[p.index].Add(d)
	p.entries++

	// switch buffers if current is maxed
	if p.entries >= p.entrieLimit {
		p.entries = 0
		p.index = (p.index + 1) % 2
		f := bloom.NewWithEstimates(uint(p.entrieLimit), p.falsePositiveRatio)
		p.filters[p.index] = f // replace old filter
	}

	p.mutex.Unlock()
	return familiar
}

func (p *probabilistic) Witness(data []byte) bool {
	return p.WitnessDigest(sha256.Sum256(data))
}
<commit_msg>added package documentation<commit_after>/*
Déjà vu: Quickly detect already witnessed data.

Limited memory of witnessed data, oldest are forgotten. Library is thread safe.
Offers deterministic and probabilistic (over an order of magnatude less memory
consuming) implementation.
*/
package dejavu

import (
	"crypto/sha256"
	"github.com/willf/bloom"
	"sync"
)

// DejaVu witnesses data and recalls if seen before.
type DejaVu interface {

	// Witness data and add to memory. Returns true if previously seen.
	Witness(data []byte) bool

	// WitnessDigest is equivalent to the Winness method but bypasses hashing
	// the data. Use this to improve performance if you already happen
	// to have the sha256 digest.
	WitnessDigest(digest [sha256.Size]byte) bool
}

//////////////////////////////////
// DETERMINISTIC IMPLEMENTATION //
//////////////////////////////////

type deterministic struct {
	buffer [][sha256.Size]byte       // ring buffer
	size   int                       // ring buffer size
	index  int                       // current ring buffer index
	lookup map[[sha256.Size]byte]int // digest -> newest index (optimization)
	mutex  *sync.Mutex
}

// NewDeterministic creates a deterministic DejaVu memory. Will remember
// most recent entries within given entrie limit and forget older entries.
func NewDeterministic(entrieLimit uint32) DejaVu {
	return &deterministic{
		buffer: make([][sha256.Size]byte, entrieLimit),
		size:   int(entrieLimit),
		index:  0,
		lookup: make(map[[sha256.Size]byte]int),
		mutex:  new(sync.Mutex),
	}
}

func (d *deterministic) WitnessDigest(digest [sha256.Size]byte) bool {
	d.mutex.Lock()

	_, familiar := d.lookup[digest] // check if previously seen

	// rm oldest lookup key if no newer entry
	maxed := len(d.buffer) == d.size // overwriting oldest entry
	if maxed && (d.lookup[d.buffer[d.index]] == d.index) {
		delete(d.lookup, d.buffer[d.index]) // no newer entries
	}

	// add entry and update index/lookup
	d.buffer[d.index] = digest
	d.lookup[digest] = d.index
	d.index = (d.index + 1) % d.size

	d.mutex.Unlock()
	return familiar
}

func (d *deterministic) Witness(data []byte) bool {
	return d.WitnessDigest(sha256.Sum256(data))
}

//////////////////////////////////
// PROBABILISTIC IMPLEMENTATION //
//////////////////////////////////

type probabilistic struct {
	filters            [2]*bloom.BloomFilter // alternatingly replaced when maxed
	entrieLimit        uint32                // filter size
	falsePositiveRatio float64               // remember for buffer switch
	index              int                   // current filter index
	entries            uint32                // entries in currently indexed filter
	mutex              *sync.Mutex
}

// NewProbabilistic creates a probabilistic DejaVu memory. Probably remembers
// most recent entries within given entrie limit and false positive ratio.
// False positive ratio should be between 0.0 and 1.0.
func NewProbabilistic(entrieLimit uint32, falsePositiveRatio float64) DejaVu {
	a := bloom.NewWithEstimates(uint(entrieLimit), falsePositiveRatio)
	b := bloom.NewWithEstimates(uint(entrieLimit), falsePositiveRatio)
	return &probabilistic{
		filters:            [2]*bloom.BloomFilter{a, b},
		entrieLimit:        entrieLimit,
		falsePositiveRatio: falsePositiveRatio,
		index:              0,
		entries:            0,
		mutex:              new(sync.Mutex),
	}
}

func (p *probabilistic) WitnessDigest(digest [sha256.Size]byte) bool {
	p.mutex.Lock()

	// check if exists
	d := digest[:]
	familiar := p.filters[0].Test(d) || p.filters[1].Test(d)

	// always add in case its from the old buffer
	p.filters[p.index].Add(d)
	p.entries++

	// switch buffers if current is maxed
	if p.entries >= p.entrieLimit {
		p.entries = 0
		p.index = (p.index + 1) % 2
		f := bloom.NewWithEstimates(uint(p.entrieLimit), p.falsePositiveRatio)
		p.filters[p.index] = f // replace old filter
	}

	p.mutex.Unlock()
	return familiar
}

func (p *probabilistic) Witness(data []byte) bool {
	return p.WitnessDigest(sha256.Sum256(data))
}
<|endoftext|>


<commit_before>// This file is part of Ringot.
/*
Copyright 2016 tSU-RooT <tsu.root@gmail.com>

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"
	"github.com/mattn/go-runewidth"
	"github.com/nsf/termbox-go"
	"unicode/utf8"
)

const (
	inputMode   = "*Input Mode*"
	confirmText = "ok?[Enter/C-g]"
	Margin      = 18
)

type buffer struct {
	content      []byte
	cursorX      int
	cursorOffset int
	mode         string
	process      func(string)
	inputing     bool
	confirm      bool
	confirmLock  lock

	linePosInfo int
}

func newBuffer() *buffer {
	return &buffer{}
}

func (bf *buffer) draw() {
	t := bf.mode
	if bf.inputing {
		t = inputMode
	}
	// Draw upper line
	width, height := getTermSize()
	fillLine(0, height-2, ColorGray2)

	info := fmt.Sprintf("User:@%s [%s]", user.ScreenName, user.UserName)
	x := width - runewidth.StringWidth(info) - 1
	drawText(info, x, height-2, ColorGreen, ColorGray2)

	info = fmt.Sprintf("L%d", bf.linePosInfo)
	x -= runewidth.StringWidth(info) + 1
	drawText(info, x, height-2, ColorWhite, ColorGray2)

	x = 2
	drawText(t, x, height-2, ColorYellow, ColorGray2)
	x += runewidth.StringWidth(t)
	termbox.SetCell(x, height-2, ' ', ColorBackground, ColorGray2)
	x++

	// Draw lower line
	con := string(bf.content[bf.cursorOffset:])
	drawText(con, 0, height-1, ColorWhite, ColorBackground)
	x = runewidth.StringWidth(con)
	if bf.confirm {
		x++
		t := confirmText
		drawText(t, x, height-1, ColorRed, ColorBackground)
		x += runewidth.StringWidth(t)
	}
	fillLine(x, height-1, ColorBackground)
}

func (bf *buffer) runeUnderCursor() (rune, int) {
	return utf8.DecodeRune(bf.content[bf.cursorX:])
}

func (bf *buffer) insertRune(r rune) {
	var u [utf8.UTFMax]byte
	s := utf8.EncodeRune(u[:], r)
	bf.content = byteSliceInsert(bf.content, u[:s], bf.cursorX)
	bf.cursorMoveForward()
}

func (bf *buffer) deleteRuneBackward() {
	if bf.cursorX == 0 {
		return
	}
	bf.cursorMoveBackward()
	_, s := bf.runeUnderCursor()
	bf.content = byteSliceRemove(bf.content, bf.cursorX, bf.cursorX+s)
}

func (bf *buffer) cursorMoveBackward() {
	if bf.cursorX <= 0 {
		return
	}
	_, s := utf8.DecodeLastRune(bf.content[:bf.cursorX])
	bf.cursorX -= s
	if bf.cursorOffset > 0 && bf.cursorX <= bf.cursorOffset+Margin {
		_, s := utf8.DecodeLastRune(bf.content[:bf.cursorOffset])
		bf.cursorOffset -= s
	}
	return
}

func (bf *buffer) cursorMoveForward() {
	if bf.cursorX >= len(bf.content) {
		return
	}
	_, size := utf8.DecodeRune(bf.content[bf.cursorX:])
	bf.cursorX += size
	width, _ := getTermSize()
	cw := runewidth.StringWidth(string(bf.content[bf.cursorOffset:bf.cursorX]))
	if cw >= width-Margin {
		_, size = utf8.DecodeRune(bf.content[bf.cursorOffset:])
		bf.cursorOffset += size
	}
}

func (bf *buffer) cursorMoveToTop() {
	bf.cursorX = 0
}

func (bf *buffer) cursorMoveToBottom() {
	bf.cursorX = len(bf.content)
}

func (bf *buffer) updateCursorPosition() {
	if (!bf.inputing) || bf.confirm || bf.cursorX < 0 || bf.cursorX > len(bf.content) {
		termbox.HideCursor()
		return
	}
	_, h := getTermSize()
	x := runewidth.StringWidth(string(bf.content[bf.cursorOffset:bf.cursorX]))
	termbox.SetCursor(x, h-1)
}

func (bf *buffer) setContent(s string) {
	b := []byte(s)
	bf.content = make([]byte, len(b), 180)
	copy(bf.content, b)
	bf.cursorX = len(b)
	bf.cursorOffset = 0
}

func (bf *buffer) setModeStr(m viewmode) {
	s := ""
	switch m {
	case home:
		s = "*Timeline View*"
	case mention:
		s = "*Mention View*"
	case conversation:
		s = "*Conversation View*"
	case usertimeline:
		s = "*UserTimeline View*"
	}
	bf.mode = s
}
<commit_msg>Fix cursor move<commit_after>// This file is part of Ringot.
/*
Copyright 2016 tSU-RooT <tsu.root@gmail.com>

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"
	"github.com/mattn/go-runewidth"
	"github.com/nsf/termbox-go"
	"unicode/utf8"
)

const (
	inputMode   = "*Input Mode*"
	confirmText = "ok?[Enter/C-g]"
	Margin      = 18
)

type buffer struct {
	content      []byte
	cursorX      int
	cursorOffset int
	mode         string
	process      func(string)
	inputing     bool
	confirm      bool
	confirmLock  lock

	linePosInfo int
}

func newBuffer() *buffer {
	return &buffer{}
}

func (bf *buffer) draw() {
	t := bf.mode
	if bf.inputing {
		t = inputMode
	}
	// Draw upper line
	width, height := getTermSize()
	fillLine(0, height-2, ColorGray2)

	info := fmt.Sprintf("User:@%s [%s]", user.ScreenName, user.UserName)
	x := width - runewidth.StringWidth(info) - 1
	drawText(info, x, height-2, ColorGreen, ColorGray2)

	info = fmt.Sprintf("L%d", bf.linePosInfo)
	x -= runewidth.StringWidth(info) + 1
	drawText(info, x, height-2, ColorWhite, ColorGray2)

	x = 2
	drawText(t, x, height-2, ColorYellow, ColorGray2)
	x += runewidth.StringWidth(t)
	termbox.SetCell(x, height-2, ' ', ColorBackground, ColorGray2)
	x++

	// Draw lower line
	con := string(bf.content[bf.cursorOffset:])
	drawText(con, 0, height-1, ColorWhite, ColorBackground)
	x = runewidth.StringWidth(con)
	if bf.confirm {
		x++
		t := confirmText
		drawText(t, x, height-1, ColorRed, ColorBackground)
		x += runewidth.StringWidth(t)
	}
	fillLine(x, height-1, ColorBackground)
}

func (bf *buffer) runeUnderCursor() (rune, int) {
	return utf8.DecodeRune(bf.content[bf.cursorX:])
}

func (bf *buffer) insertRune(r rune) {
	var u [utf8.UTFMax]byte
	s := utf8.EncodeRune(u[:], r)
	bf.content = byteSliceInsert(bf.content, u[:s], bf.cursorX)
	bf.cursorMoveForward()
}

func (bf *buffer) deleteRuneBackward() {
	if bf.cursorX == 0 {
		return
	}
	bf.cursorMoveBackward()
	_, s := bf.runeUnderCursor()
	bf.content = byteSliceRemove(bf.content, bf.cursorX, bf.cursorX+s)
}

func (bf *buffer) cursorMoveBackward() {
	if bf.cursorX <= 0 {
		return
	}
	_, s := utf8.DecodeLastRune(bf.content[:bf.cursorX])
	bf.cursorX -= s
	if bf.cursorOffset > 0 && bf.cursorX <= bf.cursorOffset+Margin {
		_, s := utf8.DecodeLastRune(bf.content[:bf.cursorOffset])
		bf.cursorOffset -= s
	}
	return
}

func (bf *buffer) cursorMoveForward() {
	if bf.cursorX >= len(bf.content) {
		return
	}
	_, size := utf8.DecodeRune(bf.content[bf.cursorX:])
	bf.cursorX += size
	width, _ := getTermSize()
	cw := runewidth.StringWidth(string(bf.content[bf.cursorOffset:bf.cursorX]))
	if cw >= width-Margin {
		_, size = utf8.DecodeRune(bf.content[bf.cursorOffset:])
		bf.cursorOffset += size
	}
}

func (bf *buffer) cursorMoveToTop() {
	bf.cursorX = 0
	bf.cursorOffset = 0
}

func (bf *buffer) cursorMoveToBottom() {
	width, _ := getTermSize()
	bf.cursorX = len(bf.content)
	cw := runewidth.StringWidth(string(bf.content))
	if cw >= width-Margin {
		bf.cursorOffset = cw - (width - Margin)
	}

}

func (bf *buffer) updateCursorPosition() {
	if (!bf.inputing) || bf.confirm || bf.cursorX < 0 || bf.cursorX > len(bf.content) {
		termbox.HideCursor()
		return
	}
	_, h := getTermSize()
	x := runewidth.StringWidth(string(bf.content[bf.cursorOffset:bf.cursorX]))
	termbox.SetCursor(x, h-1)
}

func (bf *buffer) setContent(s string) {
	b := []byte(s)
	bf.content = make([]byte, len(b), 180)
	copy(bf.content, b)
	bf.cursorX = len(b)
	bf.cursorOffset = 0
}

func (bf *buffer) setModeStr(m viewmode) {
	s := ""
	switch m {
	case home:
		s = "*Timeline View*"
	case mention:
		s = "*Mention View*"
	case conversation:
		s = "*Conversation View*"
	case usertimeline:
		s = "*UserTimeline View*"
	}
	bf.mode = s
}
<|endoftext|>


<commit_before>// Copyright 2015 Lukas Weber. All rights reserved.
// Use of this source code is governed by the MIT-styled
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"strings"

	termbox "github.com/nsf/termbox-go"
)

// A Buffer is a screen of the ui. Buffers are opened on a stack.
type Buffer interface {
	// Draw content on the screen
	Draw()
	// Title displayed in the bottom bar. It has to identify buffer uniquely.
	Title() string
	// Name of the buffer
	Name() string
	// Close the Buffer
	Close()

	// HandleCommand handles string commands. If it returns bool, the
	// command was accepted. If not, it was invalid.
	HandleCommand(cmd string, args []string, stack *BufferStack) bool
}

// BufferStack is the Stack structure managing drawing of the screen and
// buffers.
type BufferStack struct {
	buffers []Buffer

	prompt Prompt
}

func invalidCommand(cmd string) {
	StatusLine = "invalid command: " + cmd
}

func (b *BufferStack) Init() {
	fields := strings.Fields(config.General.Initial_Command)
	if len(fields) > 0 {
		accept := b.handleCommand(fields[0], fields[1:])
		if !accept {
			invalidCommand(fields[0])
		}
		if len(b.buffers) == 0 {
			b.Push(NewSearchBuffer(""))
		}
	}
}

func (b *BufferStack) Push(n Buffer) {
	for i, buf := range b.buffers {
		// If the buffer already exists, change to it instead.
		if buf.Name() == n.Name() && buf.Title() == n.Title() {
			n.Close()
			copy(b.buffers[i:], b.buffers[i+1:])
			b.buffers[len(b.buffers)-1] = buf
			b.refresh()
			return
		}
	}
	b.buffers = append(b.buffers, n)
	b.refresh()
}

// This string will be displayed at the bottom of the screen. useful for error messages.
var StatusLine string

func (b *BufferStack) Pop() {
	if len(b.buffers) == 0 {
		return
	}
	b.buffers[len(b.buffers)-1].Close()
	b.buffers = b.buffers[:len(b.buffers)-1]
	b.refresh()
}

func (b *BufferStack) refresh() {
	termbox.Clear(0, 0)
	if len(b.buffers) == 0 {
		return
	}
	b.buffers[len(b.buffers)-1].Draw()
	w, h := termbox.Size()
	cbuf := termbox.CellBuffer()
	for i := 0; i < w; i++ {
		cbuf[(h-2)*w+i].Bg = termbox.Attribute(config.Theme.BottomBar)
		cbuf[(h-2)*w+i].Fg = termbox.AttrBold
	}
	title := b.buffers[len(b.buffers)-1].Title()
	name := b.buffers[len(b.buffers)-1].Name()
	printLine(0, h-2, fmt.Sprintf("[%d: %s] %s", len(b.buffers)-1, name, title), -1, -1)
	if b.prompt.Active() {
		b.prompt.Draw()
	} else if StatusLine != "" {
		_, h := termbox.Size()
		printLine(0, h-1, StatusLine, -1, -1)
	}
	termbox.Flush()
}

func (b *BufferStack) handleCommand(cmd string, args []string) bool {
	switch cmd {
	case "close":
		b.Pop()
	case "quit":
		for len(b.buffers) > 0 {
			b.Pop()
		}
	case "search":
		b.Push(NewSearchBuffer(strings.Join(args, " ")))
	case "compose":
		b.Push(NewComposeBuffer(composeMail()))
	case "help":
		b.Push(&HelpBuffer{b.buffers[len(b.buffers)-1].Name()})
	case "prompt":
		StatusLine = ""
		b.prompt.Activate(strings.Join(args, " "))
	default:
		return false
	}
	return true
}

func (b *BufferStack) HandleEvent(event *termbox.Event) {
	if len(b.buffers) == 0 {
		return
	}
	if event.Type == termbox.EventResize {
		for _, buf := range b.buffers {
			buf.HandleCommand("resize", nil, b)
		}
		b.refresh()
		return
	}

	if event.Type == termbox.EventKey {
		if b.prompt.Active() {
			cmd, args := b.prompt.HandleEvent(event)
			if len(cmd) != 0 {
				accept := b.buffers[len(b.buffers)-1].HandleCommand(cmd, args, b)
				if !accept {
					accept = b.handleCommand(cmd, args)
				}
				if !accept {
					invalidCommand(cmd)
				}
				_, h := termbox.Size()
				printLine(0, h-1, StatusLine, -1, -1)
			}
			return
		}
		cmd := getBinding("", event.Ch, event.Key)
		accept := false
		if cmd == nil {
			cmd := getBinding(b.buffers[len(b.buffers)-1].Name(), event.Ch, event.Key)
			if cmd == nil {
				return
			}
			accept = b.buffers[len(b.buffers)-1].HandleCommand(cmd.Command, cmd.Args, b)
		} else {
			accept = b.handleCommand(cmd.Command, cmd.Args)
		}
		if !accept {
			invalidCommand(cmd.Command)
		}

		if StatusLine != "" {
			_, h := termbox.Size()
			printLine(0, h-1, StatusLine, -1, -1)
		}
	}

}
<commit_msg>fix resizes<commit_after>// Copyright 2015 Lukas Weber. All rights reserved.
// Use of this source code is governed by the MIT-styled
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"strings"

	termbox "github.com/nsf/termbox-go"
)

// A Buffer is a screen of the ui. Buffers are opened on a stack.
type Buffer interface {
	// Draw content on the screen
	Draw()
	// Title displayed in the bottom bar. It has to identify buffer uniquely.
	Title() string
	// Name of the buffer
	Name() string
	// Close the Buffer
	Close()

	// HandleCommand handles string commands. If it returns bool, the
	// command was accepted. If not, it was invalid.
	HandleCommand(cmd string, args []string, stack *BufferStack) bool
}

// BufferStack is the Stack structure managing drawing of the screen and
// buffers.
type BufferStack struct {
	buffers []Buffer

	prompt Prompt
}

func invalidCommand(cmd string) {
	StatusLine = "invalid command: " + cmd
}

func (b *BufferStack) Init() {
	fields := strings.Fields(config.General.Initial_Command)
	if len(fields) > 0 {
		accept := b.handleCommand(fields[0], fields[1:])
		if !accept {
			invalidCommand(fields[0])
		}
		if len(b.buffers) == 0 {
			b.Push(NewSearchBuffer(""))
		}
	}
}

func (b *BufferStack) Push(n Buffer) {
	for i, buf := range b.buffers {
		// If the buffer already exists, change to it instead.
		if buf.Name() == n.Name() && buf.Title() == n.Title() {
			n.Close()
			copy(b.buffers[i:], b.buffers[i+1:])
			b.buffers[len(b.buffers)-1] = buf
			b.refresh()
			return
		}
	}
	b.buffers = append(b.buffers, n)
	b.refresh()
}

// This string will be displayed at the bottom of the screen. useful for error messages.
var StatusLine string

func (b *BufferStack) Pop() {
	if len(b.buffers) == 0 {
		return
	}
	b.buffers[len(b.buffers)-1].Close()
	b.buffers = b.buffers[:len(b.buffers)-1]
	b.refresh()
}

func (b *BufferStack) refresh() {
	termbox.Clear(0, 0)
	if len(b.buffers) == 0 {
		return
	}
	b.buffers[len(b.buffers)-1].Draw()
	w, h := termbox.Size()
	cbuf := termbox.CellBuffer()
	for i := 0; i < w; i++ {
		cbuf[(h-2)*w+i].Bg = termbox.Attribute(config.Theme.BottomBar)
		cbuf[(h-2)*w+i].Fg = termbox.AttrBold
	}
	title := b.buffers[len(b.buffers)-1].Title()
	name := b.buffers[len(b.buffers)-1].Name()
	printLine(0, h-2, fmt.Sprintf("[%d: %s] %s", len(b.buffers)-1, name, title), -1, -1)
	if b.prompt.Active() {
		b.prompt.Draw()
	} else if StatusLine != "" {
		_, h := termbox.Size()
		printLine(0, h-1, StatusLine, -1, -1)
	}
	termbox.Flush()
}

func (b *BufferStack) handleCommand(cmd string, args []string) bool {
	switch cmd {
	case "close":
		b.Pop()
	case "quit":
		for len(b.buffers) > 0 {
			b.Pop()
		}
	case "search":
		b.Push(NewSearchBuffer(strings.Join(args, " ")))
	case "compose":
		b.Push(NewComposeBuffer(composeMail()))
	case "help":
		b.Push(&HelpBuffer{b.buffers[len(b.buffers)-1].Name()})
	case "prompt":
		StatusLine = ""
		b.prompt.Activate(strings.Join(args, " "))
	default:
		return false
	}
	return true
}

func (b *BufferStack) HandleEvent(event *termbox.Event) {
	if len(b.buffers) == 0 {
		return
	}
	if event.Type == termbox.EventResize {
		termbox.Flush()
		for _, buf := range b.buffers {
			buf.HandleCommand("resize", nil, b)
		}
		b.refresh()
		return
	}

	if event.Type == termbox.EventKey {
		if b.prompt.Active() {
			cmd, args := b.prompt.HandleEvent(event)
			if len(cmd) != 0 {
				accept := b.buffers[len(b.buffers)-1].HandleCommand(cmd, args, b)
				if !accept {
					accept = b.handleCommand(cmd, args)
				}
				if !accept {
					invalidCommand(cmd)
				}
				_, h := termbox.Size()
				printLine(0, h-1, StatusLine, -1, -1)
			}
			return
		}
		cmd := getBinding("", event.Ch, event.Key)
		accept := false
		if cmd == nil {
			cmd := getBinding(b.buffers[len(b.buffers)-1].Name(), event.Ch, event.Key)
			if cmd == nil {
				return
			}
			accept = b.buffers[len(b.buffers)-1].HandleCommand(cmd.Command, cmd.Args, b)
		} else {
			accept = b.handleCommand(cmd.Command, cmd.Args)
		}
		if !accept {
			invalidCommand(cmd.Command)
		}

		if StatusLine != "" {
			_, h := termbox.Size()
			printLine(0, h-1, StatusLine, -1, -1)
		}
	}

}
<|endoftext|>


<commit_before>package dargo

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
)

// DeployOptions control attributes about the resulting Docker Image
type DeployOptions struct {
	Tags []string
}

// Deploy deploys to the Docker engine reachable via environment variables and
// defaults.
func Deploy(o DeployOptions) error {

	buildOptions := types.ImageBuildOptions{
		Tags: o.Tags,
	}

	cli, err := client.NewEnvClient()
	if err != nil {
		return err
	}

	self, err := makeTar()
	if err != nil {
		return err
	}

	buildResponse, err := cli.ImageBuild(context.Background(), self, buildOptions)
	if err != nil {
		return err
	}
	defer buildResponse.Body.Close()

	all, err := ioutil.ReadAll(buildResponse.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(all))
	return nil
}

// DeployAndExit checks to see if we're Enabled, then calls Deploy, logging
// Fatal errors, then exiting
func DeployAndExit(o DeployOptions) {
	if !Enable {
		return
	}
	if err := Deploy(o); err != nil {
		log.Fatal(err)
	}
	os.Exit(0)
}
<commit_msg>Refactored building the image out of the big Deploy function<commit_after>package dargo

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
)

// DeployOptions control attributes about the resulting Docker Image
type DeployOptions struct {
	Tags []string
}

func buildImage(buildOptions types.ImageBuildOptions, cli *client.Client) error {
	self, err := makeTar()
	if err != nil {
		return fmt.Errorf("Error building tar for image build: %v", err)
	}

	buildResponse, err := cli.ImageBuild(context.Background(), self, buildOptions)
	if err != nil {
		return fmt.Errorf("Error starting image build: %v", err)
	}
	defer buildResponse.Body.Close()

	all, err := ioutil.ReadAll(buildResponse.Body)
	if err != nil {
		return fmt.Errorf("Error reading from docker client: %v", err)
	}
	fmt.Println(string(all))

	return nil
}

// Deploy deploys to the Docker engine reachable via environment variables and
// defaults.
func Deploy(o DeployOptions) error {

	buildOptions := types.ImageBuildOptions{
		Tags: o.Tags,
	}

	cli, err := client.NewEnvClient()
	if err != nil {
		return fmt.Errorf("Error creating docker client: %v", err)
	}

	err = buildImage(buildOptions, cli)
	if err != nil {
		return fmt.Errorf("Error building image: %v", err)
	}

	return nil
}

// DeployAndExit checks to see if we're Enabled, then calls Deploy, logging
// Fatal errors, then exiting
func DeployAndExit(o DeployOptions) {
	if !Enable {
		return
	}
	if err := Deploy(o); err != nil {
		log.Fatal(err)
	}
	os.Exit(0)
}
<|endoftext|>


<commit_before>/***** BEGIN LICENSE BLOCK *****
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# The Initial Developer of the Original Code is the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2014
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#   Ian Neubert (ian@ianneubert.com)
#
# ***** END LICENSE BLOCK *****/

package tutum

import (
  . "github.com/mozilla-services/heka/pipeline"
  "github.com/mozilla-services/heka/message"
  // "fmt"
  // "time"
)

type TutumDecoderConfig struct {
  // Map of message field names to message string values. Note that all
  // values *must* be strings. Any specified Pid and Severity field values
  // must be parseable as int32. Any specified Timestamp field value will be
  // parsed against the specified TimestampLayout. All specified user fields
  // will be created as strings.
  MessageFields MessageTemplate `toml:"message_fields"`
  ApiKey []string `toml:"api_key"`
}

type TutumDecoder struct {
  messageFields MessageTemplate
  apikey []string
}

func (td *TutumDecoder) ConfigStruct() interface{} {
  return new(TutumDecoderConfig)
}

func (td *TutumDecoder) Init(config interface{}) (err error) {
  conf := config.(*TutumDecoderConfig)
  td.messageFields = conf.MessageFields
  td.apikey = conf.ApiKey
  return
}

func (td *TutumDecoder) Decode(pack *PipelinePack) (packs []*PipelinePack, err error) {
  // fmt.Printf("Message: %v\n", pack.Message)
  // fmt.Printf("Tags: %v\n", td.tags)

  field := message.NewFieldInit("Tags", message.Field_STRING, "")
  for _, value := range td.tags {
    field.AddValue(value)
  }
  pack.Message.AddField(field)
  // fmt.Printf("Message: %v\n", pack.Message)
  if err = td.messageFields.PopulateMessage(pack.Message, nil); err != nil {
    return
  }
  // time.Sleep(1 * time.Second)
  // fmt.Printf("Message: %v\n", pack.Message)
  return []*PipelinePack{pack}, nil
}

func init() {
  RegisterPlugin("TutumDecoder", func() interface{} {
    return new(TutumDecoder)
  })
}
<commit_msg>First draft of decoder.<commit_after>/***** BEGIN LICENSE BLOCK *****
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# The Initial Developer of the Original Code is the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2014
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#   Ian Neubert (ian@ianneubert.com)
#
# ***** END LICENSE BLOCK *****/

package tutum

import (
  . "github.com/mozilla-services/heka/pipeline"
  "github.com/mozilla-services/heka/message"
  "net/http"
  "fmt"
  "encoding/json"
  "io/ioutil"
)

type TutumDecoderConfig struct {
  // Map of message field names to message string values. Note that all
  // values *must* be strings. Any specified Pid and Severity field values
  // must be parseable as int32. Any specified Timestamp field value will be
  // parsed against the specified TimestampLayout. All specified user fields
  // will be created as strings.
  MessageFields MessageTemplate `toml:"message_fields"`
  Auth string `toml:"auth"`
}

type TutumDecoder struct {
  messageFields MessageTemplate
  auth string
  services map[string]tutumService
}

type tutumService struct {
  Id string `json:"uuid"`
  Name string `json:"name"`
}

type tutumContainer struct {
  Id string `json:"uuid"`
  Name string `json:"name"`
  ServicePath string `json:"service"`
}

type tutumStack struct {
  Id string `json:"uuid"`
  Name string `json:"name"`
}

func (td *TutumDecoder) ConfigStruct() interface{} {
  return new(TutumDecoderConfig)
}

func (td *TutumDecoder) Init(config interface{}) (err error) {
  conf := config.(*TutumDecoderConfig)
  td.messageFields = conf.MessageFields
  td.auth = conf.Auth
  td.services = make(map[string]tutumService)
  return
}

func (td *TutumDecoder) Decode(pack *PipelinePack) (packs []*PipelinePack, err error) {
  // fmt.Printf("Message: %v\n", pack.Message)

  // get ContainerName
  container_name := pack.Message.FindFirstField("ContainerName").GetValueString()[0]

  // if ContainerName is NOT in cache; then get it
  service, ok := td.services[container_name]
  if !ok {
    // find the value
    service, err = td.get_tutum_service(container_name)
    if err != nil {
      return
    }

    // save the value to the cache
    td.services[container_name] = service
  }

  // add fields to message with tutum data
  field := message.NewFieldInit("TutumServiceName", message.Field_STRING, "")
  field.AddValue(service.Name)
  pack.Message.AddField(field)

  field = message.NewFieldInit("TutumServiceId", message.Field_STRING, "")
  field.AddValue(service.Id)
  pack.Message.AddField(field)

  // fmt.Printf("Message: %v\n", pack.Message)
  if err = td.messageFields.PopulateMessage(pack.Message, nil); err != nil {
    return
  }

  // fmt.Printf("Message: %v\n", pack.Message)
  return []*PipelinePack{pack}, nil
}

func (td *TutumDecoder) get_tutum_service(container_name string) (service tutumService, err error) {
  fmt.Printf("Finding Tutum service from container named: %s\n", container_name)

  // get container information
  url := fmt.Sprintf("/api/v1/container/%s/", container_name)
  data, err := td.get_tutum_uri(url)
  if err != nil {
    return
  }

  // parse response
  var resp tutumContainer
  err = json.Unmarshal(data, &resp)
  if err != nil {
    return
  }
  // fmt.Printf("json: %v\n\n", resp)

  // get service information
  data, err = td.get_tutum_uri(resp.ServicePath)
  if err != nil {
    return
  }

  // parse response
  err = json.Unmarshal(data, &service)
  if err != nil {
    return
  }

  return
}

func (td *TutumDecoder) get_tutum_uri(uri string) (json []byte, err error) {
  base_url := "https://dashboard.tutum.co"
  url := fmt.Sprintf("%s%s", base_url, uri)

  client := &http.Client{}

  req, err := http.NewRequest("GET", url, nil)
  req.Header.Add("Authorization", td.auth)
  req.Header.Add("Accept", "application/json")

  resp, err := client.Do(req)
  if err != nil {
    return
  }

  // read body
  defer resp.Body.Close()
  json, err = ioutil.ReadAll(resp.Body)
  if err != nil {
    return
  }

  return
}

func init() {
  RegisterPlugin("TutumDecoder", func() interface{} {
    return new(TutumDecoder)
  })
}
<|endoftext|>


<commit_before>package transport

import "google.golang.org/grpc"

type CompoundServiceDesc struct {
	svc []ServiceDesc
}

func NewCompoundServiceDesc(desc ...ServiceDesc) *CompoundServiceDesc {
	return &CompoundServiceDesc{svc: desc}
}

func (d *CompoundServiceDesc) RegisterGRPC(g *grpc.Server) {
	for _, svc := range d.svc {
		svc.RegisterGRPC(g)
	}
}

func (d *CompoundServiceDesc) RegisterHTTP(r Router) {
	for _, svc := range d.svc {
		svc.RegisterHTTP(r)
	}
}

func (d *CompoundServiceDesc) SwaggerDef() []byte {
	j := &swagJoiner{}
	for _, svc := range d.svc {
		j.AddDefinition(svc.SwaggerDef())
	}
	return j.SumDefinitions()
}
<commit_msg>fixed compoundservice vs new swagger iface<commit_after>package transport

import (
	"github.com/utrack/clay/transport/swagger"
	"google.golang.org/grpc"
)

type CompoundServiceDesc struct {
	svc []ServiceDesc
}

func NewCompoundServiceDesc(desc ...ServiceDesc) *CompoundServiceDesc {
	return &CompoundServiceDesc{svc: desc}
}

func (d *CompoundServiceDesc) RegisterGRPC(g *grpc.Server) {
	for _, svc := range d.svc {
		svc.RegisterGRPC(g)
	}
}

func (d *CompoundServiceDesc) RegisterHTTP(r Router) {
	for _, svc := range d.svc {
		svc.RegisterHTTP(r)
	}
}

func (d *CompoundServiceDesc) SwaggerDef(options ...swagger.Option) []byte {
	j := &swagJoiner{}
	for _, svc := range d.svc {
		j.AddDefinition(svc.SwaggerDef(options...))
	}
	return j.SumDefinitions()
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Datacratic. All rights reserved.

package graphite

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/datacratic/gotsvis/ts"
)

const (
	TimeoutError = "timeout-error"
)

type Graphite struct {
	URL string

	Client *http.Client
}

func (graph *Graphite) Init() {
	if graph.URL == "" {
		panic("graphite URL can't be empty")
	}
	if graph.Client == nil {
		graph.Client = http.DefaultClient
	}
}

func (graph *Graphite) Do(req GraphiteRequest) *Response {

	query := req.GetQuery()
	query.Add("format", "raw")
	respHTTP, err := graph.Client.Get(graph.URL + "/render?" + query.Encode())

	resp := &Response{
		Request: req,
		Error:   err,
		data:    make(ts.TimeSeriesSlice, 0),
	}
	if respHTTP == nil || err != nil {
		if err, ok := err.(*url.Error); ok {
			if err, ok := err.Err.(net.Error); ok {
				if err.Timeout() {
					resp.Error = fmt.Errorf("%s: %s", TimeoutError, err)
					return resp
				}
			}
		}
		fmt.Println("respHTTP nil or err:", respHTTP, err)
	}

	resp.Code = respHTTP.StatusCode
	resp.Body, err = ioutil.ReadAll(respHTTP.Body)
	respHTTP.Body.Close()
	if resp.Error != nil {
		resp.Error = fmt.Errorf("%s, %s", resp.Error, err)
	} else {
		resp.Error = err
	}

	return resp
}

type GraphiteRequest interface {
	GetQuery() url.Values
}

type Request struct {
	Key   string
	From  time.Time
	Until time.Time
}

func (req *Request) GetQuery() url.Values {
	query := make(url.Values)

	query.Add("target", req.Key)

	if !req.From.IsZero() {
		query.Add("from", strconv.FormatInt(req.From.Unix(), 10))
	}
	if !req.Until.IsZero() {
		query.Add("until", strconv.FormatInt(req.Until.Unix(), 10))
	}
	return query
}

type Requests []Request

func (reqs Requests) GetQuery() url.Values {
	query := make(url.Values)
	var from, until time.Time

	for _, r := range reqs {
		query.Add("target", r.Key)
		if from.IsZero() {
			from = r.From
		} else if from.After(r.From) {
			from = r.From
		}
		if until.IsZero() {
			until = r.Until
		} else if until.Before(r.Until) {
			until = r.Until
		}
	}
	if !from.IsZero() {
		query.Add("from", strconv.FormatInt(from.Unix(), 10))
	}
	if !until.IsZero() {
		query.Add("until", strconv.FormatInt(until.Unix(), 10))
	}
	return query
}

// Response struct from a graphite request.
type Response struct {
	Request GraphiteRequest
	Body    []byte
	Code    int
	Error   error

	data ts.TimeSeriesSlice
}

// Single is used to get a single time series, and verify that there was only one
// time series in the response.
func (resp *Response) Single() (*ts.TimeSeries, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if len(resp.data) > 0 {
			resp.Error = errors.New("response length is larger than a single time series")
			return nil, resp.Error
		}

		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return &resp.data[0], nil
}

// First is used to retrieve the first time series from a response.
func (resp *Response) First() (*ts.TimeSeries, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
			return ts, nil
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return &resp.data[0], nil
}

// All is used to retrive all the time series in a response.
func (resp *Response) All() (ts.TimeSeriesSlice, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return resp.data, nil
}

func (resp *Response) GetMatchingAll(key string) (ts.TimeSeriesSlice, error) {
	tss, err := resp.All()
	if err != nil {
		return nil, err
	}
	return tss.GetMatching(key), nil
}

func (resp *Response) GetMatchingSingle(key string) (*ts.TimeSeries, error) {
	matching, err := resp.GetMatchingAll(key)
	if err != nil {
		return nil, err
	}
	if len(matching) == 0 {
		return nil, fmt.Errorf("key matching '%s' not found in response", key)
	}
	return &matching[0], nil
}

func (resp *Response) checkError() error {
	if resp == nil {
		return errors.New("response was nil")
	}
	if resp.Code != 200 {
		return fmt.Errorf("response returned status '%d' != 200", resp.Code)
	}
	return resp.Error
}

func (resp *Response) readLine(line []byte) (*ts.TimeSeries, error) {
	var key string
	var start, end time.Time
	var step time.Duration
	var data []float64

	buf := bytes.NewBuffer(line)
	if header, err := buf.ReadBytes('|'); err != nil {
		return nil, err
	} else {
		header = header[:len(header)-1]
		headers := bytes.Split(header, []byte(","))
		if len(headers) < 4 {
			resp.Error = errors.New("graphite data header size <= 4")
			return nil, resp.Error
		}

		key = string(bytes.Join(headers[:len(headers)-3], []byte(",")))
		startInt, err := strconv.ParseInt(string(headers[len(headers)-3]), 10, 64)
		if err != nil {
			return nil, errors.New("conv to int fail")
		}

		endInt, err := strconv.ParseInt(string(headers[len(headers)-2]), 10, 64)
		if err != nil {
			return nil, errors.New("conv to int fail")
		}

		step, err = time.ParseDuration(string(headers[len(headers)-1]) + "s")
		if err != nil {
			return nil, errors.New("step couldn't be determined")
		}

		start = time.Unix(startInt, 0)
		end = time.Unix(endInt, 0)

		points := end.Sub(start) / step
		data = make([]float64, points)
	}

	var err, errP error
	var point []byte
	for i := 0; err == nil; i++ {
		point, err = buf.ReadBytes(',')
		point = point[:len(point)-1]

		if bytes.Equal(point, []byte("None")) {
			data[i] = math.NaN()
			continue
		}
		data[i], errP = strconv.ParseFloat(string(point), 64)
		if errP != nil {
			resp.Error = errP
			return nil, errP
		}
	}
	if err != io.EOF {
		resp.Error = err
		return nil, resp.Error
	}
	return ts.NewTimeSeriesOfData(key, start, step, data)
}
<commit_msg>using UTC time zone when reading graphite unix timestamp<commit_after>// Copyright (c) 2014 Datacratic. All rights reserved.

package graphite

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/datacratic/gotsvis/ts"
)

const (
	TimeoutError = "timeout-error"
)

type Graphite struct {
	URL string

	Client *http.Client
}

func (graph *Graphite) Init() {
	if graph.URL == "" {
		panic("graphite URL can't be empty")
	}
	if graph.Client == nil {
		graph.Client = http.DefaultClient
	}
}

func (graph *Graphite) Do(req GraphiteRequest) *Response {

	query := req.GetQuery()
	query.Add("format", "raw")
	respHTTP, err := graph.Client.Get(graph.URL + "/render?" + query.Encode())

	resp := &Response{
		Request: req,
		Error:   err,
		data:    make(ts.TimeSeriesSlice, 0),
	}
	if respHTTP == nil || err != nil {
		if err, ok := err.(*url.Error); ok {
			if err, ok := err.Err.(net.Error); ok {
				if err.Timeout() {
					resp.Error = fmt.Errorf("%s: %s", TimeoutError, err)
					return resp
				}
			}
		}
		fmt.Println("respHTTP nil or err:", respHTTP, err)
	}

	resp.Code = respHTTP.StatusCode
	resp.Body, err = ioutil.ReadAll(respHTTP.Body)
	respHTTP.Body.Close()
	if resp.Error != nil {
		resp.Error = fmt.Errorf("%s, %s", resp.Error, err)
	} else {
		resp.Error = err
	}

	return resp
}

type GraphiteRequest interface {
	GetQuery() url.Values
}

type Request struct {
	Key   string
	From  time.Time
	Until time.Time
}

func (req *Request) GetQuery() url.Values {
	query := make(url.Values)

	query.Add("target", req.Key)

	if !req.From.IsZero() {
		query.Add("from", strconv.FormatInt(req.From.Unix(), 10))
	}
	if !req.Until.IsZero() {
		query.Add("until", strconv.FormatInt(req.Until.Unix(), 10))
	}
	return query
}

type Requests []Request

func (reqs Requests) GetQuery() url.Values {
	query := make(url.Values)
	var from, until time.Time

	for _, r := range reqs {
		query.Add("target", r.Key)
		if from.IsZero() {
			from = r.From
		} else if from.After(r.From) {
			from = r.From
		}
		if until.IsZero() {
			until = r.Until
		} else if until.Before(r.Until) {
			until = r.Until
		}
	}
	if !from.IsZero() {
		query.Add("from", strconv.FormatInt(from.Unix(), 10))
	}
	if !until.IsZero() {
		query.Add("until", strconv.FormatInt(until.Unix(), 10))
	}
	return query
}

// Response struct from a graphite request.
type Response struct {
	Request GraphiteRequest
	Body    []byte
	Code    int
	Error   error

	data ts.TimeSeriesSlice
}

// Single is used to get a single time series, and verify that there was only one
// time series in the response.
func (resp *Response) Single() (*ts.TimeSeries, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if len(resp.data) > 0 {
			resp.Error = errors.New("response length is larger than a single time series")
			return nil, resp.Error
		}

		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return &resp.data[0], nil
}

// First is used to retrieve the first time series from a response.
func (resp *Response) First() (*ts.TimeSeries, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
			return ts, nil
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return &resp.data[0], nil
}

// All is used to retrive all the time series in a response.
func (resp *Response) All() (ts.TimeSeriesSlice, error) {
	if err := resp.checkError(); err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(resp.Body)
	for line, err := buf.ReadBytes('\n'); err == nil; line, err = buf.ReadBytes('\n') {
		if ts, err := resp.readLine(line); err != nil {
			resp.Error = err
			return nil, resp.Error
		} else {
			resp.data = append(resp.data, *ts)
		}
	}

	if len(resp.data) == 0 {
		resp.Error = errors.New("no data in response")
		return nil, resp.Error
	}
	return resp.data, nil
}

func (resp *Response) GetMatchingAll(key string) (ts.TimeSeriesSlice, error) {
	tss, err := resp.All()
	if err != nil {
		return nil, err
	}
	return tss.GetMatching(key), nil
}

func (resp *Response) GetMatchingSingle(key string) (*ts.TimeSeries, error) {
	matching, err := resp.GetMatchingAll(key)
	if err != nil {
		return nil, err
	}
	if len(matching) == 0 {
		return nil, fmt.Errorf("key matching '%s' not found in response", key)
	}
	return &matching[0], nil
}

func (resp *Response) checkError() error {
	if resp == nil {
		return errors.New("response was nil")
	}
	if resp.Code != 200 {
		return fmt.Errorf("response returned status '%d' != 200", resp.Code)
	}
	return resp.Error
}

func (resp *Response) readLine(line []byte) (*ts.TimeSeries, error) {
	var key string
	var start, end time.Time
	var step time.Duration
	var data []float64

	buf := bytes.NewBuffer(line)
	if header, err := buf.ReadBytes('|'); err != nil {
		return nil, err
	} else {
		header = header[:len(header)-1]
		headers := bytes.Split(header, []byte(","))
		if len(headers) < 4 {
			resp.Error = errors.New("graphite data header size <= 4")
			return nil, resp.Error
		}

		key = string(bytes.Join(headers[:len(headers)-3], []byte(",")))
		startInt, err := strconv.ParseInt(string(headers[len(headers)-3]), 10, 64)
		if err != nil {
			return nil, errors.New("conv to int fail")
		}

		endInt, err := strconv.ParseInt(string(headers[len(headers)-2]), 10, 64)
		if err != nil {
			return nil, errors.New("conv to int fail")
		}

		step, err = time.ParseDuration(string(headers[len(headers)-1]) + "s")
		if err != nil {
			return nil, errors.New("step couldn't be determined")
		}

		start = time.Unix(startInt, 0).UTC()
		end = time.Unix(endInt, 0).UTC()

		points := end.Sub(start) / step
		data = make([]float64, points)
	}

	var err, errP error
	var point []byte
	for i := 0; err == nil; i++ {
		point, err = buf.ReadBytes(',')
		point = point[:len(point)-1]

		if bytes.Equal(point, []byte("None")) {
			data[i] = math.NaN()
			continue
		}
		data[i], errP = strconv.ParseFloat(string(point), 64)
		if errP != nil {
			resp.Error = errP
			return nil, errP
		}
	}
	if err != io.EOF {
		resp.Error = err
		return nil, resp.Error
	}
	return ts.NewTimeSeriesOfData(key, start, step, data)
}
<|endoftext|>


<commit_before><commit_msg>Avoid trying to pile line errors<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/devices"
	"github.com/ninjasphere/go-ninja/model"
)

type MediaPlayer struct {
	player     *devices.MediaPlayerDevice
	ip         string
	lastVolume float64
}

func NewMediaPlayer(driver ninja.Driver, conn *ninja.Connection, ip string) (*MediaPlayer, error) {
	name := fmt.Sprintf("Samsung TV: %s", ip)

	player, err := devices.CreateMediaPlayerDevice(driver, &model.Device{
		NaturalID:     ip,
		NaturalIDType: "samsung-tv",
		Name:          &name,
		Signatures: &map[string]string{
			"ninja:manufacturer": "Samsung",
			"ninja:productName":  "Smart TV",
			"ninja:thingType":    "mediaplayer",
		},
	}, conn)

	if err != nil {
		return nil, err
	}

	device := &MediaPlayer{
		player: player,
		ip:     ip,
	}

	player.ApplyVolume = device.applyVolume
	if err := player.EnableVolumeChannel(true); err != nil {
		player.Log().Fatalf("Failed to enable volume channel: %s", err)
	}

	player.ApplyPlayPause = device.applyPlayPause
	if err := player.EnableControlChannel([]string{}); err != nil {
		player.Log().Fatalf("Failed to enable control channel: %s", err)
	}

	return device, nil
}

func (d *MediaPlayer) applyPlayPause(play bool) error {
	if play {
		return sendCommand(d.ip, "KEY_PLAY")
	}
	return sendCommand(d.ip, "KEY_PAUSE")
}

func (d *MediaPlayer) applyVolume(state *channels.VolumeState) error {
	d.player.Log().Infof("applyVolume called, volume %v", state)

	if *state.Level > 0 && d.lastVolume == 0 {
		return sendCommand(d.ip, "KEY_MUTE")
	}

	if *state.Level == 0 && d.lastVolume > 0 {
		return sendCommand(d.ip, "KEY_MUTE")
	}

	// Do nothing for now
	return nil
}
<commit_msg>Support volumeUp, volumeDown and toggleMute<commit_after>package main

import (
	"fmt"

	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/devices"
	"github.com/ninjasphere/go-ninja/model"
)

type MediaPlayer struct {
	player     *devices.MediaPlayerDevice
	ip         string
	lastVolume float64
}

func NewMediaPlayer(driver ninja.Driver, conn *ninja.Connection, ip string) (*MediaPlayer, error) {
	name := fmt.Sprintf("Samsung TV: %s", ip)

	player, err := devices.CreateMediaPlayerDevice(driver, &model.Device{
		NaturalID:     ip,
		NaturalIDType: "samsung-tv",
		Name:          &name,
		Signatures: &map[string]string{
			"ninja:manufacturer": "Samsung",
			"ninja:productName":  "Smart TV",
			"ninja:thingType":    "mediaplayer",
		},
	}, conn)

	if err != nil {
		return nil, err
	}

	device := &MediaPlayer{
		player: player,
		ip:     ip,
	}

	player.ApplyVolume = device.applyVolume // TODO: Remove me!

	player.ApplyVolumeUp = device.applyVolumeUp
	player.ApplyVolumeDown = device.applyVolumeDown
	player.ApplyToggleMuted = device.applyToggleMuted
	if err := player.EnableVolumeChannel(false); err != nil {
		player.Log().Fatalf("Failed to enable volume channel: %s", err)
	}

	player.ApplyPlayPause = device.applyPlayPause
	if err := player.EnableControlChannel([]string{}); err != nil {
		player.Log().Fatalf("Failed to enable control channel: %s", err)
	}

	return device, nil
}

// TODO: Remove me! Just needed till led controller is better
func (d *MediaPlayer) applyVolume(state *channels.VolumeState) error {
	d.player.Log().Infof("applyVolume called, volume %v", state)

	if *state.Level > 0 && d.lastVolume == 0 {
		return sendCommand(d.ip, "KEY_MUTE")
	}

	if *state.Level == 0 && d.lastVolume > 0 {
		return sendCommand(d.ip, "KEY_MUTE")
	}

	// Do nothing for now
	return nil
}

func (d *MediaPlayer) applyPlayPause(play bool) error {
	if play {
		return sendCommand(d.ip, "KEY_PLAY")
	}
	return sendCommand(d.ip, "KEY_PAUSE")
}

func (d *MediaPlayer) applyToggleMuted() error {
	d.player.Log().Infof("applyToggleMuted called")

	return sendCommand(d.ip, "KEY_MUTE")
}

func (d *MediaPlayer) applyVolumeUp() error {
	d.player.Log().Infof("applyVolumeUp called")

	return sendCommand(d.ip, "KEY_VOLUP")
}

func (d *MediaPlayer) applyVolumeDown() error {
	d.player.Log().Infof("applyVolumeDown called")

	return sendCommand(d.ip, "KEY_VOLDOWN")
}
<|endoftext|>


<commit_before><commit_msg>DirectPayIn: add "SecureModeRedirectURL" field<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"os"
	"sync"
	"time"

	"github.com/miekg/dns"
)

var inflight = new(single)

// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other
// utilities. It add ".key" for the public key and ".private" for the private key.
func ParseKeyFile(file string) (*dns.DNSKEY, dns.PrivateKey, error) {
	f, e := os.Open(file + ".key")
	if e != nil {
		return nil, nil, e
	}
	k, e := dns.ReadRR(f, file+".key")
	if e != nil {
		return nil, nil, e
	}
	f, e = os.Open(file + ".private")
	if e != nil {
		return nil, nil, e
	}
	p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, file+".private")
	if e != nil {
		return nil, nil, e
	}
	return k.(*dns.DNSKEY), p, nil
}

// sign signs a message m, it takes care of negative or nodata responses as
// well by synthesising NSEC3 records. It will also cache the signatures, using
// a hash of the signed data as a key.
// We also fake the origin TTL in the signature, because we don't want to
// throw away signatures when services decide to have longer TTL. So we just
// set the origTTL to 60.
// TODO(miek): revisit origTTL
func (s *server) sign(m *dns.Msg, bufsize uint16) {
	now := time.Now().UTC()
	incep := uint32(now.Add(-3 * time.Hour).Unix())     // 2+1 hours, be sure to catch daylight saving time and such
	expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week

	for _, r := range rrSets(m.Answer) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Answer = append(m.Answer, sig)
		}
	}
	for _, r := range rrSets(m.Ns) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Ns = append(m.Ns, sig)
		}
	}
	for _, r := range rrSets(m.Extra) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Extra = append(m.Extra, sig)
		}
	}
	if bufsize >= 512 || bufsize <= 4096 {
		m.Truncated = m.Len() > int(bufsize)
	}
	o := new(dns.OPT)
	o.Hdr.Name = "."
	o.Hdr.Rrtype = dns.TypeOPT
	o.SetDo()
	o.SetUDPSize(4096) // TODO(miek): echo client
	m.Extra = append(m.Extra, o)
	return
}

func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.RRSIG, error) {
	key := Key(r)
	if sig, _, exp := s.scache.Search(key); sig != nil { // There can only be one sig in this cache.
		// Is it still valid 24 hours from now?
		if now.Add(+24*time.Hour).Sub(exp) < -24*time.Hour {
			return sig[0].(*dns.RRSIG), nil
		}
		s.scache.Remove(key)
	}
	s.config.log.Infof("scache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype)
	StatsDnssecCacheMiss.Inc(1)
	sig, err, shared := inflight.Do(key, func() (*dns.RRSIG, error) {
		sig1 := s.NewRRSIG(incep, expir)
		sig1.Header().Ttl = r[0].Header().Ttl
		if r[0].Header().Rrtype == dns.TypeTXT {
			sig1.OrigTtl = 0
		}
		e := sig1.Sign(s.config.PrivKey, r)
		if e != nil {
			s.config.log.Errorf("failed to sign: %s", e.Error())
		}
		return sig1, e
	})
	if err != nil {
		return nil, err
	}
	if !shared {
		s.scache.InsertSig(key, sig)
	}
	return dns.Copy(sig).(*dns.RRSIG), nil
}

func (s *server) NewRRSIG(incep, expir uint32) *dns.RRSIG {
	sig := new(dns.RRSIG)
	sig.Hdr.Rrtype = dns.TypeRRSIG
	sig.Hdr.Ttl = s.config.Ttl
	sig.OrigTtl = s.config.Ttl
	sig.Algorithm = s.config.PubKey.Algorithm
	sig.KeyTag = s.config.KeyTag
	sig.Inception = incep
	sig.Expiration = expir
	sig.SignerName = s.config.PubKey.Hdr.Name
	return sig
}

type rrset struct {
	qname string
	qtype uint16
}

func rrSets(rrs []dns.RR) map[rrset][]dns.RR {
	m := make(map[rrset][]dns.RR)
	for _, r := range rrs {
		if s, ok := m[rrset{r.Header().Name, r.Header().Rrtype}]; ok {
			s = append(s, r)
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		} else {
			s := make([]dns.RR, 1, 3)
			s[0] = r
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		}
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

// Adapted from singleinflight.go from the original Go Code. Copyright 2013 The Go Authors.
type call struct {
	wg   sync.WaitGroup
	val  *dns.RRSIG
	err  error
	dups int
}

type single struct {
	sync.Mutex
	m map[string]*call
}

func (g *single) Do(key string, fn func() (*dns.RRSIG, error)) (*dns.RRSIG, error, bool) {
	g.Lock()
	if g.m == nil {
		g.m = make(map[string]*call)
	}
	if c, ok := g.m[key]; ok {
		c.dups++
		g.Unlock()
		c.wg.Wait()
		return c.val, c.err, true
	}
	c := new(call)
	c.wg.Add(1)
	g.m[key] = c
	g.Unlock()

	c.val, c.err = fn()
	c.wg.Done()

	g.Lock()
	delete(g.m, key)
	g.Unlock()

	return c.val, c.err, c.dups > 0
}
<commit_msg>dont sign OPT records<commit_after>// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"os"
	"sync"
	"time"

	"github.com/miekg/dns"
)

var inflight = new(single)

// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other
// utilities. It add ".key" for the public key and ".private" for the private key.
func ParseKeyFile(file string) (*dns.DNSKEY, dns.PrivateKey, error) {
	f, e := os.Open(file + ".key")
	if e != nil {
		return nil, nil, e
	}
	k, e := dns.ReadRR(f, file+".key")
	if e != nil {
		return nil, nil, e
	}
	f, e = os.Open(file + ".private")
	if e != nil {
		return nil, nil, e
	}
	p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, file+".private")
	if e != nil {
		return nil, nil, e
	}
	return k.(*dns.DNSKEY), p, nil
}

// sign signs a message m, it takes care of negative or nodata responses as
// well by synthesising NSEC3 records. It will also cache the signatures, using
// a hash of the signed data as a key.
// We also fake the origin TTL in the signature, because we don't want to
// throw away signatures when services decide to have longer TTL. So we just
// set the origTTL to 60.
// TODO(miek): revisit origTTL
func (s *server) sign(m *dns.Msg, bufsize uint16) {
	now := time.Now().UTC()
	incep := uint32(now.Add(-3 * time.Hour).Unix())     // 2+1 hours, be sure to catch daylight saving time and such
	expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week

	for _, r := range rrSets(m.Answer) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Answer = append(m.Answer, sig)
		}
	}
	for _, r := range rrSets(m.Ns) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Ns = append(m.Ns, sig)
		}
	}
	for _, r := range rrSets(m.Extra) {
		if r[0].Header().Rrtype == dns.TypeRRSIG || r[0].Header().Rrtype == dns.TypeOPT {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Extra = append(m.Extra, sig)
		}
	}
	if bufsize >= 512 || bufsize <= 4096 {
		m.Truncated = m.Len() > int(bufsize)
	}
	o := new(dns.OPT)
	o.Hdr.Name = "."
	o.Hdr.Rrtype = dns.TypeOPT
	o.SetDo()
	o.SetUDPSize(4096) // TODO(miek): echo client
	m.Extra = append(m.Extra, o)
	return
}

func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.RRSIG, error) {
	key := Key(r)
	if sig, _, exp := s.scache.Search(key); sig != nil { // There can only be one sig in this cache.
		// Is it still valid 24 hours from now?
		if now.Add(+24*time.Hour).Sub(exp) < -24*time.Hour {
			return sig[0].(*dns.RRSIG), nil
		}
		s.scache.Remove(key)
	}
	s.config.log.Infof("scache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype)
	StatsDnssecCacheMiss.Inc(1)
	sig, err, shared := inflight.Do(key, func() (*dns.RRSIG, error) {
		sig1 := s.NewRRSIG(incep, expir)
		sig1.Header().Ttl = r[0].Header().Ttl
		if r[0].Header().Rrtype == dns.TypeTXT {
			sig1.OrigTtl = 0
		}
		e := sig1.Sign(s.config.PrivKey, r)
		if e != nil {
			s.config.log.Errorf("failed to sign: %s", e.Error())
		}
		return sig1, e
	})
	if err != nil {
		return nil, err
	}
	if !shared {
		s.scache.InsertSig(key, sig)
	}
	return dns.Copy(sig).(*dns.RRSIG), nil
}

func (s *server) NewRRSIG(incep, expir uint32) *dns.RRSIG {
	sig := new(dns.RRSIG)
	sig.Hdr.Rrtype = dns.TypeRRSIG
	sig.Hdr.Ttl = s.config.Ttl
	sig.OrigTtl = s.config.Ttl
	sig.Algorithm = s.config.PubKey.Algorithm
	sig.KeyTag = s.config.KeyTag
	sig.Inception = incep
	sig.Expiration = expir
	sig.SignerName = s.config.PubKey.Hdr.Name
	return sig
}

type rrset struct {
	qname string
	qtype uint16
}

func rrSets(rrs []dns.RR) map[rrset][]dns.RR {
	m := make(map[rrset][]dns.RR)
	for _, r := range rrs {
		if s, ok := m[rrset{r.Header().Name, r.Header().Rrtype}]; ok {
			s = append(s, r)
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		} else {
			s := make([]dns.RR, 1, 3)
			s[0] = r
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		}
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

// Adapted from singleinflight.go from the original Go Code. Copyright 2013 The Go Authors.
type call struct {
	wg   sync.WaitGroup
	val  *dns.RRSIG
	err  error
	dups int
}

type single struct {
	sync.Mutex
	m map[string]*call
}

func (g *single) Do(key string, fn func() (*dns.RRSIG, error)) (*dns.RRSIG, error, bool) {
	g.Lock()
	if g.m == nil {
		g.m = make(map[string]*call)
	}
	if c, ok := g.m[key]; ok {
		c.dups++
		g.Unlock()
		c.wg.Wait()
		return c.val, c.err, true
	}
	c := new(call)
	c.wg.Add(1)
	g.m[key] = c
	g.Unlock()

	c.val, c.err = fn()
	c.wg.Done()

	g.Lock()
	delete(g.m, key)
	g.Unlock()

	return c.val, c.err, c.dups > 0
}
<|endoftext|>


<commit_before>package boardgame

import (
	"github.com/workfit/tester/assert"
	"testing"
	"time"
)

func TestTimerManager(t *testing.T) {

	game := testGame()

	game.SetUp(2)

	currentVersion := game.Version()

	move := &testMoveDrawCard{
		TargetPlayerIndex: 0,
	}

	timer := newTimerManager()

	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	assert.For(t).ThatActual(timer.nextId).Equals(0)

	registeredDuration := time.Duration(50) * time.Millisecond

	id := timer.RegisterTimer(registeredDuration, game, move)

	assert.For(t).ThatActual(id).Equals(0)

	assert.For(t).ThatActual(timer.nextId).Equals(1)

	remaining := timer.GetTimerRemaining(id)

	assert.For(t).ThatActual(registeredDuration-remaining < time.Millisecond*10).IsTrue()

	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	timer.Tick()

	//Ticking before any time has really passed shouldn't trigger the next timer.
	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	<-time.After(60 * time.Millisecond)

	assert.For(t).ThatActual(timer.nextTimerFired()).IsTrue()

	timer.Tick()

	//Make sure the game was actually made after the time had elapsed.
	assert.For(t).ThatActual(game.Version()).Equals(currentVersion + 1)

	//Now that the tick has happened, there should be not more records.
	assert.For(t).ThatActual(len(timer.records)).Equals(0)
	assert.For(t).ThatActual(len(timer.recordsById)).Equals(0)

	assert.For(t).ThatActual(timer.GetTimerRemaining(id)).Equals(time.Duration(0))

}

func TestTimerManagerMultiple(t *testing.T) {

	game := testGame()

	game.SetUp(2)

	move := &testMoveDrawCard{
		TargetPlayerIndex: 0,
	}

	currentVersion := game.Version()

	timer := newTimerManager()

	firstId := timer.RegisterTimer(time.Duration(50)*time.Millisecond, game, move)
	secondId := timer.RegisterTimer(time.Duration(10)*time.Millisecond, game, move)
	thirdId := timer.RegisterTimer(time.Duration(70)*time.Millisecond, game, move)

	//Make sure that even though the second timer was added second, it is first.
	assert.For(t).ThatActual(timer.records[0].id).Equals(secondId)
	assert.For(t).ThatActual(timer.records[1].id).Equals(firstId)
	assert.For(t).ThatActual(timer.records[2].id).Equals(thirdId)

	timer.CancelTimer(secondId)

	assert.For(t).ThatActual(len(timer.records)).Equals(2)

	assert.For(t).ThatActual(timer.records[0].id).Equals(firstId)
	assert.For(t).ThatActual(timer.records[1].id).Equals(thirdId)

	assert.For(t).ThatActual(timer.nextTimerFired()).IsFalse()

	<-time.After(70 * time.Millisecond)

	timer.Tick()

	assert.For(t).ThatActual(len(timer.records)).Equals(0)

	assert.For(t).ThatActual(game.Version()).Equals(currentVersion + 2)

}
<commit_msg>Added a test of TimerProp itself. Part of #178.<commit_after>package boardgame

import (
	"github.com/workfit/tester/assert"
	"testing"
	"time"
)

func TestTimerManager(t *testing.T) {

	game := testGame()

	game.SetUp(2)

	currentVersion := game.Version()

	move := &testMoveDrawCard{
		TargetPlayerIndex: 0,
	}

	timer := newTimerManager()

	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	assert.For(t).ThatActual(timer.nextId).Equals(0)

	registeredDuration := time.Duration(50) * time.Millisecond

	id := timer.RegisterTimer(registeredDuration, game, move)

	assert.For(t).ThatActual(id).Equals(0)

	assert.For(t).ThatActual(timer.nextId).Equals(1)

	remaining := timer.GetTimerRemaining(id)

	assert.For(t).ThatActual(registeredDuration-remaining < time.Millisecond*10).IsTrue()

	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	timer.Tick()

	//Ticking before any time has really passed shouldn't trigger the next timer.
	assert.For(t).ThatActual(timer.nextTimerFired()).Equals(false)

	<-time.After(60 * time.Millisecond)

	assert.For(t).ThatActual(timer.nextTimerFired()).IsTrue()

	timer.Tick()

	//Make sure the game was actually made after the time had elapsed.
	assert.For(t).ThatActual(game.Version()).Equals(currentVersion + 1)

	//Now that the tick has happened, there should be not more records.
	assert.For(t).ThatActual(len(timer.records)).Equals(0)
	assert.For(t).ThatActual(len(timer.recordsById)).Equals(0)

	assert.For(t).ThatActual(timer.GetTimerRemaining(id)).Equals(time.Duration(0))

}

func TestTimerManagerMultiple(t *testing.T) {

	game := testGame()

	game.SetUp(2)

	move := &testMoveDrawCard{
		TargetPlayerIndex: 0,
	}

	currentVersion := game.Version()

	timer := newTimerManager()

	firstId := timer.RegisterTimer(time.Duration(50)*time.Millisecond, game, move)
	secondId := timer.RegisterTimer(time.Duration(10)*time.Millisecond, game, move)
	thirdId := timer.RegisterTimer(time.Duration(70)*time.Millisecond, game, move)

	//Make sure that even though the second timer was added second, it is first.
	assert.For(t).ThatActual(timer.records[0].id).Equals(secondId)
	assert.For(t).ThatActual(timer.records[1].id).Equals(firstId)
	assert.For(t).ThatActual(timer.records[2].id).Equals(thirdId)

	timer.CancelTimer(secondId)

	assert.For(t).ThatActual(len(timer.records)).Equals(2)

	assert.For(t).ThatActual(timer.records[0].id).Equals(firstId)
	assert.For(t).ThatActual(timer.records[1].id).Equals(thirdId)

	assert.For(t).ThatActual(timer.nextTimerFired()).IsFalse()

	<-time.After(70 * time.Millisecond)

	timer.Tick()

	assert.For(t).ThatActual(len(timer.records)).Equals(0)

	assert.For(t).ThatActual(game.Version()).Equals(currentVersion + 2)

}

func TestTimerProp(t *testing.T) {
	game := testGame()

	game.SetUp(2)

	move := &testMoveDrawCard{
		TargetPlayerIndex: 0,
	}

	currentVersion := game.Version()

	gameState, _ := concreteStates(game.CurrentState())

	gameState.Timer.Start(time.Millisecond*5, move)

	<-time.After(time.Millisecond * 300)

	assert.For(t).ThatActual(game.Version()).Equals(currentVersion + 1)

}
<|endoftext|>


<commit_before>package geo_skeleton

import "fmt"

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {
	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return string(self.File)
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {

	fmt.Println(self.getTable())

	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<commit_msg>fixed geots<commit_after>package geo_skeleton

import "fmt"

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {
	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return string(self.File)
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return string(self.Table)
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {

	fmt.Println(self.getTable())

	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<|endoftext|>


<commit_before>/**
 * Copyright 2016 IBM Corp.
 *
 * 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 order

import (
	"github.ibm.com/riethm/gopherlayer/datatypes"
	"github.ibm.com/riethm/gopherlayer/services"
	"github.ibm.com/riethm/gopherlayer/session"
)

// CheckBillingOrderStatus returns true if the status of the billing order for
// the provided product order receipt is in the list of provided statuses.
// Returns false otherwise
func CheckBillingOrderStatus(sess *session.Session, receipt *datatypes.Container_Product_Order_Receipt, statuses []string) (bool, error) {
	service := services.GetBillingOrderItemService(sess)

	item, err := service.
		Id(*receipt.PlacedOrder.Items[0].Id).
		Mask("mask[id,billingItem[id,provisionTransaction[id,transactionStatus[name]]]]").
		GetObject()

	if err != nil {
		return false, err
	}

	currentStatus := *item.BillingItem.ProvisionTransaction.TransactionStatus.Name
	for _, status := range statuses {
		if currentStatus == status {
			return true, nil
		}
	}

	return false, nil
}

// CheckBillingOrderComplete returns true if the status of the billing order for
// the provided product order receipt is "COMPLETE".  Returns false otherwise
func CheckBillingOrderComplete(sess *session.Session, receipt *datatypes.Container_Product_Order_Receipt) (bool, error) {
	return CheckBillingOrderStatus(sess, receipt, []string{"COMPLETE"})
}
<commit_msg>Add billing order item to CheckBillingOrder helper return values<commit_after>/**
 * Copyright 2016 IBM Corp.
 *
 * 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 order

import (
	"github.ibm.com/riethm/gopherlayer.git/datatypes"
	"github.ibm.com/riethm/gopherlayer.git/services"
	"github.ibm.com/riethm/gopherlayer.git/session"
)

// CheckBillingOrderStatus returns true if the status of the billing order for
// the provided product order receipt is in the list of provided statuses.
// Returns false otherwise, along with the billing order item used to check the statuses,
// and any error encountered.
func CheckBillingOrderStatus(sess *session.Session, receipt *datatypes.Container_Product_Order_Receipt, statuses []string) (bool, *datatypes.Billing_Order_Item, error) {
	service := services.GetBillingOrderItemService(sess)

	item, err := service.
		Id(*receipt.PlacedOrder.Items[0].Id).
		Mask("mask[id,billingItem[id,provisionTransaction[id,transactionStatus[name]]]]").
		GetObject()

	if err != nil {
		return false, err
	}

	currentStatus := *item.BillingItem.ProvisionTransaction.TransactionStatus.Name
	for _, status := range statuses {
		if currentStatus == status {
			return true, nil
		}
	}

	return false, item.BillingItem, nil
}

// CheckBillingOrderComplete returns true if the status of the billing order for
// the provided product order receipt is "COMPLETE". Returns false otherwise,
// along with the billing order item used to check the statuses, and any error encountered.
func CheckBillingOrderComplete(sess *session.Session, receipt *datatypes.Container_Product_Order_Receipt) (bool, *datatypes.Billing_Order_Item, error) {
	return CheckBillingOrderStatus(sess, receipt, []string{"COMPLETE"})
}
<|endoftext|>


<commit_before>// Copyright ©2016 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package combin

import (
	"math"

	"gonum.org/v1/gonum/mat"
)

const (
	badNegInput          = "combin: negative input"
	badSetSize           = "combin: n < k"
	badInput             = "combin: wrong input slice length"
	nonpositiveDimension = "combin: non-positive dimension"
)

// Binomial returns the binomial coefficient of (n,k), also commonly referred to
// as "n choose k".
//
// The binomial coefficient, C(n,k), is the number of unordered combinations of
// k elements in a set that is n elements big, and is defined as
//
//  C(n,k) = n!/((n-k)!k!)
//
// n and k must be non-negative with n >= k, otherwise Binomial will panic.
// No check is made for overflow.
func Binomial(n, k int) int {
	if n < 0 || k < 0 {
		panic(badNegInput)
	}
	if n < k {
		panic(badSetSize)
	}
	// (n,k) = (n, n-k)
	if k > n/2 {
		k = n - k
	}
	b := 1
	for i := 1; i <= k; i++ {
		b = (n - k + i) * b / i
	}
	return b
}

// GeneralizedBinomial returns the generalized binomial coefficient of (n, k),
// defined as
//  Γ(n+1) / (Γ(k+1) Γ(n-k+1))
// where Γ is the Gamma function. GeneralizedBinomial is useful for continuous
// relaxations of the binomial coefficient, or when the binomial coefficient value
// may overflow int. In the latter case, one may use math/big for an exact
// computation.
//
// n and k must be non-negative with n >= k, otherwise GeneralizedBinomial will panic.
func GeneralizedBinomial(n, k float64) float64 {
	return math.Exp(LogGeneralizedBinomial(n, k))
}

// LogGeneralizedBinomial returns the log of the generalized binomial coefficient.
// See GeneralizedBinomial for more information.
func LogGeneralizedBinomial(n, k float64) float64 {
	if n < 0 || k < 0 {
		panic(badNegInput)
	}
	if n < k {
		panic(badSetSize)
	}
	a, _ := math.Lgamma(n + 1)
	b, _ := math.Lgamma(k + 1)
	c, _ := math.Lgamma(n - k + 1)
	return a - b - c
}

// CombinationGenerator generates combinations iteratively. Combinations may be
// called to generate all combinations collectively.
type CombinationGenerator struct {
	n         int
	k         int
	previous  []int
	remaining int
}

// NewCombinationGenerator returns a CombinationGenerator for generating the
// combinations of k elements from a set of size n.
//
// n and k must be non-negative with n >= k, otherwise NewCombinationGenerator
// will panic.
func NewCombinationGenerator(n, k int) *CombinationGenerator {
	return &CombinationGenerator{
		n:         n,
		k:         k,
		remaining: Binomial(n, k),
	}
}

// Next advances the iterator if there are combinations remaining to be generated,
// and returns false if all combinations have been generated. Next must be called
// to initialize the first value before calling Combination or Combination will
// panic. The value returned by Combination is only changed during calls to Next.
func (c *CombinationGenerator) Next() bool {
	if c.remaining <= 0 {
		// Next is called before combination, so c.remaining is set to zero before
		// Combination is called. Thus, Combination cannot panic on zero, and a
		// second sentinel value is needed.
		c.remaining = -1
		return false
	}
	if c.previous == nil {
		c.previous = make([]int, c.k)
		for i := range c.previous {
			c.previous[i] = i
		}
	} else {
		nextCombination(c.previous, c.n, c.k)
	}
	c.remaining--
	return true
}

// Combination generates the next combination. If next is non-nil, it must have
// length k and the result will be stored in-place into combination. If combination
// is nil a new slice will be allocated and returned. If all of the combinations
// have already been constructed (Next() returns false), Combination will panic.
//
// Next must be called to initialize the first value before calling Combination
// or Combination will panic. The value returned by Combination is only changed
// during calls to Next.
func (c *CombinationGenerator) Combination(combination []int) []int {
	if c.remaining == -1 {
		panic("combin: all combinations have been generated")
	}
	if c.previous == nil {
		panic("combin: Combination called before Next")
	}
	if combination == nil {
		combination = make([]int, c.k)
	}
	if len(combination) != c.k {
		panic(badInput)
	}
	copy(combination, c.previous)
	return combination
}

// Combinations generates all of the combinations of k elements from a
// set of size n. The returned slice has length Binomial(n,k) and each inner slice
// has length k.
//
// n and k must be non-negative with n >= k, otherwise Combinations will panic.
//
// CombinationGenerator may alternatively be used to generate the combinations
// iteratively instead of collectively.
func Combinations(n, k int) [][]int {
	combins := Binomial(n, k)
	data := make([][]int, combins)
	if len(data) == 0 {
		return data
	}
	data[0] = make([]int, k)
	for i := range data[0] {
		data[0][i] = i
	}
	for i := 1; i < combins; i++ {
		next := make([]int, k)
		copy(next, data[i-1])
		nextCombination(next, n, k)
		data[i] = next
	}
	return data
}

// nextCombination generates the combination after s, overwriting the input value.
func nextCombination(s []int, n, k int) {
	for j := k - 1; j >= 0; j-- {
		if s[j] == n+j-k {
			continue
		}
		s[j]++
		for l := j + 1; l < k; l++ {
			s[l] = s[j] + l - j
		}
		break
	}
}

// Cartesian returns the cartesian product of the slices in data. The Cartesian
// product of two sets is the set of all combinations of the items. For example,
// given the input
//  [][]float64{{1,2},{3,4},{5,6}}
// the returned matrix will be
//  [ 1 3 5 ]
//  [ 1 3 6 ]
//  [ 1 4 5 ]
//  [ 1 4 6 ]
//  [ 2 3 5 ]
//  [ 2 3 6 ]
//  [ 2 4 5 ]
//  [ 2 4 6 ]
// If dst is nil, a new matrix will be allocated and returned, otherwise the number
// of rows of dst must equal \prod_i len(data[i]), and the number of columns in
// dst must equal len(data). Cartesian also panics if len(data) = 0.
func Cartesian(dst *mat.Dense, data [][]float64) *mat.Dense {
	if len(data) == 0 {
		panic("combin: empty data input")
	}
	cols := len(data)
	rows := 1
	lens := make([]int, cols)
	for i, d := range data {
		v := len(d)
		lens[i] = v
		rows *= v
	}
	if dst == nil {
		dst = mat.NewDense(rows, cols, nil)
	}
	r, c := dst.Dims()
	if r != rows || c != cols {
		panic("combin: destination matrix size mismatch")
	}
	idxs := make([]int, cols)
	for i := 0; i < rows; i++ {
		SubFor(idxs, i, lens)
		for j := 0; j < len(data); j++ {
			dst.Set(i, j, data[j][idxs[j]])
		}
	}
	return dst
}

// IdxFor converts a multi-dimensional index into a linear index for a
// multi-dimensional space. sub specifies the index for each dimension, and dims
// specifies the size of each dimension. IdxFor is the inverse of SubFor.
// IdxFor panics if any of the entries of sub are negative, any of the entries
// of dim are non-positive, or if sub[i] >= dims[i] for any i.
func IdxFor(sub, dims []int) int {
	// The index returned is "row-major", that is the last index of sub is
	// continuous.
	var idx int
	stride := 1
	for i := len(dims) - 1; i >= 0; i-- {
		v := sub[i]
		d := dims[i]
		if d <= 0 {
			panic(nonpositiveDimension)
		}
		if v < 0 || v >= d {
			panic("combin: invalid subscript")
		}
		idx += v * stride
		stride *= d
	}
	return idx
}

// SubFor returns the multi-dimensional subscript for the input linear index to
// the multi-dimensional space. dims specifies the size of each dimension, and
// idx specifies the linear index. SubFor is the inverse of IdxFor.
//
// If sub is non-nil the result is stored in-place into sub, and SubFor will panic
// if len(sub) != len(dims). If sub is nil a new slice of the appropriate length
// is allocated. SubFor panics if idx < 0 or if idx is greater than or equal to
// the product of the dimensions.
func SubFor(sub []int, idx int, dims []int) []int {
	if sub == nil {
		sub = make([]int, len(dims))
	}
	if len(sub) != len(dims) {
		panic(badInput)
	}
	if idx < 0 {
		panic(badNegInput)
	}
	stride := 1
	for i := len(dims) - 1; i >= 1; i-- {
		stride *= dims[i]
	}
	for i := 0; i < len(dims)-1; i++ {
		v := idx / stride
		d := dims[i]
		if d < 0 {
			panic(nonpositiveDimension)
		}
		if v >= dims[i] {
			panic("combin: index too large")
		}
		sub[i] = v
		idx -= v * stride
		stride /= dims[i+1]
	}
	if idx > dims[len(sub)-1] {
		panic("combin: index too large")
	}
	sub[len(sub)-1] = idx
	return sub
}
<commit_msg>stat/combin: Fix CombinationGenerator comment (#1028)<commit_after>// Copyright ©2016 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package combin

import (
	"math"

	"gonum.org/v1/gonum/mat"
)

const (
	badNegInput          = "combin: negative input"
	badSetSize           = "combin: n < k"
	badInput             = "combin: wrong input slice length"
	nonpositiveDimension = "combin: non-positive dimension"
)

// Binomial returns the binomial coefficient of (n,k), also commonly referred to
// as "n choose k".
//
// The binomial coefficient, C(n,k), is the number of unordered combinations of
// k elements in a set that is n elements big, and is defined as
//
//  C(n,k) = n!/((n-k)!k!)
//
// n and k must be non-negative with n >= k, otherwise Binomial will panic.
// No check is made for overflow.
func Binomial(n, k int) int {
	if n < 0 || k < 0 {
		panic(badNegInput)
	}
	if n < k {
		panic(badSetSize)
	}
	// (n,k) = (n, n-k)
	if k > n/2 {
		k = n - k
	}
	b := 1
	for i := 1; i <= k; i++ {
		b = (n - k + i) * b / i
	}
	return b
}

// GeneralizedBinomial returns the generalized binomial coefficient of (n, k),
// defined as
//  Γ(n+1) / (Γ(k+1) Γ(n-k+1))
// where Γ is the Gamma function. GeneralizedBinomial is useful for continuous
// relaxations of the binomial coefficient, or when the binomial coefficient value
// may overflow int. In the latter case, one may use math/big for an exact
// computation.
//
// n and k must be non-negative with n >= k, otherwise GeneralizedBinomial will panic.
func GeneralizedBinomial(n, k float64) float64 {
	return math.Exp(LogGeneralizedBinomial(n, k))
}

// LogGeneralizedBinomial returns the log of the generalized binomial coefficient.
// See GeneralizedBinomial for more information.
func LogGeneralizedBinomial(n, k float64) float64 {
	if n < 0 || k < 0 {
		panic(badNegInput)
	}
	if n < k {
		panic(badSetSize)
	}
	a, _ := math.Lgamma(n + 1)
	b, _ := math.Lgamma(k + 1)
	c, _ := math.Lgamma(n - k + 1)
	return a - b - c
}

// CombinationGenerator generates combinations iteratively. Combinations may be
// called to generate all combinations collectively.
type CombinationGenerator struct {
	n         int
	k         int
	previous  []int
	remaining int
}

// NewCombinationGenerator returns a CombinationGenerator for generating the
// combinations of k elements from a set of size n.
//
// n and k must be non-negative with n >= k, otherwise NewCombinationGenerator
// will panic.
func NewCombinationGenerator(n, k int) *CombinationGenerator {
	return &CombinationGenerator{
		n:         n,
		k:         k,
		remaining: Binomial(n, k),
	}
}

// Next advances the iterator if there are combinations remaining to be generated,
// and returns false if all combinations have been generated. Next must be called
// to initialize the first value before calling Combination or Combination will
// panic. The value returned by Combination is only changed during calls to Next.
func (c *CombinationGenerator) Next() bool {
	if c.remaining <= 0 {
		// Next is called before combination, so c.remaining is set to zero before
		// Combination is called. Thus, Combination cannot panic on zero, and a
		// second sentinel value is needed.
		c.remaining = -1
		return false
	}
	if c.previous == nil {
		c.previous = make([]int, c.k)
		for i := range c.previous {
			c.previous[i] = i
		}
	} else {
		nextCombination(c.previous, c.n, c.k)
	}
	c.remaining--
	return true
}

// Combination generates the current combination. If next is non-nil, it must have
// length k and the result will be stored in-place into combination. If combination
// is nil a new slice will be allocated and returned. If all of the combinations
// have already been constructed (Next() returns false), Combination will panic.
//
// Next must be called to initialize the first value before calling Combination
// or Combination will panic. The value returned by Combination is only changed
// during calls to Next.
func (c *CombinationGenerator) Combination(combination []int) []int {
	if c.remaining == -1 {
		panic("combin: all combinations have been generated")
	}
	if c.previous == nil {
		panic("combin: Combination called before Next")
	}
	if combination == nil {
		combination = make([]int, c.k)
	}
	if len(combination) != c.k {
		panic(badInput)
	}
	copy(combination, c.previous)
	return combination
}

// Combinations generates all of the combinations of k elements from a
// set of size n. The returned slice has length Binomial(n,k) and each inner slice
// has length k.
//
// n and k must be non-negative with n >= k, otherwise Combinations will panic.
//
// CombinationGenerator may alternatively be used to generate the combinations
// iteratively instead of collectively.
func Combinations(n, k int) [][]int {
	combins := Binomial(n, k)
	data := make([][]int, combins)
	if len(data) == 0 {
		return data
	}
	data[0] = make([]int, k)
	for i := range data[0] {
		data[0][i] = i
	}
	for i := 1; i < combins; i++ {
		next := make([]int, k)
		copy(next, data[i-1])
		nextCombination(next, n, k)
		data[i] = next
	}
	return data
}

// nextCombination generates the combination after s, overwriting the input value.
func nextCombination(s []int, n, k int) {
	for j := k - 1; j >= 0; j-- {
		if s[j] == n+j-k {
			continue
		}
		s[j]++
		for l := j + 1; l < k; l++ {
			s[l] = s[j] + l - j
		}
		break
	}
}

// Cartesian returns the cartesian product of the slices in data. The Cartesian
// product of two sets is the set of all combinations of the items. For example,
// given the input
//  [][]float64{{1,2},{3,4},{5,6}}
// the returned matrix will be
//  [ 1 3 5 ]
//  [ 1 3 6 ]
//  [ 1 4 5 ]
//  [ 1 4 6 ]
//  [ 2 3 5 ]
//  [ 2 3 6 ]
//  [ 2 4 5 ]
//  [ 2 4 6 ]
// If dst is nil, a new matrix will be allocated and returned, otherwise the number
// of rows of dst must equal \prod_i len(data[i]), and the number of columns in
// dst must equal len(data). Cartesian also panics if len(data) = 0.
func Cartesian(dst *mat.Dense, data [][]float64) *mat.Dense {
	if len(data) == 0 {
		panic("combin: empty data input")
	}
	cols := len(data)
	rows := 1
	lens := make([]int, cols)
	for i, d := range data {
		v := len(d)
		lens[i] = v
		rows *= v
	}
	if dst == nil {
		dst = mat.NewDense(rows, cols, nil)
	}
	r, c := dst.Dims()
	if r != rows || c != cols {
		panic("combin: destination matrix size mismatch")
	}
	idxs := make([]int, cols)
	for i := 0; i < rows; i++ {
		SubFor(idxs, i, lens)
		for j := 0; j < len(data); j++ {
			dst.Set(i, j, data[j][idxs[j]])
		}
	}
	return dst
}

// IdxFor converts a multi-dimensional index into a linear index for a
// multi-dimensional space. sub specifies the index for each dimension, and dims
// specifies the size of each dimension. IdxFor is the inverse of SubFor.
// IdxFor panics if any of the entries of sub are negative, any of the entries
// of dim are non-positive, or if sub[i] >= dims[i] for any i.
func IdxFor(sub, dims []int) int {
	// The index returned is "row-major", that is the last index of sub is
	// continuous.
	var idx int
	stride := 1
	for i := len(dims) - 1; i >= 0; i-- {
		v := sub[i]
		d := dims[i]
		if d <= 0 {
			panic(nonpositiveDimension)
		}
		if v < 0 || v >= d {
			panic("combin: invalid subscript")
		}
		idx += v * stride
		stride *= d
	}
	return idx
}

// SubFor returns the multi-dimensional subscript for the input linear index to
// the multi-dimensional space. dims specifies the size of each dimension, and
// idx specifies the linear index. SubFor is the inverse of IdxFor.
//
// If sub is non-nil the result is stored in-place into sub, and SubFor will panic
// if len(sub) != len(dims). If sub is nil a new slice of the appropriate length
// is allocated. SubFor panics if idx < 0 or if idx is greater than or equal to
// the product of the dimensions.
func SubFor(sub []int, idx int, dims []int) []int {
	if sub == nil {
		sub = make([]int, len(dims))
	}
	if len(sub) != len(dims) {
		panic(badInput)
	}
	if idx < 0 {
		panic(badNegInput)
	}
	stride := 1
	for i := len(dims) - 1; i >= 1; i-- {
		stride *= dims[i]
	}
	for i := 0; i < len(dims)-1; i++ {
		v := idx / stride
		d := dims[i]
		if d < 0 {
			panic(nonpositiveDimension)
		}
		if v >= dims[i] {
			panic("combin: index too large")
		}
		sub[i] = v
		idx -= v * stride
		stride /= dims[i+1]
	}
	if idx > dims[len(sub)-1] {
		panic("combin: index too large")
	}
	sub[len(sub)-1] = idx
	return sub
}
<|endoftext|>