<commit_before>package integration_test

import (
	"path/filepath"
	"regexp"
	"strconv"

	"github.com/blang/semver"
	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/cutlass"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("CF Python Buildpack", func() {
	var app *cutlass.App

	BeforeEach(func() {
		if isSerialTest {
			Skip("Skipping parallel tests")
		}
	})

	AfterEach(func() {
		if app != nil {
			app.Destroy()
		}
		app = nil
	})

	Context("with an unsupported dependency", func() {
		BeforeEach(func() {
			app = cutlass.New(Fixtures("unsupported_version"))
		})

		It("displays a nice error messages and gracefully fails", func() {
			Expect(app.Push()).ToNot(Succeed())
			Expect(app.ConfirmBuildpack(buildpackVersion)).To(Succeed())

			Eventually(app.Stdout.String()).Should(ContainSubstring("Could not install python: no match found for 99.99.99"))
			Eventually(app.Stdout.String()).ShouldNot(ContainSubstring("-----> Installing python"))
		})
	})

	It("deploy a web app with -e in requirements.txt", func() {
		app = cutlass.New(Fixtures("flask_git_req"))
		app.SetEnv("BP_DEBUG", "1")
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
		Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
		Expect(app.Stdout.String()).NotTo(ContainSubstring("ImportError:"))
		Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))

		By("Caching pip files", func() {
			Expect(app.Stdout.String()).To(ContainSubstring("Size of pip cache dir: "))
			matches := regexp.MustCompile("(?m)Size of pip cache dir: (\\d+)\\s.*pip_cache$").FindStringSubmatch(app.Stdout.String())
			Expect(matches).To(HaveLen(2))
			size, err := strconv.Atoi(matches[1])
			Expect(err).ToNot(HaveOccurred())

			Expect(size).To(BeNumerically(">", 5000))
		})
	})

	It("deploy a web app with -r in requirements.txt", func() {
		app = cutlass.New(Fixtures("recursive_requirements"))
		PushAppAndConfirm(app)
		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
	})

	It("deploy a web app that uses an nltk corpus", func() {
		app = cutlass.New(Fixtures("nltk_flask"))
		app.SetEnv("BP_DEBUG", "1")
		app.Memory = "256M"
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("The Fulton County Grand Jury said Friday an investigation of Atlanta's recent primary election produced"))
		Expect(app.Stdout.String()).To(ContainSubstring("Downloading NLTK packages: brown"))
		Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
	})

	It("deploy a web app that uses an tkinter", func() {
		app = cutlass.New(Fixtures("tkinter"))
		app.Buildpacks = []string{"python_buildpack"}
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("tkinter was imported"))
	})

	It("should not display the allow-all-external deprecation message", func() {
		app = cutlass.New(Fixtures("flask"))
		PushAppAndConfirm(app)
		Expect(app.Stdout.String()).ToNot(ContainSubstring("DEPRECATION: --allow-all-external has been deprecated and will be removed in the future"))
	})

	It("app has pre and post scripts", func() {
		app = cutlass.New(Fixtures("with_hooks"))
		PushAppAndConfirm(app)
		Expect(app.Stdout.String()).To(ContainSubstring("Echo from app pre compile"))
		Expect(app.Stdout.String()).To(ContainSubstring("Echo from app post compile"))
	})

	Context("uncached buildpack", func() {
		BeforeEach(func() {
			if cutlass.Cached {
				Skip("Running uncached tests")
			}
		})

		Context("pushing a Python 3 app with a runtime.txt", func() {
			Context("including flask", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_python_3"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})

			Context("including flask and no build isolation", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("no_build_isolation"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})

			Context("including django with specified python version", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("django_python_3"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("It worked!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Installing python 3.6"))
					Expect(app.Stdout.String()).To(ContainSubstring("collectstatic --noinput"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Copying "))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})
		})

		Context("pushing a Python app without the runtime.txt", func() {
			Context("", func() {
				var defaultV string

				type manifestContent struct {
					DefaultVersions []struct {
						Name    string `yaml:"name"`
						Version string `yaml:"version"`
					} `yaml:"default_versions"`
				}

				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask"))
					mc := manifestContent{}
					err := libbuildpack.NewYAML().Load(filepath.Join(bpDir, "manifest.yml"), &mc)
					Expect(err).To(BeNil())
					for _, defaultDep := range mc.DefaultVersions {
						if defaultDep.Name == "python" {
							defaultV = defaultDep.Version
						}
					}
				})

				It("deploys with default Python version", func() {
					PushAppAndConfirm(app)

					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))

					re := regexp.MustCompile("Installing python (.*)[\r\n|\r|\n]")
					match := re.FindStringSubmatch(app.Stdout.String())
					foundVersion := match[1]

					versionRange := semver.MustParseRange("<=" + defaultV)
					v1 := semver.MustParse(foundVersion)
					Expect(versionRange(v1)).To(BeTrue())
				})
			})

			Context("including django but not specified Python version", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("django_web_app"))
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("The install worked successfully!"))
					Expect(app.Stdout.String()).To(ContainSubstring("collectstatic --noinput"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
					Eventually(app.Stdout.String()).ShouldNot(MatchRegexp(`WARNING: You are using pip version \d+.\d+.\d+; however, version \d+.\d+.\d+ is available.`))
				})
			})

			Context("including flask without a vendor directory", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_not_vendored"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
				AssertUsesProxyDuringStagingIfPresent("flask_not_vendored")
			})

		})

		Context("with mercurial dependencies", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("mercurial"))
				app.SetEnv("BP_DEBUG", "1")
			})

			It("deploys", func() {
				PushAppAndConfirm(app)
				Expect(app.Stdout.String()).NotTo(ContainSubstring("Cloud Foundry does not support Pip Mercurial dependencies while in offline-mode. Vendor your dependencies if they do not work."))
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
			})
		})
	})

	Context("cached buildpack", func() {
		BeforeEach(func() {
			if !cutlass.Cached {
				Skip("Running cached tests")
			}
		})

		Context("when using flask", func() {
			Context("with Python 3", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_python_3"))
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.Stdout.String()).To(ContainSubstring("Copy [/"))
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				})
				AssertNoInternetTraffic("flask")
			})
		})

		Context("with mercurial dependencies", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("mercurial"))
			})

			It("deploys", func() {
				PushAppAndConfirm(app)
				Expect(app.Stdout.String()).To(ContainSubstring("Cloud Foundry does not support Pip Mercurial dependencies while in offline-mode. Vendor your dependencies if they do not work."))
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
			})
		})
	})

	It("sets gunicorn to send access logs to stdout by defualt", func() {
		app = cutlass.New(Fixtures("flask_latest_gunicorn"))
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
		Eventually(app.Stdout.String).Should(MatchRegexp(`\[APP/PROC/WEB/0\] .* "GET / HTTP/1.1"`))
	})

	Context("specifying pip version", func() {
		Context("default", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("flask"))
				app.SetEnv("BP_PIP_VERSION", "")
			})

			It("uses python's pip module", func() {
				PushAppAndConfirm(app)
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Using python's pip module"))
			})
		})

		Context("latest", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("flask"))
				app.SetEnv("BP_PIP_VERSION", "latest")
			})

			It("uses latest from manifest", func() {
				PushAppAndConfirm(app)
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Installing pip"))
				Expect(app.Stdout.String()).To(MatchRegexp(`Successfully installed pip-\d+.\d+.\d+`))
			})
		})
	})
})
<commit_msg>fix pip version log expectations<commit_after>package integration_test

