<commit_before>// leisp
// Copyright 2016 Zongmin Lei <leizongmin@gmail.com>. All rights reserved.
// Under the MIT License

package main

import (
	"fmt"
	"leisp/interpreter"
	"leisp/parser"

	"github.com/peterh/liner"
)

func makeIndentString(n int) string {
	s := ""
	for i := 0; i < n; i++ {
		s += "  "
	}
	return s
}

func main() {

	str := `
(defvar aa 456)
(println aa 123 "ok" :haha 'defvar)
(println {1 2.2 "aa"})
(println [1 2 3])
(println '(list 1 2 3))
(println (str 1 "2" 3.3 :4) (/ 1 2 34) (^ 2 10 2))
(defn add [a b]
  (println "arguments:" a b)
  (+ a b))
(println (add 123 aa))
(println this)
`

	parser.Dump(str)

	a := interpreter.Eval(nil, str)
	a.Print()

	rl := liner.NewLiner()
	rl.SetCtrlCAborts(true)

	brackets := make([]rune, 0)
	buffer := ""

	for {

		prompt := "leisp> "
		if len(brackets) > 0 {
			prompt = "       " + makeIndentString(len(brackets))
		}

		line, err := rl.Prompt(prompt)
		if err != nil {
			if err.Error() == "prompt aborted" {
				break
			}
			fmt.Println(err)
			break
		}

		if line == "" {
			continue
		}

		for _, r2 := range line {
			if r2 == '{' || r2 == '[' || r2 == '(' {
				brackets = append(brackets, r2)
			} else if r2 == '}' || r2 == ']' || r2 == ')' {
				r := brackets[len(brackets)-1]
				if r == '{' && r2 == '}' {
					brackets = brackets[:len(brackets)-1]
				} else if r == '[' && r2 == ']' {
					brackets = brackets[:len(brackets)-1]
				} else if r == '(' && r2 == ')' {
					brackets = brackets[:len(brackets)-1]
				} else {
					fmt.Printf("Error: %s does not matched %s\n", string(r), string(r2))
				}
			}
		}

		buffer += " " + line
		if len(brackets) == 0 {
			a := interpreter.Eval(nil, buffer)
			a.Print()
			buffer = ""
		}

	}

	rl.Close()

}
<commit_msg>REPL支持字符串输入<commit_after>// leisp
// Copyright 2016 Zongmin Lei <leizongmin@gmail.com>. All rights reserved.
// Under the MIT License

package main

import (
	"fmt"
	"leisp/interpreter"
	"leisp/parser"

	"github.com/peterh/liner"
)

func makeIndentString(n int) string {
	s := ""
	for i := 0; i < n; i++ {
		s += "  "
	}
	return s
}

func main() {

	str := `
(defvar aa 456)
(println aa 123 "ok" :haha 'defvar)
(println {1 2.2 "aa"})
(println [1 2 3])
(println '(list 1 2 3))
(println (str 1 "2" 3.3 :4) (/ 1 2 34) (^ 2 10 2))
(defn add [a b]
  (println "arguments:" a b)
  (+ a b))
(println (add 123 aa))
(println this)
`

	parser.Dump(str)

	a := interpreter.Eval(nil, str)
	a.Print()

	rl := liner.NewLiner()
	rl.SetCtrlCAborts(true)

	brackets := make([]rune, 0)
	isString := false
	buffer := ""

	for {

		prompt := "leisp> "
		if len(brackets) > 0 {
			prompt = "       " + makeIndentString(len(brackets))
		}

		line, err := rl.Prompt(prompt)
		if err != nil {
			if err.Error() == "prompt aborted" {
				break
			}
			fmt.Println(err)
			break
		}

		if line == "" {
			continue
		}

		isEscape := false
		for _, r2 := range line {
			if isString {
				if isEscape {
					isEscape = false
				} else {
					if r2 == '\\' {
						isEscape = true
					} else if r2 == '"' {
						isString = false
					}
				}
			} else {
				if r2 == '{' || r2 == '[' || r2 == '(' {
					brackets = append(brackets, r2)
				} else if r2 == '}' || r2 == ']' || r2 == ')' {
					r := brackets[len(brackets)-1]
					if r == '{' && r2 == '}' {
						brackets = brackets[:len(brackets)-1]
					} else if r == '[' && r2 == ']' {
						brackets = brackets[:len(brackets)-1]
					} else if r == '(' && r2 == ')' {
						brackets = brackets[:len(brackets)-1]
					} else {
						fmt.Printf("Error: %s does not matched %s\n", string(r), string(r2))
					}
				} else if r2 == '"' {
					isString = true
				}
			}
		}

		buffer += " " + line
		if len(brackets) == 0 && !isString {
			a := interpreter.Eval(nil, buffer)
			a.Print()
			buffer = ""
		}

	}

	rl.Close()

}
<|endoftext|>


<commit_before>package MinimapStitcher

import (
	"fmt"
	"os"
	"log"
	"io/ioutil"
	"strings"
	"strconv"
	"image/draw"
	"image"
	"image/png"
)

const (
	TILE_SIZE = 256
)

func stitch(sourceDirectory string, destinationDirectory string) {
	files, _ := ioutil.ReadDir(sourceDirectory)
	for _, f := range files {
		compileMinimap(destinationDirectory + f.Name(), sourceDirectory + f.Name(), f.Name(), false)
	}
}

func compileMinimap(resultFileName string, sourceDirectory string, minimapName string, noLiquid bool) {
	var foundNoLiquid = false
	var tiles = make(map[string]string);
	files, _ := ioutil.ReadDir(sourceDirectory)
	for _, f := range files {
		var fullFileName = sourceDirectory + "/" + f.Name()
		if strings.Contains(f.Name(), ".png") {
			var fName = strings.TrimRight(f.Name(), ".png")
			var fNameNoLiquid = strings.Contains(fName, "noLiquid")
			if fNameNoLiquid && !noLiquid {
				foundNoLiquid = true
			} else if !fNameNoLiquid && !noLiquid {
				tiles[strings.TrimLeft(fName, "map")] = fullFileName
			} else if fNameNoLiquid && noLiquid {
				tiles[strings.TrimLeft(fName, "noLiquid_map")] = fullFileName
			} else if !fNameNoLiquid && noLiquid {
				var trimmerFName = strings.TrimLeft(fName, "map")
				if _, ok := tiles[trimmerFName]; !ok {
					tiles[trimmerFName] = fullFileName
				}
			}
		}
	}

	if foundNoLiquid && !noLiquid {
		compileMinimap(resultFileName + "NoLiquid", sourceDirectory, minimapName, true)
	}

	buildMinimap(resultFileName, tiles)
}

func buildMinimap(resultFileName string, tiles map[string]string)  {
	var hc, lc, hr, lr = calculateMinimapSize(tiles)
	var files, width, height = calculateMinimapTilePlacement(tiles, hc, lc, hr, lr)
	createMinimapImage(resultFileName, width, height, files)
}

func calculateMinimapSize(tiles map[string]string) (hc, lc, hr, lr int) {
	hc = 1000
	lc = 0
	hr = 1000
	lr = 0
	for tile, _ := range tiles {
		var tileParts = strings.Split(tile, "_")
		var col, _ = strconv.Atoi(tileParts[0])
		var row, _ = strconv.Atoi(tileParts[1])
		if hc > col {
			hc = col
		}
		if lc < col {
			lc = col
		}
		if hr > row {
			hr = row
		}
		if lr < row {
			lr = row
		}
	}
	return
}

func calculateMinimapTilePlacement(tiles map[string]string, hc int, lc int, hr int, lr int) (map[string]string, int, int) {
	var files = make(map[string]string)

	var width = 0;
	var height = 0;

	for i := hc; i < lc; i++ {
		width += TILE_SIZE
		for j := hr; j < lr; j++ {
			if i == hc {
				height += TILE_SIZE
			}

			var si = strconv.Itoa(i)
			var sj = strconv.Itoa(j)
			var oi = strconv.Itoa((i - hc) * TILE_SIZE)
			var oj = strconv.Itoa((j - hr) * TILE_SIZE)
			if _, ok := tiles[si + "_" + sj]; ok {
				files[oi + "_" + oj] = tiles[si + "_" + sj]
			}
		}
	}

	return files, width, height
}

func createMinimapImage(resultFileName string, width int, height int, files map[string]string) {
	m := image.NewRGBA(image.Rect(0, 0, width, height))
	for coords, fileName := range files {
		var coordParts = strings.Split(coords, "_")
		var x, _ = strconv.Atoi(coordParts[0])
		var y, _ = strconv.Atoi(coordParts[1])

		tile, err := os.Open(fileName)
		if err != nil {
			log.Fatal(err)
		}
		defer tile.Close()

		tileImage, err := png.Decode(tile)
		if err != nil {
			fmt.Printf("%v", fileName)
			log.Fatal(err)
		}

		draw.Draw(m, image.Rect(x, y, x + TILE_SIZE, y + TILE_SIZE), tileImage, image.Point{0,0}, draw.Src)
	}

	toimg, _ := os.Create(resultFileName + ".png")
	png.Encode(toimg, m)
	defer toimg.Close()
}
<commit_msg>Exported method should start with a capital letter<commit_after>package MinimapStitcher

import (
	"fmt"
	"os"
	"log"
	"io/ioutil"
	"strings"
	"strconv"
	"image/draw"
	"image"
	"image/png"
)

const (
	TILE_SIZE = 256
)

func Stitch(sourceDirectory string, destinationDirectory string) {
	files, _ := ioutil.ReadDir(sourceDirectory)
	for _, f := range files {
		compileMinimap(destinationDirectory + f.Name(), sourceDirectory + f.Name(), f.Name(), false)
	}
}

func compileMinimap(resultFileName string, sourceDirectory string, minimapName string, noLiquid bool) {
	var foundNoLiquid = false
	var tiles = make(map[string]string);
	files, _ := ioutil.ReadDir(sourceDirectory)
	for _, f := range files {
		var fullFileName = sourceDirectory + "/" + f.Name()
		if strings.Contains(f.Name(), ".png") {
			var fName = strings.TrimRight(f.Name(), ".png")
			var fNameNoLiquid = strings.Contains(fName, "noLiquid")
			if fNameNoLiquid && !noLiquid {
				foundNoLiquid = true
			} else if !fNameNoLiquid && !noLiquid {
				tiles[strings.TrimLeft(fName, "map")] = fullFileName
			} else if fNameNoLiquid && noLiquid {
				tiles[strings.TrimLeft(fName, "noLiquid_map")] = fullFileName
			} else if !fNameNoLiquid && noLiquid {
				var trimmerFName = strings.TrimLeft(fName, "map")
				if _, ok := tiles[trimmerFName]; !ok {
					tiles[trimmerFName] = fullFileName
				}
			}
		}
	}

	if foundNoLiquid && !noLiquid {
		compileMinimap(resultFileName + "NoLiquid", sourceDirectory, minimapName, true)
	}

	buildMinimap(resultFileName, tiles)
}

