<commit_before>// Copyright 2011-2014 Dmitry Chestnykh. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package captcha

import (
	"bytes"
	"image"
	"image/color"
	"image/png"
	"io"
	"math"
)

const (
	// Standard width and height of a captcha image.
	StdWidth  = 240
	StdHeight = 80
	// Maximum absolute skew factor of a single digit.
	maxSkew = 0.7
	// Number of background circles.
	circleCount = 20
	distortCircleCount = 10
)

type Image struct {
	*image.RGBA
	numWidth  int
	numHeight int
	dotSize   int
	rng       siprng
}

// NewImage returns a new captcha image of the given width and height with the
// given digits, where each digit must be in range 0-9.
func NewImage(id string, digits []byte, width, height int) *Image {
	m := new(Image)

	// Initialize PRNG.
	m.rng.Seed(deriveSeed(imageSeedPurpose, id, digits))

	prim := color.RGBA{
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		0xFF,
	}

	m.RGBA = image.NewRGBA(image.Rect(0, 0, width, height))
	m.calculateSizes(width, height, len(digits))
	// Randomly position captcha inside the image.
	maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
	maxy := height - m.numHeight - m.dotSize*2
	var border int
	if width > height {
		border = height / 10
	} else {
		border = width / 10
	}
	x := m.rng.Int(border, maxx-border)
	y := m.rng.Int(border, maxy-border)
	// Draw digits.
	for _, n := range digits {
		m.drawDigit(getChar(n), x, y, prim)
		x += m.numWidth + m.dotSize
	}
	// Draw strike-through line.
	m.strikeThrough(prim)

	m.fillWithDistortCircles(distortCircleCount, width/4)
	// Apply wave distortion.
	m.distort(m.rng.Float(5, 10), m.rng.Float(100, 200))
	// Fill image with random circles.
	m.fillWithCircles(circleCount, m.dotSize)
	return m
}

/*
func (m *Image) getRandomPalette() color.Palette {
	p := make([]color.Color, circleCount+1)
	// Transparent color.
	p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
	// Primary color.
	prim := color.RGBA{
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		0xFF,
	}
	p[1] = prim
	// Circle colors.
	for i := 2; i <= circleCount; i++ {
		p[i] = m.randomBrightness(prim, 255)
	}
	return p
}*/

// encodedPNG encodes an image to PNG and returns
// the result as a byte slice.
func (m *Image) encodedPNG() []byte {
	var buf bytes.Buffer
	if err := png.Encode(&buf, m); err != nil {
		panic(err.Error())
	}
	return buf.Bytes()
}

// WriteTo writes captcha image in PNG format into the given writer.
func (m *Image) WriteTo(w io.Writer) (int64, error) {
	n, err := w.Write(m.encodedPNG())
	return int64(n), err
}

func (m *Image) calculateSizes(width, height, ncount int) {
	// Goal: fit all digits inside the image.
	var border int
	if width > height {
		border = height / 8
	} else {
		border = width / 8
	}
	// Convert everything to floats for calculations.
	w := float64(width - border*2)
	h := float64(height - border*2)
	// fw takes into account 1-dot spacing between digits.
	fw := float64(fontWidth + 1)
	fh := float64(fontHeight)
	nc := float64(ncount)
	// Calculate the width of a single digit taking into account only the
	// width of the image.
	nw := w / nc
	// Calculate the height of a digit from this width.
	nh := nw * fh / fw
	// Digit too high?
	if nh > h {
		// Fit digits based on height.
		nh = h
		nw = fw / fh * nh
	}
	// Calculate dot size.
	m.dotSize = int((nh / fh))
	if m.dotSize < 1 {
		m.dotSize = 1
	}
	// Save everything, making the actual width smaller by 1 dot to account
	// for spacing between digits.
	m.numWidth = int(nw) - m.dotSize
	m.numHeight = int(nh)
}

func (m *Image) drawHorizLine(fromX, toX, y int, color color.Color) {
	for x := fromX; x <= toX; x++ {
		m.Set(x, y, color)
	}
}

func (m *Image) drawCircle(x, y, radius int, color color.Color) {
	f := 1 - radius
	dfx := 1
	dfy := -2 * radius
	xo := 0
	yo := radius

	m.Set(x, y+radius, color)
	m.Set(x, y-radius, color)
	m.drawHorizLine(x-radius, x+radius, y, color)

	for xo < yo {
		if f >= 0 {
			yo--
			dfy += 2
			f += dfy
		}
		xo++
		dfx += 2
		f += dfx
		m.drawHorizLine(x-xo, x+xo, y+yo, color)
		m.drawHorizLine(x-xo, x+xo, y-yo, color)
		m.drawHorizLine(x-yo, x+yo, y+xo, color)
		m.drawHorizLine(x-yo, x+yo, y-xo, color)
	}
}

func (m *Image) colorDistortCircle(xc, yc, r int) {
	d := 2*r
	r2 := r*r

	dg := int(m.rng.Intn(240)) - 120
	if dg < 0 {
		dg -= 20
	} else {
		dg += 20
	}

	dr := int(m.rng.Intn(240)) - 120
	if dr < 0 {
		dr -= 20
	} else {
		dr += 20
	}

	db := int(m.rng.Intn(240)) - 120
	if db < 0 {
		db -= 20
	} else {
		db += 20
	}

	for y := 0; y <= d; y++ {
		for x := 0; x <= d; x++ {
			x2 := (x-r)*(x-r)
			y2 := (y-r)*(y-r)

			if x2+y2 <= r2 {
				xp := xc - r + x
				yp := yc - r + y
				r,g,b,a := m.At(xp, yp).RGBA()
				if a != 0x00 { //background
					m.Set(xp, yp, color.RGBA{
						uint8(int(r)+dr),
						uint8(int(g)+dg),
						uint8(int(b)+db),
						0xFF,
					})
				}
			}
		}
	}
}

func (m *Image) fillWithCircles(n, maxradius int) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	for i := 0; i < n; i++ {
		color := color.RGBA{
			uint8(m.rng.Intn(129)),
			uint8(m.rng.Intn(129)),
			uint8(m.rng.Intn(129)),
			0xFF,
		}
		r := m.rng.Int(1, maxradius)
		m.drawCircle(m.rng.Int(r, maxx-r), m.rng.Int(r, maxy-r), r, color)
	}
}

func (m *Image) fillWithDistortCircles(n, maxradius int) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	for i := 0; i < n; i++ {
		r := m.rng.Int(maxradius/10, maxradius-1)
		m.colorDistortCircle(m.rng.Int(-r, maxx), m.rng.Int(-r, maxy), r)
	}
}

func (m *Image) strikeThrough(color color.Color) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	y := m.rng.Int(maxy/3, maxy-maxy/3)
	amplitude := m.rng.Float(5, 20)
	period := m.rng.Float(80, 180)
	dx := 2.0 * math.Pi / period
	for x := 0; x < maxx; x++ {
		xo := amplitude * math.Cos(float64(y)*dx)
		yo := amplitude * math.Sin(float64(x)*dx)
		for yn := 0; yn < m.dotSize; yn++ {
			r := m.rng.Int(0, m.dotSize)
			m.drawCircle(x+int(xo), y+int(yo)+(yn*m.dotSize), r/2, color)
		}
	}
}

func (m *Image) drawDigit(digit []byte, x, y int, color color.Color) {
	skf := m.rng.Float(-maxSkew, maxSkew)
	xs := float64(x)
	r := m.dotSize / 2
	y += m.rng.Int(-r, r)
	for yo := 0; yo < fontHeight; yo++ {
		for xo := 0; xo < fontWidth; xo++ {
			if digit[yo*fontWidth+xo] != blackChar {
				continue
			}
			m.drawCircle(x+xo*m.dotSize, y+yo*m.dotSize, r, color)
		}
		xs += skf
		x = int(xs)
	}
}

func (m *Image) distort(amplude float64, period float64) {
	w := m.Bounds().Max.X
	h := m.Bounds().Max.Y

	oldm := m
	newm := image.NewRGBA(image.Rect(0, 0, w, h))

	dx := 2.0 * math.Pi / period
	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			xo := amplude * math.Sin(float64(y)*dx)
			yo := amplude * math.Cos(float64(x)*dx)
			newm.Set(x, y, oldm.At(x+int(xo), y+int(yo)))
		}
	}
	m.RGBA = newm
}

func (m *Image) randomBrightness(c color.RGBA, max uint8) color.RGBA {
	minc := min3(c.R, c.G, c.B)
	maxc := max3(c.R, c.G, c.B)
	if maxc > max {
		return c
	}
	n := m.rng.Intn(int(max-maxc)) - int(minc)
	return color.RGBA{
		uint8(int(c.R) + n),
		uint8(int(c.G) + n),
		uint8(int(c.B) + n),
		uint8(c.A),
	}
}

func min3(x, y, z uint8) (m uint8) {
	m = x
	if y < m {
		m = y
	}
	if z < m {
		m = z
	}
	return
}

func max3(x, y, z uint8) (m uint8) {
	m = x
	if y > m {
		m = y
	}
	if z > m {
		m = z
	}
	return
}
<commit_msg>all circles should be at least a quarter visible<commit_after>// Copyright 2011-2014 Dmitry Chestnykh. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package captcha

import (
	"bytes"
	"image"
	"image/color"
	"image/png"
	"io"
	"math"
)

const (
	// Standard width and height of a captcha image.
	StdWidth  = 240
	StdHeight = 80
	// Maximum absolute skew factor of a single digit.
	maxSkew = 0.7
	// Number of background circles.
	circleCount = 20
	distortCircleCount = 10
)

type Image struct {
	*image.RGBA
	numWidth  int
	numHeight int
	dotSize   int
	rng       siprng
}

// NewImage returns a new captcha image of the given width and height with the
// given digits, where each digit must be in range 0-9.
func NewImage(id string, digits []byte, width, height int) *Image {
	m := new(Image)

	// Initialize PRNG.
	m.rng.Seed(deriveSeed(imageSeedPurpose, id, digits))

	prim := color.RGBA{
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		0xFF,
	}

	m.RGBA = image.NewRGBA(image.Rect(0, 0, width, height))
	m.calculateSizes(width, height, len(digits))
	// Randomly position captcha inside the image.
	maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
	maxy := height - m.numHeight - m.dotSize*2
	var border int
	if width > height {
		border = height / 10
	} else {
		border = width / 10
	}
	x := m.rng.Int(border, maxx-border)
	y := m.rng.Int(border, maxy-border)
	// Draw digits.
	for _, n := range digits {
		m.drawDigit(getChar(n), x, y, prim)
		x += m.numWidth + m.dotSize
	}
	// Draw strike-through line.
	m.strikeThrough(prim)

	m.fillWithDistortCircles(distortCircleCount, width/4)
	// Apply wave distortion.
	m.distort(m.rng.Float(5, 10), m.rng.Float(100, 200))
	// Fill image with random circles.
	m.fillWithCircles(circleCount, m.dotSize)
	return m
}

/*
func (m *Image) getRandomPalette() color.Palette {
	p := make([]color.Color, circleCount+1)
	// Transparent color.
	p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
	// Primary color.
	prim := color.RGBA{
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		uint8(m.rng.Intn(129)),
		0xFF,
	}
	p[1] = prim
	// Circle colors.
	for i := 2; i <= circleCount; i++ {
		p[i] = m.randomBrightness(prim, 255)
	}
	return p
}*/

// encodedPNG encodes an image to PNG and returns
// the result as a byte slice.
func (m *Image) encodedPNG() []byte {
	var buf bytes.Buffer
	if err := png.Encode(&buf, m); err != nil {
		panic(err.Error())
	}
	return buf.Bytes()
}

// WriteTo writes captcha image in PNG format into the given writer.
func (m *Image) WriteTo(w io.Writer) (int64, error) {
	n, err := w.Write(m.encodedPNG())
	return int64(n), err
}

func (m *Image) calculateSizes(width, height, ncount int) {
	// Goal: fit all digits inside the image.
	var border int
	if width > height {
		border = height / 8
	} else {
		border = width / 8
	}
	// Convert everything to floats for calculations.
	w := float64(width - border*2)
	h := float64(height - border*2)
	// fw takes into account 1-dot spacing between digits.
	fw := float64(fontWidth + 1)
	fh := float64(fontHeight)
	nc := float64(ncount)
	// Calculate the width of a single digit taking into account only the
	// width of the image.
	nw := w / nc
	// Calculate the height of a digit from this width.
	nh := nw * fh / fw
	// Digit too high?
	if nh > h {
		// Fit digits based on height.
		nh = h
		nw = fw / fh * nh
	}
	// Calculate dot size.
	m.dotSize = int((nh / fh))
	if m.dotSize < 1 {
		m.dotSize = 1
	}
	// Save everything, making the actual width smaller by 1 dot to account
	// for spacing between digits.
	m.numWidth = int(nw) - m.dotSize
	m.numHeight = int(nh)
}

