<commit_before>package python

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"strings"

	"sourcegraph.com/sourcegraph/srclib/graph"
	"sourcegraph.com/sourcegraph/srclib/grapher"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

type GraphContext struct {
	Unit *unit.SourceUnit
	Reqs []*requirement
}

func NewGraphContext(unit *unit.SourceUnit) *GraphContext {
	var g GraphContext
	g.Unit = unit
	for _, dep := range unit.Dependencies {
		if req, err := asRequirement(dep); err == nil {
			g.Reqs = append(g.Reqs, req)
		}
	}
	return &g
}

// Graphs the Python source unit. If run outside of a Docker container, this assumes that the source unit has already
// been installed (via pip or `python setup.py install`).
func (c *GraphContext) Graph() (*grapher.Output, error) {
	if os.Getenv("IN_DOCKER_CONTAINER") != "" {
		// NOTE: this may cause an error when graphing any source unit that depends
		// on jedi (or any other dependency of the graph code)
		requirementFiles, err := filepath.Glob(filepath.Join(c.Unit.Dir, "*requirements.txt"))
		if err != nil {
			return nil, err
		}
		for _, requirementFile := range requirementFiles {
			exec.Command("pip", "install", "-r", requirementFile)
		}
		exec.Command("pip", "install", "-I", c.Unit.Dir)
	}

	cmd := exec.Command("python", "-m", "grapher.graph", c.Unit.Dir, "--verbose")
	cmd.Stderr = os.Stderr
	b, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	var raw RawOutput
	if err := json.Unmarshal(b, &raw); err != nil {
		return nil, err
	}

	out := c.transform(&raw, c.Unit)
	return out, nil
}

func (c *GraphContext) transform(raw *RawOutput, unit *unit.SourceUnit) *grapher.Output {
	var out grapher.Output

	for _, def := range raw.Defs {
		out.Symbols = append(out.Symbols, c.transformDef(def))
		if doc := c.transformDefDoc(def); doc != nil {
			out.Docs = append(out.Docs, doc)
		}
	}
	for _, ref := range raw.Refs {
		if outRef, err := c.transformRef(ref); err == nil {
			out.Refs = append(out.Refs, outRef)
		} else {
			log.Printf("Could not transform ref %v: %s", ref, err)
		}
	}

	return &out
}

var jediKindToSymbolKind = map[string]graph.SymbolKind{
	"statement":        graph.Var,
	"statementelement": graph.Var,
	"param":            graph.Var,
	"module":           graph.Module,
	"submodule":        graph.Module,
	"class":            graph.Type,
	"function":         graph.Func,
	"lambda":           graph.Func,
	"import":           graph.Var,
}

func (c *GraphContext) transformDef(rawDef *RawDef) *graph.Symbol {
	return &graph.Symbol{
		SymbolKey: graph.SymbolKey{
			Repo:     c.Unit.Repo,
			Unit:     c.Unit.Name,
			UnitType: c.Unit.Type,
			Path:     graph.SymbolPath(rawDef.Path),
		},
		TreePath: graph.TreePath(rawDef.Path), // TODO: make this consistent w/ old way
		Kind:     jediKindToSymbolKind[rawDef.Kind],
		Name:     rawDef.Name,
		File:     rawDef.File,
		DefStart: rawDef.DefStart,
		DefEnd:   rawDef.DefEnd,
		Exported: rawDef.Exported,
		Data:     nil, // TODO
	}
}

func (c *GraphContext) transformRef(rawRef *RawRef) (*graph.Ref, error) {
	defUnit, err := c.inferSourceUnit(rawRef, c.Reqs)
	if err != nil {
		return nil, err
	}

	return &graph.Ref{
		SymbolRepo:     defUnit.Repo,
		SymbolUnitType: defUnit.Type,
		SymbolUnit:     defUnit.Name,
		SymbolPath:     graph.SymbolPath(rawRef.DefPath),

		Repo:     c.Unit.Repo,
		Unit:     c.Unit.Name,
		UnitType: c.Unit.Type,

		File:  rawRef.File,
		Start: rawRef.Start,
		End:   rawRef.End,
	}, nil
}

func (c *GraphContext) transformDefDoc(rawDef *RawDef) *graph.Doc {
	return nil
}

func (c *GraphContext) inferSourceUnit(rawRef *RawRef, reqs []*requirement) (*unit.SourceUnit, error) {
	if rawRef.ToBuiltin {
		return stdLibPkg.SourceUnit(), nil
	}
	return c.inferSourceUnitFromFile(rawRef.DefFile, reqs)
}

// Note: file is expected to be an absolute path
func (c *GraphContext) inferSourceUnitFromFile(file string, reqs []*requirement) (*unit.SourceUnit, error) {
	// Case: in current source unit (u)
	pwd, _ := os.Getwd()
	if isSubPath(pwd, file) {
		return c.Unit, nil
	}

	// Case: in dependent source unit(depUnits)
	fileCmps := strings.Split(file, string(filepath.Separator))
	pkgsDirIdx := -1
	for i, cmp := range fileCmps {
		if cmp == "site-packages" || cmp == "dist-packages" {
			pkgsDirIdx = i
			break
		}
	}
	if pkgsDirIdx != -1 {
		fileSubCmps := fileCmps[pkgsDirIdx+1:]
		fileSubPath := filepath.Join(fileSubCmps...)

		var foundReq *requirement = nil
	FindReq:
		for _, req := range reqs {
			for _, pkg := range req.Packages {
				if isSubPath(moduleToFilepath(pkg, true), fileSubPath) {
					foundReq = req
					break FindReq
				}
			}
			for _, mod := range req.Modules {
				if moduleToFilepath(mod, false) == fileSubPath {
					foundReq = req
					break FindReq
				}
			}
		}

		if foundReq == nil {
			var candidatesStr string
			if len(reqs) <= 7 {
				candidatesStr = fmt.Sprintf("%v", reqs)
			} else {
				candidatesStr = fmt.Sprintf("%v...", reqs[:7])
			}
			return nil, fmt.Errorf("Could not find requirement that contains file %s. Candidates were: %s",
				file, candidatesStr)
		}

		return foundReq.SourceUnit(), nil
	}

	// Case 3: in std lib
	pythonDirIdx := -1
	for i, cmp := range fileCmps {
		log.Printf("# cmp: %s", cmp)
		if strings.HasPrefix(cmp, "python") {
			pythonDirIdx = i
			break
		}
	}
	if pythonDirIdx != -1 {
		return stdLibPkg.SourceUnit(), nil
	}

	return nil, fmt.Errorf("Cannot infer source unit for file %s", file)
}

func isSubPath(parent, child string) bool {
	relpath, err := filepath.Rel(parent, child)
	return err == nil && !strings.HasPrefix(relpath, "..")
}

func moduleToFilepath(moduleName string, isPackage bool) string {
	moduleName = strings.Replace(moduleName, ".", "/", -1)
	if !isPackage {
		moduleName += ".py"
	}
	return moduleName
}

type RawOutput struct {
	Defs []*RawDef
	Refs []*RawRef
}

type RawDef struct {
	Path      string
	Kind      string
	Name      string
	File      string // relative path (to source unit directory)
	DefStart  int
	DefEnd    int
	Exported  bool
	Docstring string
	Data      interface{}
}

type RawRef struct {
	DefPath   string
	Def       bool
	DefFile   string // absolute path
	File      string // relative path (to source unit directory)
	Start     int
	End       int
	ToBuiltin bool
}
<commit_msg>remove print<commit_after>package python

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"strings"

	"sourcegraph.com/sourcegraph/srclib/graph"
	"sourcegraph.com/sourcegraph/srclib/grapher"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

type GraphContext struct {
	Unit *unit.SourceUnit
	Reqs []*requirement
}

func NewGraphContext(unit *unit.SourceUnit) *GraphContext {
	var g GraphContext
	g.Unit = unit
	for _, dep := range unit.Dependencies {
		if req, err := asRequirement(dep); err == nil {
			g.Reqs = append(g.Reqs, req)
		}
	}
	return &g
}

// Graphs the Python source unit. If run outside of a Docker container, this assumes that the source unit has already
// been installed (via pip or `python setup.py install`).
func (c *GraphContext) Graph() (*grapher.Output, error) {
	if os.Getenv("IN_DOCKER_CONTAINER") != "" {
		// NOTE: this may cause an error when graphing any source unit that depends
		// on jedi (or any other dependency of the graph code)
		requirementFiles, err := filepath.Glob(filepath.Join(c.Unit.Dir, "*requirements.txt"))
		if err != nil {
			return nil, err
		}
		for _, requirementFile := range requirementFiles {
			exec.Command("pip", "install", "-r", requirementFile)
		}
		exec.Command("pip", "install", "-I", c.Unit.Dir)
	}

	cmd := exec.Command("python", "-m", "grapher.graph", c.Unit.Dir, "--verbose")
	cmd.Stderr = os.Stderr
	b, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	var raw RawOutput
	if err := json.Unmarshal(b, &raw); err != nil {
		return nil, err
	}

	out := c.transform(&raw, c.Unit)
	return out, nil
}

func (c *GraphContext) transform(raw *RawOutput, unit *unit.SourceUnit) *grapher.Output {
	var out grapher.Output

	for _, def := range raw.Defs {
		out.Symbols = append(out.Symbols, c.transformDef(def))
		if doc := c.transformDefDoc(def); doc != nil {
			out.Docs = append(out.Docs, doc)
		}
	}
	for _, ref := range raw.Refs {
		if outRef, err := c.transformRef(ref); err == nil {
			out.Refs = append(out.Refs, outRef)
		} else {
			log.Printf("Could not transform ref %v: %s", ref, err)
		}
	}

	return &out
}

var jediKindToSymbolKind = map[string]graph.SymbolKind{
	"statement":        graph.Var,
	"statementelement": graph.Var,
	"param":            graph.Var,
	"module":           graph.Module,
	"submodule":        graph.Module,
	"class":            graph.Type,
	"function":         graph.Func,
	"lambda":           graph.Func,
	"import":           graph.Var,
}

func (c *GraphContext) transformDef(rawDef *RawDef) *graph.Symbol {
	return &graph.Symbol{
		SymbolKey: graph.SymbolKey{
			Repo:     c.Unit.Repo,
			Unit:     c.Unit.Name,
			UnitType: c.Unit.Type,
			Path:     graph.SymbolPath(rawDef.Path),
		},
		TreePath: graph.TreePath(rawDef.Path), // TODO: make this consistent w/ old way
		Kind:     jediKindToSymbolKind[rawDef.Kind],
		Name:     rawDef.Name,
		File:     rawDef.File,
		DefStart: rawDef.DefStart,
		DefEnd:   rawDef.DefEnd,
		Exported: rawDef.Exported,
		Data:     nil, // TODO
	}
}

func (c *GraphContext) transformRef(rawRef *RawRef) (*graph.Ref, error) {
	defUnit, err := c.inferSourceUnit(rawRef, c.Reqs)
	if err != nil {
		return nil, err
	}

	return &graph.Ref{
		SymbolRepo:     defUnit.Repo,
		SymbolUnitType: defUnit.Type,
		SymbolUnit:     defUnit.Name,
		SymbolPath:     graph.SymbolPath(rawRef.DefPath),

		Repo:     c.Unit.Repo,
		Unit:     c.Unit.Name,
		UnitType: c.Unit.Type,

		File:  rawRef.File,
		Start: rawRef.Start,
		End:   rawRef.End,
	}, nil
}

func (c *GraphContext) transformDefDoc(rawDef *RawDef) *graph.Doc {
	return nil
}

func (c *GraphContext) inferSourceUnit(rawRef *RawRef, reqs []*requirement) (*unit.SourceUnit, error) {
	if rawRef.ToBuiltin {
		return stdLibPkg.SourceUnit(), nil
	}
	return c.inferSourceUnitFromFile(rawRef.DefFile, reqs)
}