import (
	"path/filepath"
	"regexp"
	"strconv"

	"github.com/blang/semver"
	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/cutlass"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("CF Python Buildpack", func() {
	var app *cutlass.App

	BeforeEach(func() {
		if isSerialTest {
			Skip("Skipping parallel tests")
		}
	})

	AfterEach(func() {
		if app != nil {
			app.Destroy()
		}
		app = nil
	})

	Context("with an unsupported dependency", func() {
		BeforeEach(func() {
			app = cutlass.New(Fixtures("unsupported_version"))
		})

		It("displays a nice error messages and gracefully fails", func() {
			Expect(app.Push()).ToNot(Succeed())
			Expect(app.ConfirmBuildpack(buildpackVersion)).To(Succeed())

			Eventually(app.Stdout.String()).Should(ContainSubstring("Could not install python: no match found for 99.99.99"))
			Eventually(app.Stdout.String()).ShouldNot(ContainSubstring("-----> Installing python"))
		})
	})

	It("deploy a web app with -e in requirements.txt", func() {
		app = cutlass.New(Fixtures("flask_git_req"))
		app.SetEnv("BP_DEBUG", "1")
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
		Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
		Expect(app.Stdout.String()).NotTo(ContainSubstring("ImportError:"))
		Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))

		By("Caching pip files", func() {
			Expect(app.Stdout.String()).To(ContainSubstring("Size of pip cache dir: "))
			matches := regexp.MustCompile("(?m)Size of pip cache dir: (\\d+)\\s.*pip_cache$").FindStringSubmatch(app.Stdout.String())
			Expect(matches).To(HaveLen(2))
			size, err := strconv.Atoi(matches[1])
			Expect(err).ToNot(HaveOccurred())

			Expect(size).To(BeNumerically(">", 5000))
		})
	})

	It("deploy a web app with -r in requirements.txt", func() {
		app = cutlass.New(Fixtures("recursive_requirements"))
		PushAppAndConfirm(app)
		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
	})

	It("deploy a web app that uses an nltk corpus", func() {
		app = cutlass.New(Fixtures("nltk_flask"))
		app.SetEnv("BP_DEBUG", "1")
		app.Memory = "256M"
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("The Fulton County Grand Jury said Friday an investigation of Atlanta's recent primary election produced"))
		Expect(app.Stdout.String()).To(ContainSubstring("Downloading NLTK packages: brown"))
		Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
	})

	It("deploy a web app that uses an tkinter", func() {
		app = cutlass.New(Fixtures("tkinter"))
		app.Buildpacks = []string{"python_buildpack"}
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("tkinter was imported"))
	})

	It("should not display the allow-all-external deprecation message", func() {
		app = cutlass.New(Fixtures("flask"))
		PushAppAndConfirm(app)
		Expect(app.Stdout.String()).ToNot(ContainSubstring("DEPRECATION: --allow-all-external has been deprecated and will be removed in the future"))
	})

	It("app has pre and post scripts", func() {
		app = cutlass.New(Fixtures("with_hooks"))
		PushAppAndConfirm(app)
		Expect(app.Stdout.String()).To(ContainSubstring("Echo from app pre compile"))
		Expect(app.Stdout.String()).To(ContainSubstring("Echo from app post compile"))
	})

	Context("uncached buildpack", func() {
		BeforeEach(func() {
			if cutlass.Cached {
				Skip("Running uncached tests")
			}
		})

		Context("pushing a Python 3 app with a runtime.txt", func() {
			Context("including flask", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_python_3"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})

			Context("including flask and no build isolation", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("no_build_isolation"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})

			Context("including django with specified python version", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("django_python_3"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("It worked!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Installing python 3.6"))
					Expect(app.Stdout.String()).To(ContainSubstring("collectstatic --noinput"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Copying "))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
			})
		})

		Context("pushing a Python app without the runtime.txt", func() {
			Context("", func() {
				var defaultV string

				type manifestContent struct {
					DefaultVersions []struct {
						Name    string `yaml:"name"`
						Version string `yaml:"version"`
					} `yaml:"default_versions"`
				}

				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask"))
					mc := manifestContent{}
					err := libbuildpack.NewYAML().Load(filepath.Join(bpDir, "manifest.yml"), &mc)
					Expect(err).To(BeNil())
					for _, defaultDep := range mc.DefaultVersions {
						if defaultDep.Name == "python" {
							defaultV = defaultDep.Version
						}
					}
				})

				It("deploys with default Python version", func() {
					PushAppAndConfirm(app)

					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))

					re := regexp.MustCompile("Installing python (.*)[\r\n|\r|\n]")
					match := re.FindStringSubmatch(app.Stdout.String())
					foundVersion := match[1]

					versionRange := semver.MustParseRange("<=" + defaultV)
					v1 := semver.MustParse(foundVersion)
					Expect(versionRange(v1)).To(BeTrue())
				})
			})

			Context("including django but not specified Python version", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("django_web_app"))
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("The install worked successfully!"))
					Expect(app.Stdout.String()).To(ContainSubstring("collectstatic --noinput"))
					Expect(app.Stdout.String()).NotTo(ContainSubstring("Error while running"))
					Eventually(app.Stdout.String()).ShouldNot(MatchRegexp(`WARNING: You are using pip version \d+.\d+.\d+; however, version \d+.\d+.\d+ is available.`))
				})
			})

			Context("including flask without a vendor directory", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_not_vendored"))
					app.SetEnv("BP_DEBUG", "1")
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
					Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
				})
				AssertUsesProxyDuringStagingIfPresent("flask_not_vendored")
			})

		})

		Context("with mercurial dependencies", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("mercurial"))
				app.SetEnv("BP_DEBUG", "1")
			})

			It("deploys", func() {
				PushAppAndConfirm(app)
				Expect(app.Stdout.String()).NotTo(ContainSubstring("Cloud Foundry does not support Pip Mercurial dependencies while in offline-mode. Vendor your dependencies if they do not work."))
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Dir checksum unchanged"))
			})
		})
	})

	Context("cached buildpack", func() {
		BeforeEach(func() {
			if !cutlass.Cached {
				Skip("Running cached tests")
			}
		})

		Context("when using flask", func() {
			Context("with Python 3", func() {
				BeforeEach(func() {
					app = cutlass.New(Fixtures("flask_python_3"))
				})

				It("deploys", func() {
					PushAppAndConfirm(app)
					Expect(app.Stdout.String()).To(ContainSubstring("Copy [/"))
					Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				})
				AssertNoInternetTraffic("flask")
			})
		})

		Context("with mercurial dependencies", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("mercurial"))
			})

			It("deploys", func() {
				PushAppAndConfirm(app)
				Expect(app.Stdout.String()).To(ContainSubstring("Cloud Foundry does not support Pip Mercurial dependencies while in offline-mode. Vendor your dependencies if they do not work."))
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
			})
		})
	})

	It("sets gunicorn to send access logs to stdout by defualt", func() {
		app = cutlass.New(Fixtures("flask_latest_gunicorn"))
		PushAppAndConfirm(app)

		Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
		Eventually(app.Stdout.String).Should(MatchRegexp(`\[APP/PROC/WEB/0\] .* "GET / HTTP/1.1"`))
	})

	Context("specifying pip version", func() {
		Context("default", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("flask"))
				app.SetEnv("BP_PIP_VERSION", "")
			})

			It("uses python's pip module", func() {
				PushAppAndConfirm(app)
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Using python's pip module"))
			})
		})

		Context("latest", func() {
			BeforeEach(func() {
				app = cutlass.New(Fixtures("flask"))
				app.SetEnv("BP_PIP_VERSION", "latest")
			})

			It("uses latest from manifest", func() {
				PushAppAndConfirm(app)
				Expect(app.GetBody("/")).To(ContainSubstring("Hello, World!"))
				Expect(app.Stdout.String()).To(ContainSubstring("Installing pip"))
				Expect(app.Stdout.String()).To(MatchRegexp(`Successfully installed pip-\d+.\d+(.\d+)?`))
			})
		})
	})
})
<|endoftext|>


<commit_before>package net

import (
	"errors"
	"fmt"
	"github.com/onsi/gomega"
)

func HaveAllRequestsCalled() gomega.OmegaMatcher {
	return allRequestsCalledMatcher{}
}

type allRequestsCalledMatcher struct{}

func (matcher allRequestsCalledMatcher) Match(actual interface{}) (bool, string, error) {
	testHandler, ok := actual.(*TestHandler)
	if !ok {
		return false, "", errors.New(fmt.Sprintf("Expected a test handler, got %T", actual))
	}

	if testHandler.AllRequestsCalled() {
		message := fmt.Sprint("Failed to call requests:\n")
		for i := testHandler.CallCount; i < len(testHandler.Requests); i++ {
			message += fmt.Sprintf("%#v\n", testHandler.Requests[i])
		}
		message += "\n"
		return true, message, nil
	} else {
		message := "Expected all requests to not be called, but they were all called"
		return false, message, nil
	}
}
<commit_msg>Fix messages in HaveAllRequestsCalled matcher<commit_after>package net

import (
	"errors"
	"fmt"
	"github.com/onsi/gomega"
)

func HaveAllRequestsCalled() gomega.OmegaMatcher {
	return allRequestsCalledMatcher{}
}

type allRequestsCalledMatcher struct{}

func (matcher allRequestsCalledMatcher) Match(actual interface{}) (bool, string, error) {
	testHandler, ok := actual.(*TestHandler)
	if !ok {
		return false, "", errors.New(fmt.Sprintf("Expected a test handler, got %T", actual))
	}

	if testHandler.AllRequestsCalled() {
		message := "Expected all requests to not be called, but they were all called"
		return true, message, nil
	} else {
		message := fmt.Sprint("Failed to call requests:\n")
		for i := testHandler.CallCount; i < len(testHandler.Requests); i++ {
			message += fmt.Sprintf("%#v\n", testHandler.Requests[i])
		}
		message += "\n"
		return false, message, nil
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 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 types

import (
	"fmt"
	"go/token"
)

// A Package describes a Go package.
type Package struct {
	path     string
	name     string
	scope    *Scope
	complete bool
	imports  []*Package
	fake     bool // scope lookup errors are silently dropped if package is fake (internal use only)
	cgo      bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
}

// NewPackage returns a new Package for the given package path and name.
// The package is not complete and contains no explicit imports.
func NewPackage(path, name string) *Package {
	scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path))
	return &Package{path: path, name: name, scope: scope}
}

// Path returns the package path.
func (pkg *Package) Path() string { return pkg.path }

// Name returns the package name.
func (pkg *Package) Name() string { return pkg.name }

// SetName sets the package name.
func (pkg *Package) SetName(name string) { pkg.name = name }

// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
func (pkg *Package) Scope() *Scope { return pkg.scope }

// A package is complete if its scope contains (at least) all
// exported objects; otherwise it is incomplete.
func (pkg *Package) Complete() bool { return pkg.complete }

// MarkComplete marks a package as complete.
func (pkg *Package) MarkComplete() { pkg.complete = true }

// Imports returns the list of packages directly imported by
// pkg; the list is in source order.
//
// If pkg was loaded from export data, Imports includes packages that
// provide package-level objects referenced by pkg. This may be more or
// less than the set of packages directly imported by pkg's source code.
func (pkg *Package) Imports() []*Package { return pkg.imports }

// SetImports sets the list of explicitly imported packages to list.
// It is the caller's responsibility to make sure list elements are unique.
func (pkg *Package) SetImports(list []*Package) { pkg.imports = list }

func (pkg *Package) String() string {
	return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path)
}
<commit_msg>go/types: return Universe for (*Package)(nil).Scope()<commit_after>// Copyright 2013 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 types

import (
	"fmt"
	"go/token"
)

// A Package describes a Go package.
type Package struct {
	path     string
	name     string
	scope    *Scope
	complete bool
	imports  []*Package
	fake     bool // scope lookup errors are silently dropped if package is fake (internal use only)
	cgo      bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
}

// NewPackage returns a new Package for the given package path and name.
// The package is not complete and contains no explicit imports.
func NewPackage(path, name string) *Package {
	scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path))
	return &Package{path: path, name: name, scope: scope}
}

// Path returns the package path.
func (pkg *Package) Path() string { return pkg.path }

// Name returns the package name.
func (pkg *Package) Name() string { return pkg.name }

// SetName sets the package name.
func (pkg *Package) SetName(name string) { pkg.name = name }

// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
// For a nil pkg receiver, Scope returns the Universe scope.
func (pkg *Package) Scope() *Scope {
	if pkg != nil {
		return pkg.scope
	}
	return Universe
}

// A package is complete if its scope contains (at least) all
// exported objects; otherwise it is incomplete.
func (pkg *Package) Complete() bool { return pkg.complete }

// MarkComplete marks a package as complete.
func (pkg *Package) MarkComplete() { pkg.complete = true }

// Imports returns the list of packages directly imported by
// pkg; the list is in source order.
//
// If pkg was loaded from export data, Imports includes packages that
// provide package-level objects referenced by pkg. This may be more or
// less than the set of packages directly imported by pkg's source code.
func (pkg *Package) Imports() []*Package { return pkg.imports }

// SetImports sets the list of explicitly imported packages to list.
// It is the caller's responsibility to make sure list elements are unique.
func (pkg *Package) SetImports(list []*Package) { pkg.imports = list }

func (pkg *Package) String() string {
	return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"sort"
)

type Hound struct {
	Config string
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
}

func (h *Hound) New() (error, bool) {
	config, err := h.LoadConfig()
	if err != nil {
		return err, false
	}

	err = h.Parse(config)
	if err != nil {
		return err, false
	}

	return nil, true
}

func (h *Hound) LoadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.Config)
	return ioutil.ReadFile(filename)
}

func (h *Hound) Parse(data []byte) error {
	return yaml.Unmarshal(data, h)
}

func (h *Hound) Sniff(fileName string, hunk *diff.Hunk) error {
	r1, _ := regexp.Compile(`^\w+\/`)
	fileName = r1.ReplaceAllString(fileName, "")
	if _, ok := h.MatchPatterns(h.Skips, []byte(fileName)); ok {
		return nil
	}

	r2, _ := regexp.Compile(`(?m)^\+\s*(.+)$`)
	matches := r2.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, ok := h.MatchPatterns(h.Warns, line); ok {
			message := color.YellowString(fmt.Sprintf("Warning: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			fmt.Print(message)
		}

		if pattern, ok := h.MatchPatterns(h.Fails, line); ok {
			err := color.RedString(fmt.Sprintf("Failure: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			return errors.New(err)
		}
	}

	return nil
}

func (h *Hound) Match(pattern string, subject []byte) (bool, error) {
	r, err := regexp.Compile(pattern)
	if err != nil {
		return false, err
	}

	if r.Match(subject) {
		return true, nil
	}

	return false, nil
}

func (h *Hound) MatchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match, _ := h.Match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<commit_msg>remove unused sort package<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
)

type Hound struct {
	Config string
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
}

func (h *Hound) New() (error, bool) {
	config, err := h.LoadConfig()
	if err != nil {
		return err, false
	}

	err = h.Parse(config)
	if err != nil {
		return err, false
	}

	return nil, true
}

func (h *Hound) LoadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.Config)
	return ioutil.ReadFile(filename)
}

func (h *Hound) Parse(data []byte) error {
	return yaml.Unmarshal(data, h)
}