func (m *Image) drawHorizLine(fromX, toX, y int, color color.Color) {
	for x := fromX; x <= toX; x++ {
		m.Set(x, y, color)
	}
}

func (m *Image) drawCircle(x, y, radius int, color color.Color) {
	f := 1 - radius
	dfx := 1
	dfy := -2 * radius
	xo := 0
	yo := radius

	m.Set(x, y+radius, color)
	m.Set(x, y-radius, color)
	m.drawHorizLine(x-radius, x+radius, y, color)

	for xo < yo {
		if f >= 0 {
			yo--
			dfy += 2
			f += dfy
		}
		xo++
		dfx += 2
		f += dfx
		m.drawHorizLine(x-xo, x+xo, y+yo, color)
		m.drawHorizLine(x-xo, x+xo, y-yo, color)
		m.drawHorizLine(x-yo, x+yo, y+xo, color)
		m.drawHorizLine(x-yo, x+yo, y-xo, color)
	}
}

func (m *Image) colorDistortCircle(xc, yc, r int) {
	d := 2*r
	r2 := r*r

	dg := int(m.rng.Intn(240)) - 120
	if dg < 0 {
		dg -= 20
	} else {
		dg += 20
	}

	dr := int(m.rng.Intn(240)) - 120
	if dr < 0 {
		dr -= 20
	} else {
		dr += 20
	}

	db := int(m.rng.Intn(240)) - 120
	if db < 0 {
		db -= 20
	} else {
		db += 20
	}

	for y := 0; y <= d; y++ {
		for x := 0; x <= d; x++ {
			x2 := (x-r)*(x-r)
			y2 := (y-r)*(y-r)

			if x2+y2 <= r2 {
				xp := xc - r + x
				yp := yc - r + y
				r,g,b,a := m.At(xp, yp).RGBA()
				if a != 0x00 { //background
					m.Set(xp, yp, color.RGBA{
						uint8(int(r)+dr),
						uint8(int(g)+dg),
						uint8(int(b)+db),
						0xFF,
					})
				}
			}
		}
	}
}

func (m *Image) fillWithCircles(n, maxradius int) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	for i := 0; i < n; i++ {
		color := color.RGBA{
			uint8(m.rng.Intn(129)),
			uint8(m.rng.Intn(129)),
			uint8(m.rng.Intn(129)),
			0xFF,
		}
		r := m.rng.Int(1, maxradius)
		m.drawCircle(m.rng.Int(r, maxx-r), m.rng.Int(r, maxy-r), r, color)
	}
}

func (m *Image) fillWithDistortCircles(n, maxradius int) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	for i := 0; i < n; i++ {
		r := m.rng.Int(maxradius/10, maxradius-1)
		m.colorDistortCircle(m.rng.Int(0, maxx), m.rng.Int(0, maxy), r)
	}
}

func (m *Image) strikeThrough(color color.Color) {
	maxx := m.Bounds().Max.X
	maxy := m.Bounds().Max.Y
	y := m.rng.Int(maxy/3, maxy-maxy/3)
	amplitude := m.rng.Float(5, 20)
	period := m.rng.Float(80, 180)
	dx := 2.0 * math.Pi / period
	for x := 0; x < maxx; x++ {
		xo := amplitude * math.Cos(float64(y)*dx)
		yo := amplitude * math.Sin(float64(x)*dx)
		for yn := 0; yn < m.dotSize; yn++ {
			r := m.rng.Int(0, m.dotSize)
			m.drawCircle(x+int(xo), y+int(yo)+(yn*m.dotSize), r/2, color)
		}
	}
}

func (m *Image) drawDigit(digit []byte, x, y int, color color.Color) {
	skf := m.rng.Float(-maxSkew, maxSkew)
	xs := float64(x)
	r := m.dotSize / 2
	y += m.rng.Int(-r, r)
	for yo := 0; yo < fontHeight; yo++ {
		for xo := 0; xo < fontWidth; xo++ {
			if digit[yo*fontWidth+xo] != blackChar {
				continue
			}
			m.drawCircle(x+xo*m.dotSize, y+yo*m.dotSize, r, color)
		}
		xs += skf
		x = int(xs)
	}
}

func (m *Image) distort(amplude float64, period float64) {
	w := m.Bounds().Max.X
	h := m.Bounds().Max.Y

	oldm := m
	newm := image.NewRGBA(image.Rect(0, 0, w, h))

	dx := 2.0 * math.Pi / period
	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			xo := amplude * math.Sin(float64(y)*dx)
			yo := amplude * math.Cos(float64(x)*dx)
			newm.Set(x, y, oldm.At(x+int(xo), y+int(yo)))
		}
	}
	m.RGBA = newm
}

func (m *Image) randomBrightness(c color.RGBA, max uint8) color.RGBA {
	minc := min3(c.R, c.G, c.B)
	maxc := max3(c.R, c.G, c.B)
	if maxc > max {
		return c
	}
	n := m.rng.Intn(int(max-maxc)) - int(minc)
	return color.RGBA{
		uint8(int(c.R) + n),
		uint8(int(c.G) + n),
		uint8(int(c.B) + n),
		uint8(c.A),
	}
}

func min3(x, y, z uint8) (m uint8) {
	m = x
	if y < m {
		m = y
	}
	if z < m {
		m = z
	}
	return
}

func max3(x, y, z uint8) (m uint8) {
	m = x
	if y > m {
		m = y
	}
	if z > m {
		m = z
	}
	return
}
<|endoftext|>


<commit_before>package signals

import (
	"image"
	"image/color"
	"image/color/palette"
)

// Depiction of a Function, implements Depictor
type Depiction struct {
	Function
	size                     image.Rectangle
	pixelsPerUnitX           int
	belowColour, aboveColour color.Color
}

// makes a Depiction of a LimitedSignal, scaled to pxMaxx x pxMaxy pixels and sets its colours.
func NewDepiction(s LimitedFunction, pxMaxX, pxMaxY int, c1, c2 color.Color) Depiction {
	return Depiction{s, image.Rect(0, -pxMaxY/2, pxMaxX, pxMaxY/2), int(int64(pxMaxX) * int64(unitX) / int64(s.MaxX())), c1, c2}
}

func (i Depiction) Bounds() image.Rectangle {
	return i.size
}

func (i Depiction) At(xp, yp int) color.Color {
	if i.property(x(xp)*unitX/x(i.pixelsPerUnitX)-x(i.size.Min.X)) <= unitY/y(i.size.Max.Y)*y(yp)-y(i.size.Min.Y) {
		return i.aboveColour
	}
	return i.belowColour
}

// a Depictor is an image.Image without a colormodel, so is more general.
// embedded in one of the helper wrappers gets you an image.Image.
// (this and the wrappers might be moved, in a later versions, to their own package)
type Depictor interface {
	Bounds() image.Rectangle
	At(x, y int) color.Color
}

// RGBA depiction wrapper
type RGBAImage struct {
	Depictor
}

func (i RGBAImage) ColorModel() color.Model { return color.RGBAModel }

// gray depiction wrapper.
type GrayImage struct {
	Depictor
}

func (i GrayImage) ColorModel() color.Model { return color.GrayModel }

// plan9 paletted, depiction wrapper.
type Plan9PalettedImage struct {
	Depictor
}

func (i Plan9PalettedImage) ColorModel() color.Model { return color.Palette(palette.Plan9) }

// WebSafe paletted, depiction wrapper.
type WebSafePalettedImage struct {
	Depictor
}

func (i WebSafePalettedImage) ColorModel() color.Model { return color.Palette(palette.WebSafe) }
<commit_msg>comment<commit_after>package signals

import (
	"image"
	"image/color"
	"image/color/palette"
)

// Depiction of a Function, implements Depictor
type Depiction struct {
	Function
	size                     image.Rectangle
	pixelsPerUnitX           int
	belowColour, aboveColour color.Color
}

// makes a Depiction of a LimitedSignal, scaled to pxMaxx x pxMaxy pixels and sets its colours.
func NewDepiction(s LimitedFunction, pxMaxX, pxMaxY int, c1, c2 color.Color) Depiction {
	return Depiction{s, image.Rect(0, -pxMaxY/2, pxMaxX, pxMaxY/2), int(int64(pxMaxX) * int64(unitX) / int64(s.MaxX())), c1, c2}
}

func (i Depiction) Bounds() image.Rectangle {
	return i.size
}

func (i Depiction) At(xp, yp int) color.Color {
	if i.property(x(xp)*unitX/x(i.pixelsPerUnitX)-x(i.size.Min.X)) <= unitY/y(i.size.Max.Y)*y(yp)-y(i.size.Min.Y) {
		return i.aboveColour
	}
	return i.belowColour
}

// a Depictor is an image.Image without a colormodel, so is more general.
// embedded in one of the helper wrappers gets you an image.Image.
// (this and the wrappers might be moved, in a later version of theis package, to their own package.)
type Depictor interface {
	Bounds() image.Rectangle
	At(x, y int) color.Color
}

// RGBA depiction wrapper
type RGBAImage struct {
	Depictor
}

func (i RGBAImage) ColorModel() color.Model { return color.RGBAModel }

// gray depiction wrapper.
type GrayImage struct {
	Depictor
}

func (i GrayImage) ColorModel() color.Model { return color.GrayModel }

// plan9 paletted, depiction wrapper.
type Plan9PalettedImage struct {
	Depictor
}

func (i Plan9PalettedImage) ColorModel() color.Model { return color.Palette(palette.Plan9) }

// WebSafe paletted, depiction wrapper.
type WebSafePalettedImage struct {
	Depictor
}

func (i WebSafePalettedImage) ColorModel() color.Model { return color.Palette(palette.WebSafe) }
<|endoftext|>


<commit_before>// Copyright 2013 The Walk 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 main