// Note: file is expected to be an absolute path
func (c *GraphContext) inferSourceUnitFromFile(file string, reqs []*requirement) (*unit.SourceUnit, error) {
	// Case: in current source unit (u)
	pwd, _ := os.Getwd()
	if isSubPath(pwd, file) {
		return c.Unit, nil
	}

	// Case: in dependent source unit(depUnits)
	fileCmps := strings.Split(file, string(filepath.Separator))
	pkgsDirIdx := -1
	for i, cmp := range fileCmps {
		if cmp == "site-packages" || cmp == "dist-packages" {
			pkgsDirIdx = i
			break
		}
	}
	if pkgsDirIdx != -1 {
		fileSubCmps := fileCmps[pkgsDirIdx+1:]
		fileSubPath := filepath.Join(fileSubCmps...)

		var foundReq *requirement = nil
	FindReq:
		for _, req := range reqs {
			for _, pkg := range req.Packages {
				if isSubPath(moduleToFilepath(pkg, true), fileSubPath) {
					foundReq = req
					break FindReq
				}
			}
			for _, mod := range req.Modules {
				if moduleToFilepath(mod, false) == fileSubPath {
					foundReq = req
					break FindReq
				}
			}
		}

		if foundReq == nil {
			var candidatesStr string
			if len(reqs) <= 7 {
				candidatesStr = fmt.Sprintf("%v", reqs)
			} else {
				candidatesStr = fmt.Sprintf("%v...", reqs[:7])
			}
			return nil, fmt.Errorf("Could not find requirement that contains file %s. Candidates were: %s",
				file, candidatesStr)
		}

		return foundReq.SourceUnit(), nil
	}

	// Case 3: in std lib
	pythonDirIdx := -1
	for i, cmp := range fileCmps {
		if strings.HasPrefix(cmp, "python") {
			pythonDirIdx = i
			break
		}
	}
	if pythonDirIdx != -1 {
		return stdLibPkg.SourceUnit(), nil
	}

	return nil, fmt.Errorf("Cannot infer source unit for file %s", file)
}

func isSubPath(parent, child string) bool {
	relpath, err := filepath.Rel(parent, child)
	return err == nil && !strings.HasPrefix(relpath, "..")
}

func moduleToFilepath(moduleName string, isPackage bool) string {
	moduleName = strings.Replace(moduleName, ".", "/", -1)
	if !isPackage {
		moduleName += ".py"
	}
	return moduleName
}

type RawOutput struct {
	Defs []*RawDef
	Refs []*RawRef
}

type RawDef struct {
	Path      string
	Kind      string
	Name      string
	File      string // relative path (to source unit directory)
	DefStart  int
	DefEnd    int
	Exported  bool
	Docstring string
	Data      interface{}
}

type RawRef struct {
	DefPath   string
	Def       bool
	DefFile   string // absolute path
	File      string // relative path (to source unit directory)
	Start     int
	End       int
	ToBuiltin bool
}
<|endoftext|>


<commit_before>package resp

//go:generate bash -c "go run generate/*.go | gofmt -s > auto.go"

import (
	"math"
	"math/cmplx"
	"strings"
)

type Symmetry uint

const (
	SymmetryUnknown Symmetry = iota
	SymmetryNone
	SymmetryEven
	SymmetryOdd
)

type PzTransferFunction uint

const (
	PZFunctionUnknown PzTransferFunction = iota
	PZFunctionLaplaceRadiansPerSecond
	PZFunctionLaplaceHertz
	PZFunctionLaplaceZTransform
)

type ApproximationType uint

const (
	ApproximationTypeUnknown ApproximationType = iota
	ApproximationTypeMaclaurin
)

type Datalogger struct {
	DataloggerList []string
	Type           string
	Label          string
	SampleRate     float64
	Frequency      float64
	StorageFormat  string
	ClockDrift     float64
	FilterList     []string
	Stages         []ResponseStage
	Reversed       bool
}

type DataloggerModel struct {
	Name         string
	Type         string // FDSN StationXML Datalogger Type
	Description  string // FDSN StationXML Datalogger Description
	Manufacturer string // FDSN StationXML Datalogger Manufacturer
	Vendor       string // FDSN StationXML Datalogger Vendor
}

type Sensor struct {
	SensorList []string
	FilterList []string
	Stages     []ResponseStage
	Channels   string
	Reversed   bool
}

func (s Sensor) Labels(axial bool) string {
	labels := s.Channels
	if axial {
		labels = strings.Replace(labels, "N", "1", -1)
		labels = strings.Replace(labels, "E", "2", -1)
	} else {
		labels = strings.Replace(labels, "1", "N", -1)
		labels = strings.Replace(labels, "2", "E", -1)
	}
	return labels
}

type SensorComponent struct {
	Azimuth float64
	Dip     float64
}

type SensorModel struct {
	Name         string
	Type         string // FDSN StationXML Sensor Type
	Description  string // FDSN StationXML Sensor Description
	Manufacturer string // FDSN StationXML Vendor Description
	Vendor       string // FDSN StationXML Vendor Description

	Components []SensorComponent
}

type Response struct {
	Name        string
	Sensors     []Sensor
	Dataloggers []Datalogger
}

type Stream struct {
	Datalogger
	Sensor

	Components []SensorComponent
}

func (s Stream) Channels(axial bool) []string {
	var channels []string

	labels := s.Sensor.Labels(axial)
	if len(s.Components) < len(labels) && len(labels) > 0 {
		labels = labels[0:len(s.Components)]
	}

	for _, component := range labels {
		channels = append(channels, s.Datalogger.Label+string(component))
	}

	return channels
}

func (s Stream) Gain() float64 {
	var gain float64 = 1.0

	for _, stage := range append(s.Sensor.Stages, s.Datalogger.Stages...) {
		if stage.StageSet == nil {
			continue
		}
		switch stage.StageSet.GetType() {
		case "fir":
			gain *= stage.StageSet.(FIR).Gain
		default:
			gain *= stage.Gain
		}
	}

	return gain
}

type StageSet interface {
	GetType() string
}

type ResponseStage struct {
	Type       string
	Lookup     string
	Filter     string
	StageSet   StageSet
	Frequency  float64
	SampleRate float64
	Decimate   int32
	Gain       float64
	//	Scale       float64
	Correction  float64
	Delay       float64
	InputUnits  string
	OutputUnits string
}

type PAZ struct {
	Name  string
	Code  PzTransferFunction
	Type  string
	Notes string
	Poles []complex128
	Zeros []complex128
}

func (p PAZ) GetType() string {
	return "paz"
}

func (p PAZ) Gain(freq float64) float64 {
	w := complex(0.0, func() float64 {
		switch p.Code {
		case PZFunctionLaplaceRadiansPerSecond:
			return 2.0 * math.Pi * freq
		default:
			return freq
		}
	}())
	h := complex(float64(1.0), float64(0.0))

	for _, zero := range p.Zeros {
		h *= (w - zero)
	}

	for _, pole := range p.Poles {
		h /= (w - pole)
	}
	return cmplx.Abs(h)
}

type FIR struct {
	Name       string
	Causal     bool
	Symmetry   Symmetry
	Decimation float64
	Gain       float64
	Notes      *string
	Factors    []float64
	Reversed   *bool
}

func (f FIR) GetType() string {
	return "fir"
}

type Coefficient struct {
	Value float64
}

type Polynomial struct {
	Name                    string
	Gain                    float64
	ApproximationType       ApproximationType
	FrequencyLowerBound     float64
	FrequencyUpperBound     float64
	ApproximationLowerBound float64
	ApproximationUpperBound float64
	MaximumError            float64
	Notes                   *string

	Coefficients []Coefficient
}

func (p Polynomial) GetType() string {
	return "poly"
}

type A2D struct {
	Name  string
	Code  PzTransferFunction
	Type  string
	Notes string
}