func (h *Hound) Sniff(fileName string, hunk *diff.Hunk) error {
	r1, _ := regexp.Compile(`^\w+\/`)
	fileName = r1.ReplaceAllString(fileName, "")
	if _, ok := h.MatchPatterns(h.Skips, []byte(fileName)); ok {
		return nil
	}

	r2, _ := regexp.Compile(`(?m)^\+\s*(.+)$`)
	matches := r2.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, ok := h.MatchPatterns(h.Warns, line); ok {
			message := color.YellowString(fmt.Sprintf("Warning: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			fmt.Print(message)
		}

		if pattern, ok := h.MatchPatterns(h.Fails, line); ok {
			err := color.RedString(fmt.Sprintf("Failure: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			return errors.New(err)
		}
	}

	return nil
}

func (h *Hound) Match(pattern string, subject []byte) (bool, error) {
	r, err := regexp.Compile(pattern)
	if err != nil {
		return false, err
	}

	if r.Match(subject) {
		return true, nil
	}

	return false, nil
}

func (h *Hound) MatchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match, _ := h.Match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<|endoftext|>


<commit_before>// The lemming/log package is your standard logger.  It is designed to be
// extremely simple to use.  It requires nothing more than an import, unless
// you want to be fancy and log to stderr or your own creation.
//
// Example:
//
//     import "github.com/opendns/lemming/log"
//
//     func main() {
//             log.Info("Starting")
//             if err := doSomething(); err != nil {
//                     log.Warning("Something failed: %v", err)
//             }
//             if err := doSomethingReallyImportant(); err != nil {
//			log.Error("We're totally broken: %v", err)
//             }
//             log.Info("Exiting")
//      }
//
package log

import (
	"fmt"
	"io"
	"os"
	"time"
)

var logger struct {
	Initialized bool
	Writer      io.Writer
}

// Writer returns the writer currently selected by the logger output.
func Writer() io.Writer {
	return logger.Writer
}

// Init initializes the global logger.  Output will be sent to stdout.  This is
// the default and will be called automatically, so normally there is no need
// to call it explicitly.
func Init() {
	InitWithWriter(os.Stdout)
}

// InitWithStderr initializes the global logger.  Output will be sent to
// stderr.
func InitWithStderr() {
	InitWithWriter(os.Stderr)
}

// InitWithWriter initializes the global logger.  Output will be sent to the
// given io.Writer.
func InitWithWriter(w io.Writer) {
	logger.Writer = w
	logger.Initialized = true
}

// Debug logs the given message at DEBUG level.  This is for getting verbose
// detail from the program during development or debugging, whose content would
// not be interesting to an end-user.
func Debug(format string, v ...interface{}) {
	doLog("DEBUG", format, v...)
}

// Info logs the given message at INFO level.  This is for normal program status.
func Info(format string, v ...interface{}) {
	doLog("INFO", format, v...)
}

// Warning logs the given message at WARNING level.  This is for unusual
// occurrences that should be brought to the user's attention.
func Warning(format string, v ...interface{}) {
	doLog("WARNING", format, v...)
}

// Error logs the given message at ERROR level, then panics.  This is used for
// breaking issues (bad program state, unavailable resources, etc.).
func Error(format string, v ...interface{}) {
	msg := formatLog("ERROR", format, v...)
	doRawLog(msg)
	panic(msg) // TODO: Make panic-on-error configurable
}

// Format a log message into a single string.
func formatLog(level string, format string, v ...interface{}) string {
	var msg string
	if len(v) > 0 {
		msg = fmt.Sprintf(format, v...)
	} else {
		// Don't run the message through fmt.Sprintf if no args were
		// supplied.  This avoids the %!(MISSING) spam that fmt adds if
		// it sees an unmatched formatting string (e.g. a %s without a
		// matching arg).  This makes it easy to log.Info(someVariable)
		// without worrying about junk in the output should it contain
		// a % sign.
		msg = format
	}
	timestr := time.Now().UTC().Format("2006-01-02 15:04:05.000000")
	return fmt.Sprintf("%s [%s]: %s\n", timestr, level, msg)
}

// Log the given pre-formatted string.
func doRawLog(msg string) {
	if !logger.Initialized {
		Init() // Stdout by default
	}
	if _, err := logger.Writer.Write([]byte(msg)); err != nil {
		panic("Cannot write to log output")
	}
}

// Format and log a message.
func doLog(level string, format string, v ...interface{}) {
	msg := formatLog(level, format, v...)
	doRawLog(msg)
}
<commit_msg>Update log.go<commit_after>// The lemming/log package is your standard logger.  It is designed to be
// extremely simple to use.  It requires nothing more than an import, unless
// you want to be fancy and log to stderr or your own creation.
//
// Example:
//
//     import "github.com/opendns/lemming/lib/log"
//
//     func main() {
//             log.Info("Starting")
//             if err := doSomething(); err != nil {
//                     log.Warning("Something failed: %v", err)
//             }
//             if err := doSomethingReallyImportant(); err != nil {
//			log.Error("We're totally broken: %v", err)
//             }
//             log.Info("Exiting")
//      }
//
package log

import (
	"fmt"
	"io"
	"os"
	"time"
)

var logger struct {
	Initialized bool
	Writer      io.Writer
}

// Writer returns the writer currently selected by the logger output.
func Writer() io.Writer {
	return logger.Writer
}

// Init initializes the global logger.  Output will be sent to stdout.  This is
// the default and will be called automatically, so normally there is no need
// to call it explicitly.
func Init() {
	InitWithWriter(os.Stdout)
}

// InitWithStderr initializes the global logger.  Output will be sent to
// stderr.
func InitWithStderr() {
	InitWithWriter(os.Stderr)
}

// InitWithWriter initializes the global logger.  Output will be sent to the
// given io.Writer.
func InitWithWriter(w io.Writer) {
	logger.Writer = w
	logger.Initialized = true
}

// Debug logs the given message at DEBUG level.  This is for getting verbose
// detail from the program during development or debugging, whose content would
// not be interesting to an end-user.
func Debug(format string, v ...interface{}) {
	doLog("DEBUG", format, v...)
}

// Info logs the given message at INFO level.  This is for normal program status.
func Info(format string, v ...interface{}) {
	doLog("INFO", format, v...)
}

// Warning logs the given message at WARNING level.  This is for unusual
// occurrences that should be brought to the user's attention.
func Warning(format string, v ...interface{}) {
	doLog("WARNING", format, v...)
}

// Error logs the given message at ERROR level, then panics.  This is used for
// breaking issues (bad program state, unavailable resources, etc.).
func Error(format string, v ...interface{}) {
	msg := formatLog("ERROR", format, v...)
	doRawLog(msg)
	panic(msg) // TODO: Make panic-on-error configurable
}

// Format a log message into a single string.
func formatLog(level string, format string, v ...interface{}) string {
	var msg string
	if len(v) > 0 {
		msg = fmt.Sprintf(format, v...)
	} else {
		// Don't run the message through fmt.Sprintf if no args were
		// supplied.  This avoids the %!(MISSING) spam that fmt adds if
		// it sees an unmatched formatting string (e.g. a %s without a
		// matching arg).  This makes it easy to log.Info(someVariable)
		// without worrying about junk in the output should it contain
		// a % sign.
		msg = format
	}
	timestr := time.Now().UTC().Format("2006-01-02 15:04:05.000000")
	return fmt.Sprintf("%s [%s]: %s\n", timestr, level, msg)
}

// Log the given pre-formatted string.
func doRawLog(msg string) {
	if !logger.Initialized {
		Init() // Stdout by default
	}
	if _, err := logger.Writer.Write([]byte(msg)); err != nil {
		panic("Cannot write to log output")
	}
}

// Format and log a message.
func doLog(level string, format string, v ...interface{}) {
	msg := formatLog(level, format, v...)
	doRawLog(msg)
}
<|endoftext|>


<commit_before>// Package mix combines sources into an output audio stream
package mix

import (
	"io"
	"math"
	"time"

	"github.com/go-mix/mix/bind/spec"

	"github.com/go-mix/mix/bind"
	"github.com/go-mix/mix/bind/debug"
	"github.com/go-mix/mix/bind/sample"
	"github.com/go-mix/mix/lib/fire"
	"github.com/go-mix/mix/lib/source"
)

// NextSample returns the next sample mixed in all channels
func NextSample() []sample.Value {
	smp := make([]sample.Value, masterSpec.Channels)
	var fireSample []sample.Value
	for _, fire := range mixLiveFires {
		if fireTz := fire.At(nowTz); fireTz > 0 {
			fireSample = mixSourceAt(fire.Source, fire.Volume, fire.Pan, fireTz)
			for c := 0; c < masterSpec.Channels; c++ {
				smp[c] += fireSample[c]
			}
		}
	}
	//	debug.Printf("*Mixer.nextSample %+v\n", sample)
	nowTz++
	out := make([]sample.Value, masterSpec.Channels)
	for c := 0; c < masterSpec.Channels; c++ {
		out[c] = mixLogarithmicRangeCompression(smp[c])
	}
	if nowTz > nextCycleTz {
		mixCycle()
	}
	return out
}

// Configure the mixer frequency, format, channels & sample rate.
func Configure(s spec.AudioSpec) {
	masterSpec = &s
	masterFreq = float64(s.Freq)
	masterTzDur = time.Second / time.Duration(masterFreq)
	masterCycleDurTz = spec.Tz(masterFreq)
	source.Configure(s)
}

// Spec spec returns the current audio specification.
func Spec() *spec.AudioSpec {
	return masterSpec
}

// Teardown everything and release all memory.
func Teardown() {
	ClearAllFires()
	outputToDur = time.Duration(0)
}

// SetFire to represent a single audio source playing at a specific time in the future (in time.Duration from play start), with sustain time.Duration, volume from 0 to 1, and pan from -1 to +1
func SetFire(source string, begin time.Duration, sustain time.Duration, volume float64, pan float64) *fire.Fire {
	mixPrepareSource(mixSourcePrefix + source)
	beginTz := spec.Tz(begin.Nanoseconds() / masterTzDur.Nanoseconds())
	var endTz spec.Tz
	if sustain != 0 {
		endTz = beginTz + spec.Tz(sustain.Nanoseconds()/masterTzDur.Nanoseconds())
	}
	f := fire.New(mixSourcePrefix+source, beginTz, endTz, volume, pan)
	mixReadyFires = append(mixReadyFires, f)
	return f
}

// FireCount returns the current total ready fires + live fires.
func FireCount() int {
	return len(mixLiveFires) + len(mixReadyFires)
}

// StartAt to specify what time to begin mixing.
func StartAt(t time.Time) {
	startAtTime = t
}

// GetStartTime returns the time mixing began.
func GetStartTime() time.Time {
	return startAtTime
}

// GetNowAt returns current mix position
func GetNowAt() time.Duration {
	return time.Duration(nowTz) * masterTzDur
}

// ClearAllFires to remove all ready & live fires.
func ClearAllFires() {
	mixReadyFires = make([]*fire.Fire, 0)
	mixLiveFires = make([]*fire.Fire, 0)
}

// SetSoundsPath to set the sound path prefix.
func SetSoundsPath(prefix string) {
	mixSourcePrefix = prefix
}

// GetCycleDurationTz sets the duration of a mix cycle.
func SetCycleDuration(d time.Duration) {
	if masterFreq == 0 {
		panic("Must specify mixing frequency before setting cycle duration!")
	}
	masterCycleDurTz = spec.Tz((d / time.Second) * time.Duration(masterFreq))
}

// GetCycleDurationTz returns the duration of a mix cycle.
func GetCycleDurationTz() spec.Tz {
	return masterCycleDurTz
}

// OutputStart requires a known length
func OutputStart(length time.Duration, out io.Writer) {
	bind.OutputStart(length, out)
}

// OutputContinueTo to  mix and output as []byte via stdout, up to a specified duration-since-start
func OutputContinueTo(t time.Duration) {
	deltaDur := t - outputToDur
	deltaTz := spec.Tz(masterFreq * float64((deltaDur)/time.Second))
	debug.Printf("mix.OutputContinueTo(%+v) deltaDur:%+v nowTz:%+v deltaTz:%+v begin...", t, deltaDur, nowTz, deltaTz)
	bind.OutputNext(deltaTz)
	outputToDur = t
	debug.Printf("mix.OutputContinueTo(%+v) ...done! nowTz:%+v outputToDur:%+v", t, nowTz, outputToDur)
}

// OutputBegin to output WAV closer as []byte via stdout
func OutputClose() {
	// nothing to do
}

//
// Private
//

var (
	outputToDur      time.Duration
	startAtTime      time.Time
	nowTz            spec.Tz
	nextCycleTz      spec.Tz
	masterCycleDurTz spec.Tz
	masterTzDur      time.Duration
	// TODO: implement mixFreq float64
	mixSourcePrefix string
	mixReadyFires   []*fire.Fire
	mixLiveFires    []*fire.Fire
	masterSpec      *spec.AudioSpec
	masterFreq      float64
)

func init() {
	startAtTime = time.Now().Add(0xFFFF * time.Hour) // this gets reset by Start() or StartAt()
}

func mixSourceAt(src string, volume float64, pan float64, at spec.Tz) []sample.Value {
	s := mixGetSource(src)
	if s == nil {
		return make([]sample.Value, masterSpec.Channels)
	}
	// if at != 0 {
	// 	debug.Printf("About to source.SampleAt %v in %v\n", at, s.URL)
	// }
	return s.SampleAt(at, volume, pan)
}

func mixPrepareSource(src string) {
	source.Prepare(src)
}

func mixGetSource(src string) *source.Source {
	return source.Get(src)
}

// TODO:
// Make a new empty map[string]*Source, e.g. keepSource
// While iterating over the ready & active fires (see issues #11 and #18; implemented as of pull #29) copy any used *Source to the new keepSource
// Replace the mixSource with keepSource
func mixCycle() {
	var f *fire.Fire
	// for garbage collection of unused sources:
	keepSource := make(map[string]bool)
	// if a fire is near-to-playback, move it to the live fire queue
	keepReadyFires := make([]*fire.Fire, 0)
	for _, f = range mixReadyFires {
		keepSource[f.Source] = true
		if f.BeginTz < nowTz+masterCycleDurTz*2 { // for now, double a mix cycle is consider near-playback
			mixLiveFires = append(mixLiveFires, f)
		} else {
			keepReadyFires = append(keepReadyFires, f)
		}
	}
	mixReadyFires = keepReadyFires
	// keep only active fires
	keepLiveFires := make([]*fire.Fire, 0)
	for _, f = range mixLiveFires {
		if f.IsAlive() {
			keepSource[f.Source] = true
			keepLiveFires = append(keepLiveFires, f)
		} else {
			f.Teardown()
		}
	}
	mixLiveFires = keepLiveFires
	source.Prune(keepSource)
	nextCycleTz = nowTz + masterCycleDurTz
	if debug.Active() && source.Count() > 0 {
		debug.Printf("mix [%dz] fire-ready:%d fire-active:%d sources:%d\n", nowTz, len(mixReadyFires), len(mixLiveFires), source.Count())
	}
}

func mixLogarithmicRangeCompression(i sample.Value) sample.Value {
	if i < -1 {
		return sample.Value(-math.Log(-float64(i)-0.85)/14 - 0.75)
	} else if i > 1 {
		return sample.Value(math.Log(float64(i)-0.85)/14 + 0.75)
	} else {
		return sample.Value(i / 1.61803398875)
	}
}
<commit_msg>Update mix.go<commit_after>// Package mix combines sources into an output audio stream
package mix

import (
	"io"
	"math"
	"time"

	"github.com/go-mix/mix/bind/spec"

	"github.com/go-mix/mix/bind"
	"github.com/go-mix/mix/bind/debug"
	"github.com/go-mix/mix/bind/sample"
	"github.com/go-mix/mix/lib/fire"
	"github.com/go-mix/mix/lib/source"
)

// NextSample returns the next sample mixed in all channels
func NextSample() []sample.Value {
	smp := make([]sample.Value, masterSpec.Channels)
	var fireSample []sample.Value
	for _, fire := range mixLiveFires {
		if fireTz := fire.At(nowTz); fireTz > 0 {
			fireSample = mixSourceAt(fire.Source, fire.Volume, fire.Pan, fireTz)
			for c := 0; c < masterSpec.Channels; c++ {
				smp[c] += fireSample[c]
			}
		}
	}
	//	debug.Printf("*Mixer.nextSample %+v\n", sample)
	nowTz++
	out := make([]sample.Value, masterSpec.Channels)
	for c := 0; c < masterSpec.Channels; c++ {
		out[c] = mixLogarithmicRangeCompression(smp[c])
	}
	if nowTz > nextCycleTz {
		mixCycle()
	}
	return out
}

// Configure the mixer frequency, format, channels & sample rate.
func Configure(s spec.AudioSpec) {
	masterSpec = &s
	masterFreq = float64(s.Freq)
	masterTzDur = time.Second / time.Duration(masterFreq)
	masterCycleDurTz = spec.Tz(masterFreq)
	source.Configure(s)
}

// Spec spec returns the current audio specification.
func Spec() *spec.AudioSpec {
	return masterSpec
}

// Teardown everything and release all memory.
func Teardown() {
	ClearAllFires()
	outputToDur = time.Duration(0)
	nextCycleTz = 0
	nowTz = 0
}

// SetFire to represent a single audio source playing at a specific time in the future (in time.Duration from play start), with sustain time.Duration, volume from 0 to 1, and pan from -1 to +1
func SetFire(source string, begin time.Duration, sustain time.Duration, volume float64, pan float64) *fire.Fire {
	mixPrepareSource(mixSourcePrefix + source)
	beginTz := spec.Tz(begin.Nanoseconds() / masterTzDur.Nanoseconds())
	var endTz spec.Tz
	if sustain != 0 {
		endTz = beginTz + spec.Tz(sustain.Nanoseconds()/masterTzDur.Nanoseconds())
	}
	f := fire.New(mixSourcePrefix+source, beginTz, endTz, volume, pan)
	mixReadyFires = append(mixReadyFires, f)
	return f
}

// FireCount returns the current total ready fires + live fires.
func FireCount() int {
	return len(mixLiveFires) + len(mixReadyFires)
}

// StartAt to specify what time to begin mixing.
func StartAt(t time.Time) {
	startAtTime = t
}

// GetStartTime returns the time mixing began.
func GetStartTime() time.Time {
	return startAtTime
}

// GetNowAt returns current mix position
func GetNowAt() time.Duration {
	return time.Duration(nowTz) * masterTzDur
}

// ClearAllFires to remove all ready & live fires.
func ClearAllFires() {
	mixReadyFires = make([]*fire.Fire, 0)
	mixLiveFires = make([]*fire.Fire, 0)
}

// SetSoundsPath to set the sound path prefix.
func SetSoundsPath(prefix string) {
	mixSourcePrefix = prefix
}

// GetCycleDurationTz sets the duration of a mix cycle.
func SetCycleDuration(d time.Duration) {
	if masterFreq == 0 {
		panic("Must specify mixing frequency before setting cycle duration!")
	}
	masterCycleDurTz = spec.Tz((d / time.Second) * time.Duration(masterFreq))
}

// GetCycleDurationTz returns the duration of a mix cycle.
func GetCycleDurationTz() spec.Tz {
	return masterCycleDurTz
}

// OutputStart requires a known length
func OutputStart(length time.Duration, out io.Writer) {
	bind.OutputStart(length, out)
}

// OutputContinueTo to  mix and output as []byte via stdout, up to a specified duration-since-start
func OutputContinueTo(t time.Duration) {
	deltaDur := t - outputToDur
	deltaTz := spec.Tz(masterFreq * float64((deltaDur)/time.Second))
	debug.Printf("mix.OutputContinueTo(%+v) deltaDur:%+v nowTz:%+v deltaTz:%+v begin...", t, deltaDur, nowTz, deltaTz)
	bind.OutputNext(deltaTz)
	outputToDur = t
	debug.Printf("mix.OutputContinueTo(%+v) ...done! nowTz:%+v outputToDur:%+v", t, nowTz, outputToDur)
}

// OutputBegin to output WAV closer as []byte via stdout
func OutputClose() {
	// nothing to do
}

//
// Private
//

var (
	outputToDur      time.Duration
	startAtTime      time.Time
	nowTz            spec.Tz
	nextCycleTz      spec.Tz
	masterCycleDurTz spec.Tz
	masterTzDur      time.Duration
	// TODO: implement mixFreq float64
	mixSourcePrefix string
	mixReadyFires   []*fire.Fire
	mixLiveFires    []*fire.Fire
	masterSpec      *spec.AudioSpec
	masterFreq      float64
)

func init() {
	startAtTime = time.Now().Add(0xFFFF * time.Hour) // this gets reset by Start() or StartAt()
}

func mixSourceAt(src string, volume float64, pan float64, at spec.Tz) []sample.Value {
	s := mixGetSource(src)
	if s == nil {
		return make([]sample.Value, masterSpec.Channels)
	}
	// if at != 0 {
	// 	debug.Printf("About to source.SampleAt %v in %v\n", at, s.URL)
	// }
	return s.SampleAt(at, volume, pan)
}

func mixPrepareSource(src string) {
	source.Prepare(src)
}

func mixGetSource(src string) *source.Source {
	return source.Get(src)
}

// TODO:
// Make a new empty map[string]*Source, e.g. keepSource
// While iterating over the ready & active fires (see issues #11 and #18; implemented as of pull #29) copy any used *Source to the new keepSource
// Replace the mixSource with keepSource
func mixCycle() {
	var f *fire.Fire
	// for garbage collection of unused sources:
	keepSource := make(map[string]bool)
	// if a fire is near-to-playback, move it to the live fire queue
	keepReadyFires := make([]*fire.Fire, 0)
	for _, f = range mixReadyFires {
		keepSource[f.Source] = true
		if f.BeginTz < nowTz+masterCycleDurTz*2 { // for now, double a mix cycle is consider near-playback
			mixLiveFires = append(mixLiveFires, f)
		} else {
			keepReadyFires = append(keepReadyFires, f)
		}
	}
	mixReadyFires = keepReadyFires
	// keep only active fires
	keepLiveFires := make([]*fire.Fire, 0)
	for _, f = range mixLiveFires {
		if f.IsAlive() {
			keepSource[f.Source] = true
			keepLiveFires = append(keepLiveFires, f)
		} else {
			f.Teardown()
		}
	}
	mixLiveFires = keepLiveFires
	source.Prune(keepSource)
	nextCycleTz = nowTz + masterCycleDurTz
	if debug.Active() && source.Count() > 0 {
		debug.Printf("mix [%dz] fire-ready:%d fire-active:%d sources:%d\n", nowTz, len(mixReadyFires), len(mixLiveFires), source.Count())
	}
}

func mixLogarithmicRangeCompression(i sample.Value) sample.Value {
	if i < -1 {
		return sample.Value(-math.Log(-float64(i)-0.85)/14 - 0.75)
	} else if i > 1 {
		return sample.Value(math.Log(float64(i)-0.85)/14 + 0.75)
	} else {
		return sample.Value(i / 1.61803398875)
	}
}
<|endoftext|>


<commit_before>package logyard

import (
	"github.com/ActiveState/zmqpubsub"
)

var Broker zmqpubsub.Broker

func init() {
	Broker.PubAddr = "tcp://127.0.0.1:5559"
	Broker.SubAddr = "tcp://127.0.0.1:5560"
	Broker.BufferSize = 100
}
<commit_msg>[103527] Merge branch 'stackon_appstore'<commit_after>package logyard

import (
	"github.com/ActiveState/log"
	"github.com/ActiveState/zmqpubsub"
)

var Broker zmqpubsub.Broker

func init() {
	Broker.PubAddr = "ipc:///var/stackato/run/logyardpub.sock"
	Broker.SubAddr = "ipc:///var/stackato/run/logyardsub.sock"
	Broker.BufferSize = 100

	log.Infof("Loygard broker config: %+v\n", Broker)
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"io/ioutil"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	_ "github.com/go-sql-driver/mysql"
)

var (
	errMySQLDuplicateEntry = uint16(0x426)
)

type mariaDB struct {
	db *sql.DB
}

func mustSetupMariaDB(config mariadbConfig) *mariaDB {
	db, err := setupMariaDB(config)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("Could not setup MariaDB.")
	}
	return db
}

func setupMariaDB(conf mariadbConfig) (*mariaDB, error) {
	db, err := sql.Open("mysql", conf.URL)
	if err != nil {
		return nil, err
	}

	if err = db.Ping(); err != nil {
		return nil, err
	}

	log.Infof("Set up MariaDB connection for %#v.", conf.URL)

	mustRunMariaDBSQL(db)

	log.Infof("Initialize schema and tables")

	return &mariaDB{db}, nil
}

func mustRunMariaDBSQL(db *sql.DB) {
	queries, err := ioutil.ReadFile("mariadb.sql")
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatalf("Failed to read cql initialization file.")
	}

	mustRunQuery(db, string(queries))
}

func mustRunQuery(db *sql.DB, sql string) {
	for _, q := range strings.Split(sql, ";") {
		if len(q) > 5 {
			_, err := db.Exec(q)
			if err != nil {
				log.WithFields(log.Fields{"query": q, "err": err}).Fatal("Failed to run sql in mariadb")
			}
		}
	}
}

func (m *mariaDB) saveScrape(topic string, partition int32, offset int64) error {
	q := `INSERT INTO bookie.scrape
					(topic, topic_partition, lastOffset, updated)
				VALUES
					(?, ?, ?, UTC_TIMESTAMP())
				ON DUPLICATE KEY UPDATE
					lastOffset = ?,
					updated = UTC_TIMESTAMP()
				`

	_, err := m.db.Exec(q,
		topic,
		partition,
		offset+1,
		offset+1,
	)

	if err != nil {
		fs := log.Fields{
			"tenant":     topic,
			"campaignID": partition,
			"execution":  offset,
			"err":        err,
		}
		log.WithFields(fs).Error("Failed to save scrape")
		return err
	}

	return nil
}

func (m *mariaDB) getLastNFSMs(n int) ([]fsm, error) {
	fsms := []fsm{}
	q := `SELECT
			f.*, t.k, t.v
		  FROM
		    (SELECT fsmID, created FROM bookie.fsm ORDER BY created DESC LIMIT ?) f
		  JOIN
		    bookie.tags t USING(fsmID)
		  `

	dbRows, err := m.db.Query(q, n)
	if err != nil {
		return fsms, err
	}

	defer closeRows(dbRows)

	tm := map[string]map[string]string{}
	for dbRows.Next() {
		var fsmID, _created, k, v string

		if err = dbRows.Scan(&fsmID, &_created, &k, &v); err != nil {
			log.WithFields(log.Fields{"err": err, "number": n}).Errorf("failed to get last n fsms")
			return fsms, err
		}

		tgs, ok := tm[fsmID]
		if !ok {
			tgs = map[string]string{}
		}
		tgs[k] = v
		tm[fsmID] = tgs

		created, err := time.Parse("2006-01-02 15:04:05", _created)
		if err != nil {
			return fsms, err
		}

		f := fsm{
			ID:      fsmID,
			Created: created,
		}
		fsms = append(fsms, f)
	}

	for _, f := range fsms {
		tgs, _ := tm[f.ID]
		f.Tags = tgs
	}

	return fsms, nil
}

func (m *mariaDB) saveFSM(f fsmDataPoint) error {
	q := `INSERT INTO bookie.fsm(fsmID, created) values (?, ?) ON DUPLICATE KEY UPDATE created = ?;`

	_, err := m.db.Exec(q,
		f.fsmID,
		f.created,
		f.created,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":   f.fsmID,
			"created": f.created,
			"err":     err,
		}
		log.WithFields(fs).Error("Failed to save FSM")
		return err
	}

	q = `INSERT INTO bookie.offset
				(fsmID, topic, topic_partition, startOffset, lastOffset, count, updated)
			VALUES
				(?, ?, ?, ?, ?, ?, UTC_TIMESTAMP())
			ON DUPLICATE KEY UPDATE
				startOffset = ?,
				lastOffset = ?,
				count = ?,
				updated = UTC_TIMESTAMP()
			`

	_, err = m.db.Exec(q,
		f.fsmID,
		f.topic,
		f.partition,
		f.startOffset,
		f.lastOffset,
		f.count,
		f.startOffset,
		f.lastOffset,
		f.count,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":       f.fsmID,
			"topic":       f.topic,
			"partition":   f.partition,
			"startOffset": f.startOffset,
			"lastOffset":  f.lastOffset,
			"err":         err,
		}
		log.WithFields(fs).Error("Failed to save FSM offsets")
		return err
	}

	for k, v := range f.tags {
		q := `INSERT INTO bookie.tags(fsmID, k, v) values (?, ?, ?) ON DUPLICATE KEY UPDATE v = ?;`

		_, err := m.db.Exec(q, f.fsmID, k, v, v)

		if err != nil {
			fs := log.Fields{"fsmID": f.fsmID, "key": k, "value": v, "err": err}
			log.WithFields(fs).Error("Failed to save FSM tags")
			return err
		}
	}

	return nil
}