import (
	"log"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

type MyMainWindow struct {
	*walk.MainWindow
}

func main() {
	mw := new(MyMainWindow)

	var openAction, showAboutBoxAction *walk.Action
	var recentMenu *walk.Menu

	if err := (MainWindow{
		AssignTo: &mw.MainWindow,
		Title:    "Walk Actions Example",
		MenuItems: []MenuItem{
			Menu{
				Text: "&File",
				Items: []MenuItem{
					Action{
						AssignTo:    &openAction,
						Text:        "&Open",
						Image:       "../img/open.png",
						Enabled:     Bind("openEnabledCB.Checked"),
						Visible:     Bind("openVisibleCB.Checked"),
						OnTriggered: func() { mw.openAction_Triggered() },
					},
					Menu{
						AssignTo: &recentMenu,
						Text:     "Recent",
					},
					Separator{},
					Action{
						Text:        "E&xit",
						OnTriggered: func() { walk.App().Exit(0) },
					},
				},
			},
			Menu{
				Text: "&Help",
				Items: []MenuItem{
					Action{
						AssignTo:    &showAboutBoxAction,
						Text:        "About",
						OnTriggered: func() { mw.showAboutBoxAction_Triggered() },
					},
				},
			},
		},
		ToolBarItems: []MenuItem{
			ActionRef{&openAction},
			Separator{},
			ActionRef{&showAboutBoxAction},
		},
		ContextMenuItems: []MenuItem{
			ActionRef{&showAboutBoxAction},
		},
		MinSize: Size{300, 200},
		Layout:  VBox{},
		Children: []Widget{
			CheckBox{
				Name:    "openEnabledCB",
				Text:    "Open Enabled",
				Checked: true,
			},
			CheckBox{
				Name:    "openVisibleCB",
				Text:    "Open Visible",
				Checked: true,
			},
		},
	}.Create()); err != nil {
		log.Fatal(err)
	}

	openRecent1Action := walk.NewAction()
	openRecent1Action.SetText("Blah")
	recentMenu.Actions().Add(openRecent1Action)

	openRecent2Action := walk.NewAction()
	openRecent2Action.SetText("Yadda")
	recentMenu.Actions().Add(openRecent2Action)

	openRecent3Action := walk.NewAction()
	openRecent3Action.SetText("Oink")
	recentMenu.Actions().Add(openRecent3Action)

	mw.Run()
}

func (mw *MyMainWindow) openAction_Triggered() {
	walk.MsgBox(mw, "Open", "Pretend to open a file...", walk.MsgBoxIconInformation)
}

func (mw *MyMainWindow) showAboutBoxAction_Triggered() {
	walk.MsgBox(mw, "About", "Walk Actions Example", walk.MsgBoxIconInformation)
}
<commit_msg>examples/actions: Use a custom condition in a composite condition binding<commit_after>// Copyright 2013 The Walk 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 main

import (
	"log"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

var isSpecialMode = walk.NewMutableCondition()

type MyMainWindow struct {
	*walk.MainWindow
}

func main() {
	MustRegisterCondition("isSpecialMode", isSpecialMode)

	mw := new(MyMainWindow)

	var openAction, showAboutBoxAction *walk.Action
	var recentMenu *walk.Menu
	var toggleSpecialModePB *walk.PushButton

	if err := (MainWindow{
		AssignTo: &mw.MainWindow,
		Title:    "Walk Actions Example",
		MenuItems: []MenuItem{
			Menu{
				Text: "&File",
				Items: []MenuItem{
					Action{
						AssignTo:    &openAction,
						Text:        "&Open",
						Image:       "../img/open.png",
						Enabled:     Bind("enabledCB.Checked"),
						Visible:     Bind("openVisibleCB.Checked"),
						OnTriggered: func() { mw.openAction_Triggered() },
					},
					Menu{
						AssignTo: &recentMenu,
						Text:     "Recent",
					},
					Separator{},
					Action{
						Text:        "E&xit",
						OnTriggered: func() { walk.App().Exit(0) },
					},
				},
			},
			Menu{
				Text: "&Help",
				Items: []MenuItem{
					Action{
						AssignTo:    &showAboutBoxAction,
						Text:        "About",
						OnTriggered: func() { mw.showAboutBoxAction_Triggered() },
					},
				},
			},
		},
		ToolBarItems: []MenuItem{
			ActionRef{&openAction},
			Separator{},
			ActionRef{&showAboutBoxAction},
			Action{
				Text:        "Special",
				Enabled:     Bind("isSpecialMode && enabledCB.Checked"),
				OnTriggered: func() { mw.specialAction_Triggered() },
			},
		},
		ContextMenuItems: []MenuItem{
			ActionRef{&showAboutBoxAction},
		},
		MinSize: Size{300, 200},
		Layout:  VBox{},
		Children: []Widget{
			CheckBox{
				Name:    "enabledCB",
				Text:    "Open / Special Enabled",
				Checked: true,
			},
			CheckBox{
				Name:    "openVisibleCB",
				Text:    "Open Visible",
				Checked: true,
			},
			PushButton{
				AssignTo: &toggleSpecialModePB,
				Text:     "Enable Special Mode",
				OnClicked: func() {
					isSpecialMode.SetSatisfied(!isSpecialMode.Satisfied())

					if isSpecialMode.Satisfied() {
						toggleSpecialModePB.SetText("Disable Special Mode")
					} else {
						toggleSpecialModePB.SetText("Enable Special Mode")
					}
				},
			},
		},
	}.Create()); err != nil {
		log.Fatal(err)
	}

	addRecentFileActions := func(texts ...string) {
		for _, text := range texts {
			a := walk.NewAction()
			a.SetText(text)
			a.Triggered().Attach(func() { mw.openAction_Triggered() })
			recentMenu.Actions().Add(a)
		}
	}

	addRecentFileActions("Foo", "Bar", "Baz")

	mw.Run()
}

func (mw *MyMainWindow) openAction_Triggered() {
	walk.MsgBox(mw, "Open", "Pretend to open a file...", walk.MsgBoxIconInformation)
}

func (mw *MyMainWindow) showAboutBoxAction_Triggered() {
	walk.MsgBox(mw, "About", "Walk Actions Example", walk.MsgBoxIconInformation)
}

func (mw *MyMainWindow) specialAction_Triggered() {
	walk.MsgBox(mw, "Special", "Nothing to see here.", walk.MsgBoxIconInformation)
}
<|endoftext|>


<commit_before>package mailman

import (
	"bytes"
	"fmt"
	"net/mail"
	"strconv"
	"strings"
	"time"

	"github.com/muesli/gomail"
	"github.com/mxk/go-imap/imap"

	"github.com/muesli/polly/api/db"
)

var (
	context *db.PollyContext
)

// SetupMailmanContext sets the context
func SetupMailmanContext(ctx *db.PollyContext) {
	context = ctx
}

func sendMail(tos []string, from, subject, body, mid, contenttype, contenttypetransfer string) {
	m := gomail.NewMessage()
	m.SetHeader("From", from)
	m.SetHeader("Subject", subject)
	m.SetHeader("Message-ID", mid)
	m.SetHeader("Errors-To", context.Config.Connections.Email.Mailman.BounceAddress)
	m.SetHeader("X-BeenThere", context.Config.Connections.Email.Mailman.Address)
	m.SetAddressHeader("To", context.Config.Connections.Email.Mailman.Address, context.Config.Connections.Email.Mailman.Name)
	m.SetAddressHeader("Envelope-Sender", context.Config.Connections.Email.Mailman.BounceAddress, context.Config.Connections.Email.Mailman.Name)
	m.SetAddressHeader("List-Id", context.Config.Connections.Email.Mailman.Address, context.Config.Connections.Email.Mailman.Name)

	if len(contenttype) > 0 {
		m.SetHeader("Content-Type", contenttype)
	}
	if len(contenttypetransfer) > 0 {
		m.SetHeader("Content-Transfer-Encoding", contenttypetransfer)
	}

	m.SetRawBody(body)

	d := gomail.NewDialer(context.Config.Connections.Email.SMTP.Server, context.Config.Connections.Email.SMTP.Port,
		context.Config.Connections.Email.SMTP.User, context.Config.Connections.Email.SMTP.Password)
	s, err := d.Dial()
	if err != nil {
		panic(err)
	}
	defer s.Close()

	err = s.Send(context.Config.Connections.Email.Mailman.Address, tos, m)
	if err != nil {
		panic(err)
	}
}

// RunLoop fetches mail and delivers them to recipients - forever
func RunLoop() {
	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
		err error
	)

	// Connect to the server
	c, err = imap.DialTLS(context.Config.Connections.Email.IMAP.Server+":"+strconv.FormatInt(int64(context.Config.Connections.Email.IMAP.Port), 10), nil)
	if err != nil || c == nil || c.Data == nil {
		panic(err)
	}

	// Print server greeting (first response in the unilateral server data queue)
	fmt.Println("IMAP Server says hello:", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login(context.Config.Connections.Email.IMAP.User, context.Config.Connections.Email.IMAP.Password)
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))
	if cmd == nil {
		return
	}

	// Print mailbox information
	fmt.Println("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		fmt.Println("|--", rsp.MailboxInfo().Name)
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		fmt.Println("Server data:", rsp)
	}
	c.Data = nil

	mm, _ := context.GetMailman(context.Config.Connections.Email.Mailman.Address)
	for {
		// Open a mailbox (synchronous command - no need for imap.Wait)
		c.Select("INBOX", true)
		fmt.Printf("Mailbox status: %s (msgs: %d, last-seen: %d)\n", c.Mailbox.Name, c.Mailbox.Messages, mm.LastSeen)

		if mm.LastSeen == 0 {
			mm.LastSeen = uint64(c.Mailbox.Messages)
		}

		// Fetch new mails
		set, _ := imap.NewSeqSet("")
		set.Add(strconv.FormatUint(mm.LastSeen+1, 10) + ":*")
		cmd, _ = c.UIDFetch(set, "RFC822.HEADER", "RFC822.TEXT")

		// Process responses while the command is running
		fmt.Println("\nChecking mailman INBOX")
		for cmd.InProgress() {
			// Wait for the next response (no timeout)
			c.Recv(-1)

			// Process command data
			for _, rsp = range cmd.Data {
				header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
				body := string(imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"]))
				if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
					from := msg.Header.Get("From")
					subj := msg.Header.Get("Subject")
					mid := msg.Header.Get("Message-ID")
					contenttype := msg.Header.Get("Content-Type")
					contenttypetrasnfer := msg.Header.Get("Content-Transfer-Encoding")

					fmt.Println("|-- From", from)
					fmt.Println("|-- Subject", subj)
					fmt.Println("|-- ID", mid)

					users, err := context.LoadAllUsers()
					if err != nil {
						panic(err)
					}
					tos := []string{}
					for _, user := range users {
						if !user.Activated {
							continue
						}
						tos = append(tos, user.Email)
					}

					if msg.Header.Get("X-BeenThere") != context.Config.Connections.Email.Mailman.Address && !strings.Contains(body, "X-BeenThere: "+context.Config.Connections.Email.Mailman.Address) {
						if len(tos) > 0 {
							sendMail(tos, from, subj, body, mid, contenttype, contenttypetrasnfer)
						}
					} else {
						fmt.Println("IGNORING MESSAGE!")
					}
					mm.LastSeen = uint64(rsp.MessageInfo().UID)
					mm.Update(context)
				}
			}

			cmd.Data = nil

			// Process unilateral server data
			for _, rsp = range c.Data {
				// fmt.Println("Server data:", rsp)
			}
			c.Data = nil
		}

		// Check command completion status
		if rsp, err := cmd.Result(imap.OK); err != nil {
			if err == imap.ErrAborted {
				fmt.Println("Fetch command aborted")
			} else {
				fmt.Println("Fetch error:", rsp.Info)
				return
			}
		}

		time.Sleep(1 * time.Minute)
	}
}
<commit_msg>Support non-TLS IMAP logins<commit_after>package mailman

import (
	"bytes"
	"fmt"
	"net/mail"
	"strconv"
	"strings"
	"time"

	"github.com/muesli/gomail"
	"github.com/mxk/go-imap/imap"

	"github.com/muesli/polly/api/db"
)

var (
	context *db.PollyContext
)

// SetupMailmanContext sets the context
func SetupMailmanContext(ctx *db.PollyContext) {
	context = ctx
}

func sendMail(tos []string, from, subject, body, mid, contenttype, contenttypetransfer string) {
	m := gomail.NewMessage()
	m.SetHeader("From", from)
	m.SetHeader("Subject", subject)
	m.SetHeader("Message-ID", mid)
	m.SetHeader("Errors-To", context.Config.Connections.Email.Mailman.BounceAddress)
	m.SetHeader("X-BeenThere", context.Config.Connections.Email.Mailman.Address)
	m.SetAddressHeader("To", context.Config.Connections.Email.Mailman.Address, context.Config.Connections.Email.Mailman.Name)
	m.SetAddressHeader("Envelope-Sender", context.Config.Connections.Email.Mailman.BounceAddress, context.Config.Connections.Email.Mailman.Name)
	m.SetAddressHeader("List-Id", context.Config.Connections.Email.Mailman.Address, context.Config.Connections.Email.Mailman.Name)

	if len(contenttype) > 0 {
		m.SetHeader("Content-Type", contenttype)
	}
	if len(contenttypetransfer) > 0 {
		m.SetHeader("Content-Transfer-Encoding", contenttypetransfer)
	}

	m.SetRawBody(body)

	d := gomail.NewDialer(context.Config.Connections.Email.SMTP.Server, context.Config.Connections.Email.SMTP.Port,
		context.Config.Connections.Email.SMTP.User, context.Config.Connections.Email.SMTP.Password)
	s, err := d.Dial()
	if err != nil {
		panic(err)
	}
	defer s.Close()

	err = s.Send(context.Config.Connections.Email.Mailman.Address, tos, m)
	if err != nil {
		panic(err)
	}
}