func buildMinimap(resultFileName string, tiles map[string]string)  {
	var hc, lc, hr, lr = calculateMinimapSize(tiles)
	var files, width, height = calculateMinimapTilePlacement(tiles, hc, lc, hr, lr)
	createMinimapImage(resultFileName, width, height, files)
}

func calculateMinimapSize(tiles map[string]string) (hc, lc, hr, lr int) {
	hc = 1000
	lc = 0
	hr = 1000
	lr = 0
	for tile, _ := range tiles {
		var tileParts = strings.Split(tile, "_")
		var col, _ = strconv.Atoi(tileParts[0])
		var row, _ = strconv.Atoi(tileParts[1])
		if hc > col {
			hc = col
		}
		if lc < col {
			lc = col
		}
		if hr > row {
			hr = row
		}
		if lr < row {
			lr = row
		}
	}
	return
}

func calculateMinimapTilePlacement(tiles map[string]string, hc int, lc int, hr int, lr int) (map[string]string, int, int) {
	var files = make(map[string]string)

	var width = 0;
	var height = 0;

	for i := hc; i < lc; i++ {
		width += TILE_SIZE
		for j := hr; j < lr; j++ {
			if i == hc {
				height += TILE_SIZE
			}

			var si = strconv.Itoa(i)
			var sj = strconv.Itoa(j)
			var oi = strconv.Itoa((i - hc) * TILE_SIZE)
			var oj = strconv.Itoa((j - hr) * TILE_SIZE)
			if _, ok := tiles[si + "_" + sj]; ok {
				files[oi + "_" + oj] = tiles[si + "_" + sj]
			}
		}
	}

	return files, width, height
}

func createMinimapImage(resultFileName string, width int, height int, files map[string]string) {
	m := image.NewRGBA(image.Rect(0, 0, width, height))
	for coords, fileName := range files {
		var coordParts = strings.Split(coords, "_")
		var x, _ = strconv.Atoi(coordParts[0])
		var y, _ = strconv.Atoi(coordParts[1])

		tile, err := os.Open(fileName)
		if err != nil {
			log.Fatal(err)
		}
		defer tile.Close()

		tileImage, err := png.Decode(tile)
		if err != nil {
			fmt.Printf("%v", fileName)
			log.Fatal(err)
		}

		draw.Draw(m, image.Rect(x, y, x + TILE_SIZE, y + TILE_SIZE), tileImage, image.Point{0,0}, draw.Src)
	}

	toimg, _ := os.Create(resultFileName + ".png")
	png.Encode(toimg, m)
	defer toimg.Close()
}
<|endoftext|>


<commit_before>// Copyright 2016, Marc Lavergne <mlavergn@gmail.com>. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package goweb

import (
	"godom"
	. "golog"
	"regexp"
)

type JScript struct {
}

//
// Constructor
//
func NewJScript() *JScript {
	return &JScript{}
}

func (self *JScript) ParseRedirect(d *godom.DOM) string {
	var result string

	scripts := d.Find("script", nil)
	if len(scripts) > 0 {
		LogDebug("SCRIPTs found")

		re, _ := regexp.Compile("document.location\\s?=\\s?['\"](.+)[\"'];")

		for _, script := range scripts {
			match := re.FindStringSubmatch(script.Text())
			if len(match) > 1 {
				result = match[1]
			}
		}
		if len(result) > 0 {
			LogDebug("Script redirect detected: " + result)
		} else {
			LogDebug("No script redirect detected")
		}
	} else {
		LogDebug("META not found")
	}

	return result
}
<commit_msg>Minor change to DOMNode API<commit_after>// Copyright 2016, Marc Lavergne <mlavergn@gmail.com>. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package goweb

import (
	"godom"
	. "golog"
	"regexp"
)

type JScript struct {
}

//
// Constructor
//
func NewJScript() *JScript {
	return &JScript{}
}

func (self *JScript) ParseRedirect(d *godom.DOM) string {
	var result string

	scripts := d.Find("script", nil)
	if len(scripts) > 0 {
		LogDebug("SCRIPTs found")

		re, _ := regexp.Compile("document.location\\s?=\\s?['\"](.+)[\"'];")

		for _, script := range scripts {
			match := re.FindStringSubmatch(script.Text)
			if len(match) > 1 {
				result = match[1]
			}
		}
		if len(result) > 0 {
			LogDebug("Script redirect detected: " + result)
		} else {
			LogDebug("No script redirect detected")
		}
	} else {
		LogDebug("META not found")
	}

	return result
}
<|endoftext|>


<commit_before>package graph

// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"math"
	"runtime"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

var MaxProcs = runtime.GOMAXPROCS(0)

func FastRandMinCut(g *Undirected, iter int) (c []*Edge, w float64) {
	k := newKargerR(g)
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

// parallelised outside the recursion tree

func FastRandMinCutPar(g *Undirected, iter, thread int) (c []*Edge, w float64) {
	if thread > MaxProcs {
		thread = MaxProcs
	}
	if thread > iter {
		thread = iter
	}
	iter, rem := iter/thread+1, iter%thread

	type r struct {
		c []*Edge
		w float64
	}
	rs := make([]*r, thread)

	wg := &sync.WaitGroup{}
	for j := 0; j < thread; j++ {
		if rem == 0 {
			iter--
		}
		if rem >= 0 {
			rem--
		}
		wg.Add(1)
		go func(j, iter int) {
			defer wg.Done()
			k := newKargerR(g)
			k.init()
			var (
				w = math.Inf(1)
				c []*Edge
			)
			for i := 0; i < iter; i++ {
				k.fastRandMinCut()
				if k.w < w {
					w = k.w
					c = k.c
				}
			}

			rs[j] = &r{c, w}
		}(j, iter)
	}

	w = math.Inf(1)
	wg.Wait()
	for _, subr := range rs {
		if subr.w < w {
			w = subr.w
			c = subr.c
		}
	}

	return
}

type kargerR struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
}

func newKargerR(g *Undirected) *kargerR {
	return &kargerR{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerR) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerR) copy(t *kargerR) {
	self.order = t.order
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerR) fastRandMinCut() {
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	sub := make([]*kargerR, 2)
	for i := range sub {
		sub[i] = newKargerR(self.g)
		sub[i].copy(self)
		sub[i].randContract(t)
		sub[i].fastRandMinCut()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerR) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerR) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerR) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}

// parallelised within the recursion tree

func ParFastRandMinCut(g *Undirected, iter, threads int) (c []*Edge, w float64) {
	k := newKargerRP(g)
	k.split = bits(threads)
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

type kargerRP struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
	depth int
	split int
}

func bits(i int) (b int) {
	for ; i > 1; i >>= 1 {
		b++
	}
	return
}

func newKargerRP(g *Undirected) *kargerRP {
	return &kargerRP{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerRP) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerRP) copy(t *kargerRP) {
	self.order = t.order
	self.depth = t.depth
	self.split = t.split
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerRP) fastRandMinCut() {
	self.depth++
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if self.depth < self.split {
		wg = &sync.WaitGroup{}
	}

	sub := make([]*kargerRP, 2)
	for i := range sub {
		if wg != nil {
			wg.Add(1)
			go func(i int) {
				defer wg.Done()
				sub[i] = newKargerRP(self.g)
				sub[i].copy(self)
				sub[i].randContract(t)
				sub[i].fastRandMinCut()
			}(i)
		} else {
			sub[i] = newKargerRP(self.g)
			sub[i].copy(self)
			sub[i].randContract(t)
			sub[i].fastRandMinCut()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerRP) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerRP) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerRP) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}
<commit_msg>Optimisation of recursive karger<commit_after>package graph

// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"math"
	"runtime"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

var MaxProcs = runtime.GOMAXPROCS(0)

func FastRandMinCut(g *Undirected, iter int) (c []*Edge, w float64) {
	k := newKargerR(g)
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

// parallelised outside the recursion tree

func FastRandMinCutPar(g *Undirected, iter, thread int) (c []*Edge, w float64) {
	if thread > MaxProcs {
		thread = MaxProcs
	}
	if thread > iter {
		thread = iter
	}
	iter, rem := iter/thread+1, iter%thread

	type r struct {
		c []*Edge
		w float64
	}
	rs := make([]*r, thread)

	wg := &sync.WaitGroup{}
	for j := 0; j < thread; j++ {
		if rem == 0 {
			iter--
		}
		if rem >= 0 {
			rem--
		}
		wg.Add(1)
		go func(j, iter int) {
			defer wg.Done()
			k := newKargerR(g)
			k.init()
			var (
				w = math.Inf(1)
				c []*Edge
			)
			for i := 0; i < iter; i++ {
				k.fastRandMinCut()
				if k.w < w {
					w = k.w
					c = k.c
				}
			}

			rs[j] = &r{c, w}
		}(j, iter)
	}

	w = math.Inf(1)
	wg.Wait()
	for _, subr := range rs {
		if subr.w < w {
			w = subr.w
			c = subr.c
		}
	}

	return
}

type kargerR struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
}

func newKargerR(g *Undirected) *kargerR {
	return &kargerR{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerR) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerR) copy(t *kargerR) {
	self.order = t.order
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerR) fastRandMinCut() {
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	sub := []*kargerR{self, newKargerR(self.g)}
	sub[1].copy(self)
	for i := range sub {
		sub[i].randContract(t)
		sub[i].fastRandMinCut()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerR) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerR) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerR) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}

// parallelised within the recursion tree

func ParFastRandMinCut(g *Undirected, iter, threads int) (c []*Edge, w float64) {
	k := newKargerRP(g)
	k.split = bits(threads)
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

type kargerRP struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
	depth int
	split int
}

func bits(i int) (b int) {
	for ; i > 1; i >>= 1 {
		b++
	}
	return
}

func newKargerRP(g *Undirected) *kargerRP {
	return &kargerRP{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerRP) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerRP) copy(t *kargerRP) {
	self.order = t.order
	self.depth = t.depth
	self.split = t.split
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerRP) fastRandMinCut() {
	self.depth++
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if self.depth < self.split {
		wg = &sync.WaitGroup{}
	}

	sub := []*kargerRP{self, newKargerRP(self.g)}
	sub[1].copy(self)
	for i := range sub {
		if wg != nil {
			wg.Add(1)
			go func(i int) {
				defer wg.Done()
				sub[i].randContract(t)
				sub[i].fastRandMinCut()
			}(i)
		} else {
			sub[i].randContract(t)
			sub[i].fastRandMinCut()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerRP) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerRP) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerRP) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}
<|endoftext|>


<commit_before>package lfs

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/client"
	"github.com/docker/go-connections/nat"
	git "github.com/libgit2/git2go"
	"github.com/pkg/errors"
)

// git lfs track
// Since the git-lfs devs discourage using git-lfs in go projects we're just
// calling the git-lfs CLI.
func Track(filename, repositoryLocation string) (string, error) {
	cmd := exec.Command("git-lfs", "track", filename)
	cmd.Dir = repositoryLocation
	out, err := cmd.Output()

	// wait to ensure .gitattributes file is up to date.
	// a monument to all my sins.
	time.Sleep(2 * time.Second)

	output := string(out)
	output = strings.TrimRight(output, "\n")

	return output, err
}