func (m *mariaDB) saveAlias(fsmID string, fsmAlias string) error {
	q := `INSERT INTO bookie.fsmAliases(fsmID, fsmAlias) (?, ?) ON DUPLICATE KEY UPDATE 1 = 1`

	_, err := m.db.Exec(q,
		fsmID,
		fsmAlias,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":    fsmID,
			"fsmAlias": fsmAlias,
			"err":      err,
		}
		log.WithFields(fs).Error("Failed to save FSM alias")
		return err
	}

	return nil
}

func (m *mariaDB) mustLoadScrapes() map[string]topicRecord {
	trs := map[string]topicRecord{}

	q := `SELECT topic, topic_partition, lastOffset FROM bookie.scrape`
	dbRows, err := m.db.Query(q)
	if err != nil {
		log.Fatal(err)
	}

	for dbRows.Next() {
		var topic string
		var partition int32
		var lastOffset int64

		if err = dbRows.Scan(&topic, &partition, &lastOffset); err != nil {
			log.Fatal(err)
		}
		if _, ok := trs[topic]; !ok {
			trs[topic] = topicRecord{
				topic:      topic,
				partitions: map[int32]int64{},
			}
		}
		trs[topic].partitions[partition] = lastOffset
	}

	return trs
}

func (m *mariaDB) findFSM(fsmID string) (fsm, error) {
	var (
		err error
		fs  = log.Fields{"fsmID": fsmID}
	)
	fsm := fsm{Topics: map[string]topic{}}

	q := `SELECT
					fsmID, o.topic, o.topic_partition, o.startOffset, o.lastOffset, f.created, o.updated, o.count, s.lastOffset, t.k, t.v
				FROM
					bookie.offset o
				JOIN
					bookie.fsm f USING(fsmID)
				JOIN
					bookie.scrape s USING(topic, topic_partition)
				JOIN
				    bookie.tags t USING(fsmID)
				WHERE
					fsmID = ?`
	dbRows, err := m.db.Query(q, fsmID)
	if err != nil {
		return fsm, err
	}

	defer closeRows(dbRows)

	topicCounts := map[string]int64{}
	tags := map[string]string{}
	for dbRows.Next() {
		var fsmID, topic, k, v string
		var part int32
		var startOffset, lastOffset, count, lastScrapedOffset int64
		var _created, _updated string

		if err = dbRows.Scan(&fsmID, &topic, &part, &startOffset, &lastOffset, &_created, &_updated, &count, &lastScrapedOffset, &k, &v); err != nil {
			fs["error"] = err
			log.WithFields(fs).Errorf("failed to scan execution uuid")
			return fsm, err
		}
		tags[k] = v
		created, err := time.Parse("2006-01-02 15:04:05", _created)
		if err != nil {
			return fsm, err
		}

		fsm.Created = created
		fsm.ID = fsmID
		t, ok := fsm.Topics[topic]
		if !ok {
			t.Partitions = make(map[int32]partition)
		}

		t.Partitions[part] = partition{
			Start:       startOffset,
			End:         lastOffset,
			LastScraped: lastScrapedOffset,
			Count:       count,
		}
		fsm.Topics[topic] = t

		if _, ok := topicCounts[topic]; !ok {
			topicCounts[topic] = 0
		}
		topicCounts[topic] += count
	}

	fsm.Tags = tags

	for t, c := range topicCounts {
		tp := fsm.Topics[t]
		tp.Count = c
		fsm.Topics[t] = tp
	}

	return fsm, nil
}