// RunLoop fetches mail and delivers them to recipients - forever
func RunLoop() {
	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
		err error
	)

	// Connect to the server
	if context.Config.Connections.Email.IMAP.Port == 993 {
		c, err = imap.DialTLS(context.Config.Connections.Email.IMAP.Server+":"+strconv.FormatInt(int64(context.Config.Connections.Email.IMAP.Port), 10), nil)
	} else {
		c, err = imap.Dial(context.Config.Connections.Email.IMAP.Server + ":" + strconv.FormatInt(int64(context.Config.Connections.Email.IMAP.Port), 10))
	}
	if err != nil || c == nil || c.Data == nil {
		panic(err)
	}

	// Print server greeting (first response in the unilateral server data queue)
	fmt.Println("IMAP Server says hello:", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login(context.Config.Connections.Email.IMAP.User, context.Config.Connections.Email.IMAP.Password)
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))
	if cmd == nil {
		return
	}

	// Print mailbox information
	fmt.Println("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		fmt.Println("|--", rsp.MailboxInfo().Name)
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		fmt.Println("Server data:", rsp)
	}
	c.Data = nil

	mm, _ := context.GetMailman(context.Config.Connections.Email.Mailman.Address)
	for {
		// Open a mailbox (synchronous command - no need for imap.Wait)
		c.Select("INBOX", true)
		fmt.Printf("Mailbox status: %s (msgs: %d, last-seen: %d)\n", c.Mailbox.Name, c.Mailbox.Messages, mm.LastSeen)

		if mm.LastSeen == 0 {
			mm.LastSeen = uint64(c.Mailbox.Messages)
		}

		// Fetch new mails
		set, _ := imap.NewSeqSet("")
		set.Add(strconv.FormatUint(mm.LastSeen+1, 10) + ":*")
		cmd, _ = c.UIDFetch(set, "RFC822.HEADER", "RFC822.TEXT")

		// Process responses while the command is running
		fmt.Println("\nChecking mailman INBOX")
		for cmd.InProgress() {
			// Wait for the next response (no timeout)
			c.Recv(-1)

			// Process command data
			for _, rsp = range cmd.Data {
				header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
				body := string(imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"]))
				if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
					from := msg.Header.Get("From")
					subj := msg.Header.Get("Subject")
					mid := msg.Header.Get("Message-ID")
					contenttype := msg.Header.Get("Content-Type")
					contenttypetrasnfer := msg.Header.Get("Content-Transfer-Encoding")

					fmt.Println("|-- From", from)
					fmt.Println("|-- Subject", subj)
					fmt.Println("|-- ID", mid)

					users, err := context.LoadAllUsers()
					if err != nil {
						panic(err)
					}
					tos := []string{}
					for _, user := range users {
						if !user.Activated {
							continue
						}
						tos = append(tos, user.Email)
					}

					if msg.Header.Get("X-BeenThere") != context.Config.Connections.Email.Mailman.Address && !strings.Contains(body, "X-BeenThere: "+context.Config.Connections.Email.Mailman.Address) {
						if len(tos) > 0 {
							sendMail(tos, from, subj, body, mid, contenttype, contenttypetrasnfer)
						}
					} else {
						fmt.Println("IGNORING MESSAGE!")
					}
					mm.LastSeen = uint64(rsp.MessageInfo().UID)
					mm.Update(context)
				}
			}

			cmd.Data = nil

			// Process unilateral server data
			for _, rsp = range c.Data {
				// fmt.Println("Server data:", rsp)
			}
			c.Data = nil
		}

		// Check command completion status
		if rsp, err := cmd.Result(imap.OK); err != nil {
			if err == imap.ErrAborted {
				fmt.Println("Fetch command aborted")
			} else {
				fmt.Println("Fetch error:", rsp.Info)
				return
			}
		}

		time.Sleep(1 * time.Minute)
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/go-martini/martini"
	"launchpad.net/gocheck"

	"github.com/wiliamsouza/apollo/token"
)

func (s *S) TestAuthN(c *gocheck.C) {
	request, err := http.NewRequest("POST", "/protected", nil)
	c.Assert(err, gocheck.IsNil)
	t, err := token.New("jhon@doe.com")
	c.Assert(err, gocheck.IsNil)
	request.Header.Set("Authorization", fmt.Sprintf("Bearer %v", t))
	tt, err := token.Validate(request)
	c.Assert(err, gocheck.IsNil)
	tk := &token.Token{Email: tt.Claims["email"].(string), Exp: tt.Claims["exp"].(float64)}
	request.Header.Set("Content-Type", "application/json")
	response := httptest.NewRecorder()
	context := martini.New().createContext(response, request)
	AuthN()(response, request, context)
	c.Assert(response.Code, gocheck.Equals, http.StatusOK)
	c.Assert(response.Body.String(), gocheck.Equals, "success")
}
<commit_msg>Fixed AuthN middleware test<commit_after>package api

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/go-martini/martini"
	"launchpad.net/gocheck"

	"github.com/wiliamsouza/apollo/token"
)

func (s *S) TestAuthN(c *gocheck.C) {
	request, err := http.NewRequest("POST", "/protected", nil)
	c.Assert(err, gocheck.IsNil)
	t, err := token.New("jhon@doe.com")
	c.Assert(err, gocheck.IsNil)
	request.Header.Set("Authorization", fmt.Sprintf("Bearer %v", t))
	_, err = token.Validate(request)
	c.Assert(err, gocheck.IsNil)
	request.Header.Set("Content-Type", "application/json")
	response := httptest.NewRecorder()
	m := martini.Classic()
	m.Post("/protected", AuthN(), func() int {
		return http.StatusOK
	})
	m.ServeHTTP(response, request)
	c.Assert(response.Code, gocheck.Equals, http.StatusOK)
}
<|endoftext|>


<commit_before>package villa

import (
	"os"
	"os/exec"
	"path/filepath"
	"io/ioutil"
)

// Path is a wrapper for a path in the OS
type Path string

/*
	filepath package
*/

func (p Path) Abs() (pth Path, err error) {
	pt, err := filepath.Abs(string(p))
	return Path(pt), err
}

func (p Path) Join(elem ...interface{}) Path {
	els := make(StringSlice, 0, len(elem) + 1)
	els.Add(p).Add(elem...)
	return Path(filepath.Join(els...))
}

func (p Path) Ext() string {
	return filepath.Ext(string(p))
}

/*
	os
*/

func (p Path) Mkdir(perm os.FileMode) error {
	return os.Mkdir(string(p), perm)
}

func (p Path) MkdirAll(perm os.FileMode) error {
	return os.MkdirAll(string(p), perm)
}

func (p Path) S() string {
	return string(p)
}

func (p Path) Stat() (fi os.FileInfo, err error) {
	return os.Stat(string(p))
}

func (p Path) Symlink(dst Path) error {
	return os.Symlink(string(p), string(dst))
}

/*
	ioutil package
*/

func (p Path) ReadDir() (fi []os.FileInfo, err error) {
	return ioutil.ReadDir(string(p))
}

func (p Path) ReadFile() ([]byte, error) {
	return ioutil.ReadFile(string(p))
}

func (p Path) WriteFile(data []byte, perm os.FileMode) error {
	return ioutil.WriteFile(string(p), data, perm)
}

func (p Path) TempDir(prefix string) (name Path, err error) {
	nm, err := ioutil.TempDir(string(p), prefix)
	return Path(nm), err
}

/*
	exec package
*/

func (p Path) Command(arg ...string) *exec.Cmd {
	return exec.Command(string(p), arg...)
}

/*
	Composite
*/

// Exists checks whether the file exists
func (p Path) Exists() bool {
	_, err := p.Stat()
	return err == nil
}
<commit_msg>ADD some mothods<commit_after>package villa

import (
	"os"
	"os/exec"
	"path/filepath"
	"io/ioutil"
)

// Path is a wrapper for a path in the OS
type Path string

/*
	filepath package
*/

func (p Path) Abs() (pth Path, err error) {
	pt, err := filepath.Abs(string(p))
	return Path(pt), err
}

func (p Path) Join(elem ...interface{}) Path {
	els := make(StringSlice, 0, len(elem) + 1)
	els.Add(p).Add(elem...)
	return Path(filepath.Join(els...))
}

func (p Path) Ext() string {
	return filepath.Ext(string(p))
}

/*
	os
*/

// Create is a wrapper to os.Create
func (p Path) Create() (file *os.File, err error) {
	return os.Create(string(p))
}

// Open is a wrapper to os.Open
func (p Path) Open() (file *os.File, err error) {
	return os.Open(string(p))

}
// Open is a wrapper to os.OpenFile
func (p Path) OpenFile(flag int, perm os.FileMode) (file *os.File, err error) {
	return os.OpenFile(string(p), flag, perm)
}

// Mkdir is a wrappter to os.Mkdir
func (p Path) Mkdir(perm os.FileMode) error {
	return os.Mkdir(string(p), perm)
}

// MkdirAll is a wrappter to os.MkdirAll
func (p Path) MkdirAll(perm os.FileMode) error {
	return os.MkdirAll(string(p), perm)
}

// Stat is a wrappter to os.Stat
func (p Path) Stat() (fi os.FileInfo, err error) {
	return os.Stat(string(p))
}

// Symlink is a wrappter to os.Symlink
func (p Path) Symlink(dst Path) error {
	return os.Symlink(string(p), string(dst))
}

/*
	ioutil package
*/

func (p Path) ReadDir() (fi []os.FileInfo, err error) {
	return ioutil.ReadDir(string(p))
}

func (p Path) ReadFile() ([]byte, error) {
	return ioutil.ReadFile(string(p))
}

func (p Path) WriteFile(data []byte, perm os.FileMode) error {
	return ioutil.WriteFile(string(p), data, perm)
}

func (p Path) TempDir(prefix string) (name Path, err error) {
	nm, err := ioutil.TempDir(string(p), prefix)
	return Path(nm), err
}

/*
	exec package
*/

// Command is a wrappter to exec.Command
func (p Path) Command(arg ...string) *exec.Cmd {
	return exec.Command(string(p), arg...)
}

/*
	Composite
*/

// Exists checks whether the file exists
func (p Path) Exists() bool {
	_, err := p.Stat()
	return err == nil
}

// S converts Path back to string
func (p Path) S() string {
	return string(p)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"time"
	"bufio"
	"io"
	"net/http"
	"strings"
	"sync"
	"os/exec"
	"strconv"
	"github.com/vaxx99/play/stream"
	"github.com/gotk3/gotk3/gtk"
	"github.com/gotk3/gotk3/pango"
)

type Labels struct {
	Count, Station, Bitrate, Genre, Timer, Title *gtk.Label
}