func (a A2D) GetType() string {
	return "a2d"
}
<commit_msg>fix empty auto.go file issue (#219)<commit_after>package resp

//go:generate bash -c "go run generate/*.go | gofmt -s > auto.go; test -s auto.go || rm auto.go"

import (
	"math"
	"math/cmplx"
	"strings"
)

type Symmetry uint

const (
	SymmetryUnknown Symmetry = iota
	SymmetryNone
	SymmetryEven
	SymmetryOdd
)

type PzTransferFunction uint

const (
	PZFunctionUnknown PzTransferFunction = iota
	PZFunctionLaplaceRadiansPerSecond
	PZFunctionLaplaceHertz
	PZFunctionLaplaceZTransform
)

type ApproximationType uint

const (
	ApproximationTypeUnknown ApproximationType = iota
	ApproximationTypeMaclaurin
)

type Datalogger struct {
	DataloggerList []string
	Type           string
	Label          string
	SampleRate     float64
	Frequency      float64
	StorageFormat  string
	ClockDrift     float64
	FilterList     []string
	Stages         []ResponseStage
	Reversed       bool
}

type DataloggerModel struct {
	Name         string
	Type         string // FDSN StationXML Datalogger Type
	Description  string // FDSN StationXML Datalogger Description
	Manufacturer string // FDSN StationXML Datalogger Manufacturer
	Vendor       string // FDSN StationXML Datalogger Vendor
}

type Sensor struct {
	SensorList []string
	FilterList []string
	Stages     []ResponseStage
	Channels   string
	Reversed   bool
}

func (s Sensor) Labels(axial bool) string {
	labels := s.Channels
	if axial {
		labels = strings.Replace(labels, "N", "1", -1)
		labels = strings.Replace(labels, "E", "2", -1)
	} else {
		labels = strings.Replace(labels, "1", "N", -1)
		labels = strings.Replace(labels, "2", "E", -1)
	}
	return labels
}

type SensorComponent struct {
	Azimuth float64
	Dip     float64
}

type SensorModel struct {
	Name         string
	Type         string // FDSN StationXML Sensor Type
	Description  string // FDSN StationXML Sensor Description
	Manufacturer string // FDSN StationXML Vendor Description
	Vendor       string // FDSN StationXML Vendor Description

	Components []SensorComponent
}

type Response struct {
	Name        string
	Sensors     []Sensor
	Dataloggers []Datalogger
}

type Stream struct {
	Datalogger
	Sensor

	Components []SensorComponent
}

func (s Stream) Channels(axial bool) []string {
	var channels []string

	labels := s.Sensor.Labels(axial)
	if len(s.Components) < len(labels) && len(labels) > 0 {
		labels = labels[0:len(s.Components)]
	}

	for _, component := range labels {
		channels = append(channels, s.Datalogger.Label+string(component))
	}

	return channels
}

func (s Stream) Gain() float64 {
	var gain float64 = 1.0

	for _, stage := range append(s.Sensor.Stages, s.Datalogger.Stages...) {
		if stage.StageSet == nil {
			continue
		}
		switch stage.StageSet.GetType() {
		case "fir":
			gain *= stage.StageSet.(FIR).Gain
		default:
			gain *= stage.Gain
		}
	}

	return gain
}

type StageSet interface {
	GetType() string
}

type ResponseStage struct {
	Type       string
	Lookup     string
	Filter     string
	StageSet   StageSet
	Frequency  float64
	SampleRate float64
	Decimate   int32
	Gain       float64
	//	Scale       float64
	Correction  float64
	Delay       float64
	InputUnits  string
	OutputUnits string
}

type PAZ struct {
	Name  string
	Code  PzTransferFunction
	Type  string
	Notes string
	Poles []complex128
	Zeros []complex128
}

func (p PAZ) GetType() string {
	return "paz"
}

func (p PAZ) Gain(freq float64) float64 {
	w := complex(0.0, func() float64 {
		switch p.Code {
		case PZFunctionLaplaceRadiansPerSecond:
			return 2.0 * math.Pi * freq
		default:
			return freq
		}
	}())
	h := complex(float64(1.0), float64(0.0))

	for _, zero := range p.Zeros {
		h *= (w - zero)
	}

	for _, pole := range p.Poles {
		h /= (w - pole)
	}
	return cmplx.Abs(h)
}

type FIR struct {
	Name       string
	Causal     bool
	Symmetry   Symmetry
	Decimation float64
	Gain       float64
	Notes      *string
	Factors    []float64
	Reversed   *bool
}

func (f FIR) GetType() string {
	return "fir"
}

type Coefficient struct {
	Value float64
}

type Polynomial struct {
	Name                    string
	Gain                    float64
	ApproximationType       ApproximationType
	FrequencyLowerBound     float64
	FrequencyUpperBound     float64
	ApproximationLowerBound float64
	ApproximationUpperBound float64
	MaximumError            float64
	Notes                   *string

	Coefficients []Coefficient
}

func (p Polynomial) GetType() string {
	return "poly"
}

type A2D struct {
	Name  string
	Code  PzTransferFunction
	Type  string
	Notes string
}

func (a A2D) GetType() string {
	return "a2d"
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"launchpad.net/gnuflag"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/log"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/worker/machiner"
	"launchpad.net/tomb"
	"time"
)

// MachineAgent is a cmd.Command responsible for running a machine agent.
type MachineAgent struct {
	tomb      tomb.Tomb
	Conf      AgentConf
	MachineId int
}

// Info returns usage information for the command.
func (a *MachineAgent) Info() *cmd.Info {
	return &cmd.Info{"machine", "", "run a juju machine agent", ""}
}

// Init initializes the command for running.
func (a *MachineAgent) Init(f *gnuflag.FlagSet, args []string) error {
	a.Conf.addFlags(f)
	f.IntVar(&a.MachineId, "machine-id", -1, "id of the machine to run")
	if err := f.Parse(true, args); err != nil {
		return err
	}
	if a.MachineId < 0 {
		return fmt.Errorf("--machine-id option must be set, and expects a non-negative integer")
	}
	return a.Conf.checkArgs(f.Args())
}

// Stop stops the machine agent.
func (a *MachineAgent) Stop() error {
	a.tomb.Kill(nil)
	return a.tomb.Wait()
}

// Run runs a machine agent.
func (a *MachineAgent) Run(_ *cmd.Context) error {
	defer a.tomb.Done()
	for {
		log.Printf("machine agent starting")
		err := a.runOnce()
		if err == nil {
			// We have been explicitly stopped.
			return nil
		}
		if ug, ok := err.(*UpgradedError); ok {
			tools, err := environs.ChangeAgentTools("machine", ug.Binary)
			if err != nil {
				log.Printf("cannot change agent tools: %v", err)
				time.Sleep(retryDelay)
				continue
			}
			log.Printf("upgrade to %v from %q", tools.Binary, tools.URL)
			// Return and let upstart deal with the restart.
			return nil
		}
		log.Printf("error from provisioner or firewaller: %v", err)
		time.Sleep(retryDelay)
	}
	panic("unreachable")
}

func (a *MachineAgent) runOnce() error {
	st, err := state.Open(&a.Conf.StateInfo)
	if err != nil {
		return err
	}
	defer st.Close()
	m, err := st.Machine(a.MachineId)
	if err != nil {
		return err
	}
	return runTasks(a.tomb.Dying(),
		machiner.NewMachiner(m),
		NewUpgrader("machine", m),
	)
}
<commit_msg>cmd/jujud: fix stopped check<commit_after>package main

import (
	"fmt"
	"launchpad.net/gnuflag"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/log"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/worker/machiner"
	"launchpad.net/tomb"
	"time"
)

// MachineAgent is a cmd.Command responsible for running a machine agent.
type MachineAgent struct {
	tomb      tomb.Tomb
	Conf      AgentConf
	MachineId int
}

// Info returns usage information for the command.
func (a *MachineAgent) Info() *cmd.Info {
	return &cmd.Info{"machine", "", "run a juju machine agent", ""}
}

// Init initializes the command for running.
func (a *MachineAgent) Init(f *gnuflag.FlagSet, args []string) error {
	a.Conf.addFlags(f)
	f.IntVar(&a.MachineId, "machine-id", -1, "id of the machine to run")
	if err := f.Parse(true, args); err != nil {
		return err
	}
	if a.MachineId < 0 {
		return fmt.Errorf("--machine-id option must be set, and expects a non-negative integer")
	}
	return a.Conf.checkArgs(f.Args())
}

// Stop stops the machine agent.
func (a *MachineAgent) Stop() error {
	a.tomb.Kill(nil)
	return a.tomb.Wait()
}

// Run runs a machine agent.
func (a *MachineAgent) Run(_ *cmd.Context) error {
	defer a.tomb.Done()
	for {
		log.Printf("machine agent starting")
		err := a.runOnce()
		if a.tomb.Err() != tomb.ErrStillAlive {
			// We have been explicitly stopped.
			return err
		}
		if ug, ok := err.(*UpgradedError); ok {
			tools, err := environs.ChangeAgentTools("machine", ug.Binary)
			if err != nil {
				log.Printf("cannot change agent tools: %v", err)
				time.Sleep(retryDelay)
				continue
			}
			log.Printf("exiting to upgrade to %v from %q", tools.Binary, tools.URL)
			// Return and let upstart deal with the restart.
			return nil
		}
		log.Printf("error from provisioner or firewaller: %v", err)
		time.Sleep(retryDelay)
	}
	panic("unreachable")
}

func (a *MachineAgent) runOnce() error {
	st, err := state.Open(&a.Conf.StateInfo)
	if err != nil {
		return err
	}
	defer st.Close()
	m, err := st.Machine(a.MachineId)
	if err != nil {
		return err
	}
	return runTasks(a.tomb.Dying(),
		machiner.NewMachiner(m),
		NewUpgrader("machine", m),
	)
}
<|endoftext|>


<commit_before>package storage

import (
	"log"
	"os"

	"github.com/khlieng/dispatch/Godeps/_workspace/src/github.com/boltdb/bolt"
)

var (
	appDir string
	db     *bolt.DB

	bucketUsers    = []byte("Users")
	bucketServers  = []byte("Servers")
	bucketChannels = []byte("Channels")
	bucketMessages = []byte("Messages")
)

func Initialize() {
	log.Println("Storing data at", Path.Root())

	var err error
	db, err = bolt.Open(Path.Database(), 0600, nil)
	if err != nil {
		log.Fatal("Could not open database:", err)
	}

	db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists(bucketUsers)
		tx.CreateBucketIfNotExists(bucketServers)
		tx.CreateBucketIfNotExists(bucketChannels)

		return nil
	})
}

func Close() {
	db.Close()
}

func Clear() {
	os.RemoveAll(Path.Logs())
	os.Remove(Path.Database())
}
<commit_msg>Remove unused variable appDir<commit_after>package storage

import (
	"log"
	"os"

	"github.com/khlieng/dispatch/Godeps/_workspace/src/github.com/boltdb/bolt"
)

var (
	db *bolt.DB

	bucketUsers    = []byte("Users")
	bucketServers  = []byte("Servers")
	bucketChannels = []byte("Channels")
	bucketMessages = []byte("Messages")
)

func Initialize() {
	log.Println("Storing data at", Path.Root())

	var err error
	db, err = bolt.Open(Path.Database(), 0600, nil)
	if err != nil {
		log.Fatal("Could not open database:", err)
	}

	db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists(bucketUsers)
		tx.CreateBucketIfNotExists(bucketServers)
		tx.CreateBucketIfNotExists(bucketChannels)

		return nil
	})
}

func Close() {
	db.Close()
}

func Clear() {
	os.RemoveAll(Path.Logs())
	os.Remove(Path.Database())
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"sort"
	"strconv"

	_ "code.google.com/p/go-sqlite/go1/sqlite3"
	"github.com/rwcarlsen/cyan/query"
)

var (
	help   = flag.Bool("h", false, "Print this help message")
	dbname = flag.String("db", "", "cyclus sqlite database to query")
	simid  = flag.String("simid", "", "simulation id (empty string defaults to first sim id in database")
)

var command string

var db *sql.DB

var cmds = NewCmdSet()

func init() {
	cmds.Register("agents", "list all agents in the simulation", doAgents)
	cmds.Register("sims", "list all simulations in the database", doSims)
	cmds.Register("inv", "show inventory of one or more agents at a specific timestep", doInv)
	cmds.Register("created", "show material created by one or more agents between specific timesteps", doCreated)
	cmds.Register("deployseries", "print a time-series of a prototype's total active deployments", doDeploySeries)
	cmds.Register("flow", "Show total transacted material between two groups of agents between specific timesteps", doFlow)
	cmds.Register("invseries", "print a time series of an agent's inventory for specified isotopes", doInvSeries)
	cmds.Register("flowgraph", "print a graphviz dot graph of resource arcs between facilities", doFlowGraph)
}

func main() {
	log.SetFlags(0)
	flag.Parse()

	if *help || flag.NArg() < 1 {
		fmt.Println("Usage: metric -db <cyclus-db> [opts] <command> [args...]")
		fmt.Println("Calculates metrics for cyclus simulation data in a sqlite database.")
		flag.PrintDefaults()
		fmt.Println("\nCommands:")
		for i := range cmds.Names {
			fmt.Printf("    - %v: %v\n", cmds.Names[i], cmds.Helps[i])
		}
		return
	} else if *dbname == "" {
		log.Fatal("must specify database with db flag")
	}

	var err error
	db, err = sql.Open("sqlite3", *dbname)
	fatalif(err)
	defer db.Close()

	if *simid == "" {
		ids, err := query.SimIds(db)
		fatalif(err)
		*simid = ids[0]
	}

	cmds.Execute(flag.Args())
}

func doSims(args []string) {
	ids, err := query.SimIds(db)
	fatalif(err)
	for _, id := range ids {
		info, err := query.SimStat(db, id)
		fatalif(err)
		fmt.Println(info)
	}
}

func doAgents(args []string) {
	ags, err := query.AllAgents(db, *simid)
	fatalif(err)
	for _, a := range ags {
		fmt.Println(a)
	}
}

