<commit_before>package sdl

/*
#include "sdl_wrapper.h"
*/
import "C"
import "unsafe"
import "reflect"

const (
	SWSURFACE = C.SDL_SWSURFACE
	PREALLOC  = C.SDL_PREALLOC
	RLEACCEL  = C.SDL_RLEACCEL
	DONTFREE  = C.SDL_DONTFREE
)

// Surface (https://wiki.libsdl.org/SDL_Surface)
type Surface struct {
	Flags    uint32
	Format   *PixelFormat
	W        int32
	H        int32
	Pitch    int32
	pixels   unsafe.Pointer // use Pixels() for access
	UserData unsafe.Pointer
	Locked   int32
	LockData unsafe.Pointer
	ClipRect Rect
	_        unsafe.Pointer // private c field 'map'
	RefCount int32
}
type cSurface C.SDL_Surface

func (surface *Surface) cptr() *C.SDL_Surface {
	return (*C.SDL_Surface)(unsafe.Pointer(surface))
}

// Surface (https://wiki.libsdl.org/SDL_MustLock)
func (surface *Surface) MustLock() bool {
	return (surface.Flags & RLEACCEL) != 0
}

// CreateRGBSurface (https://wiki.libsdl.org/SDL_CreateRGBSurface)
func CreateRGBSurface(flags uint32, width, height, depth int32, Rmask, Gmask, Bmask, Amask uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurface(C.Uint32(flags),
		C.int(width),
		C.int(height),
		C.int(depth),
		C.Uint32(Rmask),
		C.Uint32(Gmask),
		C.Uint32(Bmask),
		C.Uint32(Amask))))
}

// CreateRGBSurfaceFrom (https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom)
func CreateRGBSurfaceFrom(pixels unsafe.Pointer, width, height, depth, pitch int, Rmask, Gmask, Bmask, Amask uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurfaceFrom(pixels,
		C.int(width),
		C.int(height),
		C.int(depth),
		C.int(pitch),
		C.Uint32(Rmask),
		C.Uint32(Gmask),
		C.Uint32(Bmask),
		C.Uint32(Amask))))
}