func main() {
	gtk.Init(nil)

	check := func(m string, e error) {
		if e != nil {
			log.Println(m, e)
		}
	}

	win, e := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	check("", e)
	win.SetSkipTaskbarHint(true)

	//Linux screen resolution
	out, _ := exec.Command("xdpyinfo").Output()
	dpi := string(out)
	dpi = dpi[strings.Index(dpi, "dimensions:")+len("dimensions:") : strings.Index(dpi, "pixels")]
	a := strings.Split(dpi, "x")
	W, e := strconv.Atoi(strings.TrimSpace(a[0]))
	H, e := strconv.Atoi(strings.TrimSpace(a[1]))
	check("Resolution:", e)
	if e != nil {
		W, H = 1024, 768
	}

	win.SetSizeRequest(400, 10)
	win.Connect("destroy", func() {
		gtk.MainQuit()
	})

	provider, _ := gtk.CssProviderNew()
	provider.LoadFromData(`@define-color base #333;@define-color fore #ccc;@define-color diff #555;*{background-color: @base;border:0;}.container{color: @fore;border:1px solid @base;}.plus{color: @fore;border:0;font-size:20px;}.station{color:@fore;border:0;font-size:10px;}.bitrate{color:#ccc;border:0;font-size:10px;}.timer{color:#ccc;border:0;font-size:10px;padding-right:5px;}.title{color:#cff;border:0;font-size:10px;font-style: italic;}.genre{color:#fcc;border:0;font-size:10px;}`)
	win.SetTitle("xPlay")
	win.SetIconFromFile("fsto.png")
	win.SetDefaultSize(400, 10)
	win.SetResizable(false)
	win.SetKeepAbove(true)

	cont, _ := gtk.GridNew()
	cont.SetRowHomogeneous(true)
	cont.SetSizeRequest(400, 10)

	plus, _ := gtk.LabelNew("")
	station, _ := gtk.LabelNew("")
	bitrate, _ := gtk.LabelNew("")
	genre, _ := gtk.LabelNew("")
	title, _ := gtk.LabelNew("")
	timer, _ := gtk.LabelNew("00:00:00")

	var labs = &Labels{plus, station, bitrate, genre, timer, title}

	ebox, _ := gtk.EventBoxNew()
	ubox, _ := gtk.EventBoxNew()
	cbox, _ := gtk.EventBoxNew()
	bbox, _ := gtk.EventBoxNew()

	Style(provider, &cont.Widget, "container")
	Style(provider, &station.Widget, "station")
	Style(provider, &bitrate.Widget, "bitrate")
	Style(provider, &genre.Widget, "genre")
	Style(provider, &title.Widget, "title")
	Style(provider, &timer.Widget, "timer")
	Style(provider, &plus.Widget, "plus")

	plus.SetSizeRequest(20, 10)
	station.SetSizeRequest(300, 10)
	station.SetXAlign(0)
	bitrate.SetSizeRequest(40, 10)
	bitrate.SetXAlign(0)
	timer.SetSizeRequest(30, 10)
	timer.SetXAlign(0)
	title.SetSizeRequest(300, 10)
	title.SetXAlign(0)

	station.SetMaxWidthChars(10)
	station.SetEllipsize(pango.ELLIPSIZE_END)
	station.SetJustify(gtk.JUSTIFY_LEFT)

	title.SetMaxWidthChars(10)
	title.SetEllipsize(pango.ELLIPSIZE_END)
	title.SetJustify(gtk.JUSTIFY_LEFT)
	title.SetVisible(false)

	bitrate.SetMaxWidthChars(10)
	bitrate.SetEllipsize(pango.ELLIPSIZE_END)
	bitrate.SetJustify(gtk.JUSTIFY_LEFT)

	ebox.Add(timer)
	ubox.Add(station)
	cbox.Add(plus)
	bbox.Add(bitrate)

	cont.Attach(cbox, 0, 0, 1, 1)
	cont.Attach(ubox, 1, 0, 1, 1)
	cont.Attach(title, 1, 0, 1, 1)
	cont.Attach(bbox, 2, 0, 1, 1)
	cont.Attach(ebox, 3, 0, 1, 1)

	var ch = make(chan struct{})
	var run = 0
	var play = stream.NewPlayer()
	var tmp = stream.Streams{}

	proxy := os.Getenv("http_proxy")

	if proxy == "" {
		tmp = append(tmp, stream.Stream{Crnt: 0, Next: 0, SName: "Radio Swiss Jazz", SUrl: "http://stream.srg-ssr.ch/m/rsj/aacp_96"})
	} else {
		os.Setenv("http_proxy", proxy)
		tmp = stream.Plist()
	}
	cplay := tmp[0]

	labs.Count.SetMarkup("•")
	labs.Station.SetText(cplay.SName)

	ubox.Connect("event", func() {
		if labs.Station.GetVisible() == false {
			labs.Station.SetVisible(true)
			labs.Title.SetVisible(false)
		} else {
			labs.Station.SetVisible(false)
			labs.Title.SetVisible(true)
		}
	})

	ebox.Connect("button-press-event", func() {
		hb := &http.Response{}
		ha := 0
		titl := &Titles{Lab: labs}
		timr := &Timer{time.Now(), labs}
		var wg sync.WaitGroup
		if run == 0 {
			run = 1
			uri, prx := cplay.SUrl, cplay.SProxy
			hb, ha = stream.TryOne(uri, prx)
			if ha == 0 {
				hb, ha = stream.TryTwo(uri, prx)
			}
			labs.Station.SetText(cplay.SName)
			if hb.StatusCode == 200 && ha > 0 {
				data := &Data{hb.Body, ha}
				titl.Now = &timr.Now
				cplay.SBitr = hb.Header.Get("icy-br")
				titl.Tch = data.Update(&wg, ch)
				labs.Station.SetVisible(false)
				labs.Title.SetVisible(true)
				wg.Add(1)
				go titl.Update(&wg, ch)
				labs.Count.SetMarkup("•")
				labs.Bitrate.SetMarkup("" + cplay.SBitr + " k")
				wg.Add(1)
				go timr.Update(&wg, ch)
				play.Player(cplay.SUrl)
			} else {
				run = 0
				labs.Title.SetVisible(false)
			}
		} else {
			run = 0
			labs.Clear()
			labs.Count.SetMarkup("•")
			play.Player("")
			ch <- struct{}{}
			ch <- struct{}{}
			labs.Title.SetVisible(false)
			labs.Station.SetVisible(true)
			wg.Wait()
		}
	})

	cbox.Connect("button-press-event", func() {
		cplay = tmp[cplay.Next]
		labs.Clear()
		labs.Station.SetText(cplay.SName)
		labs.Count.SetMarkup("•")
	})

	ubox.Connect("button-press-event", func() {
		if proxy != "" {
			tmp = stream.Plist()
			labs.Clear()
			labs.Station.SetText(cplay.SName)
			labs.Count.SetMarkup("•")
			cplay = tmp[0]
		}
	})

	//bbox.Connect("event", func() {
	//	bitrate.SetMarkup("move")
	//})

	bbox.Connect("button-press-event", func() {
		x, y := win.GetPosition()
		w, h := win.GetSize()

		if win.GetDecorated() == true {
			win.SetDecorated(false)
			if x < W/2 {
				x = 0
			}
			if y < H/2 {
				y = 0
			}
			if x > W/2 {
				x = W - w
			}
			if y > H/2 {
				y = H
			}
			win.Move(x, y)
		} else {
			win.Move(W/2-w/2, H/2-h/2)
			win.SetDecorated(true)
		}
	})
	win.Add(cont)
	win.ShowAll()
	gtk.Main()
}

func Style(p *gtk.CssProvider, w *gtk.Widget, cn string) error {
	ctx, err := w.GetStyleContext()
	if err != nil {
		return err
	}
	ctx.AddProvider(p, 600)
	ctx.AddClass(cn)
	return nil
}

type Timer struct {
	Now time.Time
	Lab *Labels
}

func (t *Timer) Update(wg *sync.WaitGroup, ch chan struct{}) {
	for {
		select {
		default:
			time.Sleep(1 * time.Second)
			dur := time.Since(t.Now)
			tm, _ := time.Parse("150405", "000000")
			tt := tm.Add(dur)
			t.Lab.Timer.SetMarkup("" + tt.Format("15:04:05") + "")
		case <-ch:
			t.Lab.Timer.SetText("00:00:00")
			wg.Done()
			return
		}
	}
}

type Titles struct {
	Tch <-chan string
	Lab *Labels
	Now *time.Time
}

type Data struct {
	rdr  io.Reader
	skip int
}

func (t *Titles) Update(wg *sync.WaitGroup, ch chan struct{}) {
	select {
	default:
		for meta := range t.Tch {
			*t.Now = time.Now()
			t.Lab.Title.SetText(meta)
		}
	case <-ch:
		wg.Done()
		return
	}
}

func (L *Labels) Clear() {
	L.Bitrate.SetText("")
	L.Title.SetText("")
}

func (d *Data) Update(wg *sync.WaitGroup, ch chan struct{}) <-chan string {
	dh := make(chan string)
	wg.Add(1)
	go func() {
		bufrdr := bufio.NewReaderSize(d.rdr, d.skip)
		for {
			skipbytes := make([]byte, d.skip)
			_, err := io.ReadFull(bufrdr, skipbytes)
			if err != nil {
				log.Printf("Failed: %v\n", err)
				close(dh)
				return
			}
			c, err := bufrdr.ReadByte()
			if err != nil {
				log.Panic(err)
			}
			if c > 0 {
				meta, err := stream.ParseIcy(bufrdr, c)
				if err != nil {
					log.Panic(err)
				}
				dh <- meta
			}
			select {
			default:
			case <-ch:
				wg.Done()
				close(dh)
				return
			}
		}
	}()
	return dh
}

<commit_msg>UTF-8,<commit_after>package main

import (
	"log"
	"os"
	"time"
	"bufio"
	"io"
	"net/http"
	"strings"
	"sync"
	"os/exec"
	"strconv"
	"github.com/vaxx99/play/stream"
	"github.com/gotk3/gotk3/gtk"
	"github.com/gotk3/gotk3/pango"
	"github.com/gotk3/gotk3/gdk"
)

type Labels struct {
	Count, Station, Bitrate, Genre, Timer, Title *gtk.Label
}

func main() {
	gtk.Init(nil)

	check := func(m string, e error) {
		if e != nil {
			log.Println(m, e)
		}
	}

	win, e := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	check("", e)
	win.SetSkipTaskbarHint(true)

	//Linux screen resolution
	out, _ := exec.Command("xdpyinfo").Output()
	dpi := string(out)
	dpi = dpi[strings.Index(dpi, "dimensions:")+len("dimensions:") : strings.Index(dpi, "pixels")]
	a := strings.Split(dpi, "x")
	W, e := strconv.Atoi(strings.TrimSpace(a[0]))
	H, e := strconv.Atoi(strings.TrimSpace(a[1]))
	check("Resolution:", e)
	if e != nil {
		W, H = 1024, 768
	}

	//win.SetSizeRequest(300, 12)
	win.Connect("destroy", func() {
		gtk.MainQuit()
	})

	win.Connect("key-press-event",func(win *gtk.Window,ev *gdk.Event){
		keyEvent := &gdk.EventKey{ev}
		if keyEvent.KeyVal() == gdk.KEY_Escape{
			gtk.MainQuit()
		}

	})

	provider, _ := gtk.CssProviderNew()
	provider.LoadFromData(`@define-color base #333;@define-color fore #ccc;@define-color diff #555;*{background-color: @base;border:0;}.container{color: @fore;border:1px solid @base;}.plus{color: @fore;border:0;font-size:20px;}.station{color:@fore;border:0;font-size:10px;}.bitrate{color:#ccc;border:0;font-size:10px;}.timer{color:#ccc;border:0;font-size:10px;padding-right:4px;}.title{color:#cff;border:0;font-size:10px;}.genre{color:#fcc;border:0;font-size:10px;}`)
	win.SetTitle("xPlay")
	win.SetIconFromFile("fsto.png")
	win.SetDefaultSize(300, 12)
	win.SetResizable(false)
	win.SetKeepAbove(true)

	cont, _ := gtk.GridNew()
	cont.SetRowHomogeneous(true)
	cont.SetColumnSpacing(4)
	cont.SetSizeRequest(300, 12)
	cont.SetVExpand(false)

	plus, _ := gtk.LabelNew("")
	station, _ := gtk.LabelNew("")
	bitrate, _ := gtk.LabelNew("")
	genre, _ := gtk.LabelNew("")
	title, _ := gtk.LabelNew("")
	timer, _ := gtk.LabelNew("00:00")

	var labs = &Labels{plus, station, bitrate, genre, timer, title}

	ebox, _ := gtk.EventBoxNew()
	ubox, _ := gtk.EventBoxNew()
	cbox, _ := gtk.EventBoxNew()
	bbox, _ := gtk.EventBoxNew()

	Style(provider, &cont.Widget, "container")
	Style(provider, &station.Widget, "station")
	Style(provider, &bitrate.Widget, "bitrate")
	Style(provider, &genre.Widget, "genre")
	Style(provider, &title.Widget, "title")
	Style(provider, &timer.Widget, "timer")
	Style(provider, &plus.Widget, "plus")

	plus.SetSizeRequest(20, 12)
	station.SetSizeRequest(230, 12)
	station.SetXAlign(0)
	bitrate.SetSizeRequest(20, 12)
	bitrate.SetXAlign(-1)
	timer.SetSizeRequest(20, 12)
	timer.SetXAlign(-1)
	title.SetSizeRequest(230, 12)
	title.SetXAlign(0)

	station.SetMaxWidthChars(10)
	station.SetEllipsize(pango.ELLIPSIZE_END)
	station.SetJustify(gtk.JUSTIFY_LEFT)

	title.SetLines(2)
	title.SetMaxWidthChars(10)
	title.SetLineWrap(true)
	//title.SetEllipsize(pango.ELLIPSIZE_END)
	title.SetJustify(gtk.JUSTIFY_CENTER)
	title.SetVisible(false)

	bitrate.SetMaxWidthChars(10)
	bitrate.SetEllipsize(pango.ELLIPSIZE_END)
	bitrate.SetJustify(gtk.JUSTIFY_RIGHT)
	timer.SetJustify(gtk.JUSTIFY_RIGHT)

	ebox.Add(timer)
	ubox.Add(station)
	cbox.Add(plus)
	bbox.Add(bitrate)

	cont.Attach(cbox, 0, 0, 1, 1)
	cont.Attach(ubox, 1, 0, 1, 1)
	cont.Attach(title, 1, 0, 1, 1)
	cont.Attach(bbox, 2, 0, 1, 1)
	cont.Attach(ebox, 3, 0, 1, 1)

	var ch = make(chan struct{})
	var run = 0
	var play = stream.NewPlayer()
	var tmp = stream.Streams{}

	proxy := os.Getenv("http_proxy")

	if proxy == "" {
		tmp = append(tmp, stream.Stream{Crnt: 0, Next: 0, SName: "Radio Swiss Jazz", SUrl: "http://stream.srg-ssr.ch/m/rsj/aacp_96"})
	} else {
		os.Setenv("http_proxy", proxy)
		tmp = stream.Plist()
	}
	cplay := tmp[0]

	labs.Count.SetMarkup("•")
	labs.Station.SetText(cplay.SName)

	ubox.Connect("event", func() {
		if labs.Station.GetVisible() == false {
			labs.Station.SetVisible(true)
			labs.Title.SetVisible(false)
		} else {
			labs.Station.SetVisible(false)
			labs.Title.SetVisible(true)
		}
	})

	ebox.Connect("button-press-event", func() {
		hb := &http.Response{}
		ha := 0
		titl := &Titles{Lab: labs}
		timr := &Timer{time.Now(), labs}
		var wg sync.WaitGroup
		if run == 0 {
			run = 1
			uri, prx := cplay.SUrl, cplay.SProxy
			hb, ha = stream.TryOne(uri, prx)
			if ha == 0 {
				hb, ha = stream.TryTwo(uri, prx)
			}
			labs.Station.SetText(cplay.SName)
			if hb.StatusCode == 200 && ha > 0 {
				data := &Data{hb.Body, ha}
				titl.Now = &timr.Now
				cplay.SBitr = hb.Header.Get("icy-br")
				titl.Tch = data.Update(&wg, ch)
				labs.Station.SetVisible(false)
				labs.Title.SetVisible(true)
				wg.Add(1)
				go titl.Update(&wg, ch)
				labs.Count.SetMarkup("•")
				labs.Bitrate.SetMarkup("" + cplay.SBitr + "k")
				wg.Add(1)
				go timr.Update(&wg, ch)
				play.Player(cplay.SUrl)
			} else {
				run = 0
				labs.Title.SetVisible(false)
			}
		} else {
			run = 0
			labs.Clear()
			labs.Count.SetMarkup("•")
			play.Player("")
			ch <- struct{}{}
			ch <- struct{}{}
			labs.Title.SetVisible(false)
			labs.Station.SetVisible(true)
			wg.Wait()
		}
	})

	cbox.Connect("button-press-event", func() {
		cplay = tmp[cplay.Next]
		labs.Clear()
		labs.Station.SetText(cplay.SName)
		labs.Count.SetMarkup("•")
	})

	ubox.Connect("button-press-event", func() {
		if proxy != "" {
			tmp = stream.Plist()
			labs.Clear()
			labs.Station.SetText(cplay.SName)
			labs.Count.SetMarkup("•")
			cplay = tmp[0]
		}
	})

	//bbox.Connect("event", func() {
	//	bitrate.SetMarkup("move")
	//})

	bbox.Connect("button-press-event", func() {
		x, y := win.GetPosition()
		w, h := win.GetSize()

		if win.GetDecorated() == true {
			win.SetDecorated(false)
			if x < W/2 {
				x = 0
			}
			if y < H/2 {
				y = 0
			}
			if x > W/2 {
				x = W - w
			}
			if y > H/2 {
				y = H
			}
			win.Move(x, y)
		} else {
			win.Move(W/2-w/2, H/2-h/2)
			win.SetDecorated(true)
		}
	})
	win.Add(cont)
	win.ShowAll()
	gtk.Main()
}