// Adds and commits data found in inputPath
func AddAndCommitData(path, msg string) (string, error) {

	repositoryLocation, err := Add(path)
	if err != nil {
		return "", err
	}

	commitId, err := commit(repositoryLocation, msg)
	if err != nil {
		return "", err
	}

	return commitId, nil
}

// Add the given path to the
func Add(path string) (string, error) {

	wd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	defer os.Chdir(wd)

	repo, repositoryLocation, err := openRepository(path)
	if err != nil {
		return "", err
	}

	os.Chdir(repositoryLocation)

	dataPath, err := filepath.Rel(repositoryLocation, path)
	if err != nil {
		return "", err
	}

	// ensure git-lfs tracks all files recursively by adding ** pattern, see
	// git PATTERN FORMAT description for more details.
	dataPattern := "" + dataPath + "/**"

	output, err := Track(dataPattern, repositoryLocation)
	if err != nil {
		return "", errors.Wrap(err, "Could not track files using git-lfs: "+output)
	}

	gitAttr := ".gitattributes"
	changed, err := fileChanged(repo, gitAttr)
	if err != nil {
		return "", err
	}

	if changed {
		err := addToIndex(repo, gitAttr)
		if err != nil {
			return "", err
		}
	}

	output, err = add(dataPath, repositoryLocation)
	if err != nil {
		return "", errors.Wrap(err, "Could not add files "+output)
	}

	return repositoryLocation, nil
}

func addToIndex(repo *git.Repository, path string) error {

	index, err := repo.Index()
	if err != nil {
		return err
	}

	err = index.AddByPath(path)
	if err != nil {
		return err
	}

	_, err = index.WriteTree()
	if err != nil {
		return err
	}

	err = index.Write()
	if err != nil {
		return err
	}

	return err
}

// Removes the last directory in a path and returns it
func popLastDirectory(path string) string {

	// split the path into a list of dirs /a/b/c --> [a,b,c] then remove
	// the last one and create a new path --> /a/b
	list := strings.Split(path, "/")
	list = list[0 : len(list)-1]
	path = "/" + filepath.Join(list...)
	return path
}

// Returns true if file is new, modified or deleted
func fileChanged(repo *git.Repository, path string) (bool, error) {
	status, err := repo.StatusFile(path)
	if err != nil {
		return false, err
	}

	if status == git.StatusWtNew || status == git.StatusWtModified ||
		status == git.StatusWtDeleted {
		return true, nil
	}

	return false, nil
}

// commits staged changes
func commit(path, msg string) (string, error) {

	repo, err := git.OpenRepository(path)
	if err != nil {
		return "", err
	}

	index, err := repo.Index()
	if err != nil {
		return "", err
	}

	treeId, err := index.WriteTree()
	if err != nil {
		return "", err
	}

	tree, err := repo.LookupTree(treeId)
	if err != nil {
		return "", err
	}

	err = index.Write()
	if err != nil {
		return "", err
	}

	var sig = &git.Signature{
		"walrus",
		"walrus@github.com/fjukstad/walrus",
		time.Now(),
	}

	var commitId *git.Oid

	currentBranch, err := repo.Head()
	if err != nil {
		commitId, err = repo.CreateCommit("HEAD", sig, sig, msg, tree)
	} else {
		currentTip, err := repo.LookupCommit(currentBranch.Target())
		if err != nil {
			return "", err
		}
		commitId, err = repo.CreateCommit("HEAD", sig, sig, msg, tree, currentTip)
	}
	if err != nil {
		return "", err
	}

	err = index.Write()
	if err != nil {
		return "", err
	}

	return commitId.String(), nil
}

// Will try to open a git repository located at the given path. If it is not
// found it will traverse the directory tree outwards until i either finds a
// repository or hits the root. If no repository is found it will initialize one
// in the current working directory.
func openRepository(path string) (repo *git.Repository, repositoryPath string, err error) {

	wd, err := os.Getwd()
	if err != nil {
		return nil, "", err
	}
	for {
		repo, err = git.OpenRepository(path)
		if err != nil {
			path = popLastDirectory(path)
			// Root hit
			if path == "/" {
				path = wd
				fmt.Println("Output directory is not in a git repository. Creating one in " + path)
				repo, err = git.InitRepository(wd, false)
				if err != nil {
					return nil, "", errors.Wrap(err, "Could not initialize git repository")
				}
				break
			}
		} else {
			break
		}
	}
	return repo, path, nil
}

// git add
// To speed up dev time for the prototype, use the exec pkg not git2go package
// to add files. Future versions will get rid of this hacky way of doing things
// by creating the blobs, softlinks etc. but that's for later!
func add(path, repositoryLocation string) (string, error) {
	cmd := exec.Command("git", "add", path)
	cmd.Dir = repositoryLocation
	out, err := cmd.Output()
	output := string(out)
	output = strings.TrimRight(output, "\n")
	return output, err
}

// Starts a git-lfs server in a Docker container
func StartServer(mountDir string) error {

	c, err := client.NewEnvClient()
	if err != nil {
		return errors.Wrap(err, "Could not create Docker client")
	}

	image := "fjukstad/lfs-server"
	_, err = c.ImagePull(context.Background(), image,
		types.ImagePullOptions{})

	if err != nil {
		return errors.Wrap(err, "Could not pull iamge")
	}

	hostPath, err := filepath.Abs(mountDir)
	if err != nil {
		return errors.Wrap(err,
			"Could not create absolute git-lfs directory path")
	}

	bind := hostPath + ":/lfs"

	ps := make(nat.PortSet)
	ps["9999/tcp"] = struct{}{}

	pm := make(nat.PortMap)
	pm["9999/tcp"] = []nat.PortBinding{nat.PortBinding{"0.0.0.0", "9999"}}

	resp, err := c.ContainerCreate(context.Background(),
		&container.Config{Image: image,
			ExposedPorts: ps},
		&container.HostConfig{
			Binds:        []string{bind},
			PortBindings: pm},
		&network.NetworkingConfig{},
		"git-lfs-server")

	if err != nil || resp.ID == " " {
		return errors.Wrap(err, "Could not create git-lfs server container")
	}

	containerId := resp.ID

	err = c.ContainerStart(context.Background(), containerId,
		types.ContainerStartOptions{})
	return err

}
<commit_msg>prevent identical entries in .gitattributes<commit_after>package lfs

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/client"
	"github.com/docker/go-connections/nat"
	git "github.com/libgit2/git2go"
	"github.com/pkg/errors"
)

// git lfs track
// Since the git-lfs devs discourage using git-lfs in go projects we're just
// calling the git-lfs CLI.
func Track(filename, repositoryLocation string) (string, error) {

	cmd := exec.Command("git-lfs", "track", filename)
	cmd.Dir = repositoryLocation
	out, err := cmd.Output()

	// wait to ensure .gitattributes file is up to date.
	// a monument to all my sins.
	time.Sleep(2 * time.Second)

	output := string(out)
	output = strings.TrimRight(output, "\n")

	return output, err
}

// Adds and commits data found in inputPath
func AddAndCommitData(path, msg string) (string, error) {

	repositoryLocation, err := Add(path)
	if err != nil {
		return "", err
	}

	commitId, err := commit(repositoryLocation, msg)
	if err != nil {
		return "", err
	}

	return commitId, nil
}

// Add the given path to the
func Add(path string) (string, error) {

	wd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	defer os.Chdir(wd)

	repo, repositoryLocation, err := openRepository(path)
	if err != nil {
		return "", err
	}

	os.Chdir(repositoryLocation)

	dataPath, err := filepath.Rel(repositoryLocation, path)
	if err != nil {
		return "", err
	}

	// ensure git-lfs tracks all files recursively by adding ** pattern, see
	// git PATTERN FORMAT description for more details.
	dataPattern := "" + dataPath + "/**"

	gitAttr := ".gitattributes"

	// if pattern already exists don't rerun the track command
	b, err := ioutil.ReadFile(gitAttr)
	if err != nil {
		pe := err.(*os.PathError)
		if pe.Err.Error() != "no such file or directory" {
			return "", err
		}
	}

	if !strings.Contains(string(b), dataPattern) {
		output, err := Track(dataPattern, repositoryLocation)
		if err != nil {
			return "", errors.Wrap(err, "Could not track files using git-lfs: "+output)
		}
	}

	changed, err := fileChanged(repo, gitAttr)
	if err != nil {
		return "", err
	}

	if changed {
		err := addToIndex(repo, gitAttr)
		if err != nil {
			return "", err
		}
	}

	output, err := add(dataPath, repositoryLocation)
	if err != nil {
		return "", errors.Wrap(err, "Could not add files "+output)
	}

	return repositoryLocation, nil
}

func addToIndex(repo *git.Repository, path string) error {

	index, err := repo.Index()
	if err != nil {
		return err
	}

	err = index.AddByPath(path)
	if err != nil {
		return err
	}

	_, err = index.WriteTree()
	if err != nil {
		return err
	}

	err = index.Write()
	if err != nil {
		return err
	}

	return err
}

// Removes the last directory in a path and returns it
func popLastDirectory(path string) string {

	// split the path into a list of dirs /a/b/c --> [a,b,c] then remove
	// the last one and create a new path --> /a/b
	list := strings.Split(path, "/")
	list = list[0 : len(list)-1]
	path = "/" + filepath.Join(list...)
	return path
}

// Returns true if file is new, modified or deleted
func fileChanged(repo *git.Repository, path string) (bool, error) {
	status, err := repo.StatusFile(path)
	if err != nil {
		return false, err
	}

	if status == git.StatusWtNew || status == git.StatusWtModified ||
		status == git.StatusWtDeleted {
		return true, nil
	}

	return false, nil
}

// commits staged changes
func commit(path, msg string) (string, error) {

	repo, err := git.OpenRepository(path)
	if err != nil {
		return "", err
	}

	index, err := repo.Index()
	if err != nil {
		return "", err
	}

	treeId, err := index.WriteTree()
	if err != nil {
		return "", err
	}

	tree, err := repo.LookupTree(treeId)
	if err != nil {
		return "", err
	}

	err = index.Write()
	if err != nil {
		return "", err
	}

	var sig = &git.Signature{
		"walrus",
		"walrus@github.com/fjukstad/walrus",
		time.Now(),
	}

	var commitId *git.Oid

	currentBranch, err := repo.Head()
	if err != nil {
		commitId, err = repo.CreateCommit("HEAD", sig, sig, msg, tree)
	} else {
		currentTip, err := repo.LookupCommit(currentBranch.Target())
		if err != nil {
			return "", err
		}
		commitId, err = repo.CreateCommit("HEAD", sig, sig, msg, tree, currentTip)
	}
	if err != nil {
		return "", err
	}

	err = index.Write()
	if err != nil {
		return "", err
	}

	return commitId.String(), nil
}