func doInv(args []string) {
	fs := flag.NewFlagSet("inv", flag.ExitOnError)
	t := fs.Int("t", -1, "timestep of inventory (-1 = end of simulation)")
	fs.Usage = func() {
		log.Print("Usage: inv [agent-id...]\nZero agents uses all agent inventories")
		fs.PrintDefaults()
	}
	fs.Parse(args)

	var agents []int
	for _, arg := range fs.Args() {
		id, err := strconv.Atoi(arg)
		fatalif(err)
		agents = append(agents, id)
	}

	m, err := query.InvAt(db, *simid, *t, agents...)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

type Row struct {
	X  int
	Ys []float64
}

type MultiSeries [][]query.XY

func (ms MultiSeries) Rows() []Row {
	rowmap := map[int]Row{}
	xs := []int{}
	for i, s := range ms {
		for _, xy := range s {
			row, ok := rowmap[xy.X]
			if !ok {
				xs = append(xs, xy.X)
				row.Ys = make([]float64, len(ms))
				row.X = xy.X
			}
			row.Ys[i] = xy.Y
			rowmap[xy.X] = row
		}
	}

	sort.Ints(xs)
	rows := make([]Row, 0, len(rowmap))
	for _, x := range xs {
		rows = append(rows, rowmap[x])
	}
	return rows
}

func doInvSeries(args []string) {
	fs := flag.NewFlagSet("invseries", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: invseries <agent-id> <isotope> [isotope...]"); fs.PrintDefaults() }
	fs.Parse(args)
	if fs.NArg() < 2 {
		fs.Usage()
		return
	}

	agent, err := strconv.Atoi(fs.Arg(0))
	fatalif(err)

	isos := []int{}
	for _, arg := range fs.Args()[1:] {
		iso, err := strconv.Atoi(arg)
		fatalif(err)
		isos = append(isos, iso)
	}

	ms := MultiSeries{}
	for _, iso := range isos {
		xys, err := query.InvSeries(db, *simid, agent, iso)
		ms = append(ms, xys)
		fatalif(err)
	}

	fmt.Printf("# Agent %v inventory in kg\n", agent)
	fmt.Printf("# [Timestep]")
	for _, iso := range isos {
		fmt.Printf(" [%v]", iso)
	}
	fmt.Printf("\n")
	for _, row := range ms.Rows() {
		fmt.Printf("%v", row.X)
		for _, y := range row.Ys {
			fmt.Printf(" %v ", y)
		}
		fmt.Printf("\n")
	}
}

func doFlowGraph(args []string) {
	fs := flag.NewFlagSet("flowgraph", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: flowgraph"); fs.PrintDefaults() }
	proto := fs.Bool("proto", false, "aggregate nodes by prototype")
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Parse(args)

	arcs, err := query.FlowGraph(db, *simid, *t0, *t1, *proto)
	fatalif(err)

	fmt.Println("digraph ResourceFlows {")
	fmt.Println("    overlap = false;")
	fmt.Println("    nodesep=1.0;")
	fmt.Println("    edge [fontsize=9];")
	for _, arc := range arcs {
		fmt.Printf("    \"%v\" -> \"%v\" [label=\"%v\\n(%.3g kg)\"];\n", arc.Src, arc.Dst, arc.Commod, arc.Quantity)
	}
	fmt.Println("}")
}

func doDeploySeries(args []string) {
	fs := flag.NewFlagSet("deployseries", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: deployseries <prototype>"); fs.PrintDefaults() }
	fs.Parse(args)
	if fs.NArg() < 1 {
		fs.Usage()
		return
	}

	proto := fs.Arg(0)
	xys, err := query.DeployCumulative(db, *simid, proto)
	fatalif(err)

	fmt.Printf("# Prototype %v total active deployments\n", proto)
	fmt.Println("# [Timestep] [Count]")
	for _, xy := range xys {
		fmt.Printf("%v %v\n", xy.X, xy.Y)
	}
}

func doCreated(args []string) {
	fs := flag.NewFlagSet("created", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: created [agent-id...]\nZero agents uses all agents"); fs.PrintDefaults() }
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Parse(args)

	var agents []int

	for _, arg := range fs.Args() {
		id, err := strconv.Atoi(arg)
		fatalif(err)
		agents = append(agents, id)
	}

	m, err := query.MatCreated(db, *simid, *t0, *t1, agents...)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

func doFlow(args []string) {
	fs := flag.NewFlagSet("created", flag.ExitOnError)
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Usage = func() {
		log.Print("Usage: flow <from-agents...> .. <to-agents...>\nZero agents uses all agents")
		fs.PrintDefaults()
	}
	fs.Parse(args)

	var from []int
	var to []int

	if flag.NArg() < 3 {
		fs.Usage()
		return
	}

	before := true
	for _, arg := range flag.Args()[3:] {
		if arg == ".." {
			before = false
			continue
		}

		id, err := strconv.Atoi(arg)
		fatalif(err)
		if before {
			from = append(from, id)
		} else {
			to = append(to, id)
		}
	}
	if len(to) < 1 {
		fs.Usage()
		return
	}

	m, err := query.Flow(db, *simid, *t0, *t1, from, to)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

func fatalif(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

type CmdSet struct {
	funcs map[string]func([]string)
	Names []string
	Helps []string
}

func NewCmdSet() *CmdSet {
	return &CmdSet{funcs: map[string]func([]string){}}
}

func (cs *CmdSet) Register(name, brief string, f func([]string)) {
	cs.Names = append(cs.Names, name)
	cs.Helps = append(cs.Helps, brief)
	cs.funcs[name] = f
}

func (cs *CmdSet) Execute(args []string) {
	cmd := args[0]
	f, ok := cs.funcs[cmd]
	if !ok {
		log.Fatalf("Invalid command '%v'", cmd)
	}
	f(args[1:])
}
<commit_msg>added way to specify custom sql queries in a config file identified by -custom cli flag<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strconv"
	"text/tabwriter"

	_ "code.google.com/p/go-sqlite/go1/sqlite3"
	"github.com/rwcarlsen/cyan/query"
)

var (
	help   = flag.Bool("h", false, "print this help message")
	custom = flag.String("custom", "", "path to custom sql query spec file")
	dbname = flag.String("db", "", "cyclus sqlite database to query")
	simid  = flag.String("simid", "", "simulation id (empty string defaults to first sim id in database")
)

var command string

var db *sql.DB

var cmds = NewCmdSet()

// map[cmdname]sqltext
var customSql = map[string]string{}

func init() {
	cmds.Register("agents", "list all agents in the simulation", doAgents)
	cmds.Register("sims", "list all simulations in the database", doSims)
	cmds.Register("inv", "show inventory of one or more agents at a specific timestep", doInv)
	cmds.Register("created", "show material created by one or more agents between specific timesteps", doCreated)
	cmds.Register("deployseries", "print a time-series of a prototype's total active deployments", doDeploySeries)
	cmds.Register("flow", "Show total transacted material between two groups of agents between specific timesteps", doFlow)
	cmds.Register("invseries", "print a time series of an agent's inventory for specified isotopes", doInvSeries)
	cmds.Register("flowgraph", "print a graphviz dot graph of resource arcs between facilities", doFlowGraph)
}

func main() {
	log.SetFlags(0)
	flag.Parse()

	if *help || flag.NArg() < 1 {
		fmt.Println("Usage: metric -db <cyclus-db> [opts] <command> [args...]")
		fmt.Println("Calculates metrics for cyclus simulation data in a sqlite database.")
		flag.PrintDefaults()
		fmt.Println("\nCommands:")
		for i := range cmds.Names {
			fmt.Printf("    - %v: %v\n", cmds.Names[i], cmds.Helps[i])
		}
		return
	} else if *dbname == "" {
		log.Fatal("must specify database with db flag")
	}

	if *custom != "" {
		data, err := ioutil.ReadFile(*custom)
		fatalif(err)
		fatalif(json.Unmarshal(data, &customSql))
	}

	var err error
	db, err = sql.Open("sqlite3", *dbname)
	fatalif(err)
	defer db.Close()

	if *simid == "" {
		ids, err := query.SimIds(db)
		fatalif(err)
		*simid = ids[0]
	}

	cmds.Execute(flag.Args())
}

func doCustom(cmd string, oargs []string) {
	s, ok := customSql[cmd]
	if !ok {
		log.Fatalf("Invalid command %v", cmd)
	}
	args := make([]interface{}, len(oargs))
	for i := range args {
		args[i] = oargs[i]
	}
	rows, err := db.Query(s, args...)
	fatalif(err)

	tw := tabwriter.NewWriter(os.Stdout, 4, 4, 1, ' ', 0)
	cols, err := rows.Columns()
	fatalif(err)
	for _, c := range cols {
		_, err := tw.Write([]byte(c + "\t"))
		fatalif(err)
	}
	_, err = tw.Write([]byte("\n"))
	fatalif(err)

	for rows.Next() {
		vs := make([]interface{}, len(cols))
		vals := make([]string, len(cols))
		for i := range vals {
			vs[i] = &vals[i]
		}
		err := rows.Scan(vs...)
		fatalif(err)

		for _, v := range vals {
			_, err := tw.Write([]byte(v + "\t"))
			fatalif(err)
		}
		_, err = tw.Write([]byte("\n"))
		fatalif(err)
	}
	fatalif(rows.Err())
	fatalif(tw.Flush())
	return
}

func doSims(cmd string, args []string) {
	ids, err := query.SimIds(db)
	fatalif(err)
	for _, id := range ids {
		info, err := query.SimStat(db, id)
		fatalif(err)
		fmt.Println(info)
	}
}

func doAgents(cmd string, args []string) {
	ags, err := query.AllAgents(db, *simid)
	fatalif(err)
	for _, a := range ags {
		fmt.Println(a)
	}
}

func doInv(cmd string, args []string) {
	fs := flag.NewFlagSet("inv", flag.ExitOnError)
	t := fs.Int("t", -1, "timestep of inventory (-1 = end of simulation)")
	fs.Usage = func() {
		log.Print("Usage: inv [agent-id...]\nZero agents uses all agent inventories")
		fs.PrintDefaults()
	}
	fs.Parse(args)

	var agents []int
	for _, arg := range fs.Args() {
		id, err := strconv.Atoi(arg)
		fatalif(err)
		agents = append(agents, id)
	}

	m, err := query.InvAt(db, *simid, *t, agents...)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

type Row struct {
	X  int
	Ys []float64
}

type MultiSeries [][]query.XY

func (ms MultiSeries) Rows() []Row {
	rowmap := map[int]Row{}
	xs := []int{}
	for i, s := range ms {
		for _, xy := range s {
			row, ok := rowmap[xy.X]
			if !ok {
				xs = append(xs, xy.X)
				row.Ys = make([]float64, len(ms))
				row.X = xy.X
			}
			row.Ys[i] = xy.Y
			rowmap[xy.X] = row
		}
	}

	sort.Ints(xs)
	rows := make([]Row, 0, len(rowmap))
	for _, x := range xs {
		rows = append(rows, rowmap[x])
	}
	return rows
}

func doInvSeries(cmd string, args []string) {
	fs := flag.NewFlagSet("invseries", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: invseries <agent-id> <isotope> [isotope...]"); fs.PrintDefaults() }
	fs.Parse(args)
	if fs.NArg() < 2 {
		fs.Usage()
		return
	}

	agent, err := strconv.Atoi(fs.Arg(0))
	fatalif(err)

	isos := []int{}
	for _, arg := range fs.Args()[1:] {
		iso, err := strconv.Atoi(arg)
		fatalif(err)
		isos = append(isos, iso)
	}

	ms := MultiSeries{}
	for _, iso := range isos {
		xys, err := query.InvSeries(db, *simid, agent, iso)
		ms = append(ms, xys)
		fatalif(err)
	}

	fmt.Printf("# Agent %v inventory in kg\n", agent)
	fmt.Printf("# [Timestep]")
	for _, iso := range isos {
		fmt.Printf(" [%v]", iso)
	}
	fmt.Printf("\n")
	for _, row := range ms.Rows() {
		fmt.Printf("%v", row.X)
		for _, y := range row.Ys {
			fmt.Printf(" %v ", y)
		}
		fmt.Printf("\n")
	}
}

func doFlowGraph(cmd string, args []string) {
	fs := flag.NewFlagSet("flowgraph", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: flowgraph"); fs.PrintDefaults() }
	proto := fs.Bool("proto", false, "aggregate nodes by prototype")
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Parse(args)

	arcs, err := query.FlowGraph(db, *simid, *t0, *t1, *proto)
	fatalif(err)

	fmt.Println("digraph ResourceFlows {")
	fmt.Println("    overlap = false;")
	fmt.Println("    nodesep=1.0;")
	fmt.Println("    edge [fontsize=9];")
	for _, arc := range arcs {
		fmt.Printf("    \"%v\" -> \"%v\" [label=\"%v\\n(%.3g kg)\"];\n", arc.Src, arc.Dst, arc.Commod, arc.Quantity)
	}
	fmt.Println("}")
}

func doDeploySeries(cmd string, args []string) {
	fs := flag.NewFlagSet("deployseries", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: deployseries <prototype>"); fs.PrintDefaults() }
	fs.Parse(args)
	if fs.NArg() < 1 {
		fs.Usage()
		return
	}

	proto := fs.Arg(0)
	xys, err := query.DeployCumulative(db, *simid, proto)
	fatalif(err)

	fmt.Printf("# Prototype %v total active deployments\n", proto)
	fmt.Println("# [Timestep] [Count]")
	for _, xy := range xys {
		fmt.Printf("%v %v\n", xy.X, xy.Y)
	}
}

func doCreated(cmd string, args []string) {
	fs := flag.NewFlagSet("created", flag.ExitOnError)
	fs.Usage = func() { log.Print("Usage: created [agent-id...]\nZero agents uses all agents"); fs.PrintDefaults() }
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Parse(args)

	var agents []int

	for _, arg := range fs.Args() {
		id, err := strconv.Atoi(arg)
		fatalif(err)
		agents = append(agents, id)
	}

	m, err := query.MatCreated(db, *simid, *t0, *t1, agents...)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

func doFlow(cmd string, args []string) {
	fs := flag.NewFlagSet("created", flag.ExitOnError)
	t0 := fs.Int("t1", -1, "beginning of time interval (default is beginning of simulation)")
	t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)")
	fs.Usage = func() {
		log.Print("Usage: flow <from-agents...> .. <to-agents...>\nZero agents uses all agents")
		fs.PrintDefaults()
	}
	fs.Parse(args)

	var from []int
	var to []int

	if flag.NArg() < 3 {
		fs.Usage()
		return
	}

	before := true
	for _, arg := range flag.Args()[3:] {
		if arg == ".." {
			before = false
			continue
		}

		id, err := strconv.Atoi(arg)
		fatalif(err)
		if before {
			from = append(from, id)
		} else {
			to = append(to, id)
		}
	}
	if len(to) < 1 {
		fs.Usage()
		return
	}

	m, err := query.Flow(db, *simid, *t0, *t1, from, to)
	fatalif(err)
	fmt.Printf("%+v\n", m)
}

func fatalif(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

type CmdSet struct {
	funcs map[string]func(string, []string) // map[cmdname]func(cmdname, args)
	Names []string
	Helps []string
}

func NewCmdSet() *CmdSet {
	return &CmdSet{funcs: map[string]func(string, []string){}}
}

func (cs *CmdSet) Register(name, brief string, f func(string, []string)) {
	cs.Names = append(cs.Names, name)
	cs.Helps = append(cs.Helps, brief)
	cs.funcs[name] = f
}

func (cs *CmdSet) Execute(args []string) {
	cmd := args[0]
	f, ok := cs.funcs[cmd]
	if !ok {
		doCustom(cmd, args[1:])
		return
	}
	f(cmd, args[1:])
}
<|endoftext|>


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

package draw

import (
	"image"
	"testing"
)

func eq(c0, c1 image.Color) bool {
	r0, g0, b0, a0 := c0.RGBA()
	r1, g1, b1, a1 := c1.RGBA()
	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
}

func fillBlue(alpha int) image.Image {
	return image.ColorImage{image.RGBAColor{0, 0, uint8(alpha), uint8(alpha)}}
}

func fillAlpha(alpha int) image.Image {
	return image.ColorImage{image.AlphaColor{uint8(alpha)}}
}

func vgradGreen(alpha int) image.Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{0, uint8(y * alpha / 15), 0, uint8(alpha)})
		}
	}
	return m
}

func vgradAlpha(alpha int) image.Image {
	m := image.NewAlpha(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.AlphaColor{uint8(y * alpha / 15)})
		}
	}
	return m
}

func hgradRed(alpha int) Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
		}
	}
	return m
}

func gradYellow(alpha int) Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
		}
	}
	return m
}