// Surface (https://wiki.libsdl.org/SDL_FreeSurface)
func (surface *Surface) Free() {
	C.SDL_FreeSurface(surface.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfacePalette)
func (surface *Surface) SetPalette(palette *Palette) error {
	if C.SDL_SetSurfacePalette(surface.cptr(), palette.cptr()) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_LockSurface)
func (surface *Surface) Lock() {
	C.SDL_LockSurface(surface.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_UnlockSurface)
func (surface *Surface) Unlock() {
	C.SDL_UnlockSurface(surface.cptr())
}

// LoadBMP_RW (https://wiki.libsdl.org/SDL_LoadBMP_RW)
func LoadBMP_RW(src *RWops, freeSrc int) *Surface {
	_surface := C.SDL_LoadBMP_RW(src.cptr(), C.int(freeSrc))
	return (*Surface)(unsafe.Pointer(_surface))
}

// LoadBMP (https://wiki.libsdl.org/SDL_LoadBMP)
func LoadBMP(file string) *Surface {
	return (*Surface)(LoadBMP_RW(RWFromFile(file, "rb"), 1))
}

// Surface (https://wiki.libsdl.org/SDL_SaveBMP_RW)
func (surface *Surface) SaveBMP_RW(dst *RWops, freeDst int) error {
	if C.SDL_SaveBMP_RW(surface.cptr(), dst.cptr(), C.int(freeDst)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_SaveBMP)
func (surface *Surface) SaveBMP(file string) error {
	return surface.SaveBMP_RW(RWFromFile(file, "wb"), 1)
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceRLE)
func (surface *Surface) SetRLE(flag int) error {
	if C.SDL_SetSurfaceRLE(surface.cptr(), C.int(flag)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_SetColorKey)
func (surface *Surface) SetColorKey(flag int, key uint32) error {
	if C.SDL_SetColorKey(surface.cptr(), C.int(flag), C.Uint32(key)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetColorKey)
func (surface *Surface) GetColorKey() (key uint32, err error) {
	_key := (*C.Uint32)(unsafe.Pointer(&key))
	if C.SDL_GetColorKey(surface.cptr(), _key) != 0 {
		return key, GetError()
	}
	return key, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceColorMod)
func (surface *Surface) SetColorMod(r, g, b uint8) error {
	if C.SDL_SetSurfaceColorMod(surface.cptr(), C.Uint8(r), C.Uint8(g), C.Uint8(b)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceColorMod)
func (surface *Surface) GetColorMod() (r, g, b uint8, err error) {
	_r := (*C.Uint8)(unsafe.Pointer(&r))
	_g := (*C.Uint8)(unsafe.Pointer(&g))
	_b := (*C.Uint8)(unsafe.Pointer(&b))
	if C.SDL_GetSurfaceColorMod(surface.cptr(), _r, _g, _b) != 0 {
		return r, g, b, GetError()
	}
	return r, g, b, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceAlphaMod)
func (surface *Surface) SetAlphaMod(alpha uint8) error {
	if C.SDL_SetSurfaceAlphaMod(surface.cptr(), C.Uint8(alpha)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceAlphaMod)
func (surface *Surface) GetAlphaMod() (alpha uint8, err error) {
	_alpha := (*C.Uint8)(unsafe.Pointer(&alpha))
	if C.SDL_GetSurfaceAlphaMod(surface.cptr(), _alpha) != 0 {
		return alpha, GetError()
	}
	return alpha, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceBlendMode)
func (surface *Surface) SetBlendMode(bm BlendMode) int {
	return int(C.SDL_SetSurfaceBlendMode(surface.cptr(), bm.c()))
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceBlendMode)
func (surface *Surface) GetBlendMode() (bm BlendMode, status int) {
	status = int(C.SDL_GetSurfaceBlendMode(surface.cptr(), bm.cptr()))
	return bm, status
}

// Surface (https://wiki.libsdl.org/SDL_SetClipRect)
func (surface *Surface) SetClipRect(rect *Rect) bool {
	return C.SDL_SetClipRect(surface.cptr(), rect.cptr()) > 0
}

// Surface (https://wiki.libsdl.org/SDL_GetClipRect)
func (surface *Surface) GetClipRect(rect *Rect) {
	C.SDL_GetClipRect(surface.cptr(), rect.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_ConvertSurface)
func (surface *Surface) Convert(fmt *PixelFormat, flags uint32) *Surface {
	_surface := C.SDL_ConvertSurface(surface.cptr(), fmt.cptr(), C.Uint32(flags))
	return (*Surface)(unsafe.Pointer(_surface))
}

// Surface (https://wiki.libsdl.org/SDL_ConvertSurfaceFormat)
func (surface *Surface) ConvertFormat(pixelFormat uint32, flags uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_ConvertSurfaceFormat(surface.cptr(), C.Uint32(pixelFormat), C.Uint32(flags))))
}

// ConvertPixels (https://wiki.libsdl.org/SDL_ConvertPixels)
func ConvertPixels(width, height int, srcFormat uint32, src unsafe.Pointer, srcPitch int,
	dstFormat uint32, dst unsafe.Pointer, dstPitch int) int {
	return int(C.SDL_ConvertPixels(C.int(width), C.int(height), C.Uint32(srcFormat), src, C.int(srcPitch), C.Uint32(dstFormat), dst, C.int(dstPitch)))
}

// Surface (https://wiki.libsdl.org/SDL_FillRect)
func (surface *Surface) FillRect(rect *Rect, color uint32) error {
	if C.SDL_FillRect(surface.cptr(), rect.cptr(), C.Uint32(color)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_FillRects)
func (surface *Surface) FillRects(rects []Rect, color uint32) error {
	if C.SDL_FillRects(surface.cptr(), rects[0].cptr(), C.int(len(rects)), C.Uint32(color)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_BlitSurface)
func (src *Surface) Blit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_BlitSurface(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_BlitScaled)
func (src *Surface) BlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_BlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_UpperBlit)
func (src *Surface) UpperBlit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_UpperBlit(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_LowerBlit)
func (src *Surface) LowerBlit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_LowerBlit(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_SoftStretch)
func (src *Surface) SoftStretch(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_SoftStretch(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_UpperBlitScaled)
func (src *Surface) UpperBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_UpperBlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_LowerBlitScaled)
func (src *Surface) LowerBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_LowerBlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

func (surface *Surface) PixelNum() int {
	return int(surface.W * surface.H)
}

func (surface *Surface) BytesPerPixel() int {
	return int(surface.Format.BytesPerPixel)
}

func (surface *Surface) Pixels() []byte {
	var b []byte
	length := int(surface.W*surface.H) * int(surface.Format.BytesPerPixel)
	sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	sliceHeader.Cap = int(length)
	sliceHeader.Len = int(length)
	sliceHeader.Data = uintptr(surface.pixels)
	return b
}

func (surface *Surface) Data() unsafe.Pointer {
	return surface.pixels
}
<commit_msg>Make SetBlendMode idiomatic with respect to errors<commit_after>package sdl

/*
#include "sdl_wrapper.h"
*/
import "C"
import "unsafe"
import "reflect"

const (
	SWSURFACE = C.SDL_SWSURFACE
	PREALLOC  = C.SDL_PREALLOC
	RLEACCEL  = C.SDL_RLEACCEL
	DONTFREE  = C.SDL_DONTFREE
)

// Surface (https://wiki.libsdl.org/SDL_Surface)
type Surface struct {
	Flags    uint32
	Format   *PixelFormat
	W        int32
	H        int32
	Pitch    int32
	pixels   unsafe.Pointer // use Pixels() for access
	UserData unsafe.Pointer
	Locked   int32
	LockData unsafe.Pointer
	ClipRect Rect
	_        unsafe.Pointer // private c field 'map'
	RefCount int32
}
type cSurface C.SDL_Surface

func (surface *Surface) cptr() *C.SDL_Surface {
	return (*C.SDL_Surface)(unsafe.Pointer(surface))
}

// Surface (https://wiki.libsdl.org/SDL_MustLock)
func (surface *Surface) MustLock() bool {
	return (surface.Flags & RLEACCEL) != 0
}

// CreateRGBSurface (https://wiki.libsdl.org/SDL_CreateRGBSurface)
func CreateRGBSurface(flags uint32, width, height, depth int32, Rmask, Gmask, Bmask, Amask uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurface(C.Uint32(flags),
		C.int(width),
		C.int(height),
		C.int(depth),
		C.Uint32(Rmask),
		C.Uint32(Gmask),
		C.Uint32(Bmask),
		C.Uint32(Amask))))
}

// CreateRGBSurfaceFrom (https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom)
func CreateRGBSurfaceFrom(pixels unsafe.Pointer, width, height, depth, pitch int, Rmask, Gmask, Bmask, Amask uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurfaceFrom(pixels,
		C.int(width),
		C.int(height),
		C.int(depth),
		C.int(pitch),
		C.Uint32(Rmask),
		C.Uint32(Gmask),
		C.Uint32(Bmask),
		C.Uint32(Amask))))
}

// Surface (https://wiki.libsdl.org/SDL_FreeSurface)
func (surface *Surface) Free() {
	C.SDL_FreeSurface(surface.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfacePalette)
func (surface *Surface) SetPalette(palette *Palette) error {
	if C.SDL_SetSurfacePalette(surface.cptr(), palette.cptr()) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_LockSurface)
func (surface *Surface) Lock() {
	C.SDL_LockSurface(surface.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_UnlockSurface)
func (surface *Surface) Unlock() {
	C.SDL_UnlockSurface(surface.cptr())
}

// LoadBMP_RW (https://wiki.libsdl.org/SDL_LoadBMP_RW)
func LoadBMP_RW(src *RWops, freeSrc int) *Surface {
	_surface := C.SDL_LoadBMP_RW(src.cptr(), C.int(freeSrc))
	return (*Surface)(unsafe.Pointer(_surface))
}

// LoadBMP (https://wiki.libsdl.org/SDL_LoadBMP)
func LoadBMP(file string) *Surface {
	return (*Surface)(LoadBMP_RW(RWFromFile(file, "rb"), 1))
}

// Surface (https://wiki.libsdl.org/SDL_SaveBMP_RW)
func (surface *Surface) SaveBMP_RW(dst *RWops, freeDst int) error {
	if C.SDL_SaveBMP_RW(surface.cptr(), dst.cptr(), C.int(freeDst)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_SaveBMP)
func (surface *Surface) SaveBMP(file string) error {
	return surface.SaveBMP_RW(RWFromFile(file, "wb"), 1)
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceRLE)
func (surface *Surface) SetRLE(flag int) error {
	if C.SDL_SetSurfaceRLE(surface.cptr(), C.int(flag)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_SetColorKey)
func (surface *Surface) SetColorKey(flag int, key uint32) error {
	if C.SDL_SetColorKey(surface.cptr(), C.int(flag), C.Uint32(key)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetColorKey)
func (surface *Surface) GetColorKey() (key uint32, err error) {
	_key := (*C.Uint32)(unsafe.Pointer(&key))
	if C.SDL_GetColorKey(surface.cptr(), _key) != 0 {
		return key, GetError()
	}
	return key, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceColorMod)
func (surface *Surface) SetColorMod(r, g, b uint8) error {
	if C.SDL_SetSurfaceColorMod(surface.cptr(), C.Uint8(r), C.Uint8(g), C.Uint8(b)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceColorMod)
func (surface *Surface) GetColorMod() (r, g, b uint8, err error) {
	_r := (*C.Uint8)(unsafe.Pointer(&r))
	_g := (*C.Uint8)(unsafe.Pointer(&g))
	_b := (*C.Uint8)(unsafe.Pointer(&b))
	if C.SDL_GetSurfaceColorMod(surface.cptr(), _r, _g, _b) != 0 {
		return r, g, b, GetError()
	}
	return r, g, b, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceAlphaMod)
func (surface *Surface) SetAlphaMod(alpha uint8) error {
	if C.SDL_SetSurfaceAlphaMod(surface.cptr(), C.Uint8(alpha)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceAlphaMod)
func (surface *Surface) GetAlphaMod() (alpha uint8, err error) {
	_alpha := (*C.Uint8)(unsafe.Pointer(&alpha))
	if C.SDL_GetSurfaceAlphaMod(surface.cptr(), _alpha) != 0 {
		return alpha, GetError()
	}
	return alpha, nil
}

// Surface (https://wiki.libsdl.org/SDL_SetSurfaceBlendMode)
func (surface *Surface) SetBlendMode(bm BlendMode) error {
	if C.SDL_SetSurfaceBlendMode(surface.cptr(), bm.c()) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_GetSurfaceBlendMode)
func (surface *Surface) GetBlendMode() (bm BlendMode, status int) {
	status = int(C.SDL_GetSurfaceBlendMode(surface.cptr(), bm.cptr()))
	return bm, status
}

// Surface (https://wiki.libsdl.org/SDL_SetClipRect)
func (surface *Surface) SetClipRect(rect *Rect) bool {
	return C.SDL_SetClipRect(surface.cptr(), rect.cptr()) > 0
}

// Surface (https://wiki.libsdl.org/SDL_GetClipRect)
func (surface *Surface) GetClipRect(rect *Rect) {
	C.SDL_GetClipRect(surface.cptr(), rect.cptr())
}

// Surface (https://wiki.libsdl.org/SDL_ConvertSurface)
func (surface *Surface) Convert(fmt *PixelFormat, flags uint32) *Surface {
	_surface := C.SDL_ConvertSurface(surface.cptr(), fmt.cptr(), C.Uint32(flags))
	return (*Surface)(unsafe.Pointer(_surface))
}

// Surface (https://wiki.libsdl.org/SDL_ConvertSurfaceFormat)
func (surface *Surface) ConvertFormat(pixelFormat uint32, flags uint32) *Surface {
	return (*Surface)(unsafe.Pointer(C.SDL_ConvertSurfaceFormat(surface.cptr(), C.Uint32(pixelFormat), C.Uint32(flags))))
}

// ConvertPixels (https://wiki.libsdl.org/SDL_ConvertPixels)
func ConvertPixels(width, height int, srcFormat uint32, src unsafe.Pointer, srcPitch int,
	dstFormat uint32, dst unsafe.Pointer, dstPitch int) int {
	return int(C.SDL_ConvertPixels(C.int(width), C.int(height), C.Uint32(srcFormat), src, C.int(srcPitch), C.Uint32(dstFormat), dst, C.int(dstPitch)))
}

// Surface (https://wiki.libsdl.org/SDL_FillRect)
func (surface *Surface) FillRect(rect *Rect, color uint32) error {
	if C.SDL_FillRect(surface.cptr(), rect.cptr(), C.Uint32(color)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_FillRects)
func (surface *Surface) FillRects(rects []Rect, color uint32) error {
	if C.SDL_FillRects(surface.cptr(), rects[0].cptr(), C.int(len(rects)), C.Uint32(color)) != 0 {
		return GetError()
	}
	return nil
}

// Surface (https://wiki.libsdl.org/SDL_BlitSurface)
func (src *Surface) Blit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_BlitSurface(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_BlitScaled)
func (src *Surface) BlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_BlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_UpperBlit)
func (src *Surface) UpperBlit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_UpperBlit(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_LowerBlit)
func (src *Surface) LowerBlit(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_LowerBlit(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_SoftStretch)
func (src *Surface) SoftStretch(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_SoftStretch(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_UpperBlitScaled)
func (src *Surface) UpperBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_UpperBlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

// Surface (https://wiki.libsdl.org/SDL_LowerBlitScaled)
func (src *Surface) LowerBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) int {
	return int(C.SDL_LowerBlitScaled(src.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()))
}

func (surface *Surface) PixelNum() int {
	return int(surface.W * surface.H)
}

func (surface *Surface) BytesPerPixel() int {
	return int(surface.Format.BytesPerPixel)
}

func (surface *Surface) Pixels() []byte {
	var b []byte
	length := int(surface.W*surface.H) * int(surface.Format.BytesPerPixel)
	sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	sliceHeader.Cap = int(length)
	sliceHeader.Len = int(length)
	sliceHeader.Data = uintptr(surface.pixels)
	return b
}

func (surface *Surface) Data() unsafe.Pointer {
	return surface.pixels
}
<|endoftext|>


<commit_before>package gnuplot

import (
  "fmt"
  "strconv"
  "os"
)

type Plotter struct {
    configures map[string] string
}

func (p *Plotter) Init() {
    p.configures = map[string] string{}
}

func (p *Plotter) Configure(key, val string) {
    p.configures[key] = val
}

func (p *Plotter) GetC(key string) string {
    return p.configures[key]
}

var DefaultFunction2dSplitNum int = 1000
type Function2d struct {
    plotter Plotter
    splitNum int
    f func(float64) float64
}

func (fun *Function2d) Init(){
    fun.splitNum = DefaultFunction2dSplitNum
    fun.plotter.configures = map[string] string {
        "_xMin": "-10.0",
        "_xMax": "10.0"}
}

func (fun *Function2d) UpdatePlotter(plotter *Plotter) {
    for key, val := range plotter.configures {
        fun.plotter.configures[key] = val
    }
}

func (fun *Function2d) GetData() [][2]float64 { // TODO: テスト書く
    xMin, _ := strconv.ParseFloat(fun.plotter.configures["_xMin"], 32)
    xMax, _ := strconv.ParseFloat(fun.plotter.configures["_xMax"], 32)
    var sep = float64(xMax - xMin) / float64(fun.splitNum - 1)

    var a [][2]float64
    for j := 0; j < fun.splitNum; j++ {
        t := xMin + float64(j) * sep
        y := fun.f(t)
        a = append(a, [2]float64{t, y})
    }
    return a
}

func (fun *Function2d) getGnuData() string {
    var s string
    for _, xs := range fun.GetData() {
        s += fmt.Sprintf("%f %f\n", xs[0], xs[1])
    }
    return s
}

func (fun *Function2d) SetF(_f func(float64) float64) {
    fun.f = _f
}

func (fun *Function2d) writeIntoGnufile(f os.File) {
    f.WriteString(fun.getGnuData())
}

var DefaultCurve2dSplitNum int = 100
type Curve2d struct {
    plotter Plotter
    splitNum int
    c func(float64) [2]float64
}

func (c *Curve2d) Init(){
    c.splitNum = DefaultCurve2dSplitNum
    c.plotter.configures = map[string] string {
        "_tMin": "-10.0",
        "_tMax": "10.0"}
}

func (c *Curve2d) UpdatePlotter(plotter *Plotter) {
    for key, val := range plotter.configures {
        c.plotter.Configure(key, val)
    }
}

func (c *Curve2d) GetData() [][2]float64 { // TODO: test
    tMin, _ := strconv.ParseFloat(c.plotter.configures["_tMin"], 32)
    tMax, _ := strconv.ParseFloat(c.plotter.configures["_tMax"], 32)
    var sep = float64(tMax - tMin) / float64(c.splitNum - 1)

    var a [][2]float64
    for j := 0; j < c.splitNum; j++ {
        var t float64 = tMin + float64(j) * sep
        cs := c.c(tMin + t * float64(j))
        a = append(a, [2]float64{cs[0], cs[1]})
    }
    return a
}

// Graph
type Graph2d struct {
    plotter Plotter
    functions []Function2d
    curves []Curve2d
}

func (g *Graph2d) AppendFunc(f Function2d){
    g.functions = append(g.functions, f)
}

func (g *Graph2d)Run() {
    // それぞれのfunctionのdataをtempファイルに書き込む
    // また, それらのファイルの名前を func_filenames []string に格納する

    // それぞれのcurveのdataをtempファイルに書き込む
    // また, それらのファイルの名前を curve_filenames []stringに格納する

    // 実行するgnuplotの実行ファイルをtempファイルに書き込む
    // gnuplotのプログラムを実行する
}
<commit_msg>Graph.gnuplot() function<commit_after>package gnuplot

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	// "os/exec"
)

type Plotter struct {
	configures map[string]string
}

func (p *Plotter) Init() {
	p.configures = map[string]string{}
}

func (p *Plotter) Configure(key, val string) {
	p.configures[key] = val
}

func (p *Plotter) GetC(key string) string {
	return p.configures[key]
}

var DefaultFunction2dSplitNum int = 1000

type Function2d struct {
	plotter  Plotter
	splitNum int
	f        func(float64) float64
}

func (fun *Function2d) Init() {
	fun.splitNum = DefaultFunction2dSplitNum
	fun.plotter.configures = map[string]string{
		"_xMin": "-10.0",
		"_xMax": "10.0"}
}

func (fun *Function2d) UpdatePlotter(plotter *Plotter) {
	for key, val := range plotter.configures {
		fun.plotter.configures[key] = val
	}
}

func (fun *Function2d) GetData() [][2]float64 { // TODO: テスト書く
	xMin, _ := strconv.ParseFloat(fun.plotter.configures["_xMin"], 32)
	xMax, _ := strconv.ParseFloat(fun.plotter.configures["_xMax"], 32)
	var sep = float64(xMax-xMin) / float64(fun.splitNum-1)

	var a [][2]float64
	for j := 0; j < fun.splitNum; j++ {
		t := xMin + float64(j)*sep
		y := fun.f(t)
		a = append(a, [2]float64{t, y})
	}
	return a
}

func (fun *Function2d) getGnuData() string {
	var s string
	for _, xs := range fun.GetData() {
		s += fmt.Sprintf("%f %f\n", xs[0], xs[1])
	}
	return s
}

func (fun *Function2d) SetF(_f func(float64) float64) {
	fun.f = _f
}

func (fun *Function2d) writeIntoGnufile(f os.File) {
	f.WriteString(fun.getGnuData())
}

var DefaultCurve2dSplitNum int = 100

type Curve2d struct {
	plotter  Plotter
	splitNum int
	c        func(float64) [2]float64
}

func (c *Curve2d) Init() {
	c.splitNum = DefaultCurve2dSplitNum
	c.plotter.configures = map[string]string{
		"_tMin": "-10.0",
		"_tMax": "10.0"}
}

func (c *Curve2d) UpdatePlotter(plotter *Plotter) {
	for key, val := range plotter.configures {
		c.plotter.Configure(key, val)
	}
}

func (c *Curve2d) GetData() [][2]float64 { // TODO: test
	tMin, _ := strconv.ParseFloat(c.plotter.configures["_tMin"], 32)
	tMax, _ := strconv.ParseFloat(c.plotter.configures["_tMax"], 32)
	var sep = float64(tMax-tMin) / float64(c.splitNum-1)

	var a [][2]float64
	for j := 0; j < c.splitNum; j++ {
		var t float64 = tMin + float64(j)*sep
		cs := c.c(tMin + t*float64(j))
		a = append(a, [2]float64{cs[0], cs[1]})
	}
	return a
}

// Graph
type Graph2d struct {
	plotter   Plotter
	functions []Function2d
	curves    []Curve2d
}

func (g *Graph2d) AppendFunc(f Function2d) {
	fmt.Println("before of AppendFunc")
	g.functions = append(g.functions, f)
	fmt.Println("after of AppendFunc")
}

func (g Graph2d) writeIntoFile(data string, f *os.File) {
	f.WriteString(data)
}

func (g Graph2d) exec_gnuplot() {
	// until
}

func (g Graph2d) gnuplot(funcFilenames []string, curveFilenames []string) string {
	var s string
	for j, _ := range g.functions {
		s += fmt.Sprintf("plot %v\n;", funcFilenames[j])
	}
	s += "\n"
	for j, _ := range g.curves {
		s += fmt.Sprintf("plot %v\n;", curveFilenames[j])
	}
	s += "pause -1;"
	s += "\n"
	return s
}

func (g *Graph2d) Run() {
	tmpDir := os.TempDir()

	// それぞれのfunctionのdataをtempファイルに書き込む
	// また, それらのファイルの名前を func_filenames []string に格納する
	var funcFilenames []string
	for _, fun := range g.functions {
		file, _ := ioutil.TempFile(tmpDir, "")
		defer func() {
			file.Close()
		}()
		g.writeIntoFile(fun.getGnuData(), file)
		funcFilenames = append(funcFilenames, file.Name())
	}

	// それぞれのcurveのdataをtempファイルに書き込む
	// また, それらのファイルの名前を curve_filenames []stringに格納する

	// 実行するgnuplotの実行ファイルをtempファイルに書き込む
	exec_file, _ := os.OpenFile("exec_gnu.gnu", os.O_CREATE|os.O_WRONLY, 0666)
	defer func() {
		exec_file.Close()
	}()
	fmt.Println(funcFilenames)
	exec_file.WriteString(fmt.Sprintf("plot \"%v\" w l; pause -1;", funcFilenames[0]))
	exec_file.Close()
}
<|endoftext|>


<commit_before>package scanner_test

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/jmikkola/parsego/parser/scanner"
	"github.com/jmikkola/parsego/parser/textpos"
)

func assertReads(t *testing.T, sc scanner.ReadRune, c rune) {
	r, err := sc.Read()
	assert.NoError(t, err, "Expected successful read")
	assert.Equal(t, c, r, "Expected char")
}

func TestRBS(t *testing.T) {
	sc := scanner.RBSFromString("some text")
	assertReads(t, sc, 's')
	assertReads(t, sc, 'o')

	sc.StartBuffer()
	assert.Equal(t, 0, sc.BufSize())
	assertReads(t, sc, 'm')
	assertReads(t, sc, 'e')

	assert.Equal(t, 2, sc.BufSize())
	assert.Equal(t, 'm', sc.ReadBuffer(0))
	assert.Equal(t, 'e', sc.ReadBuffer(1))

	sc.DropBuffer()
	assert.Equal(t, 0, sc.BufSize())

	assertReads(t, sc, ' ')
	assertReads(t, sc, 't')
}

func TestSimpleRewind(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.RewindSnapshot()
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
}

func TestSimplePop(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.PopSnapshot()
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
	assert.Equal(t, textpos.Pos(0, 6), sc.GetPos())
}

func TestRecursiveSnapshots(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assert.Equal(t, textpos.Pos(0, 1), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assert.Equal(t, textpos.Pos(0, 3), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.RewindSnapshot()
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
	assertReads(t, sc, 'e')
	assert.Equal(t, textpos.Pos(0, 5), sc.GetPos())

	sc.RewindSnapshot()
	sc.RewindSnapshot()
	assert.Equal(t, textpos.Pos(0, 1), sc.GetPos())
	assertReads(t, sc, 'b')
}

func TestRepeatedRetry(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.PopSnapshot()

	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
}

func TestTwoSnapshotsInTheSamePlace(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
}

func TestStartingSnapshotWhileReplaying(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assertReads(t, sc, 'c')
	sc.StartSnapshot()
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
	sc.RewindSnapshot()
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
}
<commit_msg>failing tests<commit_after>package scanner_test

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/jmikkola/parsego/parser/scanner"
	"github.com/jmikkola/parsego/parser/textpos"
)

func assertReads(t *testing.T, sc scanner.ReadRune, c rune) {
	r, err := sc.Read()
	assert.NoError(t, err, "Expected successful read")
	assert.Equal(t, string(c), string(r), "Expected char")
}

func TestRBS(t *testing.T) {
	sc := scanner.RBSFromString("some text")
	assertReads(t, sc, 's')
	assertReads(t, sc, 'o')

	sc.StartBuffer()
	assert.Equal(t, 0, sc.BufSize())
	assertReads(t, sc, 'm')
	assertReads(t, sc, 'e')

	assert.Equal(t, 2, sc.BufSize())
	assert.Equal(t, 'm', sc.ReadBuffer(0))
	assert.Equal(t, 'e', sc.ReadBuffer(1))

	sc.DropBuffer()
	assert.Equal(t, 0, sc.BufSize())

	assertReads(t, sc, ' ')
	assertReads(t, sc, 't')
}

func TestSimpleRewind(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.RewindSnapshot()
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
}

func TestSimplePop(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.PopSnapshot()
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
	assert.Equal(t, textpos.Pos(0, 6), sc.GetPos())
}

func TestRecursiveSnapshots(t *testing.T) {
	sc := scanner.FromString("abcdefgh")

	assert.Equal(t, textpos.Pos(0, 0), sc.GetPos())
	assertReads(t, sc, 'a')
	assert.Equal(t, textpos.Pos(0, 1), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'b')
	assert.Equal(t, textpos.Pos(0, 2), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'c')
	assert.Equal(t, textpos.Pos(0, 3), sc.GetPos())

	sc.StartSnapshot()
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())

	sc.RewindSnapshot()
	assertReads(t, sc, 'd')
	assert.Equal(t, textpos.Pos(0, 4), sc.GetPos())
	assertReads(t, sc, 'e')
	assert.Equal(t, textpos.Pos(0, 5), sc.GetPos())

	sc.RewindSnapshot()
	sc.RewindSnapshot()
	assert.Equal(t, textpos.Pos(0, 1), sc.GetPos())
	assertReads(t, sc, 'b')
}

func TestRepeatedRetry(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.PopSnapshot()

	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
}

func TestTwoSnapshotsInTheSamePlace(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
}

func TestStartingSnapshotWhileReplaying(t *testing.T) {
	sc := scanner.FromString("abcdefgh")
	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assertReads(t, sc, 'c')
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	sc.RewindSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	assertReads(t, sc, 'c')
	sc.StartSnapshot()
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
	sc.RewindSnapshot()
	assertReads(t, sc, 'd')
	assertReads(t, sc, 'e')
	assertReads(t, sc, 'f')
}

func TestBug(t *testing.T) {
	sc := scanner.FromString("abcdefghi")

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()

	sc.StartSnapshot()
	assertReads(t, sc, 'a')
	sc.PopSnapshot()

	sc.StartSnapshot()
	sc.StartSnapshot()
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	sc.StartSnapshot()
	assertReads(t, sc, 'b')
	sc.RewindSnapshot()
	sc.StartSnapshot()
	assertReads(t, sc, 'b')
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2016 All Rights Reserved.

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

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

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

package ledgermgmt

import (
	"fmt"
	"testing"

	"os"

	"github.com/hyperledger/fabric/common/configtx/test"
	"github.com/hyperledger/fabric/common/ledger/testutil"
	"github.com/hyperledger/fabric/core/ledger"
	"github.com/spf13/viper"
)

func TestMain(m *testing.M) {
	viper.Set("peer.fileSystemPath", "/tmp/fabric/ledgertests/ledgermgmt")
	os.Exit(m.Run())
}

func TestLedgerMgmt(t *testing.T) {
	InitializeTestEnv()
	defer CleanupTestEnv()

	numLedgers := 10
	ledgers := make([]ledger.PeerLedger, 10)
	for i := 0; i < numLedgers; i++ {
		gb, _ := test.MakeGenesisBlock(constructTestLedgerID(i))
		l, _ := CreateLedger(gb)
		ledgers[i] = l
	}

	ledgerID := constructTestLedgerID(2)
	t.Logf("Ledger selected for test = %s", ledgerID)
	_, err := OpenLedger(ledgerID)
	testutil.AssertEquals(t, err, ErrLedgerAlreadyOpened)

	l := ledgers[2]
	l.Close()
	l, err = OpenLedger(ledgerID)
	testutil.AssertNoError(t, err, "")

	l, err = OpenLedger(ledgerID)
	testutil.AssertEquals(t, err, ErrLedgerAlreadyOpened)

	// close all opened ledgers and ledger mgmt
	Close()
	// Restart ledger mgmt with existing ledgers
	initialize()
	l, err = OpenLedger(ledgerID)
	testutil.AssertNoError(t, err, "")
	Close()
}

func constructTestLedgerID(i int) string {
	return fmt.Sprintf("ledger_%06d", i)
}
<commit_msg>[FAB-3412] Increase coverage for ledger/ledgermgmt<commit_after>/*
Copyright IBM Corp. 2016 All Rights Reserved.

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

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

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

package ledgermgmt

import (
	"fmt"
	"testing"

	"os"

	"github.com/hyperledger/fabric/common/configtx/test"
	"github.com/hyperledger/fabric/common/ledger/testutil"
	"github.com/hyperledger/fabric/core/ledger"
	"github.com/spf13/viper"
)

func TestMain(m *testing.M) {
	viper.Set("peer.fileSystemPath", "/tmp/fabric/ledgertests/ledgermgmt")
	os.Exit(m.Run())
}

func TestLedgerMgmt(t *testing.T) {
	// Check for error when creating/opening ledger without initialization.
	gb, _ := test.MakeGenesisBlock(constructTestLedgerID(0))
	l, err := CreateLedger(gb)
	testutil.AssertNil(t, l)
	testutil.AssertEquals(t, err, ErrLedgerMgmtNotInitialized)

	ledgerID := constructTestLedgerID(2)
	l, err = OpenLedger(ledgerID)
	testutil.AssertNil(t, l)
	testutil.AssertEquals(t, err, ErrLedgerMgmtNotInitialized)

	ids, err := GetLedgerIDs()
	testutil.AssertNil(t, ids)
	testutil.AssertEquals(t, err, ErrLedgerMgmtNotInitialized)

	Close()

	InitializeTestEnv()
	defer CleanupTestEnv()

	numLedgers := 10
	ledgers := make([]ledger.PeerLedger, numLedgers)
	for i := 0; i < numLedgers; i++ {
		gb, _ := test.MakeGenesisBlock(constructTestLedgerID(i))
		l, _ := CreateLedger(gb)
		ledgers[i] = l
	}

	ids, _ = GetLedgerIDs()
	testutil.AssertEquals(t, len(ids), numLedgers)
	for i := 0; i < numLedgers; i++ {
		testutil.AssertEquals(t, ids[i], constructTestLedgerID(i))
	}

	ledgerID = constructTestLedgerID(2)
	t.Logf("Ledger selected for test = %s", ledgerID)
	_, err = OpenLedger(ledgerID)
	testutil.AssertEquals(t, err, ErrLedgerAlreadyOpened)

	l = ledgers[2]
	l.Close()
	l, err = OpenLedger(ledgerID)
	testutil.AssertNoError(t, err, "")

	l, err = OpenLedger(ledgerID)
	testutil.AssertEquals(t, err, ErrLedgerAlreadyOpened)

	// close all opened ledgers and ledger mgmt
	Close()

	// Restart ledger mgmt with existing ledgers
	Initialize()
	l, err = OpenLedger(ledgerID)
	testutil.AssertNoError(t, err, "")
	Close()
}

func constructTestLedgerID(i int) string {
	return fmt.Sprintf("ledger_%06d", i)
}
<|endoftext|>


<commit_before>// Copyright 2016 Adam H. Leventhal. All rights reserved.
// Licensed under the Apache License, version 2.0:
// http://www.apache.org/licenses/LICENSE-2.0

package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	"os"
	"path"
	"reflect"
	"time"

	"github.com/zabawaba99/firego"

	"github.com/attic-labs/noms/go/spec"
	"github.com/attic-labs/noms/go/types"
)

const SEARCHLIMIT = 100
const HNWINDOW = 14 * 24 * 60 * 60 // 2 weeks is the hacker news limit for editing

type datum struct {
	index float64
	value types.Value
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s <dst>\n", path.Base(os.Args[0]))
	}

	var start int

	flag.IntVar(&start, "s", -1, "start time in seconds since the epoch")
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		return
	}

	ds, err := spec.GetDataset(flag.Arg(0))
	if err != nil {
		fmt.Printf("Could not parse dst-dataset: %s\n", err)
		return
	}
	defer ds.Database().Close()

	mm := ds.HeadValue().(types.Map)

	if start == -1 {
		// Find the last entry that has a time field.
		key, value := mm.Last()

		var time types.Value
		var ok bool

		for i := 0; true; i += 1 {
			time, ok = value.(types.Struct).MaybeGet("time")
			if ok {
				break
			}

			if i >= SEARCHLIMIT {
				panic("no valid entry")
			}

			key = types.Number(float64(key.(types.Number)) - float64(i))
			value, ok = mm.MaybeGet(key)
			if !ok {
				panic("non-contigous shenanigans")
			}
		}

		start = int(time.(types.Number)) - HNWINDOW
	}

	fmt.Println(start)

	// Find the starting key.

	startKey := mapFindKeyBefore(mm, start)
	fmt.Println(types.EncodedIndexValue(startKey))

	// Process from startKey to maxItem to get caught up.

	update := firego.New("https://hacker-news.firebaseio.com/v0/updates", nil)
	newUpdate := make(chan firego.Event, 1000)
	if err := update.Watch(newUpdate); err != nil {
		panic(err)
	}

	max := firego.New("https://hacker-news.firebaseio.com/v0/maxitem", nil)
	var maxItem float64
	if err := max.Value(&maxItem); err != nil {
		panic(err)
	}

	newIndex := make(chan float64, 100)

	specialIndices := []float64{
		363, // Please tell us what features you'd like in news.ycombinator
	}

	go func() {
		for _, index := range specialIndices {
			newIndex <- index
		}

		for index := float64(startKey); index < maxItem; index += 1.0 {
		sent:
			for {
				select {
				case newIndex <- index:
					break sent
				case event := <-newUpdate:
					items := event.Data.(map[string]interface{})["items"].([]interface{})
					for _, item := range items {
						if item.(float64) > maxItem {
							maxItem = item.(float64)
						}
					}

					fmt.Println("got a new update ", int(maxItem))
				}
			}
		}
		close(newIndex)
	}()

	newDatum := make(chan datum, 100)

	workerPool(100, func() {
		churn(newIndex, newDatum)
	}, func() {
		close(newDatum)
	})

	for datum := range newDatum {
		mm = mm.Set(types.Number(datum.index), datum.value)
		fmt.Printf("%d/%d\n", int(datum.index), int(maxItem))
		//fmt.Println(types.EncodedIndexValue(datum.value))
	}

	fmt.Println("caught up")

	newMap := make(chan types.Map, 1) // This must be size 1

	go func(mm types.Map) {
		for {
			mp := <-newMap
			if !mm.Equals(mp) {
				fmt.Println("committing")
				nds, err := ds.CommitValue(mp)
				if err != nil {
					panic(err)
				}
				ds = nds
				mm = mp
				fmt.Println("commit complete")
			} else {
				fmt.Println("no change")
			}
		}
	}(mm)

	// Enter the steady state now that we're caught up
	newIndex = make(chan float64, 1)
	newDatum = make(chan datum, 100)

	workerPool(1, func() {
		churn(newIndex, newDatum)
	}, func() {
		close(newDatum)
	})

	remaining := make(map[float64]bool)
	for event := range newUpdate {
		if event.Type == firego.EventTypeError {
			panic(event.Data)
		}

		items := event.Data.(map[string]interface{})["items"].([]interface{})
		for _, item := range items {
			newIndex <- item.(float64)
			remaining[item.(float64)] = true
		}

		fmt.Println("batch")
		for len(remaining) != 0 {
			datum := <-newDatum
			mm = mm.Set(types.Number(datum.index), datum.value)
			delete(remaining, datum.index)
			fmt.Println(int(datum.index))
		}

		// Poke our new map into the chan. If an old one is still in there, nudge it out and add our new one.
		select {
		case newMap <- mm:
		default:
			select {
			case _ = <-newMap:
			default:
			}
			newMap <- mm
		}
	}
}

func workerPool(count int, work func(), done func()) {
	workerDone := make(chan bool, 1)
	for i := 0; i < count; i += 1 {
		go func() {
			work()
			workerDone <- true
		}()
	}

	go func() {
		for i := 0; i < count; i += 1 {
			_ = <-workerDone
		}
		close(workerDone)
		done()
	}()
}

func mapFindFromKey(mm types.Map, value int) (types.Value, types.Value) {

	for i := 0; i < SEARCHLIMIT; i += 1 {
		midKey := types.Number(value - i)
		midVal, ok := mm.MaybeGet(midKey)
		if ok {
			_, ok = midVal.(types.Struct).MaybeGet("time")
			if ok {
				return midKey, midVal
			}
		}
	}

	panic("nothing found")
}

func mapFindKeyBefore(mm types.Map, time int) types.Number {
	minKey, _ := mm.First()
	maxKey, _ := mm.Last()

	for i := 0; i < SEARCHLIMIT; i += 1 {
		midIndex := int(minKey.(types.Number) + (maxKey.(types.Number)-minKey.(types.Number))/2)

		midKey, midVal := mapFindFromKey(mm, midIndex)

		if minKey == midKey {
			fmt.Println(types.EncodedIndexValue(midVal))
			return minKey.(types.Number)
		}

		midTime := midVal.(types.Struct).Get("time").(types.Number)

		if time < int(midTime) {
			maxKey = midKey
		} else {
			minKey = midKey
		}
	}

	panic("confusing")
}
func makeClient() *http.Client {
	var tr *http.Transport
	tr = &http.Transport{
		Dial: func(network, address string) (net.Conn, error) {
			return net.DialTimeout(network, address, 30*time.Second)
		},
		TLSHandshakeTimeout:   30 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
	}

	client := &http.Client{
		Transport: tr,
		Timeout:   time.Second * 30,
	}

	return client
}

func churn(newIndex <-chan float64, newData chan<- datum) {
	client := makeClient()

	for index := range newIndex {
		id := int(index)
		url := fmt.Sprintf("https://hacker-news.firebaseio.com/v0/item/%d", id)
		for attempts := 0; true; attempts += 1 {

			if attempts > 0 {
				// If we're having no luck after this much time, we'll declare this sucker the walking undead and try to get to it later.
				if attempts > 10 {
					fmt.Printf("Braaaaiiinnnssss %d\n", id)
					sendDatum(newData, "zombie", index, map[string]types.Value{
						"id":   types.Number(index),
						"type": types.String("zombie"),
					})
					break
				}
				if attempts == 5 {
					client = makeClient()
				}
				time.Sleep(time.Millisecond * 100 * time.Duration(attempts))
			}

			fb := firego.New(url, client)

			var val map[string]interface{}
			err := fb.Value(&val)
			if err != nil {
				fmt.Printf("failed for %d (%d times) %s\n", id, attempts, err)
				continue
			}

			data := make(map[string]types.Value)
			for k, v := range val {
				switch vv := v.(type) {
				case string:
					data[k] = types.String(vv)
				case float64:
					data[k] = types.Number(vv)
				case bool:
					data[k] = types.Bool(vv)
				case []interface{}:
					ll := types.NewList()
					for _, elem := range vv {
						ll = ll.Append(types.Number(elem.(float64)))
					}
					data[k] = ll
				default:
					panic(reflect.TypeOf(v))
				}
			}

			name, ok := val["type"]
			if !ok {
				fmt.Printf("no type for id %d; trying again\n", id)
				continue
			}

			if attempts > 1 {
				fmt.Printf("success for %d after %d attempts\n", id, attempts)
			}

			sendDatum(newData, name.(string), index, data)
			break
		}
	}
}

func sendDatum(newData chan<- datum, name string, id float64, data map[string]types.Value) {
	st := types.NewStruct(name, data)
	d := datum{
		index: id,
		value: st,
	}

	select {
	case newData <- d:
	default:
		fmt.Println("blocked")
		newData <- d
	}
}
<commit_msg>update<commit_after>// Copyright 2016 Adam H. Leventhal. All rights reserved.
// Licensed under the Apache License, version 2.0:
// http://www.apache.org/licenses/LICENSE-2.0

package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	"os"
	"path"
	"reflect"
	"time"

	"github.com/zabawaba99/firego"

	"github.com/attic-labs/noms/go/spec"
	"github.com/attic-labs/noms/go/types"
)

const SEARCHLIMIT = 100
const HNWINDOW = 14 * 24 * 60 * 60 // 2 weeks is the hacker news limit for editing

type datum struct {
	index float64
	value types.Value
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s <dst>\n", path.Base(os.Args[0]))
	}

	var start int

	flag.IntVar(&start, "s", -1, "start time in seconds since the epoch")
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		return
	}

	ds, err := spec.GetDataset(flag.Arg(0))
	if err != nil {
		fmt.Printf("Could not parse dst-dataset: %s\n", err)
		return
	}
	defer ds.Database().Close()

	mm := ds.HeadValue().(types.Map)

	if start == -1 {
		// Find the last entry that has a time field.
		key, value := mm.Last()

		var time types.Value
		var ok bool

		for i := 0; true; i += 1 {
			time, ok = value.(types.Struct).MaybeGet("time")
			if ok {
				break
			}

			if i >= SEARCHLIMIT {
				panic("no valid entry")
			}

			key = types.Number(float64(key.(types.Number)) - float64(i))
			value, ok = mm.MaybeGet(key)
			if !ok {
				panic("non-contigous shenanigans")
			}
		}

		start = int(time.(types.Number)) - HNWINDOW
	}

	fmt.Println(start)

	// Find the starting key.

	startKey := mapFindKeyBefore(mm, start)
	fmt.Println(types.EncodedIndexValue(startKey))

	// Process from startKey to maxItem to get caught up.

	update := firego.New("https://hacker-news.firebaseio.com/v0/updates", nil)
	newUpdate := make(chan firego.Event, 1000)
	if err := update.Watch(newUpdate); err != nil {
		panic(err)
	}

	max := firego.New("https://hacker-news.firebaseio.com/v0/maxitem", nil)
	var maxItem float64
	if err := max.Value(&maxItem); err != nil {
		panic(err)
	}

	newIndex := make(chan float64, 100)

	specialIndices := []float64{
		363, // Please tell us what features you'd like in news.ycombinator
	}

	go func() {
		for _, index := range specialIndices {
			newIndex <- index
		}

		for index := float64(startKey); index < maxItem; index += 1.0 {
		sent:
			for {
				select {
				case newIndex <- index:
					break sent
				case event := <-newUpdate:
					items := event.Data.(map[string]interface{})["items"].([]interface{})
					for _, item := range items {
						if item.(float64) > maxItem {
							maxItem = item.(float64)
						}
					}

					fmt.Println("got a new update ", int(maxItem))
				}
			}
		}
		close(newIndex)
	}()

	newDatum := make(chan datum, 100)

	workerPool(100, func() {
		churn(newIndex, newDatum)
	}, func() {
		close(newDatum)
	})

	for datum := range newDatum {
		mm = mm.Set(types.Number(datum.index), datum.value)
		fmt.Printf("%d/%d\n", int(datum.index), int(maxItem))
		//fmt.Println(types.EncodedIndexValue(datum.value))
	}

	fmt.Println("caught up")

	newMap := make(chan types.Map, 1) // This must be size 1

	go func() {
		mm := ds.HeadValue().(types.Map)
		for {
			mp := <-newMap
			if !mm.Equals(mp) {
				fmt.Println("committing")
				nds, err := ds.CommitValue(mp)
				if err != nil {
					panic(err)
				}
				ds = nds
				mm = mp
				fmt.Println("commit complete")
			} else {
				fmt.Println("no change")
			}
		}
	}()

	newMap <- mm

	// Enter the steady state now that we're caught up
	newIndex = make(chan float64, 1)
	newDatum = make(chan datum, 100)

	workerPool(1, func() {
		churn(newIndex, newDatum)
	}, func() {
		close(newDatum)
	})

	remaining := make(map[float64]bool)
	for event := range newUpdate {
		if event.Type == firego.EventTypeError {
			panic(event.Data)
		}

		items := event.Data.(map[string]interface{})["items"].([]interface{})
		for _, item := range items {
			newIndex <- item.(float64)
			remaining[item.(float64)] = true
		}

		fmt.Println("batch")
		for len(remaining) != 0 {
			datum := <-newDatum
			nmm := mm.Set(types.Number(datum.index), datum.value)
			if mm.Equals(nmm) {
				fmt.Println(int(datum.index), " no change")
			} else {
				fmt.Println(int(datum.index))
				mm = nmm
			}

			delete(remaining, datum.index)
		}

		// Poke our new map into the chan. If an old one is still in there, nudge it out and add our new one.
		select {
		case newMap <- mm:
		default:
			select {
			case _ = <-newMap:
			default:
			}
			newMap <- mm
		}
	}
}

func workerPool(count int, work func(), done func()) {
	workerDone := make(chan bool, 1)
	for i := 0; i < count; i += 1 {
		go func() {
			work()
			workerDone <- true
		}()
	}

	go func() {
		for i := 0; i < count; i += 1 {
			_ = <-workerDone
		}
		close(workerDone)
		done()
	}()
}

func mapFindFromKey(mm types.Map, value int) (types.Value, types.Value) {

	for i := 0; i < SEARCHLIMIT; i += 1 {
		midKey := types.Number(value - i)
		midVal, ok := mm.MaybeGet(midKey)
		if ok {
			_, ok = midVal.(types.Struct).MaybeGet("time")
			if ok {
				return midKey, midVal
			}
		}
	}

	panic("nothing found")
}

func mapFindKeyBefore(mm types.Map, time int) types.Number {
	minKey, _ := mm.First()
	maxKey, _ := mm.Last()

	for i := 0; i < SEARCHLIMIT; i += 1 {
		midIndex := int(minKey.(types.Number) + (maxKey.(types.Number)-minKey.(types.Number))/2)

		midKey, midVal := mapFindFromKey(mm, midIndex)

		if minKey == midKey {
			fmt.Println(types.EncodedIndexValue(midVal))
			return minKey.(types.Number)
		}

		midTime := midVal.(types.Struct).Get("time").(types.Number)

		if time < int(midTime) {
			maxKey = midKey
		} else {
			minKey = midKey
		}
	}

	panic("confusing")
}
func makeClient() *http.Client {
	var tr *http.Transport
	tr = &http.Transport{
		Dial: func(network, address string) (net.Conn, error) {
			return net.DialTimeout(network, address, 30*time.Second)
		},
		TLSHandshakeTimeout:   30 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
	}

	client := &http.Client{
		Transport: tr,
		Timeout:   time.Second * 30,
	}

	return client
}

func churn(newIndex <-chan float64, newData chan<- datum) {
	client := makeClient()

	for index := range newIndex {
		id := int(index)
		url := fmt.Sprintf("https://hacker-news.firebaseio.com/v0/item/%d", id)
		for attempts := 0; true; attempts += 1 {

			if attempts > 0 {
				// If we're having no luck after this much time, we'll declare this sucker the walking undead and try to get to it later.
				if attempts > 10 {
					fmt.Printf("Braaaaiiinnnssss %d\n", id)
					sendDatum(newData, "zombie", index, map[string]types.Value{
						"id":   types.Number(index),
						"type": types.String("zombie"),
					})
					break
				}
				if attempts == 5 {
					client = makeClient()
				}
				time.Sleep(time.Millisecond * 100 * time.Duration(attempts))
			}

			fb := firego.New(url, client)

			var val map[string]interface{}
			err := fb.Value(&val)
			if err != nil {
				fmt.Printf("failed for %d (%d times) %s\n", id, attempts, err)
				continue
			}

			data := make(map[string]types.Value)
			for k, v := range val {
				switch vv := v.(type) {
				case string:
					data[k] = types.String(vv)
				case float64:
					data[k] = types.Number(vv)
				case bool:
					data[k] = types.Bool(vv)
				case []interface{}:
					ll := types.NewList()
					for _, elem := range vv {
						ll = ll.Append(types.Number(elem.(float64)))
					}
					data[k] = ll
				default:
					panic(reflect.TypeOf(v))
				}
			}

			name, ok := val["type"]
			if !ok {
				fmt.Printf("no type for id %d; trying again\n", id)
				continue
			}

			if attempts > 1 {
				fmt.Printf("success for %d after %d attempts\n", id, attempts)
			}

			sendDatum(newData, name.(string), index, data)
			break
		}
	}
}

func sendDatum(newData chan<- datum, name string, id float64, data map[string]types.Value) {
	st := types.NewStruct(name, data)
	d := datum{
		index: id,
		value: st,
	}

	select {
	case newData <- d:
	default:
		fmt.Println("blocked")
		newData <- d
	}
}
<|endoftext|>


<commit_before>package main

import(
	"flag"
	"fmt"
	"strings"
	"os"
	"io/ioutil"
	"time"
	"os/signal"
	"net/http"
	"math/rand"
	"net"
	"strconv"
	"sync"
	"github.com/fatih/color"
	"golang.org/x/net/html"
	"io"
	"net/url"
	"path/filepath"
)

type acceptedStatus []int

func (i *acceptedStatus) String() string {
	return fmt.Sprintf("%d", *i)
}

func (i *acceptedStatus) Set(value string) error {
	tmp, err := strconv.Atoi(value)
	if err != nil {
		*i = append(*i, -1)
	} else {
		*i = append(*i, tmp)
	}
	return nil
}

type CrawlerArguments struct {
	crawl_url string
	crawl_entries []string
	max_depth int
	concurrency int
	max_concurrency int
	valid_codes acceptedStatus
	enable_scraper bool
	proxy string
}

type CrawlerStatus struct {
	total_requests int
	request_per_second int
	total_ok int
	total_redirect int
	pages map[string]int
}

var status = CrawlerStatus{pages: make(map[string]int)}

func main() {

	var netTransport = &http.Transport{
		MaxIdleConnsPerHost: 50,
		Dial: (&net.Dialer{
			Timeout: 5 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	}

	var(
		crawl_url = flag.String("url","", "Specify the url to crawl")
		crawl_file = flag.String("wordlist", "", "Specify the wordlist used to crawl, if no specified the built-in one will be used")
		depth = flag.Int("depth", 5, "Specify the maximum recursion depth")
		concurrent = flag.Int("concurrency", 50, "Specify the concurrency connection at a time, a number between 10 and 900")
		scraper = flag.Bool("scraper", false, "Specify whenever to enable scraper engine")
		proxy_setting = flag.String("proxy", "", "Specify HTTP proxy URL")
	)
	var acceptedCodes acceptedStatus
	flag.Var(&acceptedCodes, "c", "A list of HTTP status considered as 'page found' ie: 200,302,304,401")

	flag.Parse()

	if flag.NFlag() == 0 {
		flag.PrintDefaults()
		os.Exit(0)
	}

	_, err := url.ParseRequestURI(*crawl_url)
	if err != nil {
		showError(fmt.Sprintf("Please use a valid URL ( %v )", err))
		os.Exit(-1)
	}

	if len(*proxy_setting) > 0 {
		proxy_url, err := url.ParseRequestURI(*proxy_setting)

		if err != nil {
			showError(fmt.Sprintf("Please use a valid Proxy URL ( %v )", err))
			os.Exit(-1)
		}
		netTransport.Proxy = http.ProxyURL(proxy_url)
	}

	var netClient = &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Timeout: time.Second * 5,
		Transport: netTransport,
	}

	if len(acceptedCodes) == 0 {
		showError("You must declare at least one valid status code")
		os.Exit(-1)
	}

	data, err := ioutil.ReadFile(*crawl_file)

	if err != nil{
		showError(fmt.Sprintf("Unable to open wordlist ( %v )", err))
		os.Exit(-1)
	}

	if *concurrent > 900 || *concurrent < 10 {
		showError("Error: Please set a concurrency value between 10 - 900")
		os.Exit(-1)
	}

	arguments := CrawlerArguments{crawl_url: *crawl_url, crawl_entries: strings.Split(string(data), "\n"),
		max_depth: *depth, concurrency:0, max_concurrency: *concurrent, valid_codes: acceptedCodes,
		enable_scraper: *scraper}

	if len(arguments.crawl_url) > 0 {
		go UpdateStats(&status, arguments)

		var wg sync.WaitGroup

		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		go func(){
			for sig := range c {
				if sig.String() == "interrupt" {
					showInfo(fmt.Sprintf("Total Requests: %v , Request per sec: %v, HTTP OK: %v , HTTP Redirect: %v",
						status.total_requests, status.request_per_second, status.total_ok, status.total_redirect))
					os.Exit(0)
				}
			}
		}()

		showInfo(fmt.Sprintf("Starting crawling (%v)", arguments.crawl_url))

		Crawl(&wg, arguments, 1, netClient)

	}else{
		showError("Error: you must insert a URL to crawl, use -h to check commandline options")
		os.Exit(-1)
	}

	showInfo(fmt.Sprintf("[Stats] Total Requests: %v , Request per sec: %v, HTTP OK: %v , HTTP Redirect: %v",
		status.total_requests, status.request_per_second, status.total_ok, status.total_redirect))
}

func showError(msg string) {
	HiRed := color.New(color.FgRed, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s\n", HiRed("Error"), msg)
}

func showInfo(msg string) {
	HiRed := color.New(color.FgGreen, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s\n", HiRed("INFO"), msg)
}

func showURL(url string, code string, tool string) {
	HiBlue := color.New(color.FgHiBlue, color.Bold).SprintfFunc()
	HiMagenta := color.New(color.FgHiMagenta, color.Bold).SprintfFunc()
	HiYellow := color.New(color.FgHiYellow, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s %s %s\n", HiBlue(tool), HiMagenta(url) , "=>" , HiYellow(code))
}

func contains(s []int, e int) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func UpdateStats(status *CrawlerStatus, args CrawlerArguments){
	prev_total_requests := 0
	for {
		time.Sleep(time.Second * 1)
		if prev_total_requests > 0 {
			if status.request_per_second == 0 {
				status.request_per_second = status.total_requests - prev_total_requests
				prev_total_requests = status.total_requests
			}else{
				status.request_per_second = (status.request_per_second + (status.total_requests - prev_total_requests))/2
				prev_total_requests = status.total_requests
			}
		}else{
			prev_total_requests = status.total_requests
		}

		status.total_ok = 0
		status.total_redirect = 0

		for _ , code  := range status.pages{
			if contains(args.valid_codes, code) {
				status.total_ok++
			}

			if code == 302 || code == 304{
				status.total_redirect++
			}
		}
	}
}

func ShouldGet(min, max int) bool {
	rand.Seed(time.Now().UnixNano())
	i := rand.Intn(max - min) + min
	return i > 0
}

func getTagInfo(token html.Token, base_url string) []string {
	url_info, _ := url.Parse(base_url)
	host  := url_info.Host
	var attributes_val []string
	for _, attr := range token.Attr {
		if attr.Key == "href" {
			val, err := url.ParseRequestURI(attr.Val)
			if err != nil {
				if attr.Val != "#" {
					attributes_val = append(attributes_val, base_url+"/"+filepath.Dir(attr.Val))
				}
			}else{
				if host == val.Host {
					path := filepath.Dir(val.Path)
					if len(path) > 1 {
						attributes_val = append(attributes_val, url_info.Scheme+"://"+val.Host+path)
					}
				}
			}
		}

		if attr.Key == "src" {
			val, err := url.ParseRequestURI(attr.Val)
			if err != nil {
				if attr.Val != "#" {
					attributes_val = append(attributes_val, base_url+"/"+filepath.Dir(attr.Val))
				}
			}else{
				if host == val.Host {
					path := filepath.Dir(val.Path)
					if len(path) > 1 {
						attributes_val = append(attributes_val, url_info.Scheme+"://"+val.Host+path)
					}
				}
			}
		}
	}
	return attributes_val
}

func s_contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ScrapePage(in io.ReadCloser, res *map[string]string, url string) {
	valid_tags := []string{"audio", "embed", "iframe", "img", "input", "script", "source", "track",
		"video", "a", "area", "base","link"}

	parser := html.NewTokenizer(in)
	for {
		next := parser.Next()

		switch {
		case next == html.ErrorToken:
			return
		case next == html.StartTagToken:
			token := parser.Token()
			if s_contains(valid_tags, token.Data) {
				for _, v := range getTagInfo(token, url){
					if len((*res)[v]) == 0 {
						showURL(v, "200", "SCRAPER")
						(*res)[v] = "200"
					}
				}
			}
		}
	}
}

func Request(wg *sync.WaitGroup,ch chan map[string]string , args CrawlerArguments, dir string, status *CrawlerStatus, client *http.Client) {
	tmp_url := args.crawl_url + "/" + dir
	var err error
	var response *http.Response
	var done bool = false
	for !done {
		if args.enable_scraper {
			response, err = client.Get(tmp_url)
		}else{
			if ShouldGet(0, 2) {
				response, err = client.Get(tmp_url)
			} else {
				response, err = client.Head(tmp_url)
			}
		}
		result := make(map[string]string)
		if err == nil {
			defer response.Body.Close()
			status.total_requests ++
			if !contains(args.valid_codes, response.StatusCode) {
				result[tmp_url] = ""
			} else {
				if args.enable_scraper {
					ScrapePage(response.Body, &result, tmp_url)
				}
				result[tmp_url] = strconv.Itoa(response.StatusCode)
				showURL(tmp_url, strconv.Itoa(response.StatusCode), "BUSTER")
			}
			wg.Done()
			ch <- result
			done = true
		} else {
			time.Sleep(time.Millisecond * 100)
		}
	}
}

func Dispose(args CrawlerArguments, ch chan map[string]string) []string {
	var todo []string
	for i:=0;i<args.max_concurrency;i++ {
		select {
		case res := <-ch:
			for new_url := range res {
				if len(res[new_url]) > 0 {
					todo = append(todo, new_url)
					val, _ := strconv.Atoi(res[new_url])
					status.pages[new_url] = val
				}
			}
		default:
		}
	}
	return todo
}

func Crawl(wg *sync.WaitGroup, args CrawlerArguments, depth int, client *http.Client) {
	var next_round [] string
	if depth <= args.max_depth {
		channel := make(chan map[string]string)
		for _, dir := range args.crawl_entries {
			if len(dir) > 0 {
				wg.Add(1)
				go Request(wg, channel, args, dir, &status, client)
				args.concurrency++
				if args.concurrency > args.max_concurrency {
					wg.Wait()
					next_round = append(next_round, Dispose(args, channel)...)
					args.concurrency = 0
				}
			}
		}

		if args.concurrency < args.max_concurrency {
			wg.Wait()
			next_round = append(next_round, Dispose(args, channel)...)
			args.concurrency = 0
		}

		for _, v := range next_round {
			args.crawl_url = v
			args.concurrency = 0
			Crawl(wg, args, depth+1, client)
		}
	}
}
<commit_msg>Added cookie support for authenticated directory<commit_after>package main

import(
	"flag"
	"fmt"
	"strings"
	"os"
	"io/ioutil"
	"time"
	"os/signal"
	"net/http"
	"math/rand"
	"net"
	"strconv"
	"sync"
	"github.com/fatih/color"
	"golang.org/x/net/html"
	"io"
	"net/url"
	"path/filepath"
)

type acceptedStatus []int

func (i *acceptedStatus) String() string {
	return fmt.Sprintf("%d", *i)
}

func (i *acceptedStatus) Set(value string) error {
	tmp, err := strconv.Atoi(value)
	if err != nil {
		*i = append(*i, -1)
	} else {
		*i = append(*i, tmp)
	}
	return nil
}

type neededCookies map[string]string

func (c *neededCookies) String() string {
	return fmt.Sprintf("%v", *c)
}

func (c *neededCookies) Set(value string) error {
	name_val := strings.Split(value, "=")
	if len(name_val) > 1 {
		(*c)[name_val[0]] = name_val[1]
	}
	return nil
}

type CrawlerArguments struct {
	crawl_url string
	crawl_entries []string
	max_depth int
	concurrency int
	max_concurrency int
	valid_codes acceptedStatus
	enable_scraper bool
	proxy string
	needed_cookies []http.Cookie
}

type CrawlerStatus struct {
	total_requests int
	request_per_second int
	total_ok int
	total_redirect int
	pages map[string]int
}

var status = CrawlerStatus{pages: make(map[string]int)}

func main() {

	var netTransport = &http.Transport{
		MaxIdleConnsPerHost: 50,
		Dial: (&net.Dialer{
			Timeout: 5 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	}

	var(
		crawl_url = flag.String("url","", "Specify the url to crawl")
		crawl_file = flag.String("wordlist", "", "Specify the wordlist used to crawl, if no specified the built-in one will be used")
		depth = flag.Int("depth", 5, "Specify the maximum recursion depth")
		concurrent = flag.Int("concurrency", 50, "Specify the concurrency connection at a time, a number between 10 and 900")
		scraper = flag.Bool("scraper", false, "Specify whenever to enable scraper engine")
		proxy_setting = flag.String("proxy", "", "Specify HTTP proxy URL")
	)
	var acceptedCodes acceptedStatus
	var cookies neededCookies = make(map[string]string)
	flag.Var(&acceptedCodes, "c", "A list of HTTP status considered as 'page found' ie: 200,302,304,401")
	flag.Var(&cookies, "cookie", "A list of Cookie used by application, format: name=value")

	flag.Parse()

	if flag.NFlag() == 0 {
		flag.PrintDefaults()
		os.Exit(0)
	}

	_, err := url.ParseRequestURI(*crawl_url)
	if err != nil {
		showError(fmt.Sprintf("Please use a valid URL ( %v )", err))
		os.Exit(-1)
	}

	if len(*proxy_setting) > 0 {
		proxy_url, err := url.ParseRequestURI(*proxy_setting)

		if err != nil {
			showError(fmt.Sprintf("Please use a valid Proxy URL ( %v )", err))
			os.Exit(-1)
		}
		netTransport.Proxy = http.ProxyURL(proxy_url)
	}

	var netClient = &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Timeout: time.Second * 5,
		Transport: netTransport,
	}

	if len(acceptedCodes) == 0 {
		showError("You must declare at least one valid status code")
		os.Exit(-1)
	}

	data, err := ioutil.ReadFile(*crawl_file)

	if err != nil{
		showError(fmt.Sprintf("Unable to open wordlist ( %v )", err))
		os.Exit(-1)
	}

	if *concurrent > 900 || *concurrent < 10 {
		showError("Error: Please set a concurrency value between 10 - 900")
		os.Exit(-1)
	}
	var  app_cookies []http.Cookie

	for key, val := range cookies {
		app_cookies = append(app_cookies, http.Cookie{Name: key, Value: val})
	}

	arguments := CrawlerArguments{crawl_url: *crawl_url, crawl_entries: strings.Split(string(data), "\n"),
		max_depth: *depth, concurrency:0, max_concurrency: *concurrent, valid_codes: acceptedCodes,
		enable_scraper: *scraper, needed_cookies: app_cookies}

	if len(arguments.crawl_url) > 0 {
		go UpdateStats(&status, arguments)

		var wg sync.WaitGroup

		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		go func(){
			for sig := range c {
				if sig.String() == "interrupt" {
					showInfo(fmt.Sprintf("Total Requests: %v , Request per sec: %v, HTTP OK: %v , HTTP Redirect: %v",
						status.total_requests, status.request_per_second, status.total_ok, status.total_redirect))
					os.Exit(0)
				}
			}
		}()

		showInfo(fmt.Sprintf("Starting crawling (%v)", arguments.crawl_url))

		Crawl(&wg, arguments, 1, netClient)

	}else{
		showError("Error: you must insert a URL to crawl, use -h to check commandline options")
		os.Exit(-1)
	}

	showInfo(fmt.Sprintf("[Stats] Total Requests: %v , Request per sec: %v, HTTP OK: %v , HTTP Redirect: %v",
		status.total_requests, status.request_per_second, status.total_ok, status.total_redirect))
}

func showError(msg string) {
	HiRed := color.New(color.FgRed, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s\n", HiRed("Error"), msg)
}

func showInfo(msg string) {
	HiRed := color.New(color.FgGreen, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s\n", HiRed("INFO"), msg)
}

func showURL(url string, code string, tool string) {
	HiBlue := color.New(color.FgHiBlue, color.Bold).SprintfFunc()
	HiMagenta := color.New(color.FgHiMagenta, color.Bold).SprintfFunc()
	HiYellow := color.New(color.FgHiYellow, color.Bold).SprintfFunc()
	fmt.Printf("[%s]: %s %s %s\n", HiBlue(tool), HiMagenta(url) , "=>" , HiYellow(code))
}

func contains(s []int, e int) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func UpdateStats(status *CrawlerStatus, args CrawlerArguments){
	prev_total_requests := 0
	for {
		time.Sleep(time.Second * 1)
		if prev_total_requests > 0 {
			if status.request_per_second == 0 {
				status.request_per_second = status.total_requests - prev_total_requests
				prev_total_requests = status.total_requests
			}else{
				status.request_per_second = (status.request_per_second + (status.total_requests - prev_total_requests))/2
				prev_total_requests = status.total_requests
			}
		}else{
			prev_total_requests = status.total_requests
		}

		status.total_ok = 0
		status.total_redirect = 0

		for _ , code  := range status.pages{
			if contains(args.valid_codes, code) {
				status.total_ok++
			}

			if code == 302 || code == 304{
				status.total_redirect++
			}
		}
	}
}

func ShouldGet(min, max int) bool {
	rand.Seed(time.Now().UnixNano())
	i := rand.Intn(max - min) + min
	return i > 0
}

func getTagInfo(token html.Token, base_url string) []string {
	url_info, _ := url.Parse(base_url)
	host  := url_info.Host
	var attributes_val []string
	for _, attr := range token.Attr {
		if attr.Key == "href" {
			val, err := url.ParseRequestURI(attr.Val)
			if err != nil {
				if attr.Val != "#" {
					attributes_val = append(attributes_val, base_url+"/"+filepath.Dir(attr.Val))
				}
			}else{
				if host == val.Host {
					path := filepath.Dir(val.Path)
					if len(path) > 1 {
						attributes_val = append(attributes_val, url_info.Scheme+"://"+val.Host+path)
					}
				}
			}
		}

		if attr.Key == "src" {
			val, err := url.ParseRequestURI(attr.Val)
			if err != nil {
				if attr.Val != "#" {
					attributes_val = append(attributes_val, base_url+"/"+filepath.Dir(attr.Val))
				}
			}else{
				if host == val.Host {
					path := filepath.Dir(val.Path)
					if len(path) > 1 {
						attributes_val = append(attributes_val, url_info.Scheme+"://"+val.Host+path)
					}
				}
			}
		}
	}
	return attributes_val
}

func s_contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ScrapePage(in io.ReadCloser, res *map[string]string, url string) {
	valid_tags := []string{"audio", "embed", "iframe", "img", "input", "script", "source", "track",
		"video", "a", "area", "base","link"}

	parser := html.NewTokenizer(in)
	for {
		next := parser.Next()

		switch {
		case next == html.ErrorToken:
			return
		case next == html.StartTagToken:
			token := parser.Token()
			if s_contains(valid_tags, token.Data) {
				for _, v := range getTagInfo(token, url){
					if len((*res)[v]) == 0 {
						showURL(v, "200", "SCRAPER")
						(*res)[v] = "200"
					}
				}
			}
		}
	}
}

func Request(wg *sync.WaitGroup,ch chan map[string]string , args CrawlerArguments, dir string, status *CrawlerStatus, client *http.Client) {
	tmp_url := args.crawl_url + "/" + dir
	var err error
	var response *http.Response
	var req *http.Request
	var done bool = false
	for !done {
		if args.enable_scraper {
			req, err = http.NewRequest("GET", tmp_url, nil)
		}else{
			if ShouldGet(0, 2) {
				req, err = http.NewRequest("GET", tmp_url, nil)
			} else {
				req, err = http.NewRequest("HEAD", tmp_url, nil)
			}
		}
		for _, cookie := range args.needed_cookies {
			req.AddCookie(&cookie)
		}
		response,err = client.Do(req)
		result := make(map[string]string)
		if err == nil {
			defer response.Body.Close()
			status.total_requests ++
			if !contains(args.valid_codes, response.StatusCode) {
				result[tmp_url] = ""
			} else {
				if args.enable_scraper {
					ScrapePage(response.Body, &result, tmp_url)
				}
				result[tmp_url] = strconv.Itoa(response.StatusCode)
				showURL(tmp_url, strconv.Itoa(response.StatusCode), "BUSTER")
			}
			wg.Done()
			ch <- result
			done = true
		} else {
			time.Sleep(time.Millisecond * 100)
		}
	}
}

func Dispose(args CrawlerArguments, ch chan map[string]string) []string {
	var todo []string
	for i:=0;i<args.max_concurrency;i++ {
		select {
		case res := <-ch:
			for new_url := range res {
				if len(res[new_url]) > 0 {
					todo = append(todo, new_url)
					val, _ := strconv.Atoi(res[new_url])
					status.pages[new_url] = val
				}
			}
		default:
		}
	}
	return todo
}

func Crawl(wg *sync.WaitGroup, args CrawlerArguments, depth int, client *http.Client) {
	var next_round [] string
	if depth <= args.max_depth {
		channel := make(chan map[string]string)
		for _, dir := range args.crawl_entries {
			if len(dir) > 0 {
				wg.Add(1)
				go Request(wg, channel, args, dir, &status, client)
				args.concurrency++
				if args.concurrency > args.max_concurrency {
					wg.Wait()
					next_round = append(next_round, Dispose(args, channel)...)
					args.concurrency = 0
				}
			}
		}

		if args.concurrency < args.max_concurrency {
			wg.Wait()
			next_round = append(next_round, Dispose(args, channel)...)
			args.concurrency = 0
		}

		for _, v := range next_round {
			args.crawl_url = v
			args.concurrency = 0
			Crawl(wg, args, depth+1, client)
		}
	}
}
<|endoftext|>


<commit_before>package gosplat

import (
	"strings"
	"text/template"
	"bytes"
	"encoding/json"
	 "io/ioutil"
	 "github.com/skratchdot/open-golang/open"
	 "fmt"
	 "os"
)

//
type Chart struct {
	data [] interface{}
}

func NewChart() *Chart {
	return &Chart{make([]interface{}, 0)}
}

func (v *Chart) Append(item interface{}) {
	v.data = append(v.data, item)
}

func (v *Chart) plot(t string, options []map[string] interface{}) map[string] interface{} {
	if len(options) > 0 {
		return map[string]interface{}{"type": t, "data": v.data, "options": options[0]}
	}
	return map[string]interface{}{"type": t, "data": v.data, "options": make(map[string] interface{})}
}

func (v *Chart) Linechart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Linechart", options)
}

func (v *Chart) Timeseries(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Timeseries", options)
}

func (v *Chart) Table(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Table", options)
}

func (v *Chart) Scatter(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Scatter", options)
}

func (v *Chart) Candlestick(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Candlestick", options)
}

func (v *Chart) Barchart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Barchart", options)
}

func (v *Chart) Columnchart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Columnchart", options)
}

func (v *Chart) Combochart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Combochart", options)
}

func (v *Chart) Treemap(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Treemap", options)
}

func (v *Chart) Piechart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Piechart", options)
}

type view struct {
	Title string
    Height string
    Id string
    Class string
    Data string
    Options string
	ColWidth string
}

func newView(title string, data map[string] interface{}, height string) (*view, error) {
	v := new(view)
	v.Title = title
	v.ColWidth = "grid_12"
	v.Height = height
	v.Id = strings.Replace(strings.ToLower(title), " ", "", -1)
	v.Class = data["type"].(string)
	d, err  := json.Marshal(data["data"].([]interface{}))
	if (err != nil) {
		return nil, err
	}
	v.Data = string(d)
	o, err := json.Marshal(data["options"].(map[string]interface{}))
	if (err != nil) {
		return nil, err
	}
	v.Options = string(o)
	return v, nil
}

type Row struct {
	Title string `json:"title"`
	Visualizations []*view
}

func NewRow(title string) *Row {
	return &Row{title, make([]*view, 0)}
}

func (r *Row) Append(title string, viz map[string] interface{}, height ... string) error {
        if len(r.Visualizations) == 3 {
            return fmt.Errorf("Only up to 3 graphs per row for now")
		}
		if (len(height) > 0) {
			view, err := newView(title, viz, height[0])
			if (err != nil) {
				return err
			}
			r.Visualizations = append(r.Visualizations, view)
		} else {
			view, err := newView(title, viz, "375px")
			if (err != nil ) {
				return err
			}

			r.Visualizations = append(r.Visualizations, view)
		}
		for _, v := range r.Visualizations {
			v.ColWidth = r.cols()
		}
		return nil
}

func (r *Row) cols() (string) {
	switch len(r.Visualizations) {
	case 1:
		return "grid_12"
	case 2:
		return "grid_6"
	case 3:
		return "grid_4"
	default:
		return "grid_12"
	}
}

type Frame struct {
	title string
	rows []*Row
}

func NewFrame(title string) *Frame{
	return &Frame{title, make([]*Row, 0)}
}

func (f *Frame) AppendRow(row *Row) {
	f.rows = append(f.rows, row)
}

func (f *Frame) Append(title string, v map[string]interface{}, height ... string) {
	row := NewRow("")
	if (len(height) > 0) {
		row.Append(title, v, height[0])
	} else {
		row.Append(title, v,"375px")
	}
	f.rows = append(f.rows, row)
}

func (f *Frame) Html() (*bytes.Buffer, error) {
	t := template.New("go2splat")
	t, err := t.Parse(HTML)
	if (err != nil) {
		return nil, err
	}
	h := &html{f.title, f.rows}
	out := bytes.NewBuffer([]byte{})
	err = t.Execute(out, h)
	return out, err
}

//     def tmp_write_markup(self):
//         if not os.path.exists(os.path.join(os.getcwd(), "tmp")):
//             os.makedirs(os.path.join(os.getcwd(), "tmp"))
//         f = tempfile.NamedTemporaryFile(dir=os.path.join(os.getcwd(), "tmp"), suffix=".html", delete=None)
//         f.write(self.markup().__str__())
//         f.close()
//         return f

func (f *Frame) Preview() error {
	html, err := f.Html()

	if (err != nil) {
		return nil
	}

	p, err := ioutil.TempFile("", "go2splat.preview.")

	if err != nil {
		return err
	}
	_, err = p.Write(html.Bytes())
	if (err != nil) {
		return err
	}
	p.Close()
	name := fmt.Sprintf("%s.html", p.Name())
	os.Rename(p.Name(), name)
	open.Run(name)
	return nil
}

type html struct {
	Title string
	Rows []*Row
}

<commit_msg>added some docs<commit_after>package gosplat

import (
	"strings"
	"text/template"
	"bytes"
	"encoding/json"
	 "io/ioutil"
	 "github.com/skratchdot/open-golang/open"
	 "fmt"
	 "os"
)

// Chart represents one chart in the frame
type Chart struct {
	data [] interface{}
}

// NewChart greates and initializes an empty Chart
func NewChart() *Chart {
	return &Chart{make([]interface{}, 0)}
}

// Append accumulates datapoints for the chart
// Depending on the type of chart you're planning to make Append takes iether a map[string]interface{} or []interface{}
func (v *Chart) Append(item interface{}) {
	v.data = append(v.data, item)
}

func (v *Chart) plot(t string, options []map[string] interface{}) map[string] interface{} {
	if len(options) > 0 {
		return map[string]interface{}{"type": t, "data": v.data, "options": options[0]}
	}
	return map[string]interface{}{"type": t, "data": v.data, "options": make(map[string] interface{})}
}

func (v *Chart) Linechart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Linechart", options)
}

func (v *Chart) Timeseries(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Timeseries", options)
}

func (v *Chart) Table(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Table", options)
}

func (v *Chart) Scatter(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Scatter", options)
}

func (v *Chart) Candlestick(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Candlestick", options)
}

func (v *Chart) Barchart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Barchart", options)
}

func (v *Chart) Columnchart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Columnchart", options)
}

func (v *Chart) Combochart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Combochart", options)
}

func (v *Chart) Treemap(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Treemap", options)
}

func (v *Chart) Piechart(options ... map[string] interface{}) map[string] interface{}{
	return v.plot("Piechart", options)
}

type view struct {
	Title string
    Height string
    Id string
    Class string
    Data string
    Options string
	ColWidth string
}

func newView(title string, data map[string] interface{}, height string) (*view, error) {
	v := new(view)
	v.Title = title
	v.ColWidth = "grid_12"
	v.Height = height
	v.Id = strings.Replace(strings.ToLower(title), " ", "", -1)
	v.Class = data["type"].(string)
	d, err  := json.Marshal(data["data"].([]interface{}))
	if (err != nil) {
		return nil, err
	}
	v.Data = string(d)
	o, err := json.Marshal(data["options"].(map[string]interface{}))
	if (err != nil) {
		return nil, err
	}
	v.Options = string(o)
	return v, nil
}

// Row allows to put two or three charts in one div, horizontally aligned as a grid
type Row struct {
	Title string `json:"title"`
	Visualizations []*view
}

// NewRow you Creates a new empty Row
func NewRow(title string) *Row {
	return &Row{title, make([]*view, 0)}
}

// Append adds a graphed chart to a Row
// Currently only up to 3 rows are recommended, as more won't fit on a page
func (r *Row) Append(title string, viz map[string] interface{}, height ... string) error {
        if len(r.Visualizations) == 3 {
            return fmt.Errorf("Only up to 3 graphs per row for now")
		}
		if (len(height) > 0) {
			view, err := newView(title, viz, height[0])
			if (err != nil) {
				return err
			}
			r.Visualizations = append(r.Visualizations, view)
		} else {
			view, err := newView(title, viz, "375px")
			if (err != nil ) {
				return err
			}

			r.Visualizations = append(r.Visualizations, view)
		}
		for _, v := range r.Visualizations {
			v.ColWidth = r.cols()
		}
		return nil
}

func (r *Row) cols() (string) {
	switch len(r.Visualizations) {
	case 1:
		return "grid_12"
	case 2:
		return "grid_6"
	case 3:
		return "grid_4"
	default:
		return "grid_12"
	}
}

// Frame holds a series of rows/charts in one page
type Frame struct {
	title string
	rows []*Row
}

// NewFrame Creates a new titled frame
func NewFrame(title string) *Frame{
	return &Frame{title, make([]*Row, 0)}
}

// AppendRow adds a Row in sequence
func (f *Frame) AppendRow(row *Row) {
	f.rows = append(f.rows, row)
}

// Append adds a chart with height of the chart as an optinal argument
func (f *Frame) Append(title string, v map[string]interface{}, height ... string) {
	row := NewRow("")
	if (len(height) > 0) {
		row.Append(title, v, height[0])
	} else {
		row.Append(title, v,"375px")
	}
	f.rows = append(f.rows, row)
}

// Html generates the page
func (f *Frame) Html() (*bytes.Buffer, error) {
	t := template.New("go2splat")
	t, err := t.Parse(HTML)
	if (err != nil) {
		return nil, err
	}
	h := &html{f.title, f.rows}
	out := bytes.NewBuffer([]byte{})
	err = t.Execute(out, h)
	return out, err
}

// Preview generates the page and opens it with the default browser
func (f *Frame) Preview() error {
	html, err := f.Html()

	if (err != nil) {
		return nil
	}

	p, err := ioutil.TempFile("", "go2splat.preview.")

	if err != nil {
		return err
	}
	_, err = p.Write(html.Bytes())
	if (err != nil) {
		return err
	}
	p.Close()
	name := fmt.Sprintf("%s.html", p.Name())
	os.Rename(p.Name(), name)
	open.Run(name)
	return nil
}

type html struct {
	Title string
	Rows []*Row
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/time/rate"

	yaml "gopkg.in/yaml.v2"

	"github.com/ecdsa521/torrent"
	"github.com/julienschmidt/httprouter"
)

//GFile represents one file from torrent
type GFile struct {
	Name string
	Path string
	Size int
	Done int
}

//GEntry represents one torrent in list
type GEntry struct {
	Name     string
	Hash     string
	Path     string
	Size     int64
	Done     int64
	Peers    int
	Seeds    int
	Comment  string
	Piece    int //piece size
	UL       int64
	DL       int64
	Uploaded int64
	Status   string
	Activity map[string]bool
	Files    []*torrent.File
	PeerList []*torrent.Peer
	Trackers [][]string
}

type speed struct {
	lastTime  int64
	lastSize  int64
	lastSpeed int64
}

var ulSpeedCalc map[string]speed
var dlSpeedCalc map[string]speed
var totalSpeed map[string]int64

/*
func (g *Gourmet) fakeList(num int) []GEntry {
	tmp, _ := ioutil.ReadFile("/usr/share/dict/words")
	g._wordlist = strings.Split(string(tmp), "\n")

	data := []GEntry{}
	for i := 0; i <= num; i++ {
		seeds, peers, size, done := rand.Intn(500), rand.Intn(500), rand.Int63n(50000), rand.Int63n(50000)
		if done > size {
			done = size / (rand.Int63n(4) + 1)
		}
		data = append(data, GEntry{
			Name:  g.fakeName(),
			Size:  size,
			Done:  done,
			Seeds: seeds,
			Peers: peers,
			Hash:  fmt.Sprintf("%x", sha1.Sum([]byte(g.fakeName()))),
			Path:  "C:/Windows/system32/" + g.fakeName(),
		})
	}
	return data
}
func (g *Gourmet) fakeName() string {
	rand.Seed(time.Now().UnixNano())
	r := rand.Intn(len(g._wordlist))
	return strings.TrimSpace(g._wordlist[r])
}
*/

//Start the webserver and setup routes
func (g *Gourmet) Start() {
	g.router = httprouter.New()
	g.router.GET("/", g.listPage)
	g.router.GET("/config", g.configPage)
	g.router.GET("/api/list", g.apiList)
	g.router.GET("/api/start", g.apiStartDL)
	g.router.GET("/api/stop", g.apiStopDL)
	g.router.GET("/api/remove", g.apiRemove)
	g.router.GET("/api/stats", g.apiStats)
	g.router.GET("/api/announce", g.apiAnnounce)
	g.router.GET("/api/add/magnet", g.apiAddMagnet)
	g.router.ServeFiles("/static/*filepath", http.Dir("static"))
	http.ListenAndServe(fmt.Sprintf(":%d", g.Config["Port"]), g.router)
}

func (g *Gourmet) listPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	g.genTemplate(w, r, "list.html", map[string]interface{}{
		"Config":  g.Config,
		"Navbar":  g.navbar("torrents"),
		"Toolbox": g.toolbox(),
		"Title":   "torrent",
		"Content": "",
		"Footer":  g.footer(),
	})
}
func (g *Gourmet) configPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	g.genTemplate(w, r, "config.html", map[string]interface{}{
		"Config":  g.Config,
		"Navbar":  g.navbar("config"),
		"Toolbox": g.toolbox(),
		"Title":   "torrent",
		"Content": "",
		"Footer":  g.footer(),
	})
}

func (g *Gourmet) speedCalcDL(v *torrent.Torrent) {
	var hex string = v.InfoHash().HexString()
	if _, ok := dlSpeedCalc[hex]; ok {
		lastSize, lastTime := dlSpeedCalc[hex].lastSize, dlSpeedCalc[hex].lastTime
		lastSpeed := (v.BytesCompleted() - lastSize) / ((time.Now().Unix() - lastTime) + 1)
		if lastSpeed < 5000 { //do not show network pings
			lastSpeed = 0
		}
		dlSpeedCalc[hex] = speed{
			lastSize:  v.BytesCompleted(),
			lastTime:  time.Now().Unix(),
			lastSpeed: lastSpeed,
		}
	} else {
		dlSpeedCalc[hex] = speed{
			lastSize:  v.BytesCompleted(),
			lastTime:  time.Now().Unix(),
			lastSpeed: 0,
		}
	}
	totalSpeed["DL"] = 0
	for _, v := range dlSpeedCalc {
		totalSpeed["DL"] += v.lastSpeed
	}
}
func (g *Gourmet) speedCalcUL(v *torrent.Torrent) {
	var hex string = v.InfoHash().HexString()
	if _, ok := ulSpeedCalc[hex]; ok {
		lastSize, lastTime := ulSpeedCalc[hex].lastSize, ulSpeedCalc[hex].lastTime
		lastSpeed := (v.Stats().BytesWritten - lastSize) / ((time.Now().Unix() - lastTime) + 1)
		if lastSpeed < 5000 { //do not show network pings
			lastSpeed = 0
		}
		ulSpeedCalc[hex] = speed{
			lastSize:  v.Stats().BytesWritten,
			lastTime:  time.Now().Unix(),
			lastSpeed: lastSpeed,
		}
	} else {
		ulSpeedCalc[hex] = speed{
			lastSize:  v.Stats().BytesWritten,
			lastTime:  time.Now().Unix(),
			lastSpeed: 0,
		}
	}
	totalSpeed["UL"] = 0
	for _, v := range ulSpeedCalc {
		totalSpeed["UL"] += v.lastSpeed
	}
}

func main() {
	ulSpeedCalc = map[string]speed{}
	dlSpeedCalc = map[string]speed{}
	totalSpeed = make(map[string]int64)
	gourmet := Gourmet{}
	text, err := ioutil.ReadFile("config.yaml")
	if err != nil {
		panic(err)
	}
	yaml.Unmarshal([]byte(text), &gourmet.Config)

	upLimit := gourmet.Config["UL"].(int)
	downLimit := gourmet.Config["DL"].(int)
	gourmet.ClientConfig = &torrent.Config{}
	gourmet.ClientConfig.Seed = true
	if upLimit > 0 {
		gourmet.ClientConfig.UploadRateLimiter = rate.NewLimiter(rate.Limit(upLimit), upLimit*2)
	}
	if downLimit > 0 {
		gourmet.ClientConfig.DownloadRateLimiter = rate.NewLimiter(rate.Limit(downLimit), downLimit*2)
	}
	gourmet.ClientConfig.Seed = true
	rand.Seed(time.Now().UnixNano())
	gourmet.ClientConfig.ListenAddr = fmt.Sprintf(":%d", rand.Intn(65530)+1)

	gourmet.Client, err = torrent.NewClient(gourmet.ClientConfig)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Starting listener on port %s\nPeer ID: %x\n", gourmet.ClientConfig.ListenAddr, gourmet.Client.PeerID())
	trackers := [][]string{
		{"udp://tracker.opentrackr.org:1337"},
		{"udp://tracker.coppersurfer.tk:6969"},
		{"udp://tracker.leechers-paradise.org:6969"},
		{"udp://zer0day.ch:1337"},
		{"udp://explodie.org:6969"},
	}
	a, _ := gourmet.Client.AddMagnet("magnet:?xt=urn:btih:6REDNTETZGFY7FH2WLNO5QHXS4MBDIQD")
	a.AddTrackers(trackers)
	b, _ := gourmet.Client.AddMagnet("magnet:?xt=urn:btih:LEDGO2NZVVBNULSQQYI4GPL4ISALHBL3")
	b.AddTrackers(trackers)
	go gourmet.Start()
	select {}
}
<commit_msg>Don't add torrents automatically<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/time/rate"

	yaml "gopkg.in/yaml.v2"

	"github.com/ecdsa521/torrent"
	"github.com/julienschmidt/httprouter"
)

//GFile represents one file from torrent
type GFile struct {
	Name string
	Path string
	Size int
	Done int
}

//GEntry represents one torrent in list
type GEntry struct {
	Name     string
	Hash     string
	Path     string
	Size     int64
	Done     int64
	Peers    int
	Seeds    int
	Comment  string
	Piece    int //piece size
	UL       int64
	DL       int64
	Uploaded int64
	Status   string
	Activity map[string]bool
	Files    []*torrent.File
	PeerList []*torrent.Peer
	Trackers [][]string
}

type speed struct {
	lastTime  int64
	lastSize  int64
	lastSpeed int64
}

var ulSpeedCalc map[string]speed
var dlSpeedCalc map[string]speed
var totalSpeed map[string]int64

/*
func (g *Gourmet) fakeList(num int) []GEntry {
	tmp, _ := ioutil.ReadFile("/usr/share/dict/words")
	g._wordlist = strings.Split(string(tmp), "\n")

	data := []GEntry{}
	for i := 0; i <= num; i++ {
		seeds, peers, size, done := rand.Intn(500), rand.Intn(500), rand.Int63n(50000), rand.Int63n(50000)
		if done > size {
			done = size / (rand.Int63n(4) + 1)
		}
		data = append(data, GEntry{
			Name:  g.fakeName(),
			Size:  size,
			Done:  done,
			Seeds: seeds,
			Peers: peers,
			Hash:  fmt.Sprintf("%x", sha1.Sum([]byte(g.fakeName()))),
			Path:  "C:/Windows/system32/" + g.fakeName(),
		})
	}
	return data
}
func (g *Gourmet) fakeName() string {
	rand.Seed(time.Now().UnixNano())
	r := rand.Intn(len(g._wordlist))
	return strings.TrimSpace(g._wordlist[r])
}
*/

//Start the webserver and setup routes
func (g *Gourmet) Start() {
	g.router = httprouter.New()
	g.router.GET("/", g.listPage)
	g.router.GET("/config", g.configPage)
	g.router.GET("/api/list", g.apiList)
	g.router.GET("/api/start", g.apiStartDL)
	g.router.GET("/api/stop", g.apiStopDL)
	g.router.GET("/api/remove", g.apiRemove)
	g.router.GET("/api/stats", g.apiStats)
	g.router.GET("/api/announce", g.apiAnnounce)
	g.router.GET("/api/add/magnet", g.apiAddMagnet)
	g.router.ServeFiles("/static/*filepath", http.Dir("static"))
	http.ListenAndServe(fmt.Sprintf(":%d", g.Config["Port"]), g.router)
}

func (g *Gourmet) listPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	g.genTemplate(w, r, "list.html", map[string]interface{}{
		"Config":  g.Config,
		"Navbar":  g.navbar("torrents"),
		"Toolbox": g.toolbox(),
		"Title":   "torrent",
		"Content": "",
		"Footer":  g.footer(),
	})
}
func (g *Gourmet) configPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	g.genTemplate(w, r, "config.html", map[string]interface{}{
		"Config":  g.Config,
		"Navbar":  g.navbar("config"),
		"Toolbox": g.toolbox(),
		"Title":   "torrent",
		"Content": "",
		"Footer":  g.footer(),
	})
}

func (g *Gourmet) speedCalcDL(v *torrent.Torrent) {
	var hex string = v.InfoHash().HexString()
	if _, ok := dlSpeedCalc[hex]; ok {
		lastSize, lastTime := dlSpeedCalc[hex].lastSize, dlSpeedCalc[hex].lastTime
		lastSpeed := (v.BytesCompleted() - lastSize) / ((time.Now().Unix() - lastTime) + 1)
		if lastSpeed < 5000 { //do not show network pings
			lastSpeed = 0
		}
		dlSpeedCalc[hex] = speed{
			lastSize:  v.BytesCompleted(),
			lastTime:  time.Now().Unix(),
			lastSpeed: lastSpeed,
		}
	} else {
		dlSpeedCalc[hex] = speed{
			lastSize:  v.BytesCompleted(),
			lastTime:  time.Now().Unix(),
			lastSpeed: 0,
		}
	}
	totalSpeed["DL"] = 0
	for _, v := range dlSpeedCalc {
		totalSpeed["DL"] += v.lastSpeed
	}
}
func (g *Gourmet) speedCalcUL(v *torrent.Torrent) {
	var hex string = v.InfoHash().HexString()
	if _, ok := ulSpeedCalc[hex]; ok {
		lastSize, lastTime := ulSpeedCalc[hex].lastSize, ulSpeedCalc[hex].lastTime
		lastSpeed := (v.Stats().BytesWritten - lastSize) / ((time.Now().Unix() - lastTime) + 1)
		if lastSpeed < 5000 { //do not show network pings
			lastSpeed = 0
		}
		ulSpeedCalc[hex] = speed{
			lastSize:  v.Stats().BytesWritten,
			lastTime:  time.Now().Unix(),
			lastSpeed: lastSpeed,
		}
	} else {
		ulSpeedCalc[hex] = speed{
			lastSize:  v.Stats().BytesWritten,
			lastTime:  time.Now().Unix(),
			lastSpeed: 0,
		}
	}
	totalSpeed["UL"] = 0
	for _, v := range ulSpeedCalc {
		totalSpeed["UL"] += v.lastSpeed
	}
}

func main() {
	ulSpeedCalc = map[string]speed{}
	dlSpeedCalc = map[string]speed{}
	totalSpeed = make(map[string]int64)
	gourmet := Gourmet{}
	text, err := ioutil.ReadFile("config.yaml")
	if err != nil {
		panic(err)
	}
	yaml.Unmarshal([]byte(text), &gourmet.Config)

	upLimit := gourmet.Config["UL"].(int)
	downLimit := gourmet.Config["DL"].(int)
	gourmet.ClientConfig = &torrent.Config{}
	gourmet.ClientConfig.Seed = true
	if upLimit > 0 {
		gourmet.ClientConfig.UploadRateLimiter = rate.NewLimiter(rate.Limit(upLimit), upLimit*2)
	}
	if downLimit > 0 {
		gourmet.ClientConfig.DownloadRateLimiter = rate.NewLimiter(rate.Limit(downLimit), downLimit*2)
	}
	gourmet.ClientConfig.Seed = true
	rand.Seed(time.Now().UnixNano())
	gourmet.ClientConfig.ListenAddr = fmt.Sprintf(":%d", rand.Intn(65530)+1)

	gourmet.Client, err = torrent.NewClient(gourmet.ClientConfig)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Starting listener on port %s\nPeer ID: %x\n", gourmet.ClientConfig.ListenAddr, gourmet.Client.PeerID())
	/*trackers := [][]string{
		{"udp://tracker.opentrackr.org:1337"},
		{"udp://tracker.coppersurfer.tk:6969"},
		{"udp://tracker.leechers-paradise.org:6969"},
		{"udp://zer0day.ch:1337"},
		{"udp://explodie.org:6969"},
	}
	a, _ := gourmet.Client.AddMagnet("magnet:?xt=urn:btih:6REDNTETZGFY7FH2WLNO5QHXS4MBDIQD")
	a.AddTrackers(trackers)
	b, _ := gourmet.Client.AddMagnet("magnet:?xt=urn:btih:LEDGO2NZVVBNULSQQYI4GPL4ISALHBL3")
	b.AddTrackers(trackers)
	*/
	go gourmet.Start()
	select {}
}
<|endoftext|>