// Will try to open a git repository located at the given path. If it is not
// found it will traverse the directory tree outwards until i either finds a
// repository or hits the root. If no repository is found it will initialize one
// in the current working directory.
func openRepository(path string) (repo *git.Repository, repositoryPath string, err error) {

	wd, err := os.Getwd()
	if err != nil {
		return nil, "", err
	}
	for {
		repo, err = git.OpenRepository(path)
		if err != nil {
			path = popLastDirectory(path)
			// Root hit
			if path == "/" {
				path = wd
				fmt.Println("Output directory is not in a git repository. Creating one in " + path)
				repo, err = git.InitRepository(wd, false)
				if err != nil {
					return nil, "", errors.Wrap(err, "Could not initialize git repository")
				}
				break
			}
		} else {
			break
		}
	}
	return repo, path, nil
}

// git add
// To speed up dev time for the prototype, use the exec pkg not git2go package
// to add files. Future versions will get rid of this hacky way of doing things
// by creating the blobs, softlinks etc. but that's for later!
func add(path, repositoryLocation string) (string, error) {
	cmd := exec.Command("git", "add", path)
	cmd.Dir = repositoryLocation
	out, err := cmd.Output()
	output := string(out)
	output = strings.TrimRight(output, "\n")
	return output, err
}

// Starts a git-lfs server in a Docker container
func StartServer(mountDir string) error {

	c, err := client.NewEnvClient()
	if err != nil {
		return errors.Wrap(err, "Could not create Docker client")
	}

	image := "fjukstad/lfs-server"
	_, err = c.ImagePull(context.Background(), image,
		types.ImagePullOptions{})

	if err != nil {
		return errors.Wrap(err, "Could not pull iamge")
	}

	hostPath, err := filepath.Abs(mountDir)
	if err != nil {
		return errors.Wrap(err,
			"Could not create absolute git-lfs directory path")
	}

	bind := hostPath + ":/lfs"

	ps := make(nat.PortSet)
	ps["9999/tcp"] = struct{}{}

	pm := make(nat.PortMap)
	pm["9999/tcp"] = []nat.PortBinding{nat.PortBinding{"0.0.0.0", "9999"}}

	resp, err := c.ContainerCreate(context.Background(),
		&container.Config{Image: image,
			ExposedPorts: ps},
		&container.HostConfig{
			Binds:        []string{bind},
			PortBindings: pm},
		&network.NetworkingConfig{},
		"git-lfs-server")

	if err != nil || resp.ID == " " {
		return errors.Wrap(err, "Could not create git-lfs server container")
	}

	containerId := resp.ID

	err = c.ContainerStart(context.Background(), containerId,
		types.ContainerStartOptions{})
	return err

}
<|endoftext|>


<commit_before>// Copyright 2015 Cocoon Alarm Ltd.
//
// See LICENSE file for terms and conditions.

// Package libflac provides Go bindings to the libFLAC codec library.
package libflac

import (
	"errors"
	"fmt"
	"io"
	"runtime"
	"unsafe"
)

/*
#cgo LDFLAGS: -lFLAC
#include <stdlib.h>

#include "FLAC/stream_decoder.h"
#include "FLAC/stream_encoder.h"

extern void
decoderErrorCallback_cgo(const FLAC__StreamDecoder *,
		         FLAC__StreamDecoderErrorStatus,
		         void *);
typedef void (*decoderErrorCallbackFn)(const FLAC__StreamDecoder *,
		                       FLAC__StreamDecoderErrorStatus,
		                       void *);

extern void
decoderMetadataCallback_cgo(const FLAC__StreamDecoder *,
			    const FLAC__StreamMetadata *,
			    void *);
typedef void (*decoderMetadataCallbackFn)(const FLAC__StreamDecoder *,
		                          FLAC__StreamMetadata *,
		                          void *);

extern FLAC__StreamDecoderWriteStatus
decoderWriteCallback_cgo(const FLAC__StreamDecoder *,
		         const FLAC__Frame *,
		         const FLAC__int32 **,
		         void *);
typedef FLAC__StreamDecoderWriteStatus (*decoderWriteCallbackFn)(const FLAC__StreamDecoder *,
                                        const FLAC__Frame *,
		                        const FLAC__int32 **,
		                        void *);

extern const char *
get_decoder_error_str(FLAC__StreamDecoderErrorStatus status);

extern int
get_decoder_channels(FLAC__StreamMetadata *metadata);

extern int
get_decoder_depth(FLAC__StreamMetadata *metadata);

extern int
get_decoder_rate(FLAC__StreamMetadata *metadata);

extern void
get_audio_samples(int32_t *output, const FLAC__int32 **input,
                  unsigned int blocksize, unsigned int channels);

*/
import "C"

// Frame is an interleaved buffer of audio data with the specified parameters.
type Frame struct {
	Channels int
	Depth    int
	Rate     int
	Buffer   []int32
}

// Decoder is a FLAC decoder.
type Decoder struct {
	d        *C.FLAC__StreamDecoder
	Channels int
	Depth    int
	Rate     int
	error    bool
	errorStr string
	frame    *Frame
}

// Encoder is a FLAC encoder.
type Encoder struct {
	e        *C.FLAC__StreamEncoder
	Channels int
	Depth    int
	Rate     int
}

//export decoderErrorCallback
func decoderErrorCallback(d *C.FLAC__StreamDecoder, status C.FLAC__StreamDecoderErrorStatus, data unsafe.Pointer) {
	decoder := (*Decoder)(data)
	decoder.error = true
	decoder.errorStr = C.GoString(C.get_decoder_error_str(status))
}

//export decoderMetadataCallback
func decoderMetadataCallback(d *C.FLAC__StreamDecoder, metadata *C.FLAC__StreamMetadata, data unsafe.Pointer) {
	decoder := (*Decoder)(data)
	if metadata._type == C.FLAC__METADATA_TYPE_STREAMINFO {
		decoder.Channels = int(C.get_decoder_channels(metadata))
		decoder.Depth = int(C.get_decoder_depth(metadata))
		decoder.Rate = int(C.get_decoder_rate(metadata))
	}
}

//export decoderWriteCallback
func decoderWriteCallback(d *C.FLAC__StreamDecoder, frame *C.FLAC__Frame, buffer **C.FLAC__int32, data unsafe.Pointer) C.FLAC__StreamDecoderWriteStatus {
	decoder := (*Decoder)(data)
	blocksize := int(frame.header.blocksize)
	decoder.frame = new(Frame)
	f := decoder.frame
	f.Channels = decoder.Channels
	f.Depth = decoder.Depth
	f.Rate = decoder.Rate
	f.Buffer = make([]int32, blocksize*decoder.Channels)
	C.get_audio_samples((*C.int32_t)(&f.Buffer[0]), buffer, C.uint(blocksize), C.uint(decoder.Channels))
	return C.FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
}

// NewDecoder creates a new Decoder object.
func NewDecoder(name string) (d *Decoder, err error) {
	d = new(Decoder)
	d.d = C.FLAC__stream_decoder_new()
	if d.d == nil {
		return nil, errors.New("failed to create decoder")
	}
	c := C.CString(name)
	defer C.free(unsafe.Pointer(c))
	runtime.SetFinalizer(d, (*Decoder).Close)
	status := C.FLAC__stream_decoder_init_file(d.d, c,
		(C.decoderWriteCallbackFn)(unsafe.Pointer(C.decoderWriteCallback_cgo)),
		(C.decoderMetadataCallbackFn)(unsafe.Pointer(C.decoderMetadataCallback_cgo)),
		(C.decoderErrorCallbackFn)(unsafe.Pointer(C.decoderErrorCallback_cgo)),
		unsafe.Pointer(d))
	if status != C.FLAC__STREAM_DECODER_INIT_STATUS_OK {
		return nil, errors.New("failed to open file")
	}
	ret := C.FLAC__stream_decoder_process_until_end_of_metadata(d.d)
	if ret == 0 || d.error == true || d.Channels == 0 {
		return nil, fmt.Errorf("failed to process metadata %s", d.errorStr)
	}
	return
}

// Close closes a decoder and frees the resources.
func (d *Decoder) Close() {
	if d.d != nil {
		C.FLAC__stream_decoder_delete(d.d)
		d.d = nil
	}
	runtime.SetFinalizer(d, nil)
}

// ReadFrame reads a frame of audio data from the decoder.
func (d *Decoder) ReadFrame() (f *Frame, err error) {
	ret := C.FLAC__stream_decoder_process_single(d.d)
	if ret == 0 || d.error == true {
		return nil, errors.New("error reading frame")
	}
	state := C.FLAC__stream_decoder_get_state(d.d)
	if state == C.FLAC__STREAM_DECODER_END_OF_STREAM {
		err = io.EOF
	}
	f = d.frame
	d.frame = nil
	return
}

// NewEncoder creates a new Encoder object.
func NewEncoder(name string, channels int, depth int, rate int) (e *Encoder, err error) {
	e = new(Encoder)
	e.e = C.FLAC__stream_encoder_new()
	if e.e == nil {
		return nil, errors.New("failed to create decoder")
	}
	c := C.CString(name)
	defer C.free(unsafe.Pointer(c))
	runtime.SetFinalizer(e, (*Encoder).Close)
	C.FLAC__stream_encoder_set_channels(e.e, C.uint(channels))
	C.FLAC__stream_encoder_set_bits_per_sample(e.e, C.uint(depth))
	C.FLAC__stream_encoder_set_sample_rate(e.e, C.uint(rate))
	status := C.FLAC__stream_encoder_init_file(e.e, c, nil, nil)
	if status != C.FLAC__STREAM_ENCODER_INIT_STATUS_OK {
		return nil, errors.New("failed to open file")
	}
	e.Channels = channels
	e.Depth = depth
	e.Rate = rate
	return
}

// WriteFrame writes a frame of audio data to the encoder.
func (e *Encoder) WriteFrame(f Frame) (err error) {
	if f.Channels != e.Channels || f.Depth != e.Depth || f.Rate != e.Rate {
		return errors.New("frame type does not match encoder")
	}
	ret := C.FLAC__stream_encoder_process_interleaved(e.e, (*C.FLAC__int32)(&f.Buffer[0]), C.uint(len(f.Buffer)/e.Channels))
	if ret == 0 {
		return errors.New("error encoding frame")
	}
	return
}

// Close closes an encoder and frees the resources.
func (e *Encoder) Close() {
	if e.e != nil {
		C.FLAC__stream_encoder_finish(e.e)
		e.e = nil
	}
	runtime.SetFinalizer(e, nil)
}
<commit_msg>libflac.go: Use pkg-config to find libs<commit_after>// Copyright 2015 Cocoon Alarm Ltd.
//
// See LICENSE file for terms and conditions.

// Package libflac provides Go bindings to the libFLAC codec library.
package libflac

import (
	"errors"
	"fmt"
	"io"
	"runtime"
	"unsafe"
)