type drawTest struct {
	desc     string
	src      image.Image
	mask     image.Image
	op       Op
	expected image.Color
}

var drawTests = []drawTest{
	// Uniform mask (0% opaque).
	drawTest{"nop", vgradGreen(255), fillAlpha(0), Over, image.RGBAColor{136, 0, 0, 255}},
	drawTest{"clear", vgradGreen(255), fillAlpha(0), Src, image.RGBAColor{0, 0, 0, 0}},
	// Uniform mask (100%, 75%, nil) and uniform source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 0, 90, 90}.
	drawTest{"fill", fillBlue(90), fillAlpha(255), Over, image.RGBAColor{88, 0, 90, 255}},
	drawTest{"fillSrc", fillBlue(90), fillAlpha(255), Src, image.RGBAColor{0, 0, 90, 90}},
	drawTest{"fillAlpha", fillBlue(90), fillAlpha(192), Over, image.RGBAColor{100, 0, 68, 255}},
	drawTest{"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, image.RGBAColor{0, 0, 68, 68}},
	drawTest{"fillNil", fillBlue(90), nil, Over, image.RGBAColor{88, 0, 90, 255}},
	drawTest{"fillNilSrc", fillBlue(90), nil, Src, image.RGBAColor{0, 0, 90, 90}},
	// Uniform mask (100%, 75%, nil) and variable source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 48, 0, 90}.
	drawTest{"copy", vgradGreen(90), fillAlpha(255), Over, image.RGBAColor{88, 48, 0, 255}},
	drawTest{"copySrc", vgradGreen(90), fillAlpha(255), Src, image.RGBAColor{0, 48, 0, 90}},
	drawTest{"copyAlpha", vgradGreen(90), fillAlpha(192), Over, image.RGBAColor{100, 36, 0, 255}},
	drawTest{"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, image.RGBAColor{0, 36, 0, 68}},
	drawTest{"copyNil", vgradGreen(90), nil, Over, image.RGBAColor{88, 48, 0, 255}},
	drawTest{"copyNilSrc", vgradGreen(90), nil, Src, image.RGBAColor{0, 48, 0, 90}},
	// Variable mask and variable source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 0, 255, 255}.
	// The mask pixel's alpha is 102, or 40%.
	drawTest{"generic", fillBlue(255), vgradAlpha(192), Over, image.RGBAColor{81, 0, 102, 255}},
	drawTest{"genericSrc", fillBlue(255), vgradAlpha(192), Src, image.RGBAColor{0, 0, 102, 102}},
}

func makeGolden(dst, src, mask image.Image, op Op) image.Image {
	// Since golden is a newly allocated image, we don't have to check if the
	// input source and mask images and the output golden image overlap.
	b := dst.Bounds()
	sx0 := src.Bounds().Min.X - b.Min.X
	sy0 := src.Bounds().Min.Y - b.Min.Y
	var mx0, my0 int
	if mask != nil {
		mx0 = mask.Bounds().Min.X - b.Min.X
		my0 = mask.Bounds().Min.Y - b.Min.Y
	}
	golden := image.NewRGBA(b.Max.X, b.Max.Y)
	for y := b.Min.Y; y < b.Max.Y; y++ {
		my, sy := my0+y, sy0+y
		for x := b.Min.X; x < b.Max.X; x++ {
			mx, sx := mx0+x, sx0+x
			const M = 1<<16 - 1
			var dr, dg, db, da uint32
			if op == Over {
				dr, dg, db, da = dst.At(x, y).RGBA()
			}
			sr, sg, sb, sa := src.At(sx, sy).RGBA()
			ma := uint32(M)
			if mask != nil {
				_, _, _, ma = mask.At(mx, my).RGBA()
			}
			a := M - (sa * ma / M)
			golden.Set(x, y, image.RGBA64Color{
				uint16((dr*a + sr*ma) / M),
				uint16((dg*a + sg*ma) / M),
				uint16((db*a + sb*ma) / M),
				uint16((da*a + sa*ma) / M),
			})
		}
	}
	golden.Rect = b
	return golden
}

func TestDraw(t *testing.T) {
loop:
	for _, test := range drawTests {
		dst := hgradRed(255)
		// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
		golden := makeGolden(dst, test.src, test.mask, test.op)
		b := dst.Bounds()
		if !b.Eq(golden.Bounds()) {
			t.Errorf("draw %s: bounds %v versus %v", test.desc, dst.Bounds(), golden.Bounds())
			continue
		}
		// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
		DrawMask(dst, b, test.src, image.ZP, test.mask, image.ZP, test.op)
		// Check that the resultant pixel at (8, 8) matches what we expect
		// (the expected value can be verified by hand).
		if !eq(dst.At(8, 8), test.expected) {
			t.Errorf("draw %s: at (8, 8) %v versus %v", test.desc, dst.At(8, 8), test.expected)
			continue
		}
		// Check that the resultant dst image matches the golden output.
		for y := b.Min.Y; y < b.Max.Y; y++ {
			for x := b.Min.X; x < b.Max.X; x++ {
				if !eq(dst.At(x, y), golden.At(x, y)) {
					t.Errorf("draw %s: at (%d, %d), %v versus golden %v", test.desc, x, y, dst.At(x, y), golden.At(x, y))
					continue loop
				}
			}
		}
	}
}

func TestDrawOverlap(t *testing.T) {
	for _, op := range []Op{Over, Src} {
		for yoff := -2; yoff <= 2; yoff++ {
		loop:
			for xoff := -2; xoff <= 2; xoff++ {
				m := gradYellow(127).(*image.RGBA)
				dst := &image.RGBA{
					Pix:    m.Pix,
					Stride: m.Stride,
					Rect:   image.Rect(5, 5, 10, 10),
				}
				src := &image.RGBA{
					Pix:    m.Pix,
					Stride: m.Stride,
					Rect:   image.Rect(5+xoff, 5+yoff, 10+xoff, 10+yoff),
				}
				// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
				golden := makeGolden(dst, src, nil, op)
				b := dst.Bounds()
				if !b.Eq(golden.Bounds()) {
					t.Errorf("drawOverlap xoff=%d,yoff=%d: bounds %v versus %v", xoff, yoff, dst.Bounds(), golden.Bounds())
					continue
				}
				// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
				DrawMask(dst, b, src, src.Bounds().Min, nil, image.ZP, op)
				// Check that the resultant dst image matches the golden output.
				for y := b.Min.Y; y < b.Max.Y; y++ {
					for x := b.Min.X; x < b.Max.X; x++ {
						if !eq(dst.At(x, y), golden.At(x, y)) {
							t.Errorf("drawOverlap xoff=%d,yoff=%d: at (%d, %d), %v versus golden %v", xoff, yoff, x, y, dst.At(x, y), golden.At(x, y))
							continue loop
						}
					}
				}
			}
		}
	}
}

// TestIssue836 verifies http://code.google.com/p/go/issues/detail?id=836.
func TestIssue836(t *testing.T) {
	a := image.NewRGBA(1, 1)
	b := image.NewRGBA(2, 2)
	b.Set(0, 0, image.RGBAColor{0, 0, 0, 5})
	b.Set(1, 0, image.RGBAColor{0, 0, 5, 5})
	b.Set(0, 1, image.RGBAColor{0, 5, 0, 5})
	b.Set(1, 1, image.RGBAColor{5, 0, 0, 5})
	Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1))
	if !eq(image.RGBAColor{5, 0, 0, 5}, a.At(0, 0)) {
		t.Errorf("Issue 836: want %v got %v", image.RGBAColor{5, 0, 0, 5}, a.At(0, 0))
	}
}
<commit_msg>exp/draw: unbreak build.<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package draw

import (
	"image"
	"testing"
)

func eq(c0, c1 image.Color) bool {
	r0, g0, b0, a0 := c0.RGBA()
	r1, g1, b1, a1 := c1.RGBA()
	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
}

func fillBlue(alpha int) image.Image {
	return image.NewColorImage(image.RGBAColor{0, 0, uint8(alpha), uint8(alpha)})
}

func fillAlpha(alpha int) image.Image {
	return image.NewColorImage(image.AlphaColor{uint8(alpha)})
}

func vgradGreen(alpha int) image.Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{0, uint8(y * alpha / 15), 0, uint8(alpha)})
		}
	}
	return m
}

func vgradAlpha(alpha int) image.Image {
	m := image.NewAlpha(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.AlphaColor{uint8(y * alpha / 15)})
		}
	}
	return m
}

func hgradRed(alpha int) Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
		}
	}
	return m
}

func gradYellow(alpha int) Image {
	m := image.NewRGBA(16, 16)
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
		}
	}
	return m
}

type drawTest struct {
	desc     string
	src      image.Image
	mask     image.Image
	op       Op
	expected image.Color
}