func Style(p *gtk.CssProvider, w *gtk.Widget, cn string) error {
	ctx, err := w.GetStyleContext()
	if err != nil {
		return err
	}
	ctx.AddProvider(p, 600)
	ctx.AddClass(cn)
	return nil
}

type Timer struct {
	Now time.Time
	Lab *Labels
}

func (t *Timer) Update(wg *sync.WaitGroup, ch chan struct{}) {
	for {
		select {
		default:
			time.Sleep(1 * time.Second)
			dur := time.Since(t.Now)
			tm, _ := time.Parse("0405", "0000")
			tt := tm.Add(dur)
			t.Lab.Timer.SetMarkup("" + tt.Format("04:05") + "")
		case <-ch:
			t.Lab.Timer.SetText("00:00")
			wg.Done()
			return
		}
	}
}

type Titles struct {
	Tch <-chan string
	Lab *Labels
	Now *time.Time
}

type Data struct {
	rdr  io.Reader
	skip int
}

func (t *Titles) Update(wg *sync.WaitGroup, ch chan struct{}) {
	select {
	default:
		for meta := range t.Tch {
			*t.Now = time.Now()
			xtx:=toUtf8([]byte(meta))
			if len(xtx)>0{
				xtx=strings.TrimLeft(xtx,"'")
				xtx=strings.TrimRight(xtx,"'")
				if strings.Contains(xtx,"&"){
					xtx = strings.Replace(xtx, "&", "&", -1)
				}
			}
			t.Lab.Title.SetMarkup(""+xtx+"")
		}
	case <-ch:
		wg.Done()
		return
	}
}

func toUtf8(iso8859_1_buf []byte) string {
	buf := make([]rune, len(iso8859_1_buf))
	for i, b := range iso8859_1_buf {
		buf[i] = rune(b)
	}
	return string(buf)
}

func (L *Labels) Clear() {
	L.Bitrate.SetText("")
	L.Title.SetText("")
}

func (d *Data) Update(wg *sync.WaitGroup, ch chan struct{}) <-chan string {
	dh := make(chan string)
	wg.Add(1)
	go func() {
		bufrdr := bufio.NewReaderSize(d.rdr, d.skip)
		for {
			skipbytes := make([]byte, d.skip)
			_, err := io.ReadFull(bufrdr, skipbytes)
			if err != nil {
				log.Printf("Failed: %v\n", err)
				close(dh)
				return
			}
			c, err := bufrdr.ReadByte()
			if err != nil {
				log.Panic(err)
			}
			if c > 0 {
				meta, err := stream.ParseIcy(bufrdr, c)
				if err != nil {
					log.Panic(err)
				}
				dh <- meta
			}
			select {
			default:
			case <-ch:
				wg.Done()
				close(dh)
				return
			}
		}
	}()
	return dh
}

<|endoftext|>


<commit_before>// Copyright © 2013-2018 Pierre Neidhardt <ambrevar@gmail.com>
// Use of this file is governed by the license that can be found in LICENSE.

package main

import (
	"io/ioutil"
	"testing"

	"github.com/ambrevar/demlo/cuesheet"
)

const (
	sampleCuesheet    = "cuesheet/testdata/sample.cue"
	scriptCase        = "scripts/30-case.lua"
	scriptPunctuation = "scripts/40-punctuation.lua"
)