/*
#cgo pkg-config: flac
#include <stdlib.h>

#include "FLAC/stream_decoder.h"
#include "FLAC/stream_encoder.h"

extern void
decoderErrorCallback_cgo(const FLAC__StreamDecoder *,
		         FLAC__StreamDecoderErrorStatus,
		         void *);
typedef void (*decoderErrorCallbackFn)(const FLAC__StreamDecoder *,
		                       FLAC__StreamDecoderErrorStatus,
		                       void *);

extern void
decoderMetadataCallback_cgo(const FLAC__StreamDecoder *,
			    const FLAC__StreamMetadata *,
			    void *);
typedef void (*decoderMetadataCallbackFn)(const FLAC__StreamDecoder *,
		                          FLAC__StreamMetadata *,
		                          void *);

extern FLAC__StreamDecoderWriteStatus
decoderWriteCallback_cgo(const FLAC__StreamDecoder *,
		         const FLAC__Frame *,
		         const FLAC__int32 **,
		         void *);
typedef FLAC__StreamDecoderWriteStatus (*decoderWriteCallbackFn)(const FLAC__StreamDecoder *,
                                        const FLAC__Frame *,
		                        const FLAC__int32 **,
		                        void *);

extern const char *
get_decoder_error_str(FLAC__StreamDecoderErrorStatus status);

extern int
get_decoder_channels(FLAC__StreamMetadata *metadata);

extern int
get_decoder_depth(FLAC__StreamMetadata *metadata);

extern int
get_decoder_rate(FLAC__StreamMetadata *metadata);

extern void
get_audio_samples(int32_t *output, const FLAC__int32 **input,
                  unsigned int blocksize, unsigned int channels);

*/
import "C"

// Frame is an interleaved buffer of audio data with the specified parameters.
type Frame struct {
	Channels int
	Depth    int
	Rate     int
	Buffer   []int32
}

// Decoder is a FLAC decoder.
type Decoder struct {
	d        *C.FLAC__StreamDecoder
	Channels int
	Depth    int
	Rate     int
	error    bool
	errorStr string
	frame    *Frame
}

// Encoder is a FLAC encoder.
type Encoder struct {
	e        *C.FLAC__StreamEncoder
	Channels int
	Depth    int
	Rate     int
}

//export decoderErrorCallback
func decoderErrorCallback(d *C.FLAC__StreamDecoder, status C.FLAC__StreamDecoderErrorStatus, data unsafe.Pointer) {
	decoder := (*Decoder)(data)
	decoder.error = true
	decoder.errorStr = C.GoString(C.get_decoder_error_str(status))
}

//export decoderMetadataCallback
func decoderMetadataCallback(d *C.FLAC__StreamDecoder, metadata *C.FLAC__StreamMetadata, data unsafe.Pointer) {
	decoder := (*Decoder)(data)
	if metadata._type == C.FLAC__METADATA_TYPE_STREAMINFO {
		decoder.Channels = int(C.get_decoder_channels(metadata))
		decoder.Depth = int(C.get_decoder_depth(metadata))
		decoder.Rate = int(C.get_decoder_rate(metadata))
	}
}

//export decoderWriteCallback
func decoderWriteCallback(d *C.FLAC__StreamDecoder, frame *C.FLAC__Frame, buffer **C.FLAC__int32, data unsafe.Pointer) C.FLAC__StreamDecoderWriteStatus {
	decoder := (*Decoder)(data)
	blocksize := int(frame.header.blocksize)
	decoder.frame = new(Frame)
	f := decoder.frame
	f.Channels = decoder.Channels
	f.Depth = decoder.Depth
	f.Rate = decoder.Rate
	f.Buffer = make([]int32, blocksize*decoder.Channels)
	C.get_audio_samples((*C.int32_t)(&f.Buffer[0]), buffer, C.uint(blocksize), C.uint(decoder.Channels))
	return C.FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
}

// NewDecoder creates a new Decoder object.
func NewDecoder(name string) (d *Decoder, err error) {
	d = new(Decoder)
	d.d = C.FLAC__stream_decoder_new()
	if d.d == nil {
		return nil, errors.New("failed to create decoder")
	}
	c := C.CString(name)
	defer C.free(unsafe.Pointer(c))
	runtime.SetFinalizer(d, (*Decoder).Close)
	status := C.FLAC__stream_decoder_init_file(d.d, c,
		(C.decoderWriteCallbackFn)(unsafe.Pointer(C.decoderWriteCallback_cgo)),
		(C.decoderMetadataCallbackFn)(unsafe.Pointer(C.decoderMetadataCallback_cgo)),
		(C.decoderErrorCallbackFn)(unsafe.Pointer(C.decoderErrorCallback_cgo)),
		unsafe.Pointer(d))
	if status != C.FLAC__STREAM_DECODER_INIT_STATUS_OK {
		return nil, errors.New("failed to open file")
	}
	ret := C.FLAC__stream_decoder_process_until_end_of_metadata(d.d)
	if ret == 0 || d.error == true || d.Channels == 0 {
		return nil, fmt.Errorf("failed to process metadata %s", d.errorStr)
	}
	return
}

// Close closes a decoder and frees the resources.
func (d *Decoder) Close() {
	if d.d != nil {
		C.FLAC__stream_decoder_delete(d.d)
		d.d = nil
	}
	runtime.SetFinalizer(d, nil)
}

// ReadFrame reads a frame of audio data from the decoder.
func (d *Decoder) ReadFrame() (f *Frame, err error) {
	ret := C.FLAC__stream_decoder_process_single(d.d)
	if ret == 0 || d.error == true {
		return nil, errors.New("error reading frame")
	}
	state := C.FLAC__stream_decoder_get_state(d.d)
	if state == C.FLAC__STREAM_DECODER_END_OF_STREAM {
		err = io.EOF
	}
	f = d.frame
	d.frame = nil
	return
}

// NewEncoder creates a new Encoder object.
func NewEncoder(name string, channels int, depth int, rate int) (e *Encoder, err error) {
	e = new(Encoder)
	e.e = C.FLAC__stream_encoder_new()
	if e.e == nil {
		return nil, errors.New("failed to create decoder")
	}
	c := C.CString(name)
	defer C.free(unsafe.Pointer(c))
	runtime.SetFinalizer(e, (*Encoder).Close)
	C.FLAC__stream_encoder_set_channels(e.e, C.uint(channels))
	C.FLAC__stream_encoder_set_bits_per_sample(e.e, C.uint(depth))
	C.FLAC__stream_encoder_set_sample_rate(e.e, C.uint(rate))
	status := C.FLAC__stream_encoder_init_file(e.e, c, nil, nil)
	if status != C.FLAC__STREAM_ENCODER_INIT_STATUS_OK {
		return nil, errors.New("failed to open file")
	}
	e.Channels = channels
	e.Depth = depth
	e.Rate = rate
	return
}

// WriteFrame writes a frame of audio data to the encoder.
func (e *Encoder) WriteFrame(f Frame) (err error) {
	if f.Channels != e.Channels || f.Depth != e.Depth || f.Rate != e.Rate {
		return errors.New("frame type does not match encoder")
	}
	ret := C.FLAC__stream_encoder_process_interleaved(e.e, (*C.FLAC__int32)(&f.Buffer[0]), C.uint(len(f.Buffer)/e.Channels))
	if ret == 0 {
		return errors.New("error encoding frame")
	}
	return
}

// Close closes an encoder and frees the resources.
func (e *Encoder) Close() {
	if e.e != nil {
		C.FLAC__stream_encoder_finish(e.e)
		e.e = nil
	}
	runtime.SetFinalizer(e, nil)
}
<|endoftext|>


<commit_before>package librato

import (
	"fmt"
	"log"
	"math"
	"reflect"
	"regexp"
	"time"

	"github.com/rcrowley/go-metrics"
)

// a regexp for extracting the unit from time.Duration.String
var unitRegexp = regexp.MustCompile("[^\\d]+$")

// a helper that turns a time.Duration into librato display attributes for timer metrics
func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
	attrs = make(map[string]interface{})
	attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
	attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
	return
}

type RateValue string

const (
	Rate1  RateValue = "Rate1"
	Rate5  RateValue = "Rate5"
	Rate15 RateValue = "Rate15"
)

type rateFn func(r RateValue) interface{}

//Can add other options to not conform to default behavior
//Doing this allows us to reduce the number of metric streams emitted by default
type EnableRateSet struct {
	Timer map[RateValue]bool
	Meter map[RateValue]bool
}

type Reporter struct {
	Email, Token    string
	Source          string
	Interval        time.Duration
	Registry        metrics.Registry
	Percentiles     []float64              // percentiles to report on histogram metrics
	TimerAttributes map[string]interface{} // units in which timers will be displayed
	RateAttributes  *EnableRateSet
	intervalSec     int64
}

func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
	return &Reporter{e, t, s, d, r, p, translateTimerAttributes(u), nil, int64(d / time.Second)}
}

func NewReporterWithRateOptions(r metrics.Registry, o EnableRateSet, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
	return &Reporter{e, t, s, d, r, p, translateTimerAttributes(u), &o, int64(d / time.Second)}
}

func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
	NewReporter(r, d, e, t, s, p, u).Run()
}

func (self *Reporter) Run() {
	ticker := time.Tick(self.Interval)
	metricsApi := &LibratoClient{self.Email, self.Token}
	for now := range ticker {
		var metrics Batch
		var err error
		if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
			log.Printf("ERROR constructing librato request body %s", err)
			continue
		}
		if err := metricsApi.PostMetrics(metrics); err != nil {
			log.Printf("ERROR sending metrics to librato %s", err)
			continue
		}
	}
}

// calculate sum of squares from data provided by metrics.Histogram
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
func sumSquares(s metrics.Sample) float64 {
	count := float64(s.Count())
	sumSquared := math.Pow(count*s.Mean(), 2)
	sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
	if math.IsNaN(sumSquares) {
		return 0.0
	}
	return sumSquares
}
func sumSquaresTimer(t metrics.Timer) float64 {
	count := float64(t.Count())
	sumSquared := math.Pow(count*t.Mean(), 2)
	sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
	if math.IsNaN(sumSquares) {
		return 0.0
	}
	return sumSquares
}