var drawTests = []drawTest{
	// Uniform mask (0% opaque).
	drawTest{"nop", vgradGreen(255), fillAlpha(0), Over, image.RGBAColor{136, 0, 0, 255}},
	drawTest{"clear", vgradGreen(255), fillAlpha(0), Src, image.RGBAColor{0, 0, 0, 0}},
	// Uniform mask (100%, 75%, nil) and uniform source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 0, 90, 90}.
	drawTest{"fill", fillBlue(90), fillAlpha(255), Over, image.RGBAColor{88, 0, 90, 255}},
	drawTest{"fillSrc", fillBlue(90), fillAlpha(255), Src, image.RGBAColor{0, 0, 90, 90}},
	drawTest{"fillAlpha", fillBlue(90), fillAlpha(192), Over, image.RGBAColor{100, 0, 68, 255}},
	drawTest{"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, image.RGBAColor{0, 0, 68, 68}},
	drawTest{"fillNil", fillBlue(90), nil, Over, image.RGBAColor{88, 0, 90, 255}},
	drawTest{"fillNilSrc", fillBlue(90), nil, Src, image.RGBAColor{0, 0, 90, 90}},
	// Uniform mask (100%, 75%, nil) and variable source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 48, 0, 90}.
	drawTest{"copy", vgradGreen(90), fillAlpha(255), Over, image.RGBAColor{88, 48, 0, 255}},
	drawTest{"copySrc", vgradGreen(90), fillAlpha(255), Src, image.RGBAColor{0, 48, 0, 90}},
	drawTest{"copyAlpha", vgradGreen(90), fillAlpha(192), Over, image.RGBAColor{100, 36, 0, 255}},
	drawTest{"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, image.RGBAColor{0, 36, 0, 68}},
	drawTest{"copyNil", vgradGreen(90), nil, Over, image.RGBAColor{88, 48, 0, 255}},
	drawTest{"copyNilSrc", vgradGreen(90), nil, Src, image.RGBAColor{0, 48, 0, 90}},
	// Variable mask and variable source.
	// At (x, y) == (8, 8):
	// The destination pixel is {136, 0, 0, 255}.
	// The source pixel is {0, 0, 255, 255}.
	// The mask pixel's alpha is 102, or 40%.
	drawTest{"generic", fillBlue(255), vgradAlpha(192), Over, image.RGBAColor{81, 0, 102, 255}},
	drawTest{"genericSrc", fillBlue(255), vgradAlpha(192), Src, image.RGBAColor{0, 0, 102, 102}},
}

func makeGolden(dst, src, mask image.Image, op Op) image.Image {
	// Since golden is a newly allocated image, we don't have to check if the
	// input source and mask images and the output golden image overlap.
	b := dst.Bounds()
	sx0 := src.Bounds().Min.X - b.Min.X
	sy0 := src.Bounds().Min.Y - b.Min.Y
	var mx0, my0 int
	if mask != nil {
		mx0 = mask.Bounds().Min.X - b.Min.X
		my0 = mask.Bounds().Min.Y - b.Min.Y
	}
	golden := image.NewRGBA(b.Max.X, b.Max.Y)
	for y := b.Min.Y; y < b.Max.Y; y++ {
		my, sy := my0+y, sy0+y
		for x := b.Min.X; x < b.Max.X; x++ {
			mx, sx := mx0+x, sx0+x
			const M = 1<<16 - 1
			var dr, dg, db, da uint32
			if op == Over {
				dr, dg, db, da = dst.At(x, y).RGBA()
			}
			sr, sg, sb, sa := src.At(sx, sy).RGBA()
			ma := uint32(M)
			if mask != nil {
				_, _, _, ma = mask.At(mx, my).RGBA()
			}
			a := M - (sa * ma / M)
			golden.Set(x, y, image.RGBA64Color{
				uint16((dr*a + sr*ma) / M),
				uint16((dg*a + sg*ma) / M),
				uint16((db*a + sb*ma) / M),
				uint16((da*a + sa*ma) / M),
			})
		}
	}
	golden.Rect = b
	return golden
}

func TestDraw(t *testing.T) {
loop:
	for _, test := range drawTests {
		dst := hgradRed(255)
		// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
		golden := makeGolden(dst, test.src, test.mask, test.op)
		b := dst.Bounds()
		if !b.Eq(golden.Bounds()) {
			t.Errorf("draw %s: bounds %v versus %v", test.desc, dst.Bounds(), golden.Bounds())
			continue
		}
		// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
		DrawMask(dst, b, test.src, image.ZP, test.mask, image.ZP, test.op)
		// Check that the resultant pixel at (8, 8) matches what we expect
		// (the expected value can be verified by hand).
		if !eq(dst.At(8, 8), test.expected) {
			t.Errorf("draw %s: at (8, 8) %v versus %v", test.desc, dst.At(8, 8), test.expected)
			continue
		}
		// Check that the resultant dst image matches the golden output.
		for y := b.Min.Y; y < b.Max.Y; y++ {
			for x := b.Min.X; x < b.Max.X; x++ {
				if !eq(dst.At(x, y), golden.At(x, y)) {
					t.Errorf("draw %s: at (%d, %d), %v versus golden %v", test.desc, x, y, dst.At(x, y), golden.At(x, y))
					continue loop
				}
			}
		}
	}
}

func TestDrawOverlap(t *testing.T) {
	for _, op := range []Op{Over, Src} {
		for yoff := -2; yoff <= 2; yoff++ {
		loop:
			for xoff := -2; xoff <= 2; xoff++ {
				m := gradYellow(127).(*image.RGBA)
				dst := &image.RGBA{
					Pix:    m.Pix,
					Stride: m.Stride,
					Rect:   image.Rect(5, 5, 10, 10),
				}
				src := &image.RGBA{
					Pix:    m.Pix,
					Stride: m.Stride,
					Rect:   image.Rect(5+xoff, 5+yoff, 10+xoff, 10+yoff),
				}
				// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
				golden := makeGolden(dst, src, nil, op)
				b := dst.Bounds()
				if !b.Eq(golden.Bounds()) {
					t.Errorf("drawOverlap xoff=%d,yoff=%d: bounds %v versus %v", xoff, yoff, dst.Bounds(), golden.Bounds())
					continue
				}
				// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
				DrawMask(dst, b, src, src.Bounds().Min, nil, image.ZP, op)
				// Check that the resultant dst image matches the golden output.
				for y := b.Min.Y; y < b.Max.Y; y++ {
					for x := b.Min.X; x < b.Max.X; x++ {
						if !eq(dst.At(x, y), golden.At(x, y)) {
							t.Errorf("drawOverlap xoff=%d,yoff=%d: at (%d, %d), %v versus golden %v", xoff, yoff, x, y, dst.At(x, y), golden.At(x, y))
							continue loop
						}
					}
				}
			}
		}
	}
}

// TestIssue836 verifies http://code.google.com/p/go/issues/detail?id=836.
func TestIssue836(t *testing.T) {
	a := image.NewRGBA(1, 1)
	b := image.NewRGBA(2, 2)
	b.Set(0, 0, image.RGBAColor{0, 0, 0, 5})
	b.Set(1, 0, image.RGBAColor{0, 0, 5, 5})
	b.Set(0, 1, image.RGBAColor{0, 5, 0, 5})
	b.Set(1, 1, image.RGBAColor{5, 0, 0, 5})
	Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1))
	if !eq(image.RGBAColor{5, 0, 0, 5}, a.At(0, 0)) {
		t.Errorf("Issue 836: want %v got %v", image.RGBAColor{5, 0, 0, 5}, a.At(0, 0))
	}
}
<|endoftext|>


<commit_before>package raft

import (
	"reflect"
	"runtime"
	"testing"
	"time"

	"github.com/coreos/etcd/raft/raftpb"
	"github.com/coreos/etcd/third_party/code.google.com/p/go.net/context"
)

// TestNodeStep ensures that node.Step sends msgProp to propc chan
// and other kinds of messages to recvc chan.
func TestNodeStep(t *testing.T) {
	for i := range mtmap {
		n := &Node{
			propc: make(chan raftpb.Message, 1),
			recvc: make(chan raftpb.Message, 1),
		}
		n.Step(context.TODO(), raftpb.Message{Type: int64(i)})
		// Proposal goes to proc chan. Others go to recvc chan.
		if int64(i) == msgProp {
			select {
			case <-n.propc:
			default:
				t.Errorf("%d: cannot receive %s on propc chan", i, mtmap[i])
			}
		} else {
			select {
			case <-n.recvc:
			default:
				t.Errorf("%d: cannot receive %s on recvc chan", i, mtmap[i])
			}
		}
	}
}

// Cancel and Stop should unblock Step()
func TestNodeStepUnblock(t *testing.T) {
	// a node without buffer to block step
	n := &Node{
		propc: make(chan raftpb.Message),
		done:  make(chan struct{}),
	}

	ctx, cancel := context.WithCancel(context.Background())
	stopFunc := func() { close(n.done) }

	tests := []struct {
		unblock func()
		werr    error
	}{
		{stopFunc, ErrStopped},
		{cancel, context.Canceled},
	}

	for i, tt := range tests {
		errc := make(chan error, 1)
		go func() {
			err := n.Step(ctx, raftpb.Message{Type: msgProp})
			errc <- err
		}()
		tt.unblock()
		select {
		case err := <-errc:
			if err != tt.werr {
				t.Errorf("#%d: err = %v, want %v", err, tt.werr)
			}
			//clean up side-effect
			if ctx.Err() != nil {
				ctx = context.TODO()
			}
			select {
			case <-n.done:
				n.done = make(chan struct{})
			default:
			}
		case <-time.After(time.Millisecond * 100):
			t.Errorf("#%d: failed to unblock step", i)
		}
	}
}

// TestBlockProposal ensures that node will block proposal when it does not
// know who is the current leader; node will accept proposal when it knows
// who is the current leader.
func TestBlockProposal(t *testing.T) {
	n := newNode()
	defer n.Stop()
	r := newRaft(1, []int64{1}, 10, 1)
	go n.run(r)

	errc := make(chan error, 1)
	go func() {
		errc <- n.Propose(context.TODO(), []byte("somedata"))
	}()

	forceGosched()
	select {
	case err := <-errc:
		t.Errorf("err = %v, want blocking", err)
	default:
	}

	n.Campaign(context.TODO())
	forceGosched()
	select {
	case err := <-errc:
		if err != nil {
			t.Errorf("err = %v, want %v", err, nil)
		}
	default:
		t.Errorf("blocking proposal, want unblocking")
	}
}

func TestReadyContainUpdates(t *testing.T) {
	tests := []struct {
		rd       Ready
		wcontain bool
	}{
		{Ready{}, false},
		{Ready{State: raftpb.State{Vote: 1}}, true},
		{Ready{Entries: make([]raftpb.Entry, 1, 1)}, true},
		{Ready{CommittedEntries: make([]raftpb.Entry, 1, 1)}, true},
		{Ready{Messages: make([]raftpb.Message, 1, 1)}, true},
	}

	for i, tt := range tests {
		if tt.rd.containsUpdates() != tt.wcontain {
			t.Errorf("#%d: containUpdates = %v, want %v", i, tt.rd.containsUpdates(), tt.wcontain)
		}
	}
}

func TestNode(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	wants := []Ready{
		{
			State:            raftpb.State{Term: 1, Vote: -1, Commit: 1, LastIndex: 1},
			Entries:          []raftpb.Entry{{Term: 1, Index: 1}},
			CommittedEntries: []raftpb.Entry{{Term: 1, Index: 1}},
		},
		{
			State:            raftpb.State{Term: 1, Vote: -1, Commit: 2, LastIndex: 2},
			Entries:          []raftpb.Entry{{Term: 1, Index: 2, Data: []byte("foo")}},
			CommittedEntries: []raftpb.Entry{{Term: 1, Index: 2, Data: []byte("foo")}},
		},
	}

	n := Start(1, []int64{1}, 0, 0)
	n.Campaign(ctx)
	if g := <-n.Ready(); !reflect.DeepEqual(g, wants[0]) {
		t.Errorf("#%d: g = %+v,\n             w   %+v", 1, g, wants[0])
	}

	n.Propose(ctx, []byte("foo"))
	if g := <-n.Ready(); !reflect.DeepEqual(g, wants[1]) {
		t.Errorf("#%d: g = %+v,\n             w   %+v", 2, g, wants[1])
	}

	select {
	case rd := <-n.Ready():
		t.Errorf("unexpected Ready: %+v", rd)
	default:
	}
}

func TestNodeRestart(t *testing.T) {
	entries := []raftpb.Entry{
		{Term: 1, Index: 1},
		{Term: 1, Index: 2, Data: []byte("foo")},
	}
	st := raftpb.State{Term: 1, Vote: -1, Commit: 1, LastIndex: 2}

	want := Ready{
		State: emptyState,
		// commit upto index commit index in st
		CommittedEntries: entries[:st.Commit],
	}

	n := Restart(1, []int64{1}, 0, 0, st, entries)
	if g := <-n.Ready(); !reflect.DeepEqual(g, want) {
		t.Errorf("g = %+v,\n             w   %+v", g, want)
	}

	select {
	case rd := <-n.Ready():
		t.Errorf("unexpected Ready: %+v", rd)
	default:
	}
}

func TestIsStateEqual(t *testing.T) {
	tests := []struct {
		st raftpb.State
		we bool
	}{
		{emptyState, true},
		{raftpb.State{Vote: 1}, false},
		{raftpb.State{Commit: 1}, false},
		{raftpb.State{Term: 1}, false},
		{raftpb.State{LastIndex: 1}, false},
	}

	for i, tt := range tests {
		if isStateEqual(tt.st, emptyState) != tt.we {
			t.Errorf("#%d, equal = %v, want %v", i, isStateEqual(tt.st, emptyState), tt.we)
		}
	}
}

// WARNING: This is a hack.
// Remove this when we are able to block/check the status of the go-routines.
func forceGosched() {
	// possibility enough to sched upto 10 go routines.
	for i := 0; i < 10000; i++ {
		runtime.Gosched()
	}
}
<commit_msg>raft: move defer after run<commit_after>package raft