func closeRows(rows *sql.Rows) {
	if err := rows.Close(); err != nil {
		log.WithField("error", err).Error("failed to close rows")
	}
}
<commit_msg>fixes duplicate fsms issue<commit_after>package main

import (
	"database/sql"
	"io/ioutil"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	_ "github.com/go-sql-driver/mysql"
)

var (
	errMySQLDuplicateEntry = uint16(0x426)
)

type mariaDB struct {
	db *sql.DB
}

func mustSetupMariaDB(config mariadbConfig) *mariaDB {
	db, err := setupMariaDB(config)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("Could not setup MariaDB.")
	}
	return db
}

func setupMariaDB(conf mariadbConfig) (*mariaDB, error) {
	db, err := sql.Open("mysql", conf.URL)
	if err != nil {
		return nil, err
	}

	if err = db.Ping(); err != nil {
		return nil, err
	}

	log.Infof("Set up MariaDB connection for %#v.", conf.URL)

	mustRunMariaDBSQL(db)

	log.Infof("Initialize schema and tables")

	return &mariaDB{db}, nil
}

func mustRunMariaDBSQL(db *sql.DB) {
	queries, err := ioutil.ReadFile("mariadb.sql")
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatalf("Failed to read cql initialization file.")
	}

	mustRunQuery(db, string(queries))
}

func mustRunQuery(db *sql.DB, sql string) {
	for _, q := range strings.Split(sql, ";") {
		if len(q) > 5 {
			_, err := db.Exec(q)
			if err != nil {
				log.WithFields(log.Fields{"query": q, "err": err}).Fatal("Failed to run sql in mariadb")
			}
		}
	}
}

func (m *mariaDB) saveScrape(topic string, partition int32, offset int64) error {
	q := `INSERT INTO bookie.scrape
					(topic, topic_partition, lastOffset, updated)
				VALUES
					(?, ?, ?, UTC_TIMESTAMP())
				ON DUPLICATE KEY UPDATE
					lastOffset = ?,
					updated = UTC_TIMESTAMP()
				`

	_, err := m.db.Exec(q,
		topic,
		partition,
		offset+1,
		offset+1,
	)

	if err != nil {
		fs := log.Fields{
			"tenant":     topic,
			"campaignID": partition,
			"execution":  offset,
			"err":        err,
		}
		log.WithFields(fs).Error("Failed to save scrape")
		return err
	}

	return nil
}

func (m *mariaDB) getLastNFSMs(n int) ([]fsm, error) {
	fsms := []fsm{}
	q := `SELECT
			f.*, t.k, t.v
		  FROM
		    (SELECT fsmID, created FROM bookie.fsm ORDER BY created DESC LIMIT ?) f
		  JOIN
		    bookie.tags t USING(fsmID)
		  `

	dbRows, err := m.db.Query(q, n)
	if err != nil {
		return fsms, err
	}

	defer closeRows(dbRows)

	tm := map[string]map[string]string{}
	fsmMap := map[string]fsm{}
	for dbRows.Next() {
		var fsmID, _created, k, v string

		if err = dbRows.Scan(&fsmID, &_created, &k, &v); err != nil {
			log.WithFields(log.Fields{"err": err, "number": n}).Errorf("failed to get last n fsms")
			return fsms, err
		}

		tgs, ok := tm[fsmID]
		if !ok {
			tgs = map[string]string{}
		}
		tgs[k] = v
		tm[fsmID] = tgs

		created, err := time.Parse("2006-01-02 15:04:05", _created)
		if err != nil {
			return fsms, err
		}
		f, ok := fsmMap[fsmID]
		if !ok {
			f = fsm{
				ID:      fsmID,
				Created: created,
			}
			fsmMap[fsmID] = f
		}

		ts := f.Tags
		if len(ts) == 0 {
			ts := map[string]string{}
			f.Tags = ts
		}
		ts[k] = v
	}

	for _, v := range fsmMap {
		fsms = append(fsms, v)
	}

	return fsms, nil
}