func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
	snapshot = Batch{
		// coerce timestamps to a stepping fn so that they line up in Librato graphs
		MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
		Source:      self.Source,
	}
	snapshot.Gauges = make([]Measurement, 0)
	snapshot.Counters = make([]Measurement, 0)
	histogramGaugeCount := 1 + len(self.Percentiles)

	self.RateAttributes = fillInDefaultRateAttrs(self.RateAttributes)

	r.Each(func(name string, metric interface{}) {
		measurement := Measurement{}
		measurement[Period] = self.Interval.Seconds()
		switch m := metric.(type) {
		case metrics.Counter:
			if m.Count() > 0 {
				measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
				measurement[Value] = float64(m.Count())
				measurement[Attributes] = map[string]interface{}{
					DisplayUnitsLong:  Operations,
					DisplayUnitsShort: OperationsShort,
					DisplayMin:        "0",
				}
				snapshot.Counters = append(snapshot.Counters, measurement)
			}
		case metrics.Gauge:
			measurement[Name] = name
			measurement[Value] = float64(m.Value())
			snapshot.Gauges = append(snapshot.Gauges, measurement)
		case metrics.GaugeFloat64:
			measurement[Name] = name
			measurement[Value] = float64(m.Value())
			snapshot.Gauges = append(snapshot.Gauges, measurement)
		case metrics.Histogram:
			if m.Count() > 0 {
				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
				s := m.Sample()
				measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
				measurement[Count] = uint64(s.Count())
				measurement[Max] = float64(s.Max())
				measurement[Min] = float64(s.Min())
				measurement[Sum] = float64(s.Sum())
				measurement[SumSquares] = sumSquares(s)
				gauges[0] = measurement
				for i, p := range self.Percentiles {
					gauges[i+1] = Measurement{
						Name:   fmt.Sprintf("%s.%.2f", measurement[Name], p),
						Value:  s.Percentile(p),
						Period: measurement[Period],
					}
				}
				snapshot.Gauges = append(snapshot.Gauges, gauges...)
			}
		case metrics.Meter:
			measurement[Name] = name
			measurement[Value] = float64(m.Count())
			snapshot.Counters = append(snapshot.Counters, measurement)
			for val, _ := range self.RateAttributes.Meter {
				snapshot.Gauges = append(snapshot.Gauges, addRateAttrs(val, m, name, self))
			}
		case metrics.Timer:
			measurement[Name] = name
			measurement[Value] = float64(m.Count())
			snapshot.Counters = append(snapshot.Counters, measurement)
			if m.Count() > 0 {
				libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
				gauges[0] = Measurement{
					Name:       libratoName,
					Count:      uint64(m.Count()),
					Sum:        m.Mean() * float64(m.Count()),
					Max:        float64(m.Max()),
					Min:        float64(m.Min()),
					SumSquares: sumSquaresTimer(m),
					Period:     int64(self.Interval.Seconds()),
					Attributes: self.TimerAttributes,
				}
				for i, p := range self.Percentiles {
					gauges[i+1] = Measurement{
						Name:       fmt.Sprintf("%s.timer.%2.0f", name, p*100),
						Value:      m.Percentile(p),
						Period:     int64(self.Interval.Seconds()),
						Attributes: self.TimerAttributes,
					}
				}
				snapshot.Gauges = append(snapshot.Gauges, gauges...)
				for val, _ := range self.RateAttributes.Timer {
					snapshot.Gauges = append(snapshot.Gauges, addRateAttrs(val, m, name, self))
				}
			}
		}
	})
	return
}

func fillInDefaultRateAttrs(r *EnableRateSet) *EnableRateSet {
	enableAll := func() map[RateValue]bool {
		return map[RateValue]bool{
			Rate1:  true,
			Rate5:  true,
			Rate15: true,
		}
	}

	if r == nil {
		r = &EnableRateSet{
			Timer: enableAll(),
			Meter: enableAll(),
		}
	} else if r.Meter == nil {
		r.Meter = enableAll()
	} else if r.Timer == nil {
		r.Timer = enableAll()
	}

	return r
}

func addRateAttrs(val RateValue, mType interface{}, name string, self *Reporter) Measurement {

	measurement := func(m interface{}, r RateValue, name string, suffix string) Measurement {

		return Measurement{
			Name: fmt.Sprintf("%s.%s", name, suffix),
			//If m - metrics.Timer and r is Rate1 then assign metrics.Timer.Rate1
			Value:  reflect.ValueOf(m).MethodByName(string(r)).Call([]reflect.Value{})[0].Float(),
			Period: int64(self.Interval.Seconds()),
			Attributes: map[string]interface{}{
				DisplayUnitsLong:  Operations,
				DisplayUnitsShort: OperationsShort,
				DisplayMin:        "0",
			},
		}
	}

	switch val {
	case Rate1:
		return measurement(mType, Rate1, name, "rate.1min")
	case Rate5:
		return measurement(mType, Rate5, name, "rate.5min")
	case Rate15:
		return measurement(mType, Rate15, name, "rate.15min")
	}

	return nil
}
<commit_msg>Fixing comment<commit_after>package librato

import (
	"fmt"
	"log"
	"math"
	"reflect"
	"regexp"
	"time"

	"github.com/rcrowley/go-metrics"
)

// a regexp for extracting the unit from time.Duration.String
var unitRegexp = regexp.MustCompile("[^\\d]+$")

// a helper that turns a time.Duration into librato display attributes for timer metrics
func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
	attrs = make(map[string]interface{})
	attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
	attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
	return
}

type RateValue string

const (
	Rate1  RateValue = "Rate1"
	Rate5  RateValue = "Rate5"
	Rate15 RateValue = "Rate15"
)

type rateFn func(r RateValue) interface{}

//Can add other options to not conform to default behavior
//Doing this allows us to reduce the number of metric streams emitted by default
type EnableRateSet struct {
	Timer map[RateValue]bool
	Meter map[RateValue]bool
}

type Reporter struct {
	Email, Token    string
	Source          string
	Interval        time.Duration
	Registry        metrics.Registry
	Percentiles     []float64              // percentiles to report on histogram metrics
	TimerAttributes map[string]interface{} // units in which timers will be displayed
	RateAttributes  *EnableRateSet
	intervalSec     int64
}

func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
	return &Reporter{e, t, s, d, r, p, translateTimerAttributes(u), nil, int64(d / time.Second)}
}

func NewReporterWithRateOptions(r metrics.Registry, o EnableRateSet, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
	return &Reporter{e, t, s, d, r, p, translateTimerAttributes(u), &o, int64(d / time.Second)}
}

func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
	NewReporter(r, d, e, t, s, p, u).Run()
}

func (self *Reporter) Run() {
	ticker := time.Tick(self.Interval)
	metricsApi := &LibratoClient{self.Email, self.Token}
	for now := range ticker {
		var metrics Batch
		var err error
		if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
			log.Printf("ERROR constructing librato request body %s", err)
			continue
		}
		if err := metricsApi.PostMetrics(metrics); err != nil {
			log.Printf("ERROR sending metrics to librato %s", err)
			continue
		}
	}
}

// calculate sum of squares from data provided by metrics.Histogram
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
func sumSquares(s metrics.Sample) float64 {
	count := float64(s.Count())
	sumSquared := math.Pow(count*s.Mean(), 2)
	sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
	if math.IsNaN(sumSquares) {
		return 0.0
	}
	return sumSquares
}
func sumSquaresTimer(t metrics.Timer) float64 {
	count := float64(t.Count())
	sumSquared := math.Pow(count*t.Mean(), 2)
	sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
	if math.IsNaN(sumSquares) {
		return 0.0
	}
	return sumSquares
}

func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
	snapshot = Batch{
		// coerce timestamps to a stepping fn so that they line up in Librato graphs
		MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
		Source:      self.Source,
	}
	snapshot.Gauges = make([]Measurement, 0)
	snapshot.Counters = make([]Measurement, 0)
	histogramGaugeCount := 1 + len(self.Percentiles)

	self.RateAttributes = fillInDefaultRateAttrs(self.RateAttributes)

	r.Each(func(name string, metric interface{}) {
		measurement := Measurement{}
		measurement[Period] = self.Interval.Seconds()
		switch m := metric.(type) {
		case metrics.Counter:
			if m.Count() > 0 {
				measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
				measurement[Value] = float64(m.Count())
				measurement[Attributes] = map[string]interface{}{
					DisplayUnitsLong:  Operations,
					DisplayUnitsShort: OperationsShort,
					DisplayMin:        "0",
				}
				snapshot.Counters = append(snapshot.Counters, measurement)
			}
		case metrics.Gauge:
			measurement[Name] = name
			measurement[Value] = float64(m.Value())
			snapshot.Gauges = append(snapshot.Gauges, measurement)
		case metrics.GaugeFloat64:
			measurement[Name] = name
			measurement[Value] = float64(m.Value())
			snapshot.Gauges = append(snapshot.Gauges, measurement)
		case metrics.Histogram:
			if m.Count() > 0 {
				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
				s := m.Sample()
				measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
				measurement[Count] = uint64(s.Count())
				measurement[Max] = float64(s.Max())
				measurement[Min] = float64(s.Min())
				measurement[Sum] = float64(s.Sum())
				measurement[SumSquares] = sumSquares(s)
				gauges[0] = measurement
				for i, p := range self.Percentiles {
					gauges[i+1] = Measurement{
						Name:   fmt.Sprintf("%s.%.2f", measurement[Name], p),
						Value:  s.Percentile(p),
						Period: measurement[Period],
					}
				}
				snapshot.Gauges = append(snapshot.Gauges, gauges...)
			}
		case metrics.Meter:
			measurement[Name] = name
			measurement[Value] = float64(m.Count())
			snapshot.Counters = append(snapshot.Counters, measurement)
			for val, _ := range self.RateAttributes.Meter {
				snapshot.Gauges = append(snapshot.Gauges, addRateAttrs(val, m, name, self))
			}
		case metrics.Timer:
			measurement[Name] = name
			measurement[Value] = float64(m.Count())
			snapshot.Counters = append(snapshot.Counters, measurement)
			if m.Count() > 0 {
				libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
				gauges[0] = Measurement{
					Name:       libratoName,
					Count:      uint64(m.Count()),
					Sum:        m.Mean() * float64(m.Count()),
					Max:        float64(m.Max()),
					Min:        float64(m.Min()),
					SumSquares: sumSquaresTimer(m),
					Period:     int64(self.Interval.Seconds()),
					Attributes: self.TimerAttributes,
				}
				for i, p := range self.Percentiles {
					gauges[i+1] = Measurement{
						Name:       fmt.Sprintf("%s.timer.%2.0f", name, p*100),
						Value:      m.Percentile(p),
						Period:     int64(self.Interval.Seconds()),
						Attributes: self.TimerAttributes,
					}
				}
				snapshot.Gauges = append(snapshot.Gauges, gauges...)
				for val, _ := range self.RateAttributes.Timer {
					snapshot.Gauges = append(snapshot.Gauges, addRateAttrs(val, m, name, self))
				}
			}
		}
	})
	return
}

func fillInDefaultRateAttrs(r *EnableRateSet) *EnableRateSet {
	enableAll := func() map[RateValue]bool {
		return map[RateValue]bool{
			Rate1:  true,
			Rate5:  true,
			Rate15: true,
		}
	}

	if r == nil {
		r = &EnableRateSet{
			Timer: enableAll(),
			Meter: enableAll(),
		}
	} else if r.Meter == nil {
		r.Meter = enableAll()
	} else if r.Timer == nil {
		r.Timer = enableAll()
	}

	return r
}

func addRateAttrs(val RateValue, mType interface{}, name string, self *Reporter) Measurement {

	measurement := func(m interface{}, r RateValue, name string, suffix string) Measurement {

		return Measurement{
			Name: fmt.Sprintf("%s.%s", name, suffix),
			//If m - metrics.Timer and r is Rate1 then invoke metrics.Timer.Rate1()
			Value:  reflect.ValueOf(m).MethodByName(string(r)).Call([]reflect.Value{})[0].Float(),
			Period: int64(self.Interval.Seconds()),
			Attributes: map[string]interface{}{
				DisplayUnitsLong:  Operations,
				DisplayUnitsShort: OperationsShort,
				DisplayMin:        "0",
			},
		}
	}

	switch val {
	case Rate1:
		return measurement(mType, Rate1, name, "rate.1min")
	case Rate5:
		return measurement(mType, Rate5, name, "rate.5min")
	case Rate15:
		return measurement(mType, Rate15, name, "rate.15min")
	}

	return nil
}
<|endoftext|>