import (
	"reflect"
	"runtime"
	"testing"
	"time"

	"github.com/coreos/etcd/raft/raftpb"
	"github.com/coreos/etcd/third_party/code.google.com/p/go.net/context"
)

// TestNodeStep ensures that node.Step sends msgProp to propc chan
// and other kinds of messages to recvc chan.
func TestNodeStep(t *testing.T) {
	for i := range mtmap {
		n := &Node{
			propc: make(chan raftpb.Message, 1),
			recvc: make(chan raftpb.Message, 1),
		}
		n.Step(context.TODO(), raftpb.Message{Type: int64(i)})
		// Proposal goes to proc chan. Others go to recvc chan.
		if int64(i) == msgProp {
			select {
			case <-n.propc:
			default:
				t.Errorf("%d: cannot receive %s on propc chan", i, mtmap[i])
			}
		} else {
			select {
			case <-n.recvc:
			default:
				t.Errorf("%d: cannot receive %s on recvc chan", i, mtmap[i])
			}
		}
	}
}

// Cancel and Stop should unblock Step()
func TestNodeStepUnblock(t *testing.T) {
	// a node without buffer to block step
	n := &Node{
		propc: make(chan raftpb.Message),
		done:  make(chan struct{}),
	}

	ctx, cancel := context.WithCancel(context.Background())
	stopFunc := func() { close(n.done) }

	tests := []struct {
		unblock func()
		werr    error
	}{
		{stopFunc, ErrStopped},
		{cancel, context.Canceled},
	}

	for i, tt := range tests {
		errc := make(chan error, 1)
		go func() {
			err := n.Step(ctx, raftpb.Message{Type: msgProp})
			errc <- err
		}()
		tt.unblock()
		select {
		case err := <-errc:
			if err != tt.werr {
				t.Errorf("#%d: err = %v, want %v", err, tt.werr)
			}
			//clean up side-effect
			if ctx.Err() != nil {
				ctx = context.TODO()
			}
			select {
			case <-n.done:
				n.done = make(chan struct{})
			default:
			}
		case <-time.After(time.Millisecond * 100):
			t.Errorf("#%d: failed to unblock step", i)
		}
	}
}

// TestBlockProposal ensures that node will block proposal when it does not
// know who is the current leader; node will accept proposal when it knows
// who is the current leader.
func TestBlockProposal(t *testing.T) {
	n := newNode()
	r := newRaft(1, []int64{1}, 10, 1)
	go n.run(r)
	defer n.Stop()

	errc := make(chan error, 1)
	go func() {
		errc <- n.Propose(context.TODO(), []byte("somedata"))
	}()

	forceGosched()
	select {
	case err := <-errc:
		t.Errorf("err = %v, want blocking", err)
	default:
	}

	n.Campaign(context.TODO())
	forceGosched()
	select {
	case err := <-errc:
		if err != nil {
			t.Errorf("err = %v, want %v", err, nil)
		}
	default:
		t.Errorf("blocking proposal, want unblocking")
	}
}

func TestReadyContainUpdates(t *testing.T) {
	tests := []struct {
		rd       Ready
		wcontain bool
	}{
		{Ready{}, false},
		{Ready{State: raftpb.State{Vote: 1}}, true},
		{Ready{Entries: make([]raftpb.Entry, 1, 1)}, true},
		{Ready{CommittedEntries: make([]raftpb.Entry, 1, 1)}, true},
		{Ready{Messages: make([]raftpb.Message, 1, 1)}, true},
	}

	for i, tt := range tests {
		if tt.rd.containsUpdates() != tt.wcontain {
			t.Errorf("#%d: containUpdates = %v, want %v", i, tt.rd.containsUpdates(), tt.wcontain)
		}
	}
}

func TestNode(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	wants := []Ready{
		{
			State:            raftpb.State{Term: 1, Vote: -1, Commit: 1, LastIndex: 1},
			Entries:          []raftpb.Entry{{Term: 1, Index: 1}},
			CommittedEntries: []raftpb.Entry{{Term: 1, Index: 1}},
		},
		{
			State:            raftpb.State{Term: 1, Vote: -1, Commit: 2, LastIndex: 2},
			Entries:          []raftpb.Entry{{Term: 1, Index: 2, Data: []byte("foo")}},
			CommittedEntries: []raftpb.Entry{{Term: 1, Index: 2, Data: []byte("foo")}},
		},
	}

	n := Start(1, []int64{1}, 0, 0)
	n.Campaign(ctx)
	if g := <-n.Ready(); !reflect.DeepEqual(g, wants[0]) {
		t.Errorf("#%d: g = %+v,\n             w   %+v", 1, g, wants[0])
	}

	n.Propose(ctx, []byte("foo"))
	if g := <-n.Ready(); !reflect.DeepEqual(g, wants[1]) {
		t.Errorf("#%d: g = %+v,\n             w   %+v", 2, g, wants[1])
	}

	select {
	case rd := <-n.Ready():
		t.Errorf("unexpected Ready: %+v", rd)
	default:
	}
}

func TestNodeRestart(t *testing.T) {
	entries := []raftpb.Entry{
		{Term: 1, Index: 1},
		{Term: 1, Index: 2, Data: []byte("foo")},
	}
	st := raftpb.State{Term: 1, Vote: -1, Commit: 1, LastIndex: 2}

	want := Ready{
		State: emptyState,
		// commit upto index commit index in st
		CommittedEntries: entries[:st.Commit],
	}

	n := Restart(1, []int64{1}, 0, 0, st, entries)
	if g := <-n.Ready(); !reflect.DeepEqual(g, want) {
		t.Errorf("g = %+v,\n             w   %+v", g, want)
	}

	select {
	case rd := <-n.Ready():
		t.Errorf("unexpected Ready: %+v", rd)
	default:
	}
}

func TestIsStateEqual(t *testing.T) {
	tests := []struct {
		st raftpb.State
		we bool
	}{
		{emptyState, true},
		{raftpb.State{Vote: 1}, false},
		{raftpb.State{Commit: 1}, false},
		{raftpb.State{Term: 1}, false},
		{raftpb.State{LastIndex: 1}, false},
	}

	for i, tt := range tests {
		if isStateEqual(tt.st, emptyState) != tt.we {
			t.Errorf("#%d, equal = %v, want %v", i, isStateEqual(tt.st, emptyState), tt.we)
		}
	}
}

// WARNING: This is a hack.
// Remove this when we are able to block/check the status of the go-routines.
func forceGosched() {
	// possibility enough to sched upto 10 go routines.
	for i := 0; i < 10000; i++ {
		runtime.Gosched()
	}
}
<|endoftext|>


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

package lcio

import (
	"bytes"
	"fmt"
	"strings"

	"go-hep.org/x/hep/sio"
)

type RawCalorimeterHits struct {
	Flags  Flags
	Params Params
	Hits   []RawCalorimeterHit
}

func (hits RawCalorimeterHits) String() string {
	o := new(bytes.Buffer)
	fmt.Fprintf(o, "%[1]s print out of RawCalorimeterHit collection %[1]s\n\n", strings.Repeat("-", 15))
	fmt.Fprintf(o, "  flag:  0x%x\n%v", hits.Flags, hits.Params)
	fmt.Fprintf(o, "     LCIO::RCHBIT_ID1    : %v\n", hits.Flags.Test(BitsRChID1))
	fmt.Fprintf(o, "     LCIO::RCHBIT_TIME   : %v\n", hits.Flags.Test(BitsRChTime))
	fmt.Fprintf(o, "     LCIO::RCHBIT_NO_PTR : %v\n", hits.Flags.Test(BitsRChNoPtr))

	// FIXME(sbinet): CellIDDecoder

	fmt.Fprintf(o, "\n")

	head := " [   id   ] |  cellId0 ( M, S, I, J, K) |cellId1 | amplitude |  time  \n"
	tail := "------------|---------------------------|--------|-----------|---------\n"
	fmt.Fprintf(o, head)
	fmt.Fprintf(o, tail)
	for _, hit := range hits.Hits {
		fmt.Fprintf(o, " [%08d] |%08d%19s|%08d|%10d |%8d", 0, hit.CellID0, "", hit.CellID1, hit.Amplitude, hit.TimeStamp)
		// FIXME(sbinet): CellIDDecoder
		fmt.Fprintf(o, "\n        id-fields: --- unknown/default ----   ")
		fmt.Fprintf(o, "\n")
	}
	fmt.Fprintf(o, tail)
	return string(o.Bytes())
}

func (*RawCalorimeterHits) VersionSio() uint32 {
	return Version
}

func (hits *RawCalorimeterHits) MarshalSio(w sio.Writer) error {
	panic("not implemented")
}

func (hits *RawCalorimeterHits) UnmarshalSio(r sio.Reader) error {
	dec := sio.NewDecoder(r)
	dec.Decode(&hits.Flags)
	dec.Decode(&hits.Params)
	var n int32
	dec.Decode(&n)
	hits.Hits = make([]RawCalorimeterHit, int(n))
	for i := range hits.Hits {
		hit := &hits.Hits[i]
		dec.Decode(&hit.CellID0)
		if r.VersionSio() == 8 || hits.Flags.Test(BitsRChID1) {
			dec.Decode(&hit.CellID1)
		}
		dec.Decode(&hit.Amplitude)
		if hits.Flags.Test(BitsRChTime) {
			dec.Decode(&hit.TimeStamp)
		}
		if !hits.Flags.Test(BitsRChNoPtr) {
			dec.Tag(hit)
		}
	}
	return dec.Err()
}

type RawCalorimeterHit struct {
	CellID0   int32
	CellID1   int32
	Amplitude int32
	TimeStamp int32
}

var _ sio.Codec = (*RawCalorimeterHits)(nil)
<commit_msg>lcio: add sio-marshaling to RawCalorimeterHits<commit_after>// Copyright 2017 The go-hep Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lcio

import (
	"bytes"
	"fmt"
	"strings"

	"go-hep.org/x/hep/sio"
)

type RawCalorimeterHits struct {
	Flags  Flags
	Params Params
	Hits   []RawCalorimeterHit
}

func (hits RawCalorimeterHits) String() string {
	o := new(bytes.Buffer)
	fmt.Fprintf(o, "%[1]s print out of RawCalorimeterHit collection %[1]s\n\n", strings.Repeat("-", 15))
	fmt.Fprintf(o, "  flag:  0x%x\n%v", hits.Flags, hits.Params)
	fmt.Fprintf(o, "     LCIO::RCHBIT_ID1    : %v\n", hits.Flags.Test(BitsRChID1))
	fmt.Fprintf(o, "     LCIO::RCHBIT_TIME   : %v\n", hits.Flags.Test(BitsRChTime))
	fmt.Fprintf(o, "     LCIO::RCHBIT_NO_PTR : %v\n", hits.Flags.Test(BitsRChNoPtr))

	// FIXME(sbinet): CellIDDecoder

	fmt.Fprintf(o, "\n")

	head := " [   id   ] |  cellId0 ( M, S, I, J, K) |cellId1 | amplitude |  time  \n"
	tail := "------------|---------------------------|--------|-----------|---------\n"
	fmt.Fprintf(o, head)
	fmt.Fprintf(o, tail)
	for _, hit := range hits.Hits {
		fmt.Fprintf(o, " [%08d] |%08d%19s|%08d|%10d |%8d", 0, hit.CellID0, "", hit.CellID1, hit.Amplitude, hit.TimeStamp)
		// FIXME(sbinet): CellIDDecoder
		fmt.Fprintf(o, "\n        id-fields: --- unknown/default ----   ")
		fmt.Fprintf(o, "\n")
	}
	fmt.Fprintf(o, tail)
	return string(o.Bytes())
}

func (*RawCalorimeterHits) VersionSio() uint32 {
	return Version
}

func (hits *RawCalorimeterHits) MarshalSio(w sio.Writer) error {
	enc := sio.NewEncoder(w)
	enc.Encode(&hits.Flags)
	enc.Encode(&hits.Params)
	enc.Encode(int32(len(hits.Hits)))
	for i := range hits.Hits {
		hit := &hits.Hits[i]
		enc.Encode(&hit.CellID0)
		if hits.Flags.Test(BitsRChID1) {
			enc.Encode(&hit.CellID1)
		}
		enc.Encode(&hit.Amplitude)
		if hits.Flags.Test(BitsRChTime) {
			enc.Encode(&hit.TimeStamp)
		}
		if !hits.Flags.Test(BitsRChNoPtr) {
			enc.Tag(hit)
		}
	}
	return enc.Err()
}