func (m *mariaDB) saveFSM(f fsmDataPoint) error {
	q := `INSERT INTO bookie.fsm(fsmID, created) values (?, ?) ON DUPLICATE KEY UPDATE created = ?;`

	_, err := m.db.Exec(q,
		f.fsmID,
		f.created,
		f.created,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":   f.fsmID,
			"created": f.created,
			"err":     err,
		}
		log.WithFields(fs).Error("Failed to save FSM")
		return err
	}

	q = `INSERT INTO bookie.offset
				(fsmID, topic, topic_partition, startOffset, lastOffset, count, updated)
			VALUES
				(?, ?, ?, ?, ?, ?, UTC_TIMESTAMP())
			ON DUPLICATE KEY UPDATE
				startOffset = ?,
				lastOffset = ?,
				count = ?,
				updated = UTC_TIMESTAMP()
			`

	_, err = m.db.Exec(q,
		f.fsmID,
		f.topic,
		f.partition,
		f.startOffset,
		f.lastOffset,
		f.count,
		f.startOffset,
		f.lastOffset,
		f.count,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":       f.fsmID,
			"topic":       f.topic,
			"partition":   f.partition,
			"startOffset": f.startOffset,
			"lastOffset":  f.lastOffset,
			"err":         err,
		}
		log.WithFields(fs).Error("Failed to save FSM offsets")
		return err
	}

	for k, v := range f.tags {
		q := `INSERT INTO bookie.tags(fsmID, k, v) values (?, ?, ?) ON DUPLICATE KEY UPDATE v = ?;`

		_, err := m.db.Exec(q, f.fsmID, k, v, v)

		if err != nil {
			fs := log.Fields{"fsmID": f.fsmID, "key": k, "value": v, "err": err}
			log.WithFields(fs).Error("Failed to save FSM tags")
			return err
		}
	}

	return nil
}

func (m *mariaDB) saveAlias(fsmID string, fsmAlias string) error {
	q := `INSERT INTO bookie.fsmAliases(fsmID, fsmAlias) (?, ?) ON DUPLICATE KEY UPDATE 1 = 1`

	_, err := m.db.Exec(q,
		fsmID,
		fsmAlias,
	)

	if err != nil {
		fs := log.Fields{
			"fsmID":    fsmID,
			"fsmAlias": fsmAlias,
			"err":      err,
		}
		log.WithFields(fs).Error("Failed to save FSM alias")
		return err
	}

	return nil
}

func (m *mariaDB) mustLoadScrapes() map[string]topicRecord {
	trs := map[string]topicRecord{}

	q := `SELECT topic, topic_partition, lastOffset FROM bookie.scrape`
	dbRows, err := m.db.Query(q)
	if err != nil {
		log.Fatal(err)
	}

	for dbRows.Next() {
		var topic string
		var partition int32
		var lastOffset int64

		if err = dbRows.Scan(&topic, &partition, &lastOffset); err != nil {
			log.Fatal(err)
		}
		if _, ok := trs[topic]; !ok {
			trs[topic] = topicRecord{
				topic:      topic,
				partitions: map[int32]int64{},
			}
		}
		trs[topic].partitions[partition] = lastOffset
	}

	return trs
}

func (m *mariaDB) findFSM(fsmID string) (fsm, error) {
	var (
		err error
		fs  = log.Fields{"fsmID": fsmID}
	)
	fsm := fsm{Topics: map[string]topic{}}

	q := `SELECT
					fsmID, o.topic, o.topic_partition, o.startOffset, o.lastOffset, f.created, o.updated, o.count, s.lastOffset, t.k, t.v
				FROM
					bookie.offset o
				JOIN
					bookie.fsm f USING(fsmID)
				JOIN
					bookie.scrape s USING(topic, topic_partition)
				JOIN
				    bookie.tags t USING(fsmID)
				WHERE
					fsmID = ?`
	dbRows, err := m.db.Query(q, fsmID)
	if err != nil {
		return fsm, err
	}

	defer closeRows(dbRows)

	topicCounts := map[string]int64{}
	tags := map[string]string{}
	for dbRows.Next() {
		var fsmID, topic, k, v string
		var part int32
		var startOffset, lastOffset, count, lastScrapedOffset int64
		var _created, _updated string

		if err = dbRows.Scan(&fsmID, &topic, &part, &startOffset, &lastOffset, &_created, &_updated, &count, &lastScrapedOffset, &k, &v); err != nil {
			fs["error"] = err
			log.WithFields(fs).Errorf("failed to scan execution uuid")
			return fsm, err
		}
		tags[k] = v
		created, err := time.Parse("2006-01-02 15:04:05", _created)
		if err != nil {
			return fsm, err
		}

		fsm.Created = created
		fsm.ID = fsmID
		t, ok := fsm.Topics[topic]
		if !ok {
			t.Partitions = make(map[int32]partition)
		}

		t.Partitions[part] = partition{
			Start:       startOffset,
			End:         lastOffset,
			LastScraped: lastScrapedOffset,
			Count:       count,
		}
		fsm.Topics[topic] = t

		if _, ok := topicCounts[topic]; !ok {
			topicCounts[topic] = 0
		}
		topicCounts[topic] += count
	}

	fsm.Tags = tags

	for t, c := range topicCounts {
		tp := fsm.Topics[t]
		tp.Count = c
		fsm.Topics[t] = tp
	}

	return fsm, nil
}

func closeRows(rows *sql.Rows) {
	if err := rows.Close(); err != nil {
		log.WithField("error", err).Error("failed to close rows")
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 go-dockerclient 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 docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id"`
	RepoTags    []string `json:",omitempty"`
	Created     int64
	Size        int64
	VirtualSize int64
	ParentId    string `json:",omitempty"`
	Repository  string `json:",omitempty"`
	Tag         string `json:",omitempty"`
}

type Image struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"containerconfig,omitempty"`
	DockerVersion   string    `json:"dockerversion,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/dkMrwP for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/7hjHHy for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/pHEbma for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/GBmyhc for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Registry server to push the image
	Registry string

	OutputStream io.Writer `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authencation in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/GBmyhc for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)

	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.stream("POST", path, true, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/PhBKnS for more details.
type PullImageOptions struct {
	Repository   string `qs:"fromImage"`
	Registry     string
	Tag          string
	OutputStream io.Writer `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)
	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, headers, in, w, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream)
}

// BuildImageOptions present the set of informations available for building
// an image from a tarfile with a Dockerfile in it,the details about Dockerfile
// see http://docs.docker.io/en/latest/reference/builder/
type BuildImageOptions struct {
	Name           string    `qs:"t"`
	NoCache        bool      `qs:"nocache"`
	SuppressOutput bool      `qs:"q"`
	RmTmpContainer bool      `qs:"rm"`
	InputStream    io.Reader `qs:"-"`
	OutputStream   io.Writer `qs:"-"`
	Remote         string    `qs:"remote"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers map[string]string
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil {
		headers = map[string]string{"Content-Type": "application/tar"}
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image
type TagImageOptions struct {
	Repo  string `qs:"repo"`
	Force bool   `qs:"force"`
}

// TagImage adds a tag to the image 'name'
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}
<commit_msg>Adding `Tag` field to TagImageOptions<commit_after>// Copyright 2014 go-dockerclient 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 docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id"`
	RepoTags    []string `json:",omitempty"`
	Created     int64
	Size        int64
	VirtualSize int64
	ParentId    string `json:",omitempty"`
	Repository  string `json:",omitempty"`
	Tag         string `json:",omitempty"`
}

type Image struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"containerconfig,omitempty"`
	DockerVersion   string    `json:"dockerversion,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/dkMrwP for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/7hjHHy for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/pHEbma for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/GBmyhc for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Registry server to push the image
	Registry string

	OutputStream io.Writer `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authencation in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/GBmyhc for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)

	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.stream("POST", path, true, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/PhBKnS for more details.
type PullImageOptions struct {
	Repository   string `qs:"fromImage"`
	Registry     string
	Tag          string
	OutputStream io.Writer `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)
	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, headers, in, w, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream)
}