<commit_before>package limiter

// -----------------------------------------------------------------
// Store
// -----------------------------------------------------------------

// Store is the common interface for limiter stores.
type Store interface {
	Get(key string, rate Rate) (Context, error)
}

// -----------------------------------------------------------------
// Context
// -----------------------------------------------------------------

// Context is the limit context.
type Context struct {
	Limit     int64
	Remaining int64
	Reset     int64
	Reached   bool
}

// -----------------------------------------------------------------
// Limiter
// -----------------------------------------------------------------

// Limiter is the limiter instance.
type Limiter struct {
	Store Store
	Rate  Rate
}

// NewLimiter returns an instance of ratelimit.
func NewLimiter(store Store, rate Rate) *Limiter {
	return &Limiter{
		Store: store,
		Rate:  rate,
	}
}

// Get returns the limit for the identifier.
func (l *Limiter) Get(key string) (Context, error) {
	return l.Store.Get(key, l.Rate)
}
<commit_msg>Remove store interface from limiter.go.<commit_after>package limiter

// -----------------------------------------------------------------
// Context
// -----------------------------------------------------------------

// Context is the limit context.
type Context struct {
	Limit     int64
	Remaining int64
	Reset     int64
	Reached   bool
}

// -----------------------------------------------------------------
// Limiter
// -----------------------------------------------------------------

// Limiter is the limiter instance.
type Limiter struct {
	Store Store
	Rate  Rate
}

// NewLimiter returns an instance of ratelimit.
func NewLimiter(store Store, rate Rate) *Limiter {
	return &Limiter{
		Store: store,
		Rate:  rate,
	}
}

// Get returns the limit for the identifier.
func (l *Limiter) Get(key string) (Context, error) {
	return l.Store.Get(key, l.Rate)
}
<|endoftext|>


<commit_before>package lazycache

import (
	"fmt"
	"github.com/amarburg/go-lazyfs"
	"os"
	"path"
)

//====

type LocalFS struct {
	Path string
}

func OpenLocalFS(path string) (*LocalFS, error) {
	fs := &LocalFS{Path: path} //Uri: uri}
	return fs, nil
}

func (fs *LocalFS) PathType(path string) int {

	fmt.Println("Finding pathType of ", path)

	// Pure heuristics right now
	if trailingSlash.MatchString(path) {
		return Directory
	}

	return File
}

func (fs *LocalFS) OriginalPath(p string) string {
	return path.Join(fs.Path, p)
}

func (fs *LocalFS) LazyFile(p string) (lazyfs.FileSource, error) {
	return lazyfs.OpenLocalFileSource(fs.Path, p)
}

func (fs *LocalFS) ReadDir(p string) (*DirListing, error) {

	listing := &DirListing{Path: p,
		Files:       make([]string, 0),
		Directories: make([]string, 0),
	}

	fullPath := path.Join(fs.Path, p)

	fmt.Printf("Querying directory: %s\n", fullPath)

	dir, err := os.Open(fullPath)
	if err != nil {
		return listing, err
	}

	files, err := dir.Readdir(0)

	if err != nil {
		return listing, err
	}

	for _, f := range files {
		if f.IsDir() {
			listing.Directories = append(listing.Directories, f.Name())
		} else if f.Mode()&os.ModeType == 0 {
			// os.ModeType includes all of the "special types" e.g. pipes, directories, etc.
			listing.Files = append(listing.Files, f.Name())
		}
	}

	return listing, err
}
<commit_msg>Allow Lazycache to follow symlinks.<commit_after>package lazycache

import (
	"fmt"
	"github.com/amarburg/go-lazyfs"
	"os"
	"path"
)

//====

type LocalFS struct {
	Path string
}

func OpenLocalFS(path string) (*LocalFS, error) {
	fs := &LocalFS{Path: path} //Uri: uri}
	return fs, nil
}

func (fs *LocalFS) PathType(path string) int {

	fmt.Println("Finding pathType of ", path)

	// Pure heuristics right now
	if trailingSlash.MatchString(path) {
		return Directory
	}

	return File
}

func (fs *LocalFS) OriginalPath(p string) string {
	return path.Join(fs.Path, p)
}

func (fs *LocalFS) LazyFile(p string) (lazyfs.FileSource, error) {
	return lazyfs.OpenLocalFileSource(fs.Path, p)
}

func (fs *LocalFS) ReadDir(p string) (*DirListing, error) {

	listing := &DirListing{Path: p,
		Files:       make([]string, 0),
		Directories: make([]string, 0),
	}

	fullPath := path.Join(fs.Path, p)

	fmt.Printf("Querying directory: %s\n", fullPath)

	dir, err := os.Open(fullPath)
	if err != nil {
		return listing, err
	}

	files, err := dir.Readdir(0)

	if err != nil {
		return listing, err
	}

	for _, f := range files {
		if f.IsDir() {
			listing.Directories = append(listing.Directories, f.Name())
		} else if f.Mode()&(os.ModeDir | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice) == 0 {
			// os.ModeType includes all of the "special types" e.g. pipes, directories, etc., but we allow symlinks...
			listing.Files = append(listing.Files, f.Name())
		}
	}

	return listing, err
}
<|endoftext|>


<commit_before>package tradingdays

import (
	"fmt"
	"testing"
	"time"

	"github.com/toomore/gogrs/utils"
)

func ExampleIsOpen() {
	fmt.Println(IsOpen(2015, 4, 17))
	fmt.Println(IsOpen(2015, 5, 1))
	// output:
	// true
	// false
}

func TestFindRecentlyOpened(t *testing.T) {
	result := FindRecentlyOpened(time.Now())
	if time.Now().UTC().Sub(result).Hours() > 24*7 {
		t.Error("Should not more than 7 days")
	}

	var date = time.Date(2015, 5, 11, 8, 30, 0, 0, utils.TaipeiTimeZone)
	result2 := FindRecentlyOpened(date)
	if result2.Unix() != time.Date(2015, 5, 8, 0, 0, 0, 0, time.UTC).Unix() {
		t.Error("Should be at 2015/5/8")
	}
}

func TestIsOpen(t *testing.T) {
	DownloadCSV(true)
	if IsOpen(2015, 4, 17) != true {
		t.Error("Should be `true`")
	}
	if IsOpen(2015, 4, 18) != false {
		t.Error("Should be `false`")
	}
	if IsOpen(2015, 4, 20) != true {
		t.Error("Should be `true`")
	}
	if IsOpen(2015, 5, 1) != false {
		t.Error("Should be `false`")
	}
}

func TestTimePerid(t *testing.T) {
	var tp1 = NewTimePeriod(time.Date(2015, 5, 8, 0, 0, 0, 0, utils.TaipeiTimeZone))
	var tp2 = NewTimePeriod(time.Date(2015, 5, 8, 10, 0, 0, 0, utils.TaipeiTimeZone))
	var tp3 = NewTimePeriod(time.Date(2015, 5, 8, 14, 0, 0, 0, utils.TaipeiTimeZone))
	var tp4 = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))

	if tp1.AtBefore() != true {
		t.Error("Should be `true`")
	}

	if tp1.AtOpen() != false {
		t.Error("Should be `false`")
	}

	if tp1.AtAfterOpen() != false {
		t.Error("Should be `false`")
	}

	if tp1.AtClose() != false {
		t.Error("Should be `false`")
	}

	if tp2.AtOpen() != true {
		t.Error("Should be `true`")
	}

	if tp2.AtBefore() != false {
		t.Error("Should be `false`")
	}

	if tp3.AtAfterOpen() != true {
		t.Error("Should be `true`")
	}

	if tp4.AtClose() != true {
		t.Error("Should be `true`")
	}
}

func BenchmarkTimePeriod(b *testing.B) {
	var tp = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))
	for i := 0; i < b.N; i++ {
		tp.AtBefore()
		tp.AtOpen()
		tp.AtAfterOpen()
		tp.AtClose()
	}
}

func ExampleNewTimePeriod() {
	var tp = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))
	fmt.Println(tp.AtBefore(), tp.AtOpen(), tp.AtAfterOpen(), tp.AtClose())
	// output:
	// false false false true
}

func BenchmarkIsOpen(b *testing.B) {
	for i := 0; i < b.N; i++ {
		IsOpen(2015, 4, 19)
	}
}

func BenchmarkDownloadCSV(b *testing.B) {
	for i := 0; i < b.N; i++ {
		DownloadCSV(true)
	}
}

func BenchmarkFindRecentlyOpened(b *testing.B) {
	var now = time.Now()
	for i := 0; i < b.N; i++ {
		FindRecentlyOpened(now)
	}
}

func init() {
	DownloadCSV(true)
}
<commit_msg>Add more testing.<commit_after>package tradingdays

import (
	"fmt"
	"testing"
	"time"

	"github.com/toomore/gogrs/utils"
)

func ExampleIsOpen() {
	fmt.Println(IsOpen(2015, 4, 17))
	fmt.Println(IsOpen(2015, 5, 1))
	// output:
	// true
	// false
}

func TestFindRecentlyOpened(t *testing.T) {
	result := FindRecentlyOpened(time.Now())
	if time.Now().UTC().Sub(result).Hours() > 24*7 {
		t.Error("Should not more than 7 days")
	}

	var date = time.Date(2015, 5, 11, 8, 30, 0, 0, utils.TaipeiTimeZone)
	result2 := FindRecentlyOpened(date)
	if result2.Unix() != time.Date(2015, 5, 8, 0, 0, 0, 0, time.UTC).Unix() {
		t.Error("Should be at 2015/5/8")
	}

	date = time.Date(2015, 5, 10, 8, 30, 0, 0, utils.TaipeiTimeZone)
	result2 = FindRecentlyOpened(date)
	if result2.Unix() != time.Date(2015, 5, 8, 0, 0, 0, 0, time.UTC).Unix() {
		t.Error("Should be at 2015/5/8")
	}
}

func TestIsOpen(t *testing.T) {
	DownloadCSV(true)
	if IsOpen(2015, 4, 17) != true {
		t.Error("Should be `true`")
	}
	if IsOpen(2015, 4, 18) != false {
		t.Error("Should be `false`")
	}
	if IsOpen(2015, 4, 20) != true {
		t.Error("Should be `true`")
	}
	if IsOpen(2015, 5, 1) != false {
		t.Error("Should be `false`")
	}
}