func TestFixPunctuation(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"a b": "a_b",
			".a":  ".a",
			"a (": "a(",
			"(a":  "( a",
			"a c": "a 	c",
			"a": "	 a 	",
			"Some i.n.i.t.i.a.l.s.": "Some i.n.i.t.i.a.l.s.",
		},
	}

	buf, err := ioutil.ReadFile(scriptPunctuation)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "punctuation", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	err = RunScript(L, "punctuation", &input, &output)
	if err != nil {
		t.Fatalf("script punctuation: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestTitleCase(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"All Lowercase Words":                     "all lowercase words",
			"All Uppercase Words":                     "ALL UPPERCASE WORDS",
			"All Crazy Case Words":                    "aLl cRaZY cASE WordS",
			"With Common Preps in a CD Into the Box.": "With common preps in a cd INTO the box.",
			"Feat and feat. The Machines.":            "Feat and Feat. the machines.",
			"Unicode Apos´trophe":                     "unicode apos´trophe",
			"...":                                                      "...",
			".'?":                                                      ".'?",
			"I'll Be Ill'":                                             "i'll be ill'",
			"Names Like O'Hara, D’Arcy":                                "Names like o'hara, d’arcy",
			"Names Like McDonald and MacNeil":                          "Names like mcdonald and macneil",
			"Éléanor":                                                  "élÉanor",
			"XIV LIV Xiv Liv. Liv. Xiv.":                               "XIV LIV xiv liv. liv. xiv.",
			"A Start With a Lowercase Constant":                        "a start with a lowercase constant",
			`"A Double Quoted Sentence" and 'One Single Quoted'.`:      `"a double quoted sentence" and 'one single quoted'.`,
			`Another "Double Quoted Sentence", and "A Sentence More".`: `another "double quoted sentence", and "a sentence more".`,
			"Some I.N.I.T.I.A.L.S.":                                    "Some i.n.i.t.i.a.l.s.",
		},
	}

	buf, err := ioutil.ReadFile(scriptCase)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "case", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	err = RunScript(L, "case", &input, &output)
	if err != nil {
		t.Fatalf("script case: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestSentenceCase(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"Capitalized words":               "capitalized words",
			"Machine":                         "machine",
			"Rise of the machines":            "Rise Of The Machines",
			"Chanson d'avant":                 "Chanson D'Avant",
			"Names like o'hara, d’arcy":       "Names LIKE O'HARA, D’ARCY",
			"Names like McDonald and MacNeil": "Names LIKE MCDONALD AND MACNEIL",
			"XIV LIV xiv liv. Liv. Xiv.":      "XIV LIV xiv liv. liv. xiv.",
		},
	}

	buf, err := ioutil.ReadFile(scriptCase)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "case", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	// Set setencecase.
	L.PushBoolean(true)
	L.SetGlobal("scase")

	err = RunScript(L, "case", &input, &output)
	if err != nil {
		t.Fatalf("script case: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestStringNorm(t *testing.T) {
	want := []struct {
		s    string
		norm string
	}{
		{s: "A", norm: "a"},
		{s: "0a", norm: "a"},
		{s: "00a", norm: "a"},
		{s: "a0", norm: "a0"},
		{s: "a.0", norm: "a"},
		{s: "a0a", norm: "a0a"},
		{s: "a.0a", norm: "aa"},
		{s: "10", norm: "10"},
		{s: "01", norm: "1"},
		{s: ".a", norm: "a"},
		{s: "..a", norm: "a"},
	}

	for _, v := range want {
		n := stringNorm(v.s)
		if n != v.norm {
			t.Errorf(`Got "%v", want norm("%v")=="%v"`, n, v.s, v.norm)
		}
	}
}

func TestStringRel(t *testing.T) {
	want := []struct {
		a   string
		b   string
		rel float64
	}{
		{a: "foo", b: "bar", rel: 0.0},
		{a: "foo", b: "foo", rel: 1.0},
		{a: "foobar", b: "foobaz", rel: 1 - float64(1)/float64(6)},
		{a: "", b: "b", rel: 0.0},
		{a: "a", b: "", rel: 0.0},
		{a: "", b: "", rel: 1.0},
		{a: "ab", b: "ba", rel: 0.5},
		{a: "abba", b: "aba", rel: 0.75},
		{a: "aba", b: "abba", rel: 0.75},
		{a: "résumé", b: "resume", rel: 1 - float64(2)/float64(6)},
	}

	for _, v := range want {
		r := stringRel(v.a, v.b)
		if r != v.rel {
			t.Errorf(`Got %v, want rel("%v", "%v")==%v`, r, v.a, v.b, v.rel)
		}
	}
}

func TestFFmpegSplitTimes(t *testing.T) {
	// We need to make up last track's duration: 3 minutes.
	totaltime := float64(17*60 + 4 + 3*60)

	want := []struct {
		track    int
		start    string
		duration string
	}{
		{track: 0, start: "00:00:00.000", duration: "00:06:40.360"},
		{track: 1, start: "00:06:40.360", duration: "00:04:13.640"},
		{track: 3, start: "00:17:04.000", duration: "00:03:00.000"},
		{track: 4, start: "", duration: ""},
		{track: 8, start: "", duration: ""},
	}

	buf, err := ioutil.ReadFile(sampleCuesheet)
	if err != nil {
		panic(err)
	}
	sheet, err := cuesheet.New(buf)
	if err != nil {
		panic(err)
	}

	for _, v := range want {
		start, duration := ffmpegSplitTimes(sheet, "Faithless - Live in Berlin (CD1).mp3", v.track, totaltime)
		if start != v.start || duration != v.duration {
			t.Errorf("Got {start: %v, duration: %v}, want {start: %v, duration: %v}", start, duration, v.start, v.duration)
		}
	}
}
<commit_msg>Fix script paths in tests<commit_after>// Copyright © 2013-2018 Pierre Neidhardt <ambrevar@gmail.com>
// Use of this file is governed by the license that can be found in LICENSE.

package main

import (
	"io/ioutil"
	"testing"

	"github.com/ambrevar/demlo/cuesheet"
)

const (
	sampleCuesheet    = "cuesheet/testdata/sample.cue"
	scriptCase        = "scripts/30-tag-case.lua"
	scriptPunctuation = "scripts/40-tag-punctuation.lua"
)

func TestFixPunctuation(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"a b": "a_b",
			".a":  ".a",
			"a (": "a(",
			"(a":  "( a",
			"a c": "a 	c",
			"a": "	 a 	",
			"Some i.n.i.t.i.a.l.s.": "Some i.n.i.t.i.a.l.s.",
		},
	}

	buf, err := ioutil.ReadFile(scriptPunctuation)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "punctuation", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	err = RunScript(L, "punctuation", &input, &output)
	if err != nil {
		t.Fatalf("script punctuation: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestTitleCase(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"All Lowercase Words":                     "all lowercase words",
			"All Uppercase Words":                     "ALL UPPERCASE WORDS",
			"All Crazy Case Words":                    "aLl cRaZY cASE WordS",
			"With Common Preps in a CD Into the Box.": "With common preps in a cd INTO the box.",
			"Feat and feat. The Machines.":            "Feat and Feat. the machines.",
			"Unicode Apos´trophe":                     "unicode apos´trophe",
			"...":                                                      "...",
			".'?":                                                      ".'?",
			"I'll Be Ill'":                                             "i'll be ill'",
			"Names Like O'Hara, D’Arcy":                                "Names like o'hara, d’arcy",
			"Names Like McDonald and MacNeil":                          "Names like mcdonald and macneil",
			"Éléanor":                                                  "élÉanor",
			"XIV LIV Xiv Liv. Liv. Xiv.":                               "XIV LIV xiv liv. liv. xiv.",
			"A Start With a Lowercase Constant":                        "a start with a lowercase constant",
			`"A Double Quoted Sentence" and 'One Single Quoted'.`:      `"a double quoted sentence" and 'one single quoted'.`,
			`Another "Double Quoted Sentence", and "A Sentence More".`: `another "double quoted sentence", and "a sentence more".`,
			"Some I.N.I.T.I.A.L.S.":                                    "Some i.n.i.t.i.a.l.s.",
		},
	}

	buf, err := ioutil.ReadFile(scriptCase)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "case", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	err = RunScript(L, "case", &input, &output)
	if err != nil {
		t.Fatalf("script case: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestSentenceCase(t *testing.T) {
	input := inputInfo{}
	output := outputInfo{
		Tags: map[string]string{
			"Capitalized words":               "capitalized words",
			"Machine":                         "machine",
			"Rise of the machines":            "Rise Of The Machines",
			"Chanson d'avant":                 "Chanson D'Avant",
			"Names like o'hara, d’arcy":       "Names LIKE O'HARA, D’ARCY",
			"Names like McDonald and MacNeil": "Names LIKE MCDONALD AND MACNEIL",
			"XIV LIV xiv liv. Liv. Xiv.":      "XIV LIV xiv liv. liv. xiv.",
		},
	}

	buf, err := ioutil.ReadFile(scriptCase)
	if err != nil {
		t.Fatal("Script is not readable", err)
	}

	// Compile scripts.
	L := MakeSandbox(nil)
	SandboxCompileScript(L, "case", string(buf))
	if err != nil {
		t.Fatal("Spurious sandbox", err)
	}
	defer L.Close()

	// Set setencecase.
	L.PushBoolean(true)
	L.SetGlobal("scase")

	err = RunScript(L, "case", &input, &output)
	if err != nil {
		t.Fatalf("script case: %s", err)
	}

	for want, got := range output.Tags {
		if got != want {
			t.Errorf(`Got "%v", want "%v"`, got, want)
		}
	}
}

func TestStringNorm(t *testing.T) {
	want := []struct {
		s    string
		norm string
	}{
		{s: "A", norm: "a"},
		{s: "0a", norm: "a"},
		{s: "00a", norm: "a"},
		{s: "a0", norm: "a0"},
		{s: "a.0", norm: "a"},
		{s: "a0a", norm: "a0a"},
		{s: "a.0a", norm: "aa"},
		{s: "10", norm: "10"},
		{s: "01", norm: "1"},
		{s: ".a", norm: "a"},
		{s: "..a", norm: "a"},
	}

	for _, v := range want {
		n := stringNorm(v.s)
		if n != v.norm {
			t.Errorf(`Got "%v", want norm("%v")=="%v"`, n, v.s, v.norm)
		}
	}
}

func TestStringRel(t *testing.T) {
	want := []struct {
		a   string
		b   string
		rel float64
	}{
		{a: "foo", b: "bar", rel: 0.0},
		{a: "foo", b: "foo", rel: 1.0},
		{a: "foobar", b: "foobaz", rel: 1 - float64(1)/float64(6)},
		{a: "", b: "b", rel: 0.0},
		{a: "a", b: "", rel: 0.0},
		{a: "", b: "", rel: 1.0},
		{a: "ab", b: "ba", rel: 0.5},
		{a: "abba", b: "aba", rel: 0.75},
		{a: "aba", b: "abba", rel: 0.75},
		{a: "résumé", b: "resume", rel: 1 - float64(2)/float64(6)},
	}

	for _, v := range want {
		r := stringRel(v.a, v.b)
		if r != v.rel {
			t.Errorf(`Got %v, want rel("%v", "%v")==%v`, r, v.a, v.b, v.rel)
		}
	}
}

func TestFFmpegSplitTimes(t *testing.T) {
	// We need to make up last track's duration: 3 minutes.
	totaltime := float64(17*60 + 4 + 3*60)

	want := []struct {
		track    int
		start    string
		duration string
	}{
		{track: 0, start: "00:00:00.000", duration: "00:06:40.360"},
		{track: 1, start: "00:06:40.360", duration: "00:04:13.640"},
		{track: 3, start: "00:17:04.000", duration: "00:03:00.000"},
		{track: 4, start: "", duration: ""},
		{track: 8, start: "", duration: ""},
	}

	buf, err := ioutil.ReadFile(sampleCuesheet)
	if err != nil {
		panic(err)
	}
	sheet, err := cuesheet.New(buf)
	if err != nil {
		panic(err)
	}

	for _, v := range want {
		start, duration := ffmpegSplitTimes(sheet, "Faithless - Live in Berlin (CD1).mp3", v.track, totaltime)
		if start != v.start || duration != v.duration {
			t.Errorf("Got {start: %v, duration: %v}, want {start: %v, duration: %v}", start, duration, v.start, v.duration)
		}
	}
}
<|endoftext|>


<commit_before>package api100

import (
	"encoding/json"
	"net/http"
	"strconv"

	db100 "github.com/Chaosvermittlung/funkloch-server/db/v100"
	"github.com/carbocation/interpose"
	"github.com/gorilla/mux"
)

func getBoxRouter(prefix string) *interpose.Middleware {
	r, m := GetNewSubrouter(prefix)
	r.HandleFunc("/", postBoxHandler).Methods("POST")
	r.HandleFunc("/list", listBoxesHandler).Methods("GET")
	r.HandleFunc("/{ID}", getBoxHandler).Methods("GET")
	r.HandleFunc("/{ID}", patchBoxHandler).Methods("PATCH")
	r.HandleFunc("/{ID}", deleteBoxHandler).Methods("DELETE")
	r.HandleFunc("/{ID}/items", getBoxItemsHandler).Methods("GET")
	r.HandleFunc("/{ID}/items/add/{IID}", addItemtoBoxHandler).Methods("POST")
	r.HandleFunc("/{ID}/items/remove/{IID}", removeItemfromBoxHandler).Methods("POST")
	return m
}

func convertBoxListEntryinBoxResponse(b db100.BoxlistEntry) boxResponse {
	var br boxResponse
	br.Box.BoxID = b.BoxID
	br.Box.Code = b.Code
	br.Box.Description = b.Description
	br.Store.StoreID = b.StoreID
	br.Store.Adress = b.Adress
	br.Store.ManagerID = b.ManagerID
	br.Store.Name = b.Name
	br.User.UserID = b.ManagerID
	br.User.Username = b.Username
	br.User.Email = b.Email
	br.User.Right = db100.UserRight(b.Right)
	return br
}

func convertBoxListinBoxResponseList(bb []db100.BoxlistEntry) []boxResponse {
	var res []boxResponse
	for _, b := range bb {
		br := convertBoxListEntryinBoxResponse(b)
		res = append(res, br)
	}
	return res
}

func postBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var b db100.Box
	err = decoder.Decode(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusBadRequest, ERROR_JSONERROR)
		return
	}
	err = b.Insert()
	if err != nil {
		apierror(w, r, "Error Inserting Box: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	j, err := json.Marshal(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func listBoxesHandler(w http.ResponseWriter, r *http.Request) {
	bb, err := db100.GetBoxesJoined()
	if err != nil {
		apierror(w, r, "Error fetching Boxes: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	res := convertBoxListinBoxResponseList(bb)
	j, err := json.Marshal(&res)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func getBoxHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	var b db100.Box
	b.BoxID = id
	ble, err := b.GetFullDetails()
	if err != nil {
		apierror(w, r, "Error fetching Box: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	br := convertBoxListEntryinBoxResponse(ble)
	j, err := json.Marshal(&br)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func patchBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var b db100.Box
	err = decoder.Decode(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusBadRequest, ERROR_JSONERROR)
		return
	}
	b.BoxID = id
	err = b.Update()
	if err != nil {
		apierror(w, r, "Error updating Equipment: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	j, err := json.Marshal(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func deleteBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	b := db100.Box{BoxID: id}
	err = b.Delete()
	if err != nil {
		apierror(w, r, "Error deleting StoreItem: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
}

func getBoxItemsHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	var b db100.Box
	b.BoxID = id

	ile, err := b.GetBoxItemsJoined()
	if err != nil {
		apierror(w, r, "Error getting Box Items: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	ir := convertItemListinItemResponseList(ile)
	j, err := json.Marshal(&ir)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func addItemtoBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting Box ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	ii := vars["IID"]
	iid, err := strconv.Atoi(ii)
	if err != nil {
		apierror(w, r, "Error converting Item ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	it := db100.Item{ItemID: iid}
	err = it.SetBox(id)
	if err != nil {
		apierror(w, r, "Error updating Item: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
}

func removeItemfromBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	ii := vars["IID"]
	iid, err := strconv.Atoi(ii)
	if err != nil {
		apierror(w, r, "Error converting Item ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	it := db100.Item{ItemID: iid}
	err = it.SetBox(0)
	if err != nil {
		apierror(w, r, "Error updating Item: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
}
<commit_msg>Redoing the endpoints for item adding and removing<commit_after>package api100

import (
	"encoding/json"
	"net/http"
	"strconv"

	db100 "github.com/Chaosvermittlung/funkloch-server/db/v100"
	"github.com/carbocation/interpose"
	"github.com/gorilla/mux"
)

func getBoxRouter(prefix string) *interpose.Middleware {
	r, m := GetNewSubrouter(prefix)
	r.HandleFunc("/", postBoxHandler).Methods("POST")
	r.HandleFunc("/list", listBoxesHandler).Methods("GET")
	r.HandleFunc("/{ID}", getBoxHandler).Methods("GET")
	r.HandleFunc("/{ID}", patchBoxHandler).Methods("PATCH")
	r.HandleFunc("/{ID}", deleteBoxHandler).Methods("DELETE")
	r.HandleFunc("/{ID}/items", getBoxItemsHandler).Methods("GET")
	r.HandleFunc("/{ID}/items/{IID}", addItemtoBoxHandler).Methods("POST")
	r.HandleFunc("/{ID}/items/{IID}", removeItemfromBoxHandler).Methods("DELETE")
	return m
}

func convertBoxListEntryinBoxResponse(b db100.BoxlistEntry) boxResponse {
	var br boxResponse
	br.Box.BoxID = b.BoxID
	br.Box.Code = b.Code
	br.Box.Description = b.Description
	br.Store.StoreID = b.StoreID
	br.Store.Adress = b.Adress
	br.Store.ManagerID = b.ManagerID
	br.Store.Name = b.Name
	br.User.UserID = b.ManagerID
	br.User.Username = b.Username
	br.User.Email = b.Email
	br.User.Right = db100.UserRight(b.Right)
	return br
}

func convertBoxListinBoxResponseList(bb []db100.BoxlistEntry) []boxResponse {
	var res []boxResponse
	for _, b := range bb {
		br := convertBoxListEntryinBoxResponse(b)
		res = append(res, br)
	}
	return res
}

func postBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var b db100.Box
	err = decoder.Decode(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusBadRequest, ERROR_JSONERROR)
		return
	}
	err = b.Insert()
	if err != nil {
		apierror(w, r, "Error Inserting Box: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	j, err := json.Marshal(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func listBoxesHandler(w http.ResponseWriter, r *http.Request) {
	bb, err := db100.GetBoxesJoined()
	if err != nil {
		apierror(w, r, "Error fetching Boxes: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	res := convertBoxListinBoxResponseList(bb)
	j, err := json.Marshal(&res)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func getBoxHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	var b db100.Box
	b.BoxID = id
	ble, err := b.GetFullDetails()
	if err != nil {
		apierror(w, r, "Error fetching Box: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	br := convertBoxListEntryinBoxResponse(ble)
	j, err := json.Marshal(&br)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func patchBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var b db100.Box
	err = decoder.Decode(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusBadRequest, ERROR_JSONERROR)
		return
	}
	b.BoxID = id
	err = b.Update()
	if err != nil {
		apierror(w, r, "Error updating Equipment: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	j, err := json.Marshal(&b)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func deleteBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	b := db100.Box{BoxID: id}
	err = b.Delete()
	if err != nil {
		apierror(w, r, "Error deleting StoreItem: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
}

func getBoxItemsHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	var b db100.Box
	b.BoxID = id

	ile, err := b.GetBoxItemsJoined()
	if err != nil {
		apierror(w, r, "Error getting Box Items: "+err.Error(), http.StatusInternalServerError, ERROR_DBQUERYFAILED)
		return
	}
	ir := convertItemListinItemResponseList(ile)
	j, err := json.Marshal(&ir)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusInternalServerError, ERROR_JSONERROR)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

func addItemtoBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	i := vars["ID"]
	id, err := strconv.Atoi(i)
	if err != nil {
		apierror(w, r, "Error converting Box ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	ii := vars["IID"]
	iid, err := strconv.Atoi(ii)
	if err != nil {
		apierror(w, r, "Error converting Item ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	it := db100.Item{ItemID: iid}
	err = it.SetBox(id)
	if err != nil {
		apierror(w, r, "Error updating Item: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
}

func removeItemfromBoxHandler(w http.ResponseWriter, r *http.Request) {
	err := userhasrRight(r, db100.USERRIGHT_MEMBER)
	if err != nil {
		apierror(w, r, err.Error(), http.StatusUnauthorized, ERROR_USERNOTAUTHORIZED)
		return
	}
	vars := mux.Vars(r)
	ii := vars["IID"]
	iid, err := strconv.Atoi(ii)
	if err != nil {
		apierror(w, r, "Error converting Item ID: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
	it := db100.Item{ItemID: iid}
	err = it.SetBox(0)
	if err != nil {
		apierror(w, r, "Error updating Item: "+err.Error(), http.StatusBadRequest, ERROR_INVALIDPARAMETER)
		return
	}
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.647"
<commit_msg>fnserver: 0.3.648 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.648"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.601"
<commit_msg>fnserver: 0.3.602 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.602"
<|endoftext|>


<commit_before>package elogo

import (
	"math"
)

const (
	K = 32
	D = 400
)

// Elo calculates Elo rating changes based on the configured factors.
type Elo struct {
	K int
	D int
}

// Outcome is a match result data for a single player.
type Outcome struct {
	Delta int
	Rating int
}

// NewElo instantiates the Elo object with default factors.
// Default K-Factor is 32
// Default deviation is 400
func NewElo() *Elo {
	return &Elo{K, D}
}

// NewEloWithFactors instantiates the Elo object with custom factor values.
func NewEloWithFactors(k, d int) *Elo {
	return &Elo{k, d}
}

// ExpectedScore gives the expected chance that the first player wins
func (e *Elo) ExpectedScore(ratingA, ratingB int) float64 {
	return e.ExpectedScoreWithFactors(ratingA, ratingB, e.D)
}

// ExpectedScoreWithFactors overrides default factors and gives the expected chance that the first player wins
func (e *Elo) ExpectedScoreWithFactors(ratingA, ratingB, d int) float64 {
	return 1 / (1 + math.Pow(10, float64(ratingB - ratingA) / float64(d)))
}

// RatingDelta gives the ratings change for the first player for the given score
func (e *Elo) RatingDelta(ratingA, ratingB int, score float64) int {
	return e.RatingDeltaWithFactors(ratingA, ratingB, score, e.K, e.D)
}

// RatingDeltaWithFactors overrides default factors and gives the ratings change for the first player for the given score
func (e *Elo) RatingDeltaWithFactors(ratingA, ratingB int, score float64, k, d int ) int {
	return int(float64(k) * (score - e.ExpectedScoreWithFactors(ratingA, ratingB, d)))
}

// Rating gives the new rating for the first player for the given score
func (e *Elo) Rating(ratingA, ratingB int, score float64) int {
	return e.RatingWithFactors(ratingA, ratingB, score, e.K, e.D)
}
// RatingWithFactors overrides default factors and gives the new rating for the first player for the given score
func (e *Elo) RatingWithFactors(ratingA, ratingB int, score float64, k, d int ) int {
	return ratingA + e.RatingDeltaWithFactors(ratingA, ratingB, score, k, d)
}

// Outcome gives an Outcome object for each player for the given score
func (e *Elo) Outcome(ratingA, ratingB int, score float64) (Outcome, Outcome) {
	return e.OutcomeWithFactors(ratingA, ratingB, score, e.K, e.D)
}

// Outcome overrides default factors and gives an Outcome object for each player for the given score
func (e *Elo) OutcomeWithFactors(ratingA, ratingB int, score float64, k, d int ) (Outcome, Outcome) {
	delta := e.RatingDeltaWithFactors(ratingA, ratingB, score, k, d)
	return Outcome{ delta, ratingA + delta }, Outcome{ -delta, ratingB - delta }
}<commit_msg>Updated docs<commit_after>package elogo

import (
	"math"
)

const (
	// K is the default K-Factor
	K = 32
	// D is the default deviation
	D = 400
)

// Elo calculates Elo rating changes based on the configured factors.
type Elo struct {
	K int
	D int
}

// Outcome is a match result data for a single player.
type Outcome struct {
	Delta int
	Rating int
}

// NewElo instantiates the Elo object with default factors.
// Default K-Factor is 32
// Default deviation is 400
func NewElo() *Elo {
	return &Elo{K, D}
}

// NewEloWithFactors instantiates the Elo object with custom factor values.
func NewEloWithFactors(k, d int) *Elo {
	return &Elo{k, d}
}

// ExpectedScore gives the expected chance that the first player wins
func (e *Elo) ExpectedScore(ratingA, ratingB int) float64 {
	return e.ExpectedScoreWithFactors(ratingA, ratingB, e.D)
}

// ExpectedScoreWithFactors overrides default factors and gives the expected chance that the first player wins
func (e *Elo) ExpectedScoreWithFactors(ratingA, ratingB, d int) float64 {
	return 1 / (1 + math.Pow(10, float64(ratingB - ratingA) / float64(d)))
}

// RatingDelta gives the ratings change for the first player for the given score
func (e *Elo) RatingDelta(ratingA, ratingB int, score float64) int {
	return e.RatingDeltaWithFactors(ratingA, ratingB, score, e.K, e.D)
}

// RatingDeltaWithFactors overrides default factors and gives the ratings change for the first player for the given score
func (e *Elo) RatingDeltaWithFactors(ratingA, ratingB int, score float64, k, d int ) int {
	return int(float64(k) * (score - e.ExpectedScoreWithFactors(ratingA, ratingB, d)))
}

// Rating gives the new rating for the first player for the given score
func (e *Elo) Rating(ratingA, ratingB int, score float64) int {
	return e.RatingWithFactors(ratingA, ratingB, score, e.K, e.D)
}
// RatingWithFactors overrides default factors and gives the new rating for the first player for the given score
func (e *Elo) RatingWithFactors(ratingA, ratingB int, score float64, k, d int ) int {
	return ratingA + e.RatingDeltaWithFactors(ratingA, ratingB, score, k, d)
}

// Outcome gives an Outcome object for each player for the given score
func (e *Elo) Outcome(ratingA, ratingB int, score float64) (Outcome, Outcome) {
	return e.OutcomeWithFactors(ratingA, ratingB, score, e.K, e.D)
}

// OutcomeWithFactors overrides default factors and gives an Outcome object for each player for the given score
func (e *Elo) OutcomeWithFactors(ratingA, ratingB int, score float64, k, d int ) (Outcome, Outcome) {
	delta := e.RatingDeltaWithFactors(ratingA, ratingB, score, k, d)
	return Outcome{ delta, ratingA + delta }, Outcome{ -delta, ratingB - delta }
}<|endoftext|>


<commit_before><commit_msg>adding bitset benchmark<commit_after><|endoftext|>


<commit_before>// Copyright The OpenTelemetry Authors
//
// 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 (
	"context"
	"log"
	"net/http"

	"github.com/labstack/echo/v4"

	"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/stdout"
	"go.opentelemetry.io/otel/propagation"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	oteltrace "go.opentelemetry.io/otel/trace"
)

var tracer = otel.Tracer("gin-server")

func main() {
	initTracer()
	r := echo.New()
	r.Use(otelecho.Middleware("my-server"))

	r.GET("/users/:id", func(c echo.Context) error {
		id := c.Param("id")
		name := getUser(c.Request().Context(), id)
		return c.JSON(http.StatusOK, struct {
			ID   string
			Name string
		}{
			ID:   id,
			Name: name,
		})
	})
	_ = r.Start(":8080")
}

func initTracer() {
	exporter, err := stdout.NewExporter(stdout.WithPrettyPrint())
	if err != nil {
		log.Fatal(err)
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()),
		sdktrace.WithSyncer(exporter),
	)
	if err != nil {
		log.Fatal(err)
	}
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
}

func getUser(ctx context.Context, id string) string {
	_, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id)))
	defer span.End()
	if id == "123" {
		return "otelecho tester"
	}
	return "unknown"
}
<commit_msg>Update server.go (#590)<commit_after>// Copyright The OpenTelemetry Authors
//
// 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 (
	"context"
	"log"
	"net/http"

	"github.com/labstack/echo/v4"

	"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/stdout"
	"go.opentelemetry.io/otel/propagation"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	oteltrace "go.opentelemetry.io/otel/trace"
)

var tracer = otel.Tracer("gin-server")

func main() {
	initTracer()
	r := echo.New()
	r.Use(otelecho.Middleware("my-server"))

	r.GET("/users/:id", func(c echo.Context) error {
		id := c.Param("id")
		name := getUser(c.Request().Context(), id)
		return c.JSON(http.StatusOK, struct {
			ID   string
			Name string
		}{
			ID:   id,
			Name: name,
		})
	})
	_ = r.Start(":8080")
}

func initTracer() {
	exporter, err := stdout.NewExporter(stdout.WithPrettyPrint())
	if err != nil {
		log.Fatal(err)
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()),
		sdktrace.WithSyncer(exporter),
	)
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
}

func getUser(ctx context.Context, id string) string {
	_, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id)))
	defer span.End()
	if id == "123" {
		return "otelecho tester"
	}
	return "unknown"
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry Authors
//
// 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 (
	"context"
	"log"
	"net/http"

	"github.com/labstack/echo/v4"

	"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
	"go.opentelemetry.io/otel/propagation"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	oteltrace "go.opentelemetry.io/otel/trace"
)

var tracer = otel.Tracer("gin-server")

func main() {
	tp, err := initTracer()
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err := tp.Shutdown(context.Background()); err != nil {
			log.Printf("Error shutting down tracer provider: %v", err)
		}
	}()
	r := echo.New()
	r.Use(otelecho.Middleware("my-server"))

	r.GET("/users/:id", func(c echo.Context) error {
		id := c.Param("id")
		name := getUser(c.Request().Context(), id)
		return c.JSON(http.StatusOK, struct {
			ID   string
			Name string
		}{
			ID:   id,
			Name: name,
		})
	})
	_ = r.Start(":8080")
}

func initTracer() (*sdktrace.TracerProvider, error) {
	exporter, err := stdout.New(stdout.WithPrettyPrint())
	if err != nil {
		return nil, err
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()),
		sdktrace.WithBatcher(exporter),
	)
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	return tp, nil
}

func getUser(ctx context.Context, id string) string {
	_, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id)))
	defer span.End()
	if id == "123" {
		return "otelecho tester"
	}
	return "unknown"
}
<commit_msg>Rename tracer name to echo-server (#2853)<commit_after>// Copyright The OpenTelemetry Authors
//
// 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 (
	"context"
	"log"
	"net/http"

	"github.com/labstack/echo/v4"

	"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
	"go.opentelemetry.io/otel/propagation"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	oteltrace "go.opentelemetry.io/otel/trace"
)

var tracer = otel.Tracer("echo-server")

func main() {
	tp, err := initTracer()
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err := tp.Shutdown(context.Background()); err != nil {
			log.Printf("Error shutting down tracer provider: %v", err)
		}
	}()
	r := echo.New()
	r.Use(otelecho.Middleware("my-server"))

	r.GET("/users/:id", func(c echo.Context) error {
		id := c.Param("id")
		name := getUser(c.Request().Context(), id)
		return c.JSON(http.StatusOK, struct {
			ID   string
			Name string
		}{
			ID:   id,
			Name: name,
		})
	})
	_ = r.Start(":8080")
}

func initTracer() (*sdktrace.TracerProvider, error) {
	exporter, err := stdout.New(stdout.WithPrettyPrint())
	if err != nil {
		return nil, err
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()),
		sdktrace.WithBatcher(exporter),
	)
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	return tp, nil
}

func getUser(ctx context.Context, id string) string {
	_, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id)))
	defer span.End()
	if id == "123" {
		return "otelecho tester"
	}
	return "unknown"
}
<|endoftext|>