// BuildImageOptions present the set of informations available for building
// an image from a tarfile with a Dockerfile in it,the details about Dockerfile
// see http://docs.docker.io/en/latest/reference/builder/
type BuildImageOptions struct {
	Name           string    `qs:"t"`
	NoCache        bool      `qs:"nocache"`
	SuppressOutput bool      `qs:"q"`
	RmTmpContainer bool      `qs:"rm"`
	InputStream    io.Reader `qs:"-"`
	OutputStream   io.Writer `qs:"-"`
	Remote         string    `qs:"remote"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers map[string]string
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil {
		headers = map[string]string{"Content-Type": "application/tar"}
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image
type TagImageOptions struct {
	Repo  string `qs:"repo"`
	Tag   string `qs:"tag"`
	Force bool   `qs:"force"`
}

// TagImage adds a tag to the image 'name'
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}
<|endoftext|>


<commit_before>//
// Laser Range Finder
// image.go
//
// Cole Smith - css@nyu.edu
// Eric Lin   - eric.lin@nyu.edu
// LICENSE: Apache 2.0
//

package rangefinder

import (
	"fmt"
	"image"
	"image/color"
	"math"
)

// Defines an image as a two dimensional array of hues
// from the HSV colorspace
type ImageMatrix struct {
	width  int
	height int
	//image  [][]float64
	image [][]*Pixel
}

// Generates a new ImageMatrix struct given an input
// image of type image.RGBA
func NewImageMatrix(inputImage *image.RGBA) *ImageMatrix {
	// Get Image width and height
	bounds := inputImage.Bounds()
	width := bounds.Max.X
	height := bounds.Max.Y

	// Fill the image 2D slice with hues
	image := make([][]*Pixel, height)
	for i := range image {
		image[i] = make([]*Pixel, width)
		for j := range image[i] {
			pixel := getHSVFromRGBA(inputImage.At(i, j))
			image[i][j] = pixel
		}
	}
	return &ImageMatrix{width, height, image}
}

// Defines a new image in binary greyscale using bool values
type MonoImageMatrix struct {
	Width         int
	Height        int
	ValueTreshold float64
	Image         [][]bool
}

// Generates a new MonoImageMatrix struct given an image of type image.RGBA,
// and the treshold at which the Value (Lume) of an image is considered a 1
// or a 0 such that:  1 <- pixel >= valueThreshold, 0 <- pixel < valueThreshold
func NewMonoImageMatrix(inputImage *image.RGBA, valueThreshold float64) *MonoImageMatrix {
	// Get Image width and height
	bounds := inputImage.Bounds()
	width := bounds.Max.X
	height := bounds.Max.Y

	image := make([][]bool, height)
	for i := range image {
		image[i] = make([]bool, width)
		for j := range image[i] {
			val := getHSVFromRGBA(inputImage.At(j, i)).val
			image[i][j] = val >= valueThreshold
		}
	}
	return &MonoImageMatrix{width, height, valueThreshold, image}
}

// Returns an empty greyscale image of width and height
// Defaults to all pixels false and a valueThreshold of 0
func NewEmptyMonoImageMatrix(width, height int) *MonoImageMatrix {
	image := make([][]bool, height)
	for i := range image {
		image[i] = make([]bool, width)
		for j := range image[i] {
			image[i][j] = false
		}
	}
	return &MonoImageMatrix{width, height, 0, image}
}

// Converts an ImageMatrix to a MonoImageMatrix using value thresholding
func (image ImageMatrix) ConvertToMonoImageMatrix(valueThreshold float64) *MonoImageMatrix {
	mono := make([][]bool, image.height)
	for i, _ := range mono {
		mono[i] = make([]bool, image.width)
		for j, _ := range mono[i] {
			val := image.image[i][j].val
			mono[i][j] = val >= valueThreshold
		}
	}
	return &MonoImageMatrix{image.width, image.height, valueThreshold, mono}
}

// Binds the pixel offset of the laser dot from the center plane
// of the image to a specified inital distance of units.
// Example: (image, 0.64, 1, "meters")
func Calibrate(image ImageMatrix, laserHue float64, initialDistance int, unitSuffix string) {
}

// Runs the image through a filter pass, to isolate the laser dot in the
// image by decreasing luminosity and apply edge detection
func (image ImageMatrix) filterImage() ImageMatrix {
	return image
}

// Iterates through image array to detect the laser dot. The pixels that
// match the hue, plus or minus the threshold value, will be marked true
// on a binary image.
func detectDotInImage(image ImageMatrix, laserHue int) MonoImageMatrix {
	dotImage := NewEmptyMonoImageMatrix(image.width, image.height)
	return *dotImage
}

// Returns the centroid of the marked pixel cluster of a binary image
func getCentroid(monoImage MonoImageMatrix) Pixel {
	var centroid Pixel
	return centroid
}

// A pixel for an image defined in the
// HSV colorspace
type Pixel struct {
	hue float64
	sat float64
	val float64
}

// Returns a Hue angle as a float64 from an RGBA Color
func getHSVFromRGBA(rgba color.Color) *Pixel {
	//Get RGB values
	red, green, blue, _ := rgba.RGBA()
	r := float64(red)
	g := float64(green)
	b := float64(blue)

	//Set up computed variables
	var hue float64 = 0.0
	var sat float64 = 0.0
	var val float64 = 0.0
	var d float64 = 0.0
	var h float64 = 0.0

    fmt.Println(r, g, b)

	//Standardize rgb values
	r = r/255
	g = g/255
	b = b/255

	//Get min and max for RGB
	min := math.Min(math.Min(r, g), b)
	max := math.Max(math.Max(r, g), b)

	//If min is equal to max, we can assume it is black and white
	if min == max {
		return &Pixel{0, 0, min}
	}

	//Get delta for max and min
	if r == min {
		d = g - b
		h = 3
	}
	else {
		if b == min
		{
			d = r - g
			h = 1
		}
		else
		{
			d = b - r
			h = 5
		}
	}

	hue = 60 * (h - d/(max - min))
	sat = (max - min)/max
	val = max

	fmt.Println(val)

	return &Pixel{hue, sat, val}
}

//// Returns the Value (Lume) as a float64 from an RGBA Color
//func getValueFromRGBA(rgba color.Color) float64 {
//red, green, blue, _ := rgba.RGBA()
//r := float64(red)
//g := float64(green)
//b := float64(blue)

//return math.Max(math.Max(r, g), b)
//}
<commit_msg>fixed formatting<commit_after>//
// Laser Range Finder
// image.go
//
// Cole Smith - css@nyu.edu
// Eric Lin   - eric.lin@nyu.edu
// LICENSE: Apache 2.0
//

package rangefinder

import (
	"fmt"
	"image"
	"image/color"
	"math"
)

// Defines an image as a two dimensional array of hues
// from the HSV colorspace
type ImageMatrix struct {
	width  int
	height int
	//image  [][]float64
	image [][]*Pixel
}

// Generates a new ImageMatrix struct given an input
// image of type image.RGBA
func NewImageMatrix(inputImage *image.RGBA) *ImageMatrix {
	// Get Image width and height
	bounds := inputImage.Bounds()
	width := bounds.Max.X
	height := bounds.Max.Y

	// Fill the image 2D slice with hues
	image := make([][]*Pixel, height)
	for i := range image {
		image[i] = make([]*Pixel, width)
		for j := range image[i] {
			pixel := getHSVFromRGBA(inputImage.At(i, j))
			image[i][j] = pixel
		}
	}
	return &ImageMatrix{width, height, image}
}

// Defines a new image in binary greyscale using bool values
type MonoImageMatrix struct {
	Width         int
	Height        int
	ValueTreshold float64
	Image         [][]bool
}

// Generates a new MonoImageMatrix struct given an image of type image.RGBA,
// and the treshold at which the Value (Lume) of an image is considered a 1
// or a 0 such that:  1 <- pixel >= valueThreshold, 0 <- pixel < valueThreshold
func NewMonoImageMatrix(inputImage *image.RGBA, valueThreshold float64) *MonoImageMatrix {
	// Get Image width and height
	bounds := inputImage.Bounds()
	width := bounds.Max.X
	height := bounds.Max.Y

	image := make([][]bool, height)
	for i := range image {
		image[i] = make([]bool, width)
		for j := range image[i] {
			val := getHSVFromRGBA(inputImage.At(j, i)).val
			image[i][j] = val >= valueThreshold
		}
	}
	return &MonoImageMatrix{width, height, valueThreshold, image}
}

// Returns an empty greyscale image of width and height
// Defaults to all pixels false and a valueThreshold of 0
func NewEmptyMonoImageMatrix(width, height int) *MonoImageMatrix {
	image := make([][]bool, height)
	for i := range image {
		image[i] = make([]bool, width)
		for j := range image[i] {
			image[i][j] = false
		}
	}
	return &MonoImageMatrix{width, height, 0, image}
}

// Converts an ImageMatrix to a MonoImageMatrix using value thresholding
func (image ImageMatrix) ConvertToMonoImageMatrix(valueThreshold float64) *MonoImageMatrix {
	mono := make([][]bool, image.height)
	for i, _ := range mono {
		mono[i] = make([]bool, image.width)
		for j, _ := range mono[i] {
			val := image.image[i][j].val
			mono[i][j] = val >= valueThreshold
		}
	}
	return &MonoImageMatrix{image.width, image.height, valueThreshold, mono}
}

// Binds the pixel offset of the laser dot from the center plane
// of the image to a specified inital distance of units.
// Example: (image, 0.64, 1, "meters")
func Calibrate(image ImageMatrix, laserHue float64, initialDistance int, unitSuffix string) {
}

// Runs the image through a filter pass, to isolate the laser dot in the
// image by decreasing luminosity and apply edge detection
func (image ImageMatrix) filterImage() ImageMatrix {
	return image
}

// Iterates through image array to detect the laser dot. The pixels that
// match the hue, plus or minus the threshold value, will be marked true
// on a binary image.
func detectDotInImage(image ImageMatrix, laserHue int) MonoImageMatrix {
	dotImage := NewEmptyMonoImageMatrix(image.width, image.height)
	return *dotImage
}

// Returns the centroid of the marked pixel cluster of a binary image
func getCentroid(monoImage MonoImageMatrix) Pixel {
	var centroid Pixel
	return centroid
}

// A pixel for an image defined in the
// HSV colorspace
type Pixel struct {
	hue float64
	sat float64
	val float64
}

// Returns a Hue angle as a float64 from an RGBA Color
func getHSVFromRGBA(rgba color.Color) *Pixel {
	//Get RGB values
	red, green, blue, _ := rgba.RGBA()
	r := float64(red)
	g := float64(green)
	b := float64(blue)

	//Set up computed variables
	var hue float64 = 0.0
	var sat float64 = 0.0
	var val float64 = 0.0
	var d float64 = 0.0
	var h float64 = 0.0

	fmt.Println(r, g, b)

	//Standardize rgb values
	r = r / 255
	g = g / 255
	b = b / 255

	//Get min and max for RGB
	min := math.Min(math.Min(r, g), b)
	max := math.Max(math.Max(r, g), b)

	//If min is equal to max, we can assume it is black and white
	if min == max {
		return &Pixel{0, 0, min}
	}

	//Get delta for max and min
	if r == min {
		d = g - b
		h = 3
	} else {
		if b == min {
			d = r - g
			h = 1
		} else {
			d = b - r
			h = 5
		}
	}

	hue = 60 * (h - d/(max-min))
	sat = (max - min) / max
	val = max

	fmt.Println(val)

	return &Pixel{hue, sat, val}
}

//// Returns the Value (Lume) as a float64 from an RGBA Color
//func getValueFromRGBA(rgba color.Color) float64 {
//red, green, blue, _ := rgba.RGBA()
//r := float64(red)
//g := float64(green)
//b := float64(blue)

//return math.Max(math.Max(r, g), b)
//}
<|endoftext|>