func TestTimePerid(t *testing.T) {
	var tp1 = NewTimePeriod(time.Date(2015, 5, 8, 0, 0, 0, 0, utils.TaipeiTimeZone))
	var tp2 = NewTimePeriod(time.Date(2015, 5, 8, 10, 0, 0, 0, utils.TaipeiTimeZone))
	var tp3 = NewTimePeriod(time.Date(2015, 5, 8, 14, 0, 0, 0, utils.TaipeiTimeZone))
	var tp4 = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))

	if tp1.AtBefore() != true {
		t.Error("Should be `true`")
	}

	if tp1.AtOpen() != false {
		t.Error("Should be `false`")
	}

	if tp1.AtAfterOpen() != false {
		t.Error("Should be `false`")
	}

	if tp1.AtClose() != false {
		t.Error("Should be `false`")
	}

	if tp2.AtOpen() != true {
		t.Error("Should be `true`")
	}

	if tp2.AtBefore() != false {
		t.Error("Should be `false`")
	}

	if tp3.AtAfterOpen() != true {
		t.Error("Should be `true`")
	}

	if tp4.AtClose() != true {
		t.Error("Should be `true`")
	}
}

func BenchmarkTimePeriod(b *testing.B) {
	var tp = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))
	for i := 0; i < b.N; i++ {
		tp.AtBefore()
		tp.AtOpen()
		tp.AtAfterOpen()
		tp.AtClose()
	}
}

func ExampleNewTimePeriod() {
	var tp = NewTimePeriod(time.Date(2015, 5, 8, 20, 0, 0, 0, utils.TaipeiTimeZone))
	fmt.Println(tp.AtBefore(), tp.AtOpen(), tp.AtAfterOpen(), tp.AtClose())
	// output:
	// false false false true
}

func BenchmarkIsOpen(b *testing.B) {
	for i := 0; i < b.N; i++ {
		IsOpen(2015, 4, 19)
	}
}

func BenchmarkDownloadCSV(b *testing.B) {
	for i := 0; i < b.N; i++ {
		DownloadCSV(true)
	}
}

func BenchmarkFindRecentlyOpened(b *testing.B) {
	var now = time.Now()
	for i := 0; i < b.N; i++ {
		FindRecentlyOpened(now)
	}
}

func init() {
	DownloadCSV(true)
}
<|endoftext|>


<commit_before>package horizon

import (
	"fmt"

	"github.com/jagregory/halgo"

	"github.com/stellar/go-horizon/db"
	"github.com/stellar/go-horizon/render"
	"github.com/stellar/go-horizon/render/sse"
)

// PaymentResource contains the payment specific details for a payment operation
type PaymentResource struct {
	OperationResource
	From   string `json:"from"`
	To     string `json:"to"`
	Amount string `json:"amount"`
}

// SseEvent converts this resource into a SSE compatible event.  Implements
// the sse.Eventable interface
func (r PaymentResource) SseEvent() sse.Event {
	return sse.Event{
		Data: r,
		ID:   r.PagingToken,
	}
}

// OperationResource is the display form of an operation.
type OperationResource struct {
	halgo.Links
	ID          int64  `json:"id"`
	PagingToken string `json:"paging_token"`
	Type        int32  `json:"type"`
	TypeString  string `json:"type_s"`
}

// SseEvent converts this resource into a SSE compatible event.  Implements
// the sse.Eventable interface
func (r OperationResource) SseEvent() sse.Event {
	return sse.Event{
		Data: r,
		ID:   r.PagingToken,
	}
}

func operationRecordToResource(record db.Record) (result render.Resource, err error) {

	op := record.(db.OperationRecord)
	self := fmt.Sprintf("/operations/%d", op.Id)
	po := "{?cursor}{?limit}{?order}"

	common := OperationResource{
		Links: halgo.Links{}.
			Self(self).
			Link("transactions", "/transactions/%d", op.TransactionId).
			Link("effects", "%s/effects/%s", self, po).
			Link("precedes", "/operations?cursor=%s&order=asc", op.PagingToken()).
			Link("succeeds", "/operations?cursor=%s&order=desc", op.PagingToken()),
		ID:          op.Id,
		PagingToken: op.PagingToken(),
		Type:        op.Type,
		TypeString:  "TODO",
	}

	// TODO: use the constant from go-stellar-base, when it exists
	if op.Type == 1 {
		result = PaymentResource{
			OperationResource: common,
			From:              op.Details.Map["from"].String,
			To:                op.Details.Map["to"].String,
			Amount:            op.Details.Map["amount"].String,
		}
	} else {
		result = common
	}

	return
}
<commit_msg>Make operation resource properly include details<commit_after>package horizon

import (
	"errors"
	"fmt"

	"github.com/jagregory/halgo"

	"github.com/stellar/go-horizon/db"
	"github.com/stellar/go-horizon/render"
	"github.com/stellar/go-horizon/render/sse"
	"github.com/stellar/go-stellar-base/xdr"
)

var operationResourceTypeNames = map[xdr.OperationType]string{
	xdr.OperationTypeCreateAccount:      "create_account",
	xdr.OperationTypePayment:            "payment",
	xdr.OperationTypePathPayment:        "path_payment",
	xdr.OperationTypeManageOffer:        "manage_offer",
	xdr.OperationTypeCreatePassiveOffer: "create_passive_offer",
	xdr.OperationTypeSetOption:          "set_options",
	xdr.OperationTypeChangeTrust:        "change_trust",
	xdr.OperationTypeAllowTrust:         "allow_trust",
	xdr.OperationTypeAccountMerge:       "account_merge",
	xdr.OperationTypeInflation:          "inflation",
}

type OperationResource map[string]interface{}

// SseEvent converts this resource into a SSE compatible event.  Implements
// the sse.Eventable interface
func (r OperationResource) SseEvent() sse.Event {

	ids, ok := r["paging_token"]

	if !ok {
		return sse.Event{Error: errors.New("paging_token not found in operation resource")}
	}

	return sse.Event{
		Data: r,
		ID:   ids.(string),
	}
}

func operationRecordToResource(record db.Record) (render.Resource, error) {
	op := record.(db.OperationRecord)
	result, err := op.Details()

	if err != nil {
		return nil, err
	}

	self := fmt.Sprintf("/operations/%d", op.Id)
	po := "{?cursor}{?limit}{?order}"

	result["_links"] = halgo.Links{}.
		Self(self).
		Link("transactions", "/transactions/%d", op.TransactionId).
		Link("effects", "%s/effects/%s", self, po).
		Link("precedes", "/operations?cursor=%s&order=asc", op.PagingToken()).
		Link("succeeds", "/operations?cursor=%s&order=desc", op.PagingToken()).
		Items
	result["id"] = op.Id
	result["paging_token"] = op.PagingToken()
	result["type"] = op.Type

	ts, ok := operationResourceTypeNames[op.Type]

	if ok {
		result["type_s"] = ts
	} else {
		result["type_s"] = "unknown"
	}

	return result, nil
}
<|endoftext|>


<commit_before>package filteranime

import (
	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
)

// LowResolutionAnimeImages filters anime with low resolution images.
func LowResolutionAnimeImages(ctx *aero.Context) string {
	return filterAnimeImages(ctx, "Anime with low resolution images", arn.AnimeImageLargeWidth, arn.AnimeImageLargeHeight)
}

// UltraLowResolutionAnimeImages filters anime with ultra low resolution images.
func UltraLowResolutionAnimeImages(ctx *aero.Context) string {
	return filterAnimeImages(ctx, "Anime with ultra low resolution images", arn.AnimeImageLargeWidth/2, arn.AnimeImageLargeHeight/2)
}

func filterAnimeImages(ctx *aero.Context, title string, minExpectedWidth int, minExpectedHeight int) string {
	return editorList(
		ctx,
		title,
		func(anime *arn.Anime) bool {
			return anime.Image.Width < minExpectedWidth || anime.Image.Height < minExpectedHeight
		},
		googleImageSearch,
	)
}

func googleImageSearch(anime *arn.Anime) string {
	return "https://www.google.com/search?q=" + anime.Title.Canonical + " anime cover" + "&tbm=isch&tbs=imgo:1,isz:lt,islt:qsvga"
}

// // LowResolutionAnimeImages ...
// func LowResolutionAnimeImages(ctx *aero.Context) string {
// 	basePath := path.Join(arn.Root, "images/anime/original/")
// 	files, err := ioutil.ReadDir(basePath)

// 	if err != nil {
// 		return ctx.Error(http.StatusInternalServerError, "Error reading anime images directory", err)
// 	}

// 	lowResAnime := []*arn.Anime{}

// 	for _, file := range files {
// 		if file.IsDir() || strings.HasPrefix(file.Name(), ".") {
// 			continue
// 		}

// 		fullPath := path.Join(basePath, file.Name())
// 		width, height, _ := getImageDimensions(fullPath)

// 		if width < arn.AnimeImageLargeWidth*2 || height < arn.AnimeImageLargeHeight*2 {
// 			animeID := file.Name()
// 			animeID = strings.TrimSuffix(animeID, filepath.Ext(animeID))

// 			anime, err := arn.GetAnime(animeID)

// 			if err == nil {
// 				lowResAnime = append(lowResAnime, anime)
// 			}
// 		}
// 	}

// 	// Sort
// 	arn.SortAnimeByQuality(lowResAnime)

// 	// Limit
// 	count := len(lowResAnime)

// 	if count > maxImageEntries {
// 		lowResAnime = lowResAnime[:maxImageEntries]
// 	}

// 	return ctx.HTML(components.AnimeEditorListFull(
// 		"Anime with low resolution images",
// 		lowResAnime,
// 		count,
// 		"/editor/anime/missing/hiresimage",
// 		func(anime *arn.Anime) string {
// 			return "https://www.google.com/search?q=" + anime.Title.Canonical + "&tbm=isch"
// 		},
// 	))
// }

// // getImageDimensions retrieves the dimensions for the given file path.
// func getImageDimensions(imagePath string) (int, int, error) {
// 	file, err := os.Open(imagePath)
// 	defer file.Close()

// 	if err != nil {
// 		return 0, 0, err
// 	}

// 	image, _, err := image.DecodeConfig(file)

// 	if err != nil {
// 		return 0, 0, err
// 	}

// 	return image.Width, image.Height, nil
// }
<commit_msg>Cleanup<commit_after>package filteranime

import (
	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
)

// LowResolutionAnimeImages filters anime with low resolution images.
func LowResolutionAnimeImages(ctx *aero.Context) string {
	return filterAnimeImages(ctx, "Anime with low resolution images", arn.AnimeImageLargeWidth, arn.AnimeImageLargeHeight)
}

// UltraLowResolutionAnimeImages filters anime with ultra low resolution images.
func UltraLowResolutionAnimeImages(ctx *aero.Context) string {
	return filterAnimeImages(ctx, "Anime with ultra low resolution images", arn.AnimeImageLargeWidth/2, arn.AnimeImageLargeHeight/2)
}

func filterAnimeImages(ctx *aero.Context, title string, minExpectedWidth int, minExpectedHeight int) string {
	return editorList(
		ctx,
		title,
		func(anime *arn.Anime) bool {
			return anime.Image.Width < minExpectedWidth || anime.Image.Height < minExpectedHeight
		},
		googleImageSearch,
	)
}

func googleImageSearch(anime *arn.Anime) string {
	return "https://www.google.com/search?q=" + anime.Title.Canonical + " anime cover" + "&tbm=isch&tbs=imgo:1,isz:lt,islt:qsvga"
}
<|endoftext|>