func (hits *RawCalorimeterHits) UnmarshalSio(r sio.Reader) error {
	dec := sio.NewDecoder(r)
	dec.Decode(&hits.Flags)
	dec.Decode(&hits.Params)
	var n int32
	dec.Decode(&n)
	hits.Hits = make([]RawCalorimeterHit, int(n))
	for i := range hits.Hits {
		hit := &hits.Hits[i]
		dec.Decode(&hit.CellID0)
		if r.VersionSio() == 8 || hits.Flags.Test(BitsRChID1) {
			dec.Decode(&hit.CellID1)
		}
		dec.Decode(&hit.Amplitude)
		if hits.Flags.Test(BitsRChTime) {
			dec.Decode(&hit.TimeStamp)
		}
		if !hits.Flags.Test(BitsRChNoPtr) {
			dec.Tag(hit)
		}
	}
	return dec.Err()
}

type RawCalorimeterHit struct {
	CellID0   int32
	CellID1   int32
	Amplitude int32
	TimeStamp int32
}

var (
	_ sio.Versioner = (*RawCalorimeterHits)(nil)
	_ sio.Codec     = (*RawCalorimeterHits)(nil)
)
<|endoftext|>


<commit_before><commit_msg>added dmidecode product<commit_after><|endoftext|>


<commit_before>// Copyright 2014 Arne Roomann-Kurrik
//
// 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 twodee

import (
	"fmt"
	"github.com/go-gl/gl"
)

type BatchRenderer struct {
	*Renderer
	Program        gl.Program
	PositionLoc    gl.AttribLocation
	TextureLoc     gl.AttribLocation
	TextureUnitLoc gl.UniformLocation
	ModelViewLoc   gl.UniformLocation
	ProjectionLoc  gl.UniformLocation
}

const BATCH_FRAGMENT = `#version 150
precision mediump float;

uniform sampler2D u_TextureUnit;
in vec2 v_TextureCoordinates;
out vec4 v_FragData;

void main()
{
    vec2 texcoords = v_TextureCoordinates;
    v_FragData = texture(u_TextureUnit, texcoords);
    //v_FragData = vec4(1.0,0.0,0.0,1.0);
}`

const BATCH_VERTEX = `#version 150

in vec4 a_Position;
in vec2 a_TextureCoordinates;

uniform mat4 m_ModelViewMatrix;
uniform mat4 m_ProjectionMatrix;

out vec2 v_TextureCoordinates;

void main()
{
    v_TextureCoordinates = a_TextureCoordinates;
    gl_Position = m_ProjectionMatrix * m_ModelViewMatrix * a_Position;
}`

func NewBatchRenderer(bounds, screen Rectangle) (tr *BatchRenderer, err error) {
	var (
		program gl.Program
		r       *Renderer
	)
	if program, err = BuildProgram(BATCH_VERTEX, BATCH_FRAGMENT); err != nil {
		return
	}
	if r, err = NewRenderer(bounds, screen); err != nil {
		return
	}
	tr = &BatchRenderer{
		Renderer:       r,
		Program:        program,
		PositionLoc:    program.GetAttribLocation("a_Position"),
		TextureLoc:     program.GetAttribLocation("a_TextureCoordinates"),
		TextureUnitLoc: program.GetUniformLocation("u_TextureUnit"),
		ModelViewLoc:   program.GetUniformLocation("m_ModelViewMatrix"),
		ProjectionLoc:  program.GetUniformLocation("m_ProjectionMatrix"),
	}
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}

func (r *BatchRenderer) Bind() error {
	r.Program.Use()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.ActiveTexture(gl.TEXTURE0)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureUnitLoc.Uniform1i(0)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.ProjectionLoc.UniformMatrix4f(false, (*[16]float32)(r.Renderer.projection))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	return nil
}

func (r *BatchRenderer) Draw(batch *Batch, x, y, rot float32) error {
	batch.Texture.Bind()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	batch.Buffer.Bind(gl.ARRAY_BUFFER)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.PositionLoc.AttribPointer(3, gl.FLOAT, false, 5*4, uintptr(0))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureLoc.AttribPointer(2, gl.FLOAT, false, 5*4, uintptr(3*4))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.PositionLoc.EnableArray()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureLoc.EnableArray()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	m := GetRotTransMatrix(x, y, 0, rot)
	r.ModelViewLoc.UniformMatrix4f(false, (*[16]float32)(m))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.DrawArrays(gl.TRIANGLES, 0, batch.Count)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	batch.Buffer.Unbind(gl.ARRAY_BUFFER)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	return nil
}

func (tr *BatchRenderer) Unbind() error {
	return nil
}

func (tr *BatchRenderer) Delete() error {
	return nil
}

type Batch struct {
	Buffer  gl.Buffer
	Texture *Texture
	Count   int
}

type TexturedTile interface {
	ScaledBounds(ratio float32) (x, y, w, h float32)
	ScaledTextureBounds(rx float32, ry float32) (x, y, w, h float32)
}

func triangles(t TexturedTile, ratio, texw, texh float32) [30]float32 {
	var (
		x, y, w, h     = t.ScaledBounds(ratio)
		tx, ty, tw, th = t.ScaledTextureBounds(texw, texh)
	)
	return [30]float32{
		x, y, 0.0,
		tx, ty,

		x + w, y + h, 0.0,
		tx + tw, ty + th,

		x, y + h, 0.0,
		tx, ty + th,

		x, y, 0.0,
		tx, ty,

		x + w, y, 0.0,
		tx + tw, ty,

		x + w, y + h, 0.0,
		tx + tw, ty + th,
	}
}

func LoadBatch(tiles []TexturedTile, metadata TileMetadata) (b *Batch, err error) {
	var (
		step     = 30
		size     = len(tiles) * step
		vertices = make([]float32, size)
		vbo      gl.Buffer
		texture  *Texture
	)
	if texture, err = LoadTexture(metadata.Path, gl.NEAREST); err != nil {
		return
	}
	for i := 0; i < len(tiles); i++ {
		if tiles[i] == nil {
			continue
		}
		v := triangles(tiles[i], float32(metadata.PxPerUnit), float32(texture.Width), float32(texture.Height))
		copy(vertices[step*i:], v[:])
	}
	fmt.Printf("VERTICES %v\n", vertices[:30])
	if vbo, err = CreateVBO(len(vertices)*4, vertices, gl.STATIC_DRAW); err != nil {
		return
	}
	b = &Batch{
		Buffer:  vbo,
		Texture: texture,
		Count:   len(vertices) / 5,
	}
	return
}

func (b *Batch) Delete() {
	b.Texture.Delete()
	b.Buffer.Delete()
}
<commit_msg>Remove debug output.<commit_after>// Copyright 2014 Arne Roomann-Kurrik
//
// 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 twodee

import (
	"fmt"
	"github.com/go-gl/gl"
)

type BatchRenderer struct {
	*Renderer
	Program        gl.Program
	PositionLoc    gl.AttribLocation
	TextureLoc     gl.AttribLocation
	TextureUnitLoc gl.UniformLocation
	ModelViewLoc   gl.UniformLocation
	ProjectionLoc  gl.UniformLocation
}

const BATCH_FRAGMENT = `#version 150
precision mediump float;

uniform sampler2D u_TextureUnit;
in vec2 v_TextureCoordinates;
out vec4 v_FragData;

void main()
{
    vec2 texcoords = v_TextureCoordinates;
    v_FragData = texture(u_TextureUnit, texcoords);
    //v_FragData = vec4(1.0,0.0,0.0,1.0);
}`

const BATCH_VERTEX = `#version 150

in vec4 a_Position;
in vec2 a_TextureCoordinates;

uniform mat4 m_ModelViewMatrix;
uniform mat4 m_ProjectionMatrix;

out vec2 v_TextureCoordinates;

void main()
{
    v_TextureCoordinates = a_TextureCoordinates;
    gl_Position = m_ProjectionMatrix * m_ModelViewMatrix * a_Position;
}`

func NewBatchRenderer(bounds, screen Rectangle) (tr *BatchRenderer, err error) {
	var (
		program gl.Program
		r       *Renderer
	)
	if program, err = BuildProgram(BATCH_VERTEX, BATCH_FRAGMENT); err != nil {
		return
	}
	if r, err = NewRenderer(bounds, screen); err != nil {
		return
	}
	tr = &BatchRenderer{
		Renderer:       r,
		Program:        program,
		PositionLoc:    program.GetAttribLocation("a_Position"),
		TextureLoc:     program.GetAttribLocation("a_TextureCoordinates"),
		TextureUnitLoc: program.GetUniformLocation("u_TextureUnit"),
		ModelViewLoc:   program.GetUniformLocation("m_ModelViewMatrix"),
		ProjectionLoc:  program.GetUniformLocation("m_ProjectionMatrix"),
	}
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}

func (r *BatchRenderer) Bind() error {
	r.Program.Use()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.ActiveTexture(gl.TEXTURE0)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureUnitLoc.Uniform1i(0)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.ProjectionLoc.UniformMatrix4f(false, (*[16]float32)(r.Renderer.projection))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	return nil
}

func (r *BatchRenderer) Draw(batch *Batch, x, y, rot float32) error {
	batch.Texture.Bind()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	batch.Buffer.Bind(gl.ARRAY_BUFFER)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.PositionLoc.AttribPointer(3, gl.FLOAT, false, 5*4, uintptr(0))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureLoc.AttribPointer(2, gl.FLOAT, false, 5*4, uintptr(3*4))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.PositionLoc.EnableArray()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	r.TextureLoc.EnableArray()
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	m := GetRotTransMatrix(x, y, 0, rot)
	r.ModelViewLoc.UniformMatrix4f(false, (*[16]float32)(m))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.DrawArrays(gl.TRIANGLES, 0, batch.Count)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	batch.Buffer.Unbind(gl.ARRAY_BUFFER)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	return nil
}

func (tr *BatchRenderer) Unbind() error {
	return nil
}

func (tr *BatchRenderer) Delete() error {
	return nil
}

type Batch struct {
	Buffer  gl.Buffer
	Texture *Texture
	Count   int
}

type TexturedTile interface {
	ScaledBounds(ratio float32) (x, y, w, h float32)
	ScaledTextureBounds(rx float32, ry float32) (x, y, w, h float32)
}

func triangles(t TexturedTile, ratio, texw, texh float32) [30]float32 {
	var (
		x, y, w, h     = t.ScaledBounds(ratio)
		tx, ty, tw, th = t.ScaledTextureBounds(texw, texh)
	)
	return [30]float32{
		x, y, 0.0,
		tx, ty,

		x + w, y + h, 0.0,
		tx + tw, ty + th,

		x, y + h, 0.0,
		tx, ty + th,

		x, y, 0.0,
		tx, ty,

		x + w, y, 0.0,
		tx + tw, ty,

		x + w, y + h, 0.0,
		tx + tw, ty + th,
	}
}

func LoadBatch(tiles []TexturedTile, metadata TileMetadata) (b *Batch, err error) {
	var (
		step     = 30
		size     = len(tiles) * step
		vertices = make([]float32, size)
		vbo      gl.Buffer
		texture  *Texture
	)
	if texture, err = LoadTexture(metadata.Path, gl.NEAREST); err != nil {
		return
	}
	for i := 0; i < len(tiles); i++ {
		if tiles[i] == nil {
			continue
		}
		v := triangles(tiles[i], float32(metadata.PxPerUnit), float32(texture.Width), float32(texture.Height))
		copy(vertices[step*i:], v[:])
	}
	if vbo, err = CreateVBO(len(vertices)*4, vertices, gl.STATIC_DRAW); err != nil {
		return
	}
	b = &Batch{
		Buffer:  vbo,
		Texture: texture,
		Count:   len(vertices) / 5,
	}
	return
}

func (b *Batch) Delete() {
	b.Texture.Delete()
	b.Buffer.Delete()
}
<|endoftext|>