<commit_before>// Copyright 2017, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package prometheus contains a Prometheus exporter that supports exporting
// OpenCensus views as Prometheus metrics.
package prometheus // import "go.opencensus.io/exporter/prometheus"

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"sort"
	"sync"

	"go.opencensus.io/internal"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/tag"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Exporter exports stats to Prometheus, users need
// to register the exporter as an http.Handler to be
// able to export.
type Exporter struct {
	opts    Options
	g       prometheus.Gatherer
	c       *collector
	handler http.Handler
}

// Options contains options for configuring the exporter.
type Options struct {
	Namespace   string
	Registry    *prometheus.Registry
	OnError     func(err error)
	ConstLabels prometheus.Labels // ConstLabels will be set as labels on all views.
}

// NewExporter returns an exporter that exports stats to Prometheus.
func NewExporter(o Options) (*Exporter, error) {
	if o.Registry == nil {
		o.Registry = prometheus.NewRegistry()
	}
	collector := newCollector(o, o.Registry)
	e := &Exporter{
		opts:    o,
		g:       o.Registry,
		c:       collector,
		handler: promhttp.HandlerFor(o.Registry, promhttp.HandlerOpts{}),
	}
	return e, nil
}

var _ http.Handler = (*Exporter)(nil)
var _ view.Exporter = (*Exporter)(nil)

func (c *collector) registerViews(views ...*view.View) {
	count := 0
	for _, view := range views {
		sig := viewSignature(c.opts.Namespace, view)
		c.registeredViewsMu.Lock()
		_, ok := c.registeredViews[sig]
		c.registeredViewsMu.Unlock()

		if !ok {
			desc := prometheus.NewDesc(
				viewName(c.opts.Namespace, view),
				view.Description,
				tagKeysToLabels(view.TagKeys),
				c.opts.ConstLabels,
			)
			c.registeredViewsMu.Lock()
			c.registeredViews[sig] = desc
			c.registeredViewsMu.Unlock()
			count++
		}
	}
	if count == 0 {
		return
	}

	c.ensureRegisteredOnce()
}

// ensureRegisteredOnce invokes reg.Register on the collector itself
// exactly once to ensure that we don't get errors such as
//  cannot register the collector: descriptor Desc{fqName: *}
//  already exists with the same fully-qualified name and const label values
// which is documented by Prometheus at
//  https://github.com/prometheus/client_golang/blob/fcc130e101e76c5d303513d0e28f4b6d732845c7/prometheus/registry.go#L89-L101
func (c *collector) ensureRegisteredOnce() {
	c.registerOnce.Do(func() {
		if err := c.reg.Register(c); err != nil {
			c.opts.onError(fmt.Errorf("cannot register the collector: %v", err))
		}
	})

}

func (o *Options) onError(err error) {
	if o.OnError != nil {
		o.OnError(err)
	} else {
		log.Printf("Failed to export to Prometheus: %v", err)
	}
}

// ExportView exports to the Prometheus if view data has one or more rows.
// Each OpenCensus AggregationData will be converted to
// corresponding Prometheus Metric: SumData will be converted
// to Untyped Metric, CountData will be a Counter Metric,
// DistributionData will be a Histogram Metric.
func (e *Exporter) ExportView(vd *view.Data) {
	if len(vd.Rows) == 0 {
		return
	}
	e.c.addViewData(vd)
}

// ServeHTTP serves the Prometheus endpoint.
func (e *Exporter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	e.handler.ServeHTTP(w, r)
}

// collector implements prometheus.Collector
type collector struct {
	opts Options
	mu   sync.Mutex // mu guards all the fields.

	registerOnce sync.Once

	// reg helps collector register views dynamically.
	reg *prometheus.Registry

	// viewData are accumulated and atomically
	// appended to on every Export invocation, from
	// stats. These views are cleared out when
	// Collect is invoked and the cycle is repeated.
	viewData map[string]*view.Data

	registeredViewsMu sync.Mutex
	// registeredViews maps a view to a prometheus desc.
	registeredViews map[string]*prometheus.Desc
}

func (c *collector) addViewData(vd *view.Data) {
	c.registerViews(vd.View)
	sig := viewSignature(c.opts.Namespace, vd.View)

	c.mu.Lock()
	c.viewData[sig] = vd
	c.mu.Unlock()
}

func (c *collector) Describe(ch chan<- *prometheus.Desc) {
	c.registeredViewsMu.Lock()
	registered := make(map[string]*prometheus.Desc)
	for k, desc := range c.registeredViews {
		registered[k] = desc
	}
	c.registeredViewsMu.Unlock()

	for _, desc := range registered {
		ch <- desc
	}
}

// Collect fetches the statistics from OpenCensus
// and delivers them as Prometheus Metrics.
// Collect is invoked everytime a prometheus.Gatherer is run
// for example when the HTTP endpoint is invoked by Prometheus.
func (c *collector) Collect(ch chan<- prometheus.Metric) {
	// We need a copy of all the view data up until this point.
	viewData := c.cloneViewData()

	for _, vd := range viewData {
		sig := viewSignature(c.opts.Namespace, vd.View)
		c.registeredViewsMu.Lock()
		desc := c.registeredViews[sig]
		c.registeredViewsMu.Unlock()

		for _, row := range vd.Rows {
			metric, err := c.toMetric(desc, vd.View, row)
			if err != nil {
				c.opts.onError(err)
			} else {
				ch <- metric
			}
		}
	}

}

func (c *collector) toMetric(desc *prometheus.Desc, v *view.View, row *view.Row) (prometheus.Metric, error) {
	switch data := row.Data.(type) {
	case *view.CountData:
		return prometheus.NewConstMetric(desc, prometheus.CounterValue, float64(data.Value), tagValues(row.Tags, v.TagKeys)...)

	case *view.DistributionData:
		points := make(map[float64]uint64)
		// Histograms are cumulative in Prometheus.
		// 1. Sort buckets in ascending order but, retain
		// their indices for reverse lookup later on.
		// TODO: If there is a guarantee that distribution elements
		// are always sorted, then skip the sorting.
		indicesMap := make(map[float64]int)
		buckets := make([]float64, 0, len(v.Aggregation.Buckets))
		for i, b := range v.Aggregation.Buckets {
			if _, ok := indicesMap[b]; !ok {
				indicesMap[b] = i
				buckets = append(buckets, b)
			}
		}
		sort.Float64s(buckets)

		// 2. Now that the buckets are sorted by magnitude
		// we can create cumulative indicesmap them back by reverse index
		cumCount := uint64(0)
		for _, b := range buckets {
			i := indicesMap[b]
			cumCount += uint64(data.CountPerBucket[i])
			points[b] = cumCount
		}
		return prometheus.NewConstHistogram(desc, uint64(data.Count), data.Sum(), points, tagValues(row.Tags, v.TagKeys)...)

	case *view.SumData:
		return prometheus.NewConstMetric(desc, prometheus.UntypedValue, data.Value, tagValues(row.Tags, v.TagKeys)...)

	case *view.LastValueData:
		return prometheus.NewConstMetric(desc, prometheus.GaugeValue, data.Value, tagValues(row.Tags, v.TagKeys)...)

	default:
		return nil, fmt.Errorf("aggregation %T is not yet supported", v.Aggregation)
	}
}

func tagKeysToLabels(keys []tag.Key) (labels []string) {
	for _, key := range keys {
		labels = append(labels, internal.Sanitize(key.Name()))
	}
	return labels
}

func tagsToLabels(tags []tag.Tag) []string {
	var names []string
	for _, tag := range tags {
		names = append(names, internal.Sanitize(tag.Key.Name()))
	}
	return names
}

func newCollector(opts Options, registrar *prometheus.Registry) *collector {
	return &collector{
		reg:             registrar,
		opts:            opts,
		registeredViews: make(map[string]*prometheus.Desc),
		viewData:        make(map[string]*view.Data),
	}
}

func tagValues(t []tag.Tag, expectedKeys []tag.Key) []string {
	var values []string
	// Add empty string for all missing keys in the tags map.
	idx := 0
	for _, t := range t {
		for t.Key != expectedKeys[idx] {
			idx++
			values = append(values, "")
		}
		values = append(values, t.Value)
		idx++
	}
	for idx < len(expectedKeys) {
		idx++
		values = append(values, "")
	}
	return values
}

func viewName(namespace string, v *view.View) string {
	var name string
	if namespace != "" {
		name = namespace + "_"
	}
	return name + internal.Sanitize(v.Name)
}

func viewSignature(namespace string, v *view.View) string {
	var buf bytes.Buffer
	buf.WriteString(viewName(namespace, v))
	for _, k := range v.TagKeys {
		buf.WriteString("-" + k.Name())
	}
	return buf.String()
}

func (c *collector) cloneViewData() map[string]*view.Data {
	c.mu.Lock()
	defer c.mu.Unlock()

	viewDataCopy := make(map[string]*view.Data)
	for sig, viewData := range c.viewData {
		viewDataCopy[sig] = viewData
	}
	return viewDataCopy
}
<commit_msg>Remove dead code in Prometheus exporter. (#990)<commit_after>// Copyright 2017, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package prometheus contains a Prometheus exporter that supports exporting
// OpenCensus views as Prometheus metrics.
package prometheus // import "go.opencensus.io/exporter/prometheus"

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"sort"
	"sync"

	"go.opencensus.io/internal"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/tag"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Exporter exports stats to Prometheus, users need
// to register the exporter as an http.Handler to be
// able to export.
type Exporter struct {
	opts    Options
	g       prometheus.Gatherer
	c       *collector
	handler http.Handler
}

// Options contains options for configuring the exporter.
type Options struct {
	Namespace   string
	Registry    *prometheus.Registry
	OnError     func(err error)
	ConstLabels prometheus.Labels // ConstLabels will be set as labels on all views.
}

// NewExporter returns an exporter that exports stats to Prometheus.
func NewExporter(o Options) (*Exporter, error) {
	if o.Registry == nil {
		o.Registry = prometheus.NewRegistry()
	}
	collector := newCollector(o, o.Registry)
	e := &Exporter{
		opts:    o,
		g:       o.Registry,
		c:       collector,
		handler: promhttp.HandlerFor(o.Registry, promhttp.HandlerOpts{}),
	}
	return e, nil
}

var _ http.Handler = (*Exporter)(nil)
var _ view.Exporter = (*Exporter)(nil)

func (c *collector) registerViews(views ...*view.View) {
	count := 0
	for _, view := range views {
		sig := viewSignature(c.opts.Namespace, view)
		c.registeredViewsMu.Lock()
		_, ok := c.registeredViews[sig]
		c.registeredViewsMu.Unlock()

		if !ok {
			desc := prometheus.NewDesc(
				viewName(c.opts.Namespace, view),
				view.Description,
				tagKeysToLabels(view.TagKeys),
				c.opts.ConstLabels,
			)
			c.registeredViewsMu.Lock()
			c.registeredViews[sig] = desc
			c.registeredViewsMu.Unlock()
			count++
		}
	}
	if count == 0 {
		return
	}

	c.ensureRegisteredOnce()
}

// ensureRegisteredOnce invokes reg.Register on the collector itself
// exactly once to ensure that we don't get errors such as
//  cannot register the collector: descriptor Desc{fqName: *}
//  already exists with the same fully-qualified name and const label values
// which is documented by Prometheus at
//  https://github.com/prometheus/client_golang/blob/fcc130e101e76c5d303513d0e28f4b6d732845c7/prometheus/registry.go#L89-L101
func (c *collector) ensureRegisteredOnce() {
	c.registerOnce.Do(func() {
		if err := c.reg.Register(c); err != nil {
			c.opts.onError(fmt.Errorf("cannot register the collector: %v", err))
		}
	})

}

func (o *Options) onError(err error) {
	if o.OnError != nil {
		o.OnError(err)
	} else {
		log.Printf("Failed to export to Prometheus: %v", err)
	}
}

// ExportView exports to the Prometheus if view data has one or more rows.
// Each OpenCensus AggregationData will be converted to
// corresponding Prometheus Metric: SumData will be converted
// to Untyped Metric, CountData will be a Counter Metric,
// DistributionData will be a Histogram Metric.
func (e *Exporter) ExportView(vd *view.Data) {
	if len(vd.Rows) == 0 {
		return
	}
	e.c.addViewData(vd)
}

// ServeHTTP serves the Prometheus endpoint.
func (e *Exporter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	e.handler.ServeHTTP(w, r)
}

// collector implements prometheus.Collector
type collector struct {
	opts Options
	mu   sync.Mutex // mu guards all the fields.

	registerOnce sync.Once

	// reg helps collector register views dynamically.
	reg *prometheus.Registry

	// viewData are accumulated and atomically
	// appended to on every Export invocation, from
	// stats. These views are cleared out when
	// Collect is invoked and the cycle is repeated.
	viewData map[string]*view.Data

	registeredViewsMu sync.Mutex
	// registeredViews maps a view to a prometheus desc.
	registeredViews map[string]*prometheus.Desc
}

func (c *collector) addViewData(vd *view.Data) {
	c.registerViews(vd.View)
	sig := viewSignature(c.opts.Namespace, vd.View)

	c.mu.Lock()
	c.viewData[sig] = vd
	c.mu.Unlock()
}

func (c *collector) Describe(ch chan<- *prometheus.Desc) {
	c.registeredViewsMu.Lock()
	registered := make(map[string]*prometheus.Desc)
	for k, desc := range c.registeredViews {
		registered[k] = desc
	}
	c.registeredViewsMu.Unlock()

	for _, desc := range registered {
		ch <- desc
	}
}

// Collect fetches the statistics from OpenCensus
// and delivers them as Prometheus Metrics.
// Collect is invoked everytime a prometheus.Gatherer is run
// for example when the HTTP endpoint is invoked by Prometheus.
func (c *collector) Collect(ch chan<- prometheus.Metric) {
	// We need a copy of all the view data up until this point.
	viewData := c.cloneViewData()

	for _, vd := range viewData {
		sig := viewSignature(c.opts.Namespace, vd.View)
		c.registeredViewsMu.Lock()
		desc := c.registeredViews[sig]
		c.registeredViewsMu.Unlock()

		for _, row := range vd.Rows {
			metric, err := c.toMetric(desc, vd.View, row)
			if err != nil {
				c.opts.onError(err)
			} else {
				ch <- metric
			}
		}
	}

}

func (c *collector) toMetric(desc *prometheus.Desc, v *view.View, row *view.Row) (prometheus.Metric, error) {
	switch data := row.Data.(type) {
	case *view.CountData:
		return prometheus.NewConstMetric(desc, prometheus.CounterValue, float64(data.Value), tagValues(row.Tags, v.TagKeys)...)

	case *view.DistributionData:
		points := make(map[float64]uint64)
		// Histograms are cumulative in Prometheus.
		// 1. Sort buckets in ascending order but, retain
		// their indices for reverse lookup later on.
		// TODO: If there is a guarantee that distribution elements
		// are always sorted, then skip the sorting.
		indicesMap := make(map[float64]int)
		buckets := make([]float64, 0, len(v.Aggregation.Buckets))
		for i, b := range v.Aggregation.Buckets {
			if _, ok := indicesMap[b]; !ok {
				indicesMap[b] = i
				buckets = append(buckets, b)
			}
		}
		sort.Float64s(buckets)

		// 2. Now that the buckets are sorted by magnitude
		// we can create cumulative indicesmap them back by reverse index
		cumCount := uint64(0)
		for _, b := range buckets {
			i := indicesMap[b]
			cumCount += uint64(data.CountPerBucket[i])
			points[b] = cumCount
		}
		return prometheus.NewConstHistogram(desc, uint64(data.Count), data.Sum(), points, tagValues(row.Tags, v.TagKeys)...)

	case *view.SumData:
		return prometheus.NewConstMetric(desc, prometheus.UntypedValue, data.Value, tagValues(row.Tags, v.TagKeys)...)

	case *view.LastValueData:
		return prometheus.NewConstMetric(desc, prometheus.GaugeValue, data.Value, tagValues(row.Tags, v.TagKeys)...)

	default:
		return nil, fmt.Errorf("aggregation %T is not yet supported", v.Aggregation)
	}
}

func tagKeysToLabels(keys []tag.Key) (labels []string) {
	for _, key := range keys {
		labels = append(labels, internal.Sanitize(key.Name()))
	}
	return labels
}

func newCollector(opts Options, registrar *prometheus.Registry) *collector {
	return &collector{
		reg:             registrar,
		opts:            opts,
		registeredViews: make(map[string]*prometheus.Desc),
		viewData:        make(map[string]*view.Data),
	}
}

func tagValues(t []tag.Tag, expectedKeys []tag.Key) []string {
	var values []string
	// Add empty string for all missing keys in the tags map.
	idx := 0
	for _, t := range t {
		for t.Key != expectedKeys[idx] {
			idx++
			values = append(values, "")
		}
		values = append(values, t.Value)
		idx++
	}
	for idx < len(expectedKeys) {
		idx++
		values = append(values, "")
	}
	return values
}

func viewName(namespace string, v *view.View) string {
	var name string
	if namespace != "" {
		name = namespace + "_"
	}
	return name + internal.Sanitize(v.Name)
}

func viewSignature(namespace string, v *view.View) string {
	var buf bytes.Buffer
	buf.WriteString(viewName(namespace, v))
	for _, k := range v.TagKeys {
		buf.WriteString("-" + k.Name())
	}
	return buf.String()
}

func (c *collector) cloneViewData() map[string]*view.Data {
	c.mu.Lock()
	defer c.mu.Unlock()

	viewDataCopy := make(map[string]*view.Data)
	for sig, viewData := range c.viewData {
		viewDataCopy[sig] = viewData
	}
	return viewDataCopy
}
<|endoftext|>


<commit_before>package gofakeit

func MimeType() string {
	return getRandValue([]string{"file", "mime_type"})
}

func Extension() string {
	return getRandValue([]string{"file", "extension"})
}
<commit_msg>file - updated comments.<commit_after>package gofakeit

// Generate Random File Mime Type
func MimeType() string {
	return getRandValue([]string{"file", "mime_type"})
}

// Generate Random File Extension
func Extension() string {
	return getRandValue([]string{"file", "extension"})
}
<|endoftext|>


<commit_before>package cli

import (
	"flag"
	"fmt"
	"io/ioutil"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"syscall"
)

const defaultPlaceholder = "value"

// BashCompletionFlag enables bash-completion for all commands and subcommands
var BashCompletionFlag Flag = BoolFlag{
	Name:   "generate-bash-completion",
	Hidden: true,
}

// VersionFlag prints the version for the application
var VersionFlag Flag = BoolFlag{
	Name:  "version, v",
	Usage: "print the version",
}

// HelpFlag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true)
var HelpFlag Flag = BoolFlag{
	Name:  "help, h",
	Usage: "show help",
}

// FlagStringer converts a flag definition to a string. This is used by help
// to display a flag.
var FlagStringer FlagStringFunc = stringifyFlag

// FlagNamePrefixer converts a full flag name and its placeholder into the help
// message flag prefix. This is used by the default FlagStringer.
var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames

// FlagEnvHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagEnvHinter FlagEnvHintFunc = withEnvHint

// FlagFileHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagFileHinter FlagFileHintFunc = withFileHint

// FlagsByName is a slice of Flag.
type FlagsByName []Flag

func (f FlagsByName) Len() int {
	return len(f)
}

func (f FlagsByName) Less(i, j int) bool {
	return lexicographicLess(f[i].GetName(), f[j].GetName())
}

func (f FlagsByName) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that
// this interface be implemented.
type Flag interface {
	fmt.Stringer
	// Apply Flag settings to the given flag set
	Apply(*flag.FlagSet)
	GetName() string
}

// RequiredFlag is an interface that allows us to mark flags as required
// it allows flags required flags to be backwards compatible with the Flag interface
type RequiredFlag interface {
	Flag

	IsRequired() bool
}

// DocGenerationFlag is an interface that allows documentation generation for the flag
type DocGenerationFlag interface {
	Flag

	// TakesValue returns true of the flag takes a value, otherwise false
	TakesValue() bool

	// GetUsage returns the usage string for the flag
	GetUsage() string

	// GetValue returns the flags value as string representation and an empty
	// string if the flag takes no value at all.
	GetValue() string
}

// errorableFlag is an interface that allows us to return errors during apply
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors
type errorableFlag interface {
	Flag

	ApplyWithError(*flag.FlagSet) error
}

func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
	set := flag.NewFlagSet(name, flag.ContinueOnError)

	for _, f := range flags {
		//TODO remove in v2 when errorableFlag is removed
		if ef, ok := f.(errorableFlag); ok {
			if err := ef.ApplyWithError(set); err != nil {
				return nil, err
			}
		} else {
			f.Apply(set)
		}
	}
	set.SetOutput(ioutil.Discard)
	return set, nil
}

func eachName(longName string, fn func(string)) {
	parts := strings.Split(longName, ",")
	for _, name := range parts {
		name = strings.Trim(name, " ")
		fn(name)
	}
}

func visibleFlags(fl []Flag) []Flag {
	var visible []Flag
	for _, f := range fl {
		field := flagValue(f).FieldByName("Hidden")
		if !field.IsValid() || !field.Bool() {
			visible = append(visible, f)
		}
	}
	return visible
}

func prefixFor(name string) (prefix string) {
	if len(name) == 1 {
		prefix = "-"
	} else {
		prefix = "--"
	}

	return
}

// Returns the placeholder, if any, and the unquoted usage string.
func unquoteUsage(usage string) (string, string) {
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name := usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break
		}
	}
	return "", usage
}

func prefixedNames(fullName, placeholder string) string {
	var prefixed string
	parts := strings.Split(fullName, ",")
	for i, name := range parts {
		name = strings.Trim(name, " ")
		prefixed += prefixFor(name) + name
		if placeholder != "" {
			prefixed += " " + placeholder
		}
		if i < len(parts)-1 {
			prefixed += ", "
		}
	}
	return prefixed
}

func withEnvHint(envVar, str string) string {
	envText := ""
	if envVar != "" {
		prefix := "$"
		suffix := ""
		sep := ", $"
		if runtime.GOOS == "windows" {
			prefix = "%"
			suffix = "%"
			sep = "%, %"
		}
		envText = " [" + prefix + strings.Join(strings.Split(envVar, ","), sep) + suffix + "]"
	}
	return str + envText
}

func withFileHint(filePath, str string) string {
	fileText := ""
	if filePath != "" {
		fileText = fmt.Sprintf(" [%s]", filePath)
	}
	return str + fileText
}

func flagValue(f Flag) reflect.Value {
	fv := reflect.ValueOf(f)
	for fv.Kind() == reflect.Ptr {
		fv = reflect.Indirect(fv)
	}
	return fv
}

func stringifyFlag(f Flag) string {
	fv := flagValue(f)

	switch f.(type) {
	case IntSliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyIntSliceFlag(f.(IntSliceFlag)),
			),
		)
	case Int64SliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyInt64SliceFlag(f.(Int64SliceFlag)),
			),
		)
	case StringSliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyStringSliceFlag(f.(StringSliceFlag)),
			),
		)
	}

	placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())

	needsPlaceholder := false
	defaultValueString := ""

	if val := fv.FieldByName("Value"); val.IsValid() {
		needsPlaceholder = true
		defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())

		if val.Kind() == reflect.String && val.String() != "" {
			defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
		}
	}

	if defaultValueString == " (default: )" {
		defaultValueString = ""
	}

	if needsPlaceholder && placeholder == "" {
		placeholder = defaultPlaceholder
	}

	usageWithDefault := strings.TrimSpace(usage + defaultValueString)

	return FlagFileHinter(
		fv.FieldByName("FilePath").String(),
		FlagEnvHinter(
			fv.FieldByName("EnvVar").String(),
			FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder)+"\t"+usageWithDefault,
		),
	)
}

func stringifyIntSliceFlag(f IntSliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, i := range f.Value.Value() {
			defaultVals = append(defaultVals, strconv.Itoa(i))
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifyInt64SliceFlag(f Int64SliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, i := range f.Value.Value() {
			defaultVals = append(defaultVals, strconv.FormatInt(i, 10))
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifyStringSliceFlag(f StringSliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, s := range f.Value.Value() {
			if len(s) > 0 {
				defaultVals = append(defaultVals, strconv.Quote(s))
			}
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifySliceFlag(usage, name string, defaultVals []string) string {
	placeholder, usage := unquoteUsage(usage)
	if placeholder == "" {
		placeholder = defaultPlaceholder
	}

	defaultVal := ""
	if len(defaultVals) > 0 {
		defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
	}

	usageWithDefault := strings.TrimSpace(usage + defaultVal)
	return FlagNamePrefixer(name, placeholder) + "\t" + usageWithDefault
}

func flagFromFileEnv(filePath, envName string) (val string, ok bool) {
	for _, envVar := range strings.Split(envName, ",") {
		envVar = strings.TrimSpace(envVar)
		if envVal, ok := syscall.Getenv(envVar); ok {
			return envVal, true
		}
	}
	for _, fileVar := range strings.Split(filePath, ",") {
		if data, err := ioutil.ReadFile(fileVar); err == nil {
			return string(data), true
		}
	}
	return "", false
}
<commit_msg>fix typo in flag.go docstring<commit_after>package cli

import (
	"flag"
	"fmt"
	"io/ioutil"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"syscall"
)

const defaultPlaceholder = "value"

// BashCompletionFlag enables bash-completion for all commands and subcommands
var BashCompletionFlag Flag = BoolFlag{
	Name:   "generate-bash-completion",
	Hidden: true,
}

// VersionFlag prints the version for the application
var VersionFlag Flag = BoolFlag{
	Name:  "version, v",
	Usage: "print the version",
}

// HelpFlag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true)
var HelpFlag Flag = BoolFlag{
	Name:  "help, h",
	Usage: "show help",
}

// FlagStringer converts a flag definition to a string. This is used by help
// to display a flag.
var FlagStringer FlagStringFunc = stringifyFlag

// FlagNamePrefixer converts a full flag name and its placeholder into the help
// message flag prefix. This is used by the default FlagStringer.
var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames

// FlagEnvHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagEnvHinter FlagEnvHintFunc = withEnvHint

// FlagFileHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagFileHinter FlagFileHintFunc = withFileHint

// FlagsByName is a slice of Flag.
type FlagsByName []Flag

func (f FlagsByName) Len() int {
	return len(f)
}

func (f FlagsByName) Less(i, j int) bool {
	return lexicographicLess(f[i].GetName(), f[j].GetName())
}

func (f FlagsByName) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that
// this interface be implemented.
type Flag interface {
	fmt.Stringer
	// Apply Flag settings to the given flag set
	Apply(*flag.FlagSet)
	GetName() string
}

// RequiredFlag is an interface that allows us to mark flags as required
// it allows flags required flags to be backwards compatible with the Flag interface
type RequiredFlag interface {
	Flag

	IsRequired() bool
}

// DocGenerationFlag is an interface that allows documentation generation for the flag
type DocGenerationFlag interface {
	Flag

	// TakesValue returns true if the flag takes a value, otherwise false
	TakesValue() bool

	// GetUsage returns the usage string for the flag
	GetUsage() string

	// GetValue returns the flags value as string representation and an empty
	// string if the flag takes no value at all.
	GetValue() string
}

// errorableFlag is an interface that allows us to return errors during apply
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors
type errorableFlag interface {
	Flag

	ApplyWithError(*flag.FlagSet) error
}

func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
	set := flag.NewFlagSet(name, flag.ContinueOnError)

	for _, f := range flags {
		//TODO remove in v2 when errorableFlag is removed
		if ef, ok := f.(errorableFlag); ok {
			if err := ef.ApplyWithError(set); err != nil {
				return nil, err
			}
		} else {
			f.Apply(set)
		}
	}
	set.SetOutput(ioutil.Discard)
	return set, nil
}

func eachName(longName string, fn func(string)) {
	parts := strings.Split(longName, ",")
	for _, name := range parts {
		name = strings.Trim(name, " ")
		fn(name)
	}
}

func visibleFlags(fl []Flag) []Flag {
	var visible []Flag
	for _, f := range fl {
		field := flagValue(f).FieldByName("Hidden")
		if !field.IsValid() || !field.Bool() {
			visible = append(visible, f)
		}
	}
	return visible
}

func prefixFor(name string) (prefix string) {
	if len(name) == 1 {
		prefix = "-"
	} else {
		prefix = "--"
	}

	return
}

// Returns the placeholder, if any, and the unquoted usage string.
func unquoteUsage(usage string) (string, string) {
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name := usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break
		}
	}
	return "", usage
}

func prefixedNames(fullName, placeholder string) string {
	var prefixed string
	parts := strings.Split(fullName, ",")
	for i, name := range parts {
		name = strings.Trim(name, " ")
		prefixed += prefixFor(name) + name
		if placeholder != "" {
			prefixed += " " + placeholder
		}
		if i < len(parts)-1 {
			prefixed += ", "
		}
	}
	return prefixed
}

func withEnvHint(envVar, str string) string {
	envText := ""
	if envVar != "" {
		prefix := "$"
		suffix := ""
		sep := ", $"
		if runtime.GOOS == "windows" {
			prefix = "%"
			suffix = "%"
			sep = "%, %"
		}
		envText = " [" + prefix + strings.Join(strings.Split(envVar, ","), sep) + suffix + "]"
	}
	return str + envText
}

func withFileHint(filePath, str string) string {
	fileText := ""
	if filePath != "" {
		fileText = fmt.Sprintf(" [%s]", filePath)
	}
	return str + fileText
}

func flagValue(f Flag) reflect.Value {
	fv := reflect.ValueOf(f)
	for fv.Kind() == reflect.Ptr {
		fv = reflect.Indirect(fv)
	}
	return fv
}

func stringifyFlag(f Flag) string {
	fv := flagValue(f)

	switch f.(type) {
	case IntSliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyIntSliceFlag(f.(IntSliceFlag)),
			),
		)
	case Int64SliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyInt64SliceFlag(f.(Int64SliceFlag)),
			),
		)
	case StringSliceFlag:
		return FlagFileHinter(
			fv.FieldByName("FilePath").String(),
			FlagEnvHinter(
				fv.FieldByName("EnvVar").String(),
				stringifyStringSliceFlag(f.(StringSliceFlag)),
			),
		)
	}

	placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())

	needsPlaceholder := false
	defaultValueString := ""

	if val := fv.FieldByName("Value"); val.IsValid() {
		needsPlaceholder = true
		defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())

		if val.Kind() == reflect.String && val.String() != "" {
			defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
		}
	}

	if defaultValueString == " (default: )" {
		defaultValueString = ""
	}

	if needsPlaceholder && placeholder == "" {
		placeholder = defaultPlaceholder
	}

	usageWithDefault := strings.TrimSpace(usage + defaultValueString)

	return FlagFileHinter(
		fv.FieldByName("FilePath").String(),
		FlagEnvHinter(
			fv.FieldByName("EnvVar").String(),
			FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder)+"\t"+usageWithDefault,
		),
	)
}

func stringifyIntSliceFlag(f IntSliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, i := range f.Value.Value() {
			defaultVals = append(defaultVals, strconv.Itoa(i))
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifyInt64SliceFlag(f Int64SliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, i := range f.Value.Value() {
			defaultVals = append(defaultVals, strconv.FormatInt(i, 10))
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifyStringSliceFlag(f StringSliceFlag) string {
	var defaultVals []string
	if f.Value != nil && len(f.Value.Value()) > 0 {
		for _, s := range f.Value.Value() {
			if len(s) > 0 {
				defaultVals = append(defaultVals, strconv.Quote(s))
			}
		}
	}

	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}

func stringifySliceFlag(usage, name string, defaultVals []string) string {
	placeholder, usage := unquoteUsage(usage)
	if placeholder == "" {
		placeholder = defaultPlaceholder
	}

	defaultVal := ""
	if len(defaultVals) > 0 {
		defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
	}

	usageWithDefault := strings.TrimSpace(usage + defaultVal)
	return FlagNamePrefixer(name, placeholder) + "\t" + usageWithDefault
}

func flagFromFileEnv(filePath, envName string) (val string, ok bool) {
	for _, envVar := range strings.Split(envName, ",") {
		envVar = strings.TrimSpace(envVar)
		if envVal, ok := syscall.Getenv(envVar); ok {
			return envVal, true
		}
	}
	for _, fileVar := range strings.Split(filePath, ",") {
		if data, err := ioutil.ReadFile(fileVar); err == nil {
			return string(data), true
		}
	}
	return "", false
}
<|endoftext|>


<commit_before>package tview

import (
	"github.com/gdamore/tcell"
)

// Configuration values.
const (
	FlexRow = iota
	FlexColumn
)

// flexItem holds layout options for one item.
type flexItem struct {
	Item       Primitive // The item to be positioned. May be nil for an empty item.
	FixedSize  int       // The item's fixed size which may not be changed, 0 if it has no fixed size.
	Proportion int       // The item's proportion.
	Focus      bool      // Whether or not this item attracts the layout's focus.
}

// Flex is a basic implementation of the Flexbox layout. The contained
// primitives are arranged horizontally or vertically. The way they are
// distributed along that dimension depends on their layout settings, which is
// either a fixed length or a proportional length. See AddItem() for details.
//
// See https://github.com/rivo/tview/wiki/Flex for an example.
type Flex struct {
	*Box

	// The items to be positioned.
	items []flexItem

	// FlexRow or FlexColumn.
	direction int

	// If set to true, Flex will use the entire screen as its available space
	// instead its box dimensions.
	fullScreen bool
}

// NewFlex returns a new flexbox layout container with no primitives and its
// direction set to FlexColumn. To add primitives to this layout, see AddItem().
// To change the direction, see SetDirection().
//
// Note that Box, the superclass of Flex, will have its background color set to
// transparent so that any nil flex items will leave their background unchanged.
// To clear a Flex's background before any items are drawn, set it to the
// desired color:
//
//   flex.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor)
func NewFlex() *Flex {
	f := &Flex{
		Box:       NewBox().SetBackgroundColor(tcell.ColorDefault),
		direction: FlexColumn,
	}
	f.focus = f
	return f
}

// SetDirection sets the direction in which the contained primitives are
// distributed. This can be either FlexColumn (default) or FlexRow.
func (f *Flex) SetDirection(direction int) *Flex {
	f.direction = direction
	return f
}

// SetFullScreen sets the flag which, when true, causes the flex layout to use
// the entire screen space instead of whatever size it is currently assigned to.
func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
	f.fullScreen = fullScreen
	return f
}

// AddItem adds a new item to the container. The "fixedSize" argument is a width
// or height that may not be changed by the layout algorithm. A value of 0 means
// that its size is flexible and may be changed. The "proportion" argument
// defines the relative size of the item compared to other flexible-size items.
// For example, items with a proportion of 2 will be twice as large as items
// with a proportion of 1. The proportion must be at least 1 if fixedSize == 0
// (ignored otherwise).
//
// If "focus" is set to true, the item will receive focus when the Flex
// primitive receives focus. If multiple items have the "focus" flag set to
// true, the first one will receive focus.
//
// You can provide a nil value for the primitive. This will still consume screen
// space but nothing will be drawn.
func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *Flex {
	f.items = append(f.items, flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus})
	return f
}

// RemoveItem removes all items for the given primitive from the container,
// keeping the order of the remaining items intact.
func (f *Flex) RemoveItem(p Primitive) *Flex {
	for index := len(f.items) - 1; index >= 0; index-- {
		if f.items[index].Item == p {
			f.items = append(f.items[:index], f.items[index+1:]...)
		}
	}
	return f
}

// Draw draws this primitive onto the screen.
func (f *Flex) Draw(screen tcell.Screen) {
	f.Box.Draw(screen)

	// Calculate size and position of the items.

	// Do we use the entire screen?
	if f.fullScreen {
		width, height := screen.Size()
		f.SetRect(0, 0, width, height)
	}

	// How much space can we distribute?
	x, y, width, height := f.GetInnerRect()
	var proportionSum int
	distSize := width
	if f.direction == FlexRow {
		distSize = height
	}
	for _, item := range f.items {
		if item.FixedSize > 0 {
			distSize -= item.FixedSize
		} else {
			proportionSum += item.Proportion
		}
	}

	// Calculate positions and draw items.
	pos := x
	if f.direction == FlexRow {
		pos = y
	}
	for _, item := range f.items {
		size := item.FixedSize
		if size <= 0 {
			size = distSize * item.Proportion / proportionSum
			distSize -= size
			proportionSum -= item.Proportion
		}
		if item.Item != nil {
			if f.direction == FlexColumn {
				item.Item.SetRect(pos, y, size, height)
			} else {
				item.Item.SetRect(x, pos, width, size)
			}
		}
		pos += size

		if item.Item != nil {
			if item.Item.GetFocusable().HasFocus() {
				defer item.Item.Draw(screen)
			} else {
				item.Item.Draw(screen)
			}
		}
	}
}

// Focus is called when this primitive receives focus.
func (f *Flex) Focus(delegate func(p Primitive)) {
	for _, item := range f.items {
		if item.Item != nil && item.Focus {
			delegate(item.Item)
			return
		}
	}
}

// HasFocus returns whether or not this primitive has focus.
func (f *Flex) HasFocus() bool {
	for _, item := range f.items {
		if item.Item != nil && item.Item.GetFocusable().HasFocus() {
			return true
		}
	}
	return false
}
<commit_msg>Added a function to resize a Flex item. Resolves #125<commit_after>package tview

import (
	"github.com/gdamore/tcell"
)

// Configuration values.
const (
	FlexRow = iota
	FlexColumn
)

// flexItem holds layout options for one item.
type flexItem struct {
	Item       Primitive // The item to be positioned. May be nil for an empty item.
	FixedSize  int       // The item's fixed size which may not be changed, 0 if it has no fixed size.
	Proportion int       // The item's proportion.
	Focus      bool      // Whether or not this item attracts the layout's focus.
}

// Flex is a basic implementation of the Flexbox layout. The contained
// primitives are arranged horizontally or vertically. The way they are
// distributed along that dimension depends on their layout settings, which is
// either a fixed length or a proportional length. See AddItem() for details.
//
// See https://github.com/rivo/tview/wiki/Flex for an example.
type Flex struct {
	*Box

	// The items to be positioned.
	items []flexItem

	// FlexRow or FlexColumn.
	direction int

	// If set to true, Flex will use the entire screen as its available space
	// instead its box dimensions.
	fullScreen bool
}

// NewFlex returns a new flexbox layout container with no primitives and its
// direction set to FlexColumn. To add primitives to this layout, see AddItem().
// To change the direction, see SetDirection().
//
// Note that Box, the superclass of Flex, will have its background color set to
// transparent so that any nil flex items will leave their background unchanged.
// To clear a Flex's background before any items are drawn, set it to the
// desired color:
//
//   flex.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor)
func NewFlex() *Flex {
	f := &Flex{
		Box:       NewBox().SetBackgroundColor(tcell.ColorDefault),
		direction: FlexColumn,
	}
	f.focus = f
	return f
}

// SetDirection sets the direction in which the contained primitives are
// distributed. This can be either FlexColumn (default) or FlexRow.
func (f *Flex) SetDirection(direction int) *Flex {
	f.direction = direction
	return f
}

// SetFullScreen sets the flag which, when true, causes the flex layout to use
// the entire screen space instead of whatever size it is currently assigned to.
func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
	f.fullScreen = fullScreen
	return f
}

// AddItem adds a new item to the container. The "fixedSize" argument is a width
// or height that may not be changed by the layout algorithm. A value of 0 means
// that its size is flexible and may be changed. The "proportion" argument
// defines the relative size of the item compared to other flexible-size items.
// For example, items with a proportion of 2 will be twice as large as items
// with a proportion of 1. The proportion must be at least 1 if fixedSize == 0
// (ignored otherwise).
//
// If "focus" is set to true, the item will receive focus when the Flex
// primitive receives focus. If multiple items have the "focus" flag set to
// true, the first one will receive focus.
//
// You can provide a nil value for the primitive. This will still consume screen
// space but nothing will be drawn.
func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *Flex {
	f.items = append(f.items, flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus})
	return f
}

// RemoveItem removes all items for the given primitive from the container,
// keeping the order of the remaining items intact.
func (f *Flex) RemoveItem(p Primitive) *Flex {
	for index := len(f.items) - 1; index >= 0; index-- {
		if f.items[index].Item == p {
			f.items = append(f.items[:index], f.items[index+1:]...)
		}
	}
	return f
}

// ResizeItem sets a new size for the item(s) with the given primitive. If there
// are multiple Flex items with the same primitive, they will all receive the
// same size. For details regarding the size parameters, see AddItem().
func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex {
	for _, item := range f.items {
		if item.Item == p {
			item.FixedSize = fixedSize
			item.Proportion = proportion
		}
	}
	return f
}

// Draw draws this primitive onto the screen.
func (f *Flex) Draw(screen tcell.Screen) {
	f.Box.Draw(screen)

	// Calculate size and position of the items.

	// Do we use the entire screen?
	if f.fullScreen {
		width, height := screen.Size()
		f.SetRect(0, 0, width, height)
	}

	// How much space can we distribute?
	x, y, width, height := f.GetInnerRect()
	var proportionSum int
	distSize := width
	if f.direction == FlexRow {
		distSize = height
	}
	for _, item := range f.items {
		if item.FixedSize > 0 {
			distSize -= item.FixedSize
		} else {
			proportionSum += item.Proportion
		}
	}

	// Calculate positions and draw items.
	pos := x
	if f.direction == FlexRow {
		pos = y
	}
	for _, item := range f.items {
		size := item.FixedSize
		if size <= 0 {
			size = distSize * item.Proportion / proportionSum
			distSize -= size
			proportionSum -= item.Proportion
		}
		if item.Item != nil {
			if f.direction == FlexColumn {
				item.Item.SetRect(pos, y, size, height)
			} else {
				item.Item.SetRect(x, pos, width, size)
			}
		}
		pos += size

		if item.Item != nil {
			if item.Item.GetFocusable().HasFocus() {
				defer item.Item.Draw(screen)
			} else {
				item.Item.Draw(screen)
			}
		}
	}
}

// Focus is called when this primitive receives focus.
func (f *Flex) Focus(delegate func(p Primitive)) {
	for _, item := range f.items {
		if item.Item != nil && item.Focus {
			delegate(item.Item)
			return
		}
	}
}

// HasFocus returns whether or not this primitive has focus.
func (f *Flex) HasFocus() bool {
	for _, item := range f.items {
		if item.Item != nil && item.Item.GetFocusable().HasFocus() {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Pagoda Box Inc
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not distributed with this file, You can obtain one
// at http://mozilla.org/MPL/2.0/.
//

//
package config

import (
	"encoding/binary"
	"fmt"
	"net"
	"os"
	"path/filepath"
)

// NanofileConfig represents all available/expected .nanofile configurable options
type NanofileConfig struct {
	CPUCap   int    `json:"cpu_cap"`  // max %CPU usage allowed to the guest vm
	CPUs     int    `json:"cpus"`     // number of CPUs to dedicate to the guest vm
	Domain   string `json:"domain"`   // the domain to use in conjuntion with the ip when accesing the guest vm (defaults to <Name>.dev)
	IP       string `json:"ip"`       // the ip added to the /etc/hosts file for accessing the guest vm
	Name     string `json:"name"`     // the name given to the project (defaults to cwd)
	Provider string `json:"provider"` // guest vm provider (virtual box, vmware, etc)
	RAM      int    `json:"ram"`      // ammount of RAM to dedicate to the guest vm
}

// ParseNanofile
func ParseNanofile() *NanofileConfig {

	//
	nanofile := &NanofileConfig{
		CPUCap:   50,
		CPUs:     2,
		Name:     filepath.Base(CWDir),
		Provider: "virtualbox",
		RAM:      1024,
	}

	nanofilePath := Root + "/.nanofile"

	// look for a global .nanofile first in the ~/.nanobox directory, and override
	// any default options found.
	if _, err := os.Stat(nanofilePath); err == nil {
		if err := ParseConfig(nanofilePath, nanofile); err != nil {
			fmt.Printf("Nanobox failed to parse your .nanofile. Please ensure it is valid YAML and try again.\n")
			Exit(1)
		}
	}

	nanofilePath = "./.nanofile"

	// then look for a local .nanofile and override any global, or remaining default
	// options found
	if _, err := os.Stat(nanofilePath); err == nil {
		if err := ParseConfig(nanofilePath, nanofile); err != nil {
			fmt.Printf("Nanobox failed to parse your .nanofile. Please ensure it is valid YAML and try again.\n")
			Exit(1)
		}
	}

	// set name specific options after potential .nanofiles have been parsed
	nanofile.Domain = fmt.Sprintf("%s.dev", nanofile.Name)
	nanofile.IP = appNameToIP(nanofile.Name)

	return nanofile
}

// appNameToIP generates an IPv4 address based off the app name for use as a
// vagrant private_network IP.
func appNameToIP(name string) string {

	var sum uint32 = 0
	var network uint32 = 2886729728 // 172.16.0.0 network

	for _, value := range []byte(name) {
		sum += uint32(value)
	}

	ip := make(net.IP, 4)

	// convert app name into a private network IP
	binary.BigEndian.PutUint32(ip, (network + sum))

	return ip.String()
}
<commit_msg>building in option to allow for configurable IP. md5 hash the app name when generating IP to ensure uniqueness<commit_after>// Copyright (c) 2015 Pagoda Box Inc
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not distributed with this file, You can obtain one
// at http://mozilla.org/MPL/2.0/.
//

//
package config

import (
	"crypto/md5"
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
)

// NanofileConfig represents all available/expected .nanofile configurable options
type NanofileConfig struct {
	CPUCap   int    `json:"cpu_cap"`  // max %CPU usage allowed to the guest vm
	CPUs     int    `json:"cpus"`     // number of CPUs to dedicate to the guest vm
	Domain   string `json:"domain"`   // the domain to use in conjuntion with the ip when accesing the guest vm (defaults to <Name>.dev)
	IP       string `json:"ip"`       // the ip added to the /etc/hosts file for accessing the guest vm
	Name     string `json:"name"`     // the name given to the project (defaults to cwd)
	Provider string `json:"provider"` // guest vm provider (virtual box, vmware, etc)
	RAM      int    `json:"ram"`      // ammount of RAM to dedicate to the guest vm
}

// ParseNanofile
func ParseNanofile() *NanofileConfig {

	//
	nanofile := &NanofileConfig{
		CPUCap:   50,
		CPUs:     2,
		Name:     filepath.Base(CWDir),
		Provider: "virtualbox",
		RAM:      1024,
	}

	nanofilePath := Root + "/.nanofile"

	// look for a global .nanofile first in the ~/.nanobox directory, and override
	// any default options found.
	if _, err := os.Stat(nanofilePath); err == nil {
		if err := ParseConfig(nanofilePath, nanofile); err != nil {
			fmt.Printf("Nanobox failed to parse your .nanofile. Please ensure it is valid YAML and try again.\n")
			Exit(1)
		}
	}

	nanofilePath = "./.nanofile"

	// then look for a local .nanofile and override any global, or remaining default
	// options found
	if _, err := os.Stat(nanofilePath); err == nil {
		if err := ParseConfig(nanofilePath, nanofile); err != nil {
			fmt.Printf("Nanobox failed to parse your .nanofile. Please ensure it is valid YAML and try again.\n")
			Exit(1)
		}
	}

	// set name specific options after potential .nanofiles have been parsed
	nanofile.Domain = fmt.Sprintf("%s.dev", nanofile.Name)

	// assign a default IP if none is specified
	if nanofile.IP == "" {
		nanofile.IP = appNameToIP(nanofile.Name)
	}

	return nanofile
}

// appNameToIP generates an IPv4 address based off the app name for use as a
// vagrant private_network IP.
func appNameToIP(name string) string {

	var network uint32 = 2886729728 // 172.16.0.0 network
	var sum uint32 = 0              // the last two octets of the assigned network

	// create an md5 of the app name to ensure a uniqe IP is generated each time
	h := md5.New()
	io.WriteString(h, name)

	// iterate through each byte in the md5 hash summing along the way
	for _, v := range []byte(h.Sum(nil)) {
		sum += uint32(v)
	}

	ip := make(net.IP, 4)

	// convert app name into a private network IP by adding the first portion of
	// the network with the generated portion
	binary.BigEndian.PutUint32(ip, (network + sum))

	return ip.String()
}
<|endoftext|>


<commit_before>package commandevaluators

import (
	"errors"
	"log"
	"strings"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/av-api/dbo"
)

type UnMuteDefault struct {
}

func (p *UnMuteDefault) Evaluate(room base.PublicRoom) ([]base.ActionStructure, error) {
	log.Printf("Evaluating UnMute command.")

	actions := []base.ActionStructure{}

  //check if request is a roomwide unmute
	if room.Muted != nil && !*room.Muted {

		log.Printf("Room-wide UnMute request recieved. Retrieving all devices")

    devices, err := dbo.GetDevicesByBuildingAndRoomAndRole(room.Building, room.Room, "AudioOut")
    if err != nil {
      return []base.ActionStructure, err
    }

    log.Printf("UnMuting alll devices in room.")

		for i := range devices {

      if devices[i].Output {

        log.Printf("Adding device %+v", devices[i].Name)

        actions = append(actions, base.ActionStructure{
          Action:               "UnMute",
          GeneratingEvaluator:  "UnMuteDefault",
          Device:               devices[i],
          DeviceSpecific:       false,
        })

      }

    }

	}

  //check specific devices
  log.Printf("Evaluating individual audio devices for unmuting.")

  for _, audioDevice := range room.AudioDevices{

    log.Printf("Adding device %+v", audioDevice.Name)

    if audioDevice.Muted != nil && !*audioDevice.Muted {

      device, err := dbo.GetDeviceByName(room.Building, room.Room, audioDevice.Name)
      if err != nil {
        return []base.ActionStructure, err
      }

      actions = append(actions, base.ActionStructure{
        Action:               "UnMute",
        GeneratingEvaluator:  "UnMuteDefault",
        Device:               device,
        DeviceSpecific:       true,
      })

    }

  }

log.Printf("%v actions generated.", len(actions))
log.Printf("Evalutation complete.")

return actions, nil

}

func (p *UnMuteDefault) Validate(action base.ActionStructure) error {

  log.Printf("Validating action for command \"UnMute\"")

  ok, _ := checkCommands(action.Device.Commands, "UnMute")

  if !ok || !strings.EqualFold(action.Action, "UnMute"){
    log.Printf("ERROR. %s is an invalid command for %s", action.Action, action.Device.Name)
		return errors.New(action.Action + " is an invalid command for" + action.Device.Name)
  }

  log.Printf("Done.")
  return nil
}

func (p *UnMuteDefault) GetIncompatableCommands() (incompatibleActions []string) {

	incompatibleActions = []string{
		"Mute",
	}

	return
}
<commit_msg>fixed compile-time errors<commit_after>package commandevaluators

import (
	"errors"
	"log"
	"strings"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/av-api/dbo"
)

type UnMuteDefault struct {
}

func (p *UnMuteDefault) Evaluate(room base.PublicRoom) ([]base.ActionStructure, error) {
	log.Printf("Evaluating UnMute command.")

	actions := []base.ActionStructure{}

	//check if request is a roomwide unmute
	if room.Muted != nil && !*room.Muted {

		log.Printf("Room-wide UnMute request recieved. Retrieving all devices")

		devices, err := dbo.GetDevicesByBuildingAndRoomAndRole(room.Building, room.Room, "AudioOut")
		if err != nil {
			return []base.ActionStructure{}, err
		}

		log.Printf("UnMuting alll devices in room.")

		for i := range devices {

			if devices[i].Output {

				log.Printf("Adding device %+v", devices[i].Name)

				actions = append(actions, base.ActionStructure{
					Action:              "UnMute",
					GeneratingEvaluator: "UnMuteDefault",
					Device:              devices[i],
					DeviceSpecific:      false,
				})

			}

		}

	}

	//check specific devices
	log.Printf("Evaluating individual audio devices for unmuting.")

	for _, audioDevice := range room.AudioDevices {

		log.Printf("Adding device %+v", audioDevice.Name)

		if audioDevice.Muted != nil && !*audioDevice.Muted {

			device, err := dbo.GetDeviceByName(room.Building, room.Room, audioDevice.Name)
			if err != nil {
				return []base.ActionStructure{}, err
			}

			actions = append(actions, base.ActionStructure{
				Action:              "UnMute",
				GeneratingEvaluator: "UnMuteDefault",
				Device:              device,
				DeviceSpecific:      true,
			})

		}

	}

	log.Printf("%v actions generated.", len(actions))
	log.Printf("Evalutation complete.")

	return actions, nil

}

func (p *UnMuteDefault) Validate(action base.ActionStructure) error {

	log.Printf("Validating action for command \"UnMute\"")

	ok, _ := checkCommands(action.Device.Commands, "UnMute")

	if !ok || !strings.EqualFold(action.Action, "UnMute") {
		log.Printf("ERROR. %s is an invalid command for %s", action.Action, action.Device.Name)
		return errors.New(action.Action + " is an invalid command for" + action.Device.Name)
	}

	log.Printf("Done.")
	return nil
}

func (p *UnMuteDefault) GetIncompatableCommands() (incompatibleActions []string) {

	incompatibleActions = []string{
		"Mute",
	}

	return
}
<|endoftext|>


<commit_before>package v2

import (
	"os"

	"code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/commands"
	"code.cloudfoundry.org/cli/commands/flags"
)

type DeleteSpaceCommand struct {
	RequiredArgs flags.Space `positional-args:"yes"`
	Force        bool        `short:"f" description:"Force deletion without confirmation"`
	usage        interface{} `usage:"CF_NAME delete-space SPACE [-f]"`
}

func (_ DeleteSpaceCommand) Setup(config commands.Config, ui commands.UI) error {
	return nil
}

func (_ DeleteSpaceCommand) Execute(args []string) error {
	cmd.Main(os.Getenv("CF_TRACE"), os.Args)
	return nil
}
<commit_msg>Add delete-space -o flag to V2 command list<commit_after>package v2

import (
	"os"

	"code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/commands"
	"code.cloudfoundry.org/cli/commands/flags"
)

type DeleteSpaceCommand struct {
	RequiredArgs flags.Space `positional-args:"yes"`
	Force        bool        `short:"f" description:"Force deletion without confirmation"`
	Org          string      `short:"o" description:"Delete space within specified org"`
	usage        interface{} `usage:"CF_NAME delete-space SPACE [-o] [-f]"`
}

func (_ DeleteSpaceCommand) Setup(config commands.Config, ui commands.UI) error {
	return nil
}

func (_ DeleteSpaceCommand) Execute(args []string) error {
	cmd.Main(os.Getenv("CF_TRACE"), os.Args)
	return nil
}
<|endoftext|>


<commit_before>package config

import (
	"github.com/joho/godotenv"
	"log"
	"os"
)

type Settings struct {
	ApiKey     string
	ApiSecret  string
	Exchange   string
	Queue      string
	BindingKey string
	lifetime   string
}

func LoadSettings(filenames ...string) *Settings {
	log.Println("LoadSettings")
	err := godotenv.Load(filenames)
	if err != nil {
		log.Fatal("Error loading .env file")
	}
	return &Settings{
		os.Getenv("API_KEY"),
		os.Getenv("API_SECRET"),
		os.Getenv("EXCHANGE"),
		os.Getenv("QUEUE"),
		os.Getenv("BINDING_KEY"),
		os.Getenv("LIFETIME")}
}
<commit_msg>Messing around with testing and varargs.<commit_after>package config

import (
	"github.com/joho/godotenv"
	"log"
	"os"
)

type Settings struct {
	ApiKey     string
	ApiSecret  string
	Exchange   string
	Queue      string
	BindingKey string
	lifetime   string
}

func LoadSettings(filenames ...string) *Settings {
	log.Println("LoadSettings")
	err := godotenv.Load(filenames...)
	if err != nil {
		log.Fatal("Error loading .env file")
	}
	return &Settings{
		os.Getenv("API_KEY"),
		os.Getenv("API_SECRET"),
		os.Getenv("EXCHANGE"),
		os.Getenv("QUEUE"),
		os.Getenv("BINDING_KEY"),
		os.Getenv("LIFETIME")}
}
<|endoftext|>


<commit_before>package game

import (
	"errors"
	"github.com/svera/acquire/board"
	"github.com/svera/acquire/corporation"
	"github.com/svera/acquire/fsm"
	"github.com/svera/acquire/player"
	"github.com/svera/acquire/tileset"
)

const totalCorporations = 7

type Game struct {
	board         board.Interface
	state         fsm.State
	players       []player.Interface
	corporations  [7]corporation.Interface
	tileset       tileset.Interface
	currentPlayer int
}

func New(
	board board.Interface, players []player.Interface, corporations [7]corporation.Interface, tileset tileset.Interface) (*Game, error) {
	if len(players) < 3 || len(players) > 6 {
		return nil, errors.New("Number of players must be between 3 and 6")
	}

	gm := Game{
		board:         board,
		players:       players,
		corporations:  corporations,
		tileset:       tileset,
		currentPlayer: 0,
		state:         &fsm.PlayTile{},
	}
	for _, plyr := range gm.players {
		gm.giveInitialTileset(plyr)
	}
	for i, corp := range gm.corporations {
		corp.SetId(i)
	}
	return &gm, nil
}

// Initialises player hand of tiles
func (g *Game) giveInitialTileset(plyr player.Interface) {
	for i := 0; i < 6; i++ {
		tile, _ := g.tileset.Draw()
		plyr.PickTile(tile)
	}
}

// Check if game end conditions are reached
func (g *Game) AreEndConditionsReached() bool {
	active := g.getActiveCorporations()
	if len(active) == 0 {
		return false
	}
	for _, corp := range active {
		if corp.Size() >= 41 {
			return true
		}
		if !corp.IsSafe() {
			return false
		}
	}
	return true
}

// Returns all corporations on the board
func (g *Game) getActiveCorporations() []corporation.Interface {
	active := []corporation.Interface{}
	for _, corp := range g.corporations {
		if corp.IsActive() {
			active = append(active, corp)
		}
	}
	return active
}

// Calculates and returns bonus amounts to be paid to owners of stock of a
// defunct corporation
func (g *Game) PayBonusesForDefunctCorporation(corp corporation.Interface) {
	stockHolders := g.GetMainStockHolders(corp)
	numberMajorityHolders := len(stockHolders["majority"])
	numberMinorityHolders := len(stockHolders["minority"])

	for _, majorityStockHolder := range stockHolders["majority"] {
		majorityStockHolder.ReceiveBonus(corp.MajorityBonus() / int(numberMajorityHolders))
	}
	for _, minorityStockHolder := range stockHolders["minority"] {
		minorityStockHolder.ReceiveBonus(corp.MinorityBonus() / int(numberMinorityHolders))
	}
}

// Taken from the game rules:
// "If only one player owns stock in the defunct corporation, that player gets both bonuses. If there's
// a tie for majority stockholder, add the majority and minority bonuses and divide evenly (the minority
// shareholder gets no bonus. If there's a tie for minority stockholder, split the minority bonus among
// the tied players"
func (g *Game) GetMainStockHolders(corp corporation.Interface) map[string][]player.ShareInterface {
	mainStockHolders := map[string][]player.ShareInterface{"majority": {}, "minority": {}}
	stockHolders := g.getStockHolders(corp)

	if len(stockHolders) == 1 {
		return map[string][]player.ShareInterface{
			"majority": {stockHolders[0]},
			"minority": {stockHolders[0]},
		}
	}

	mainStockHolders["majority"] = stockHoldersWithSameAmount(0, stockHolders, corp)
	if len(mainStockHolders["majority"]) > 1 {
		return mainStockHolders
	}
	mainStockHolders["minority"] = stockHoldersWithSameAmount(1, stockHolders, corp)
	return mainStockHolders
}

// Loop stockHolders from start to get all stock holders with the same amount of shares for
// the passed corporation
func stockHoldersWithSameAmount(start int, stockHolders []player.ShareInterface, corp corporation.Interface) []player.ShareInterface {
	group := []player.ShareInterface{stockHolders[start]}

	i := start + 1
	for i < len(stockHolders) && stockHolders[start].Shares(corp) == stockHolders[i].Shares(corp) {
		group = append(group, stockHolders[i])
		i++
	}
	return group
}

// Get players who have stock of the passed corporation, ordered descendently by number of stock shares
// of that corporation
func (g *Game) getStockHolders(corp corporation.Interface) []player.ShareInterface {
	var stockHolders []player.ShareInterface
	sharesDesc := func(p1, p2 player.ShareInterface) bool {
		return p1.Shares(corp) > p2.Shares(corp)
	}

	for _, player := range g.players {
		if player.Shares(corp) > 0 {
			stockHolders = append(stockHolders, player)
		}
	}
	player.By(sharesDesc).Sort(stockHolders)
	return stockHolders
}

// Returns true if a tile is permanently unplayable, that is,
// that putting it on the board would merge two or more safe corporations
func (g *Game) isTileUnplayable(tile tileset.Position) bool {
	adjacents := g.board.AdjacentCells(tile)
	for _, adjacent := range adjacents {
		safeNeighbours := 0
		boardCell := g.board.Cell(adjacent)
		if boardCell != board.Empty && boardCell != board.OrphanTile {
			if g.corporations[boardCell].IsSafe() {
				safeNeighbours++
			}
		}
		if safeNeighbours == 2 {
			return true
		}
	}
	return false
}

// Returns true if a tile is temporarily unplayable, that is,
// that putting it on the board would create an 8th corporation
func (g *Game) isTileTemporaryUnplayable(tile tileset.Position) bool {
	if len(g.getActiveCorporations()) < totalCorporations {
		return false
	}
	adjacents := g.board.AdjacentCells(tile)
	for _, adjacent := range adjacents {
		boardCell := g.board.Cell(adjacent)
		if boardCell == board.OrphanTile {
			return true
		}
	}
	return false
}

// Returns player currently in turn
func (g *Game) CurrentPlayer() player.Interface {
	return g.players[g.currentPlayer]
}

func (g *Game) PlayTile(tile tileset.Position) error {
	if _, ok := g.state.(*fsm.PlayTile); !ok {
		return errors.New("Action not allowed")
	}
	if g.isTileTemporaryUnplayable(tile) {
		return errors.New("Tile is temporary unplayable")
	}
	if err := g.CurrentPlayer().DiscardTile(tile); err != nil {
		return err
	}
	/*
		if merge, tiles := g.board.TileMergeCorporations(tile); merge {
			// move state machine status
		} else if found, tiles := g.board.TileFoundCorporation(tile); found {

		} else */if grow, tiles, corporationId := g.board.TileGrowCorporation(tile); grow {
		g.growCorporation(g.corporations[corporationId], tiles)
	} else {
		g.board.PutTile(tile)
		g.state.ToBuyStock()
	}
	return nil
}

func (g *Game) growCorporation(corp corporation.Interface, tiles []tileset.Position) {
	g.board.SetTiles(corp, tiles)
	corp.AddTiles(tiles)
	g.state.ToBuyStock()
}

// Increases the number which specifies the current player
func (g *Game) nextPlayer() {
	g.currentPlayer++
	if g.currentPlayer == len(g.players) {
		g.currentPlayer = 0
	}
}

// Buys stock from corporations
func (g *Game) BuyStock(buys map[int]int) error {
	if _, ok := g.state.(*fsm.BuyStock); !ok {
		return errors.New("Action not allowed")
	}

	if err := g.checkBuy(buys); err != nil {
		return err
	}

	for corporationId, amount := range buys {
		corp := g.corporations[corporationId]
		g.CurrentPlayer().Buy(corp, amount)
	}

	g.DrawTile()
	return nil
}

func (g *Game) checkBuy(buys map[int]int) error {
	var totalStock, totalPrice int = 0, 0
	for corporationId, amount := range buys {
		corp := g.corporations[corporationId]
		if corp.Size() == 0 {
			return errors.New("Player cannot buy shares of a corporation not on board")
		}
		if amount > corp.Stock() {
			return errors.New("Player cannot buy more shares than the available stock")
		}
		totalStock += amount
		totalPrice += corp.StockPrice() * amount
	}
	if totalStock > 3 {
		return errors.New("Player cannot buy more than 3 stock shares per turn")
	}

	if totalPrice > g.CurrentPlayer().Cash() {
		return errors.New("Player doesn't have enough cash to buy those stock shares")
	}
	return nil
}

// A player takes a tile from the facedown cluster to replace
// the one he/she played. This is not done until the end of
// the turn. At this time, if a player has any permanently
// unplayable tiles that player discard the unplayable tiles
// and draws an equal number of replacement tiles. This can
// only be done once per turn.
func (g *Game) DrawTile() error {
	if tile, err := g.tileset.Draw(); err != nil {
		return err
	}
	g.CurrentPlayer().PickTile(tile)
	for _, tile := range g.CurrentPlayer().Tiles() {
		if g.isTileUnplayable(tile) {
			g.CurrentPlayer().DiscardTile(tile)
			if tile, err := g.tileset.Draw(); err != nil {
				return err
			}
			g.CurrentPlayer().PickTile(tile)
		}
	}

	g.state.ToPlayTile()
	g.nextPlayer()
	return nil
}
<commit_msg>Small fixes, WIP<commit_after>package game

import (
	"errors"
	"github.com/svera/acquire/board"
	"github.com/svera/acquire/corporation"
	"github.com/svera/acquire/fsm"
	"github.com/svera/acquire/player"
	"github.com/svera/acquire/tileset"
)

const totalCorporations = 7

type Game struct {
	board         board.Interface
	state         fsm.State
	players       []player.Interface
	corporations  [7]corporation.Interface
	tileset       tileset.Interface
	currentPlayer int
}

func New(
	board board.Interface, players []player.Interface, corporations [7]corporation.Interface, tileset tileset.Interface) (*Game, error) {
	if len(players) < 3 || len(players) > 6 {
		return nil, errors.New("Number of players must be between 3 and 6")
	}

	gm := Game{
		board:         board,
		players:       players,
		corporations:  corporations,
		tileset:       tileset,
		currentPlayer: 0,
		state:         &fsm.PlayTile{},
	}
	for _, plyr := range gm.players {
		gm.giveInitialTileset(plyr)
	}
	for i, corp := range gm.corporations {
		corp.SetId(i)
	}
	return &gm, nil
}

// Initialises player hand of tiles
func (g *Game) giveInitialTileset(plyr player.Interface) {
	for i := 0; i < 6; i++ {
		tile, _ := g.tileset.Draw()
		plyr.PickTile(tile)
	}
}

// Check if game end conditions are reached
func (g *Game) AreEndConditionsReached() bool {
	active := g.getActiveCorporations()
	if len(active) == 0 {
		return false
	}
	for _, corp := range active {
		if corp.Size() >= 41 {
			return true
		}
		if !corp.IsSafe() {
			return false
		}
	}
	return true
}

// Returns all corporations on the board
func (g *Game) getActiveCorporations() []corporation.Interface {
	active := []corporation.Interface{}
	for _, corp := range g.corporations {
		if corp.IsActive() {
			active = append(active, corp)
		}
	}
	return active
}

// Calculates and returns bonus amounts to be paid to owners of stock of a
// defunct corporation
func (g *Game) PayBonusesForDefunctCorporation(corp corporation.Interface) {
	stockHolders := g.GetMainStockHolders(corp)
	numberMajorityHolders := len(stockHolders["majority"])
	numberMinorityHolders := len(stockHolders["minority"])

	for _, majorityStockHolder := range stockHolders["majority"] {
		majorityStockHolder.ReceiveBonus(corp.MajorityBonus() / int(numberMajorityHolders))
	}
	for _, minorityStockHolder := range stockHolders["minority"] {
		minorityStockHolder.ReceiveBonus(corp.MinorityBonus() / int(numberMinorityHolders))
	}
}

// Taken from the game rules:
// "If only one player owns stock in the defunct corporation, that player gets both bonuses. If there's
// a tie for majority stockholder, add the majority and minority bonuses and divide evenly (the minority
// shareholder gets no bonus. If there's a tie for minority stockholder, split the minority bonus among
// the tied players"
func (g *Game) GetMainStockHolders(corp corporation.Interface) map[string][]player.ShareInterface {
	mainStockHolders := map[string][]player.ShareInterface{"majority": {}, "minority": {}}
	stockHolders := g.getStockHolders(corp)

	if len(stockHolders) == 1 {
		return map[string][]player.ShareInterface{
			"majority": {stockHolders[0]},
			"minority": {stockHolders[0]},
		}
	}

	mainStockHolders["majority"] = stockHoldersWithSameAmount(0, stockHolders, corp)
	if len(mainStockHolders["majority"]) > 1 {
		return mainStockHolders
	}
	mainStockHolders["minority"] = stockHoldersWithSameAmount(1, stockHolders, corp)
	return mainStockHolders
}

// Loop stockHolders from start to get all stock holders with the same amount of shares for
// the passed corporation
func stockHoldersWithSameAmount(start int, stockHolders []player.ShareInterface, corp corporation.Interface) []player.ShareInterface {
	group := []player.ShareInterface{stockHolders[start]}

	i := start + 1
	for i < len(stockHolders) && stockHolders[start].Shares(corp) == stockHolders[i].Shares(corp) {
		group = append(group, stockHolders[i])
		i++
	}
	return group
}

// Get players who have stock of the passed corporation, ordered descendently by number of stock shares
// of that corporation
func (g *Game) getStockHolders(corp corporation.Interface) []player.ShareInterface {
	var stockHolders []player.ShareInterface
	sharesDesc := func(p1, p2 player.ShareInterface) bool {
		return p1.Shares(corp) > p2.Shares(corp)
	}

	for _, player := range g.players {
		if player.Shares(corp) > 0 {
			stockHolders = append(stockHolders, player)
		}
	}
	player.By(sharesDesc).Sort(stockHolders)
	return stockHolders
}

// Returns true if a tile is permanently unplayable, that is,
// that putting it on the board would merge two or more safe corporations
func (g *Game) isTileUnplayable(tile tileset.Position) bool {
	adjacents := g.board.AdjacentCells(tile)
	for _, adjacent := range adjacents {
		safeNeighbours := 0
		boardCell := g.board.Cell(adjacent)
		if boardCell != board.Empty && boardCell != board.OrphanTile {
			if g.corporations[boardCell].IsSafe() {
				safeNeighbours++
			}
		}
		if safeNeighbours == 2 {
			return true
		}
	}
	return false
}

// Returns true if a tile is temporarily unplayable, that is,
// that putting it on the board would create an 8th corporation
func (g *Game) isTileTemporaryUnplayable(tile tileset.Position) bool {
	if len(g.getActiveCorporations()) < totalCorporations {
		return false
	}
	adjacents := g.board.AdjacentCells(tile)
	for _, adjacent := range adjacents {
		boardCell := g.board.Cell(adjacent)
		if boardCell == board.OrphanTile {
			return true
		}
	}
	return false
}

// Returns player currently in turn
func (g *Game) CurrentPlayer() player.Interface {
	return g.players[g.currentPlayer]
}

func (g *Game) PlayTile(tile tileset.Position) error {
	if _, ok := g.state.(*fsm.PlayTile); !ok {
		return errors.New("Action not allowed")
	}
	if g.isTileTemporaryUnplayable(tile) {
		return errors.New("Tile is temporary unplayable")
	}
	if err := g.CurrentPlayer().DiscardTile(tile); err != nil {
		return err
	}
	/*
		if merge, tiles := g.board.TileMergeCorporations(tile); merge {
			// move state machine status
		} else if found, tiles := g.board.TileFoundCorporation(tile); found {

		} else */if grow, tiles, corporationId := g.board.TileGrowCorporation(tile); grow {
		g.growCorporation(g.corporations[corporationId], tiles)
	} else {
		g.board.PutTile(tile)
		g.state.ToBuyStock()
	}
	return nil
}

func (g *Game) growCorporation(corp corporation.Interface, tiles []tileset.Position) {
	g.board.SetTiles(corp, tiles)
	corp.AddTiles(tiles)
	g.state.ToBuyStock()
}

// Increases the number which specifies the current player
func (g *Game) nextPlayer() {
	g.currentPlayer++
	if g.currentPlayer == len(g.players) {
		g.currentPlayer = 0
	}
}

// Buys stock from corporations
func (g *Game) BuyStock(buys map[int]int) error {
	if _, ok := g.state.(*fsm.BuyStock); !ok {
		return errors.New("Action not allowed")
	}

	if err := g.checkBuy(buys); err != nil {
		return err
	}

	for corporationId, amount := range buys {
		corp := g.corporations[corporationId]
		g.CurrentPlayer().Buy(corp, amount)
	}

	return g.drawTile()
}

func (g *Game) checkBuy(buys map[int]int) error {
	var totalStock, totalPrice int = 0, 0
	for corporationId, amount := range buys {
		corp := g.corporations[corporationId]
		if corp.Size() == 0 {
			return errors.New("Player cannot buy shares of a corporation not on board")
		}
		if amount > corp.Stock() {
			return errors.New("Player cannot buy more shares than the available stock")
		}
		totalStock += amount
		totalPrice += corp.StockPrice() * amount
	}
	if totalStock > 3 {
		return errors.New("Player cannot buy more than 3 stock shares per turn")
	}

	if totalPrice > g.CurrentPlayer().Cash() {
		return errors.New("Player doesn't have enough cash to buy those stock shares")
	}
	return nil
}

// A player takes a tile from the facedown cluster to replace
// the one he/she played. This is not done until the end of
// the turn. At this time, if a player has any permanently
// unplayable tiles that player discard the unplayable tiles
// and draws an equal number of replacement tiles. This can
// only be done once per turn.
func (g *Game) drawTile() error {
	if tile, err := g.tileset.Draw(); err != nil {
		return err
	}
	g.CurrentPlayer().PickTile(tile)
	for _, tile := range g.CurrentPlayer().Tiles() {
		if g.isTileUnplayable(tile) {
			g.CurrentPlayer().DiscardTile(tile)
			if tile, err := g.tileset.Draw(); err != nil {
				return err
			}
			g.CurrentPlayer().PickTile(tile)
		}
	}

	g.state.ToPlayTile()
	g.nextPlayer()
	return nil
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/graphql-go/graphql/language/ast"
	"github.com/graphql-go/graphql/language/kinds"
)

// Line represents a line of text in context of a byte array
type Line struct {
	Start  int
	End    int
	Source []byte
}

// Text returns the contents of the line as a string
func (line Line) Text() string {
	return string(line.Source[line.Start:line.End])
}

// IsStartOfLine returns true if index is inside the white space between
// the beginning of the line and any non white space character
func (line Line) IsStartOfLine(index int) bool {
	pos := line.Start
	if index < line.Start || index > line.End {
		return false
	}
	for _, c := range line.Text() {
		if unicode.IsSpace(rune(c)) == true {
			pos++
			continue
		}

		if index <= pos {
			return true
		}

		break
	}
	return false
}

// GetLine takes a byte array and a start position
// returns a line
func GetLine(src []byte, index int) (Line, error) {
	start, end := index, index+1
	l := len(src)

	if index > l {
		return Line{}, fmt.Errorf("index out of range")
	}

	// Find the beginning of the line
	for start > 0 && src[start-1] != '\n' {
		start--
	}

	// Find the end of the line
	for end < l && src[end-1] != '\n' {
		end++
	}

	return Line{
		Source: src,
		Start:  start,
		End:    end,
	}, nil
}

// GetCommentBlock takes a byte array and a start position
// and may return a comment block if it finds one
func GetCommentBlock(src []byte, start int) []string {

	pos := start
	linegap := 0
	var comments []string

	line, err := GetLine(src, pos)
	if err != nil {
		return nil
	}

	if line.IsStartOfLine(start) == false {
		return nil
	}

	for {
		line, err := GetLine(src, pos)
		if err != nil {
			break
		}

		trimLine := strings.TrimSpace(line.Text())

		if strings.HasPrefix(trimLine, "#") {
			block := strings.TrimSpace(strings.TrimLeft(trimLine, "#"))
			comments = append([]string{block}, comments...)
			linegap = 0
		}

		if linegap > 0 {
			break
		}

		pos = (line.Start - 1)
		linegap++

		if pos <= 0 {
			break
		}
	}

	return comments
}

// ParseType Convert a schema type to a ast.Type
func ParseType(t string, loc *ast.Location) ast.Type {

	if strings.HasSuffix(t, "!") {
		return &ast.NonNull{
			Kind: kinds.NonNull,
			Loc:  loc,
		}
	}

	if strings.HasPrefix(t, "[") && strings.HasSuffix(t, "]") {
		return &ast.List{
			Kind: kinds.List,
			Loc:  loc,
		}
	}

	return &ast.Named{
		Kind: kinds.Named,
		Loc:  loc,
	}
}
<commit_msg>Tweak function GetCommentBlock<commit_after>package utils

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/graphql-go/graphql/language/ast"
	"github.com/graphql-go/graphql/language/kinds"
)

// Line represents a line of text in context of a byte array
type Line struct {
	Start  int
	End    int
	Source []byte
}

// Text returns the contents of the line as a string
func (line Line) Text() string {
	return string(line.Source[line.Start:line.End])
}

// IsStartOfLine returns true if index is inside the white space between
// the beginning of the line and any non white space character
func (line Line) IsStartOfLine(index int) bool {
	pos := line.Start
	if index < line.Start || index > line.End {
		return false
	}
	for _, c := range line.Text() {
		if unicode.IsSpace(rune(c)) == true {
			pos++
			continue
		}

		if index <= pos {
			return true
		}

		break
	}
	return false
}

// GetLine takes a byte array and a start position
// returns a line
func GetLine(src []byte, index int) (Line, error) {
	start, end := index, index+1
	l := len(src)

	if index > l {
		return Line{}, fmt.Errorf("index out of range")
	}

	// Find the beginning of the line
	for start > 0 && src[start-1] != '\n' {
		start--
	}

	// Find the end of the line
	for end < l && src[end-1] != '\n' {
		end++
	}

	return Line{
		Source: src,
		Start:  start,
		End:    end,
	}, nil
}

// GetCommentBlock takes a byte array and a start position
// and may return a comment block if it finds one
func GetCommentBlock(src []byte, index int) (block []string) {

	pos := index
	linegap := false

	for {
		line, err := GetLine(src, pos)
		if err != nil {
			break
		}

		if line.IsStartOfLine(index) == false && linegap == false {
			return
		}

		text := strings.TrimSpace(line.Text())

		if strings.HasPrefix(text, "#") {
			comment := strings.TrimSpace(strings.TrimLeft(text, "#"))

			// Prepend new data to the comment block
			block = append([]string{comment}, block...)
			linegap = false
		}

		if linegap == true {
			break
		}

		pos = line.Start - 1
		linegap = true

		if pos <= 0 {
			break
		}
	}

	return block
}

// ParseType Convert a schema type to a ast.Type
func ParseType(t string, loc *ast.Location) ast.Type {

	if strings.HasSuffix(t, "!") {
		return &ast.NonNull{
			Kind: kinds.NonNull,
			Loc:  loc,
		}
	}

	if strings.HasPrefix(t, "[") && strings.HasSuffix(t, "]") {
		return &ast.List{
			Kind: kinds.List,
			Loc:  loc,
		}
	}

	return &ast.Named{
		Kind: kinds.Named,
		Loc:  loc,
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package space

import (
	"github.com/drakmaniso/glam/geom"
	"github.com/drakmaniso/glam/math"
)

//------------------------------------------------------------------------------

// Identity matrix.
func Identity() geom.Mat4 {
	return geom.Mat4{
		{1, 0, 0, 0},
		{0, 1, 0, 0},
		{0, 0, 1, 0},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// Apply a tranformation matrix to a vector (i.e. returns matrix multiplied by
// column vector).
func Apply(m geom.Mat4, v geom.Vec4) geom.Vec4 {
	return geom.Vec4{
		X: m[0][0]*v.X + m[1][0]*v.Y + m[2][0]*v.Z + m[3][0]*v.W,
		Y: m[0][1]*v.X + m[1][1]*v.Y + m[2][1]*v.Z + m[3][1]*v.W,
		Z: m[0][2]*v.X + m[1][2]*v.Y + m[2][2]*v.Z + m[3][2]*v.W,
		W: m[0][3]*v.X + m[1][3]*v.Y + m[2][3]*v.Z + m[3][3]*v.W,
	}
}

//------------------------------------------------------------------------------

// Translation by a vector.
func Translation(t geom.Vec3) geom.Mat4 {
	return geom.Mat4{
		{1, 0, 0, 0},
		{0, 1, 0, 0},
		{0, 0, 1, 0},
		{t.X, t.Y, t.Z, 1},
	}
}

//------------------------------------------------------------------------------

// Rotation around an axis.
func Rotation(angle float32, axis geom.Vec3) geom.Mat4 {
	c := math.Cos(angle)
	s := math.Sin(angle)

	return geom.Mat4{
		{c + axis.X*axis.X*(1-c), -axis.Z*s + axis.X*axis.Y*(1-c), axis.Y*s + axis.X*axis.Z*(1-c), 0},
		{axis.Z*s + axis.Y*axis.X*(1-c), c + axis.Y*axis.Y*(1-c), -axis.X*s + axis.Y*axis.Z*(1-c), 0},
		{-axis.Y*s + axis.Z*axis.X*(1-c), axis.X*s + axis.Z*axis.Y*(1-c), c + axis.Z*axis.Z*(1-c), 0},
		{0, 0, 0, 1},
	}
}

func EulerXYZ(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleX)
	s1 := math.Sin(angleX)
	c2 := math.Cos(angleY)
	s2 := math.Sin(angleY)
	c3 := math.Cos(angleZ)
	s3 := math.Sin(angleZ)

	return geom.Mat4{
		{c2 * c3, c1*s3 + c3*s1*s2, s1*s3 - c1*c3*s2},
		{-c2 * s3, c1*c3 - s1*s2*s3, c3*s1 + c1*s2*s3},
		{s2, -c2 * s1, c1 * c2},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// Scaling along the 3 axis.
func Scaling(s geom.Vec3) geom.Mat4 {
	return geom.Mat4{
		{s.X, 0, 0, 0},
		{0, s.Y, 0, 0},
		{0, 0, s.Z, 0},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// LookAt returns a transform which put eye at origin and target along
// negative Z. In other words, if a projection matrix is applied to the result,
// target will be in the center of the viewport.
func LookAt(eye, target, up geom.Vec3) geom.Mat4 {
	f := target.Minus(eye).Normalized()
	u := up.Normalized()
	s := f.Cross(u).Normalized()
	u = s.Cross(f)

	return geom.Mat4{
		{s.X, u.X, -f.X, 0},
		{s.Y, u.Y, -f.Y, 0},
		{s.Z, u.Z, -f.Z, 0},
		{-s.Dot(eye), -u.Dot(eye), f.Dot(eye), 1},
	}
}

//------------------------------------------------------------------------------

// Perspective returns a perspective projection matrix.
func Perspective(fieldOfView, aspectRatio, near, far float32) geom.Mat4 {
	f := float32(1.0) / math.Tan(fieldOfView/float32(2.0))

	return geom.Mat4{
		{f / aspectRatio, 0, 0, 0},
		{0, f, 0, 0},
		{0, 0, (far + near) / (near - far), -1},
		{0, 0, (2 * far * near) / (near - far), 0},
	}
}

// PerspectiveFrustum returns a perspective projection matrix.
func PerspectiveFrustum(left, right, bottom, top, near, far float32) geom.Mat4 {
	return geom.Mat4{
		{(2 * near) / (right - left), 0, 0, 0},
		{0, (2 * near) / (top - bottom), 0, 0},
		{(right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1},
		{0, 0, -(2 * far * near) / (far - near), 0},
	}
}

// Orthographic returns an orthographic (parallel) projection matrix.
// (zoom is the height of the projection plane).
func Orthographic(zoom, aspectRatio, near, far float32) geom.Mat4 {
	top := zoom / 2
	right := top * aspectRatio
	return geom.Mat4{
		{1 / right, 0, 0, 0},
		{0, 1 / top, 0, 0},
		{0, 0, -2 / (far - near), 0},
		{0, 0, -(far + near) / (far - near), 1},
	}
}

// OrthographicFrustum returns an orthographic (parallel) projection matrix.
func OrthographicFrustum(left, right, bottom, top, near, far float32) geom.Mat4 {
	return geom.Mat4{
		{2 / (right - left), 0, 0, 0},
		{0, 2 / (top - bottom), 0, 0},
		{0, 0, -2 / (far - near), 0},
		{-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1},
	}
}

//------------------------------------------------------------------------------
<commit_msg>Add remaining Euler transforms<commit_after>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package space

import (
	"github.com/drakmaniso/glam/geom"
	"github.com/drakmaniso/glam/math"
)

//------------------------------------------------------------------------------

// Identity matrix.
func Identity() geom.Mat4 {
	return geom.Mat4{
		{1, 0, 0, 0},
		{0, 1, 0, 0},
		{0, 0, 1, 0},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// Apply a tranformation matrix to a vector (i.e. returns matrix multiplied by
// column vector).
func Apply(m geom.Mat4, v geom.Vec4) geom.Vec4 {
	return geom.Vec4{
		X: m[0][0]*v.X + m[1][0]*v.Y + m[2][0]*v.Z + m[3][0]*v.W,
		Y: m[0][1]*v.X + m[1][1]*v.Y + m[2][1]*v.Z + m[3][1]*v.W,
		Z: m[0][2]*v.X + m[1][2]*v.Y + m[2][2]*v.Z + m[3][2]*v.W,
		W: m[0][3]*v.X + m[1][3]*v.Y + m[2][3]*v.Z + m[3][3]*v.W,
	}
}

//------------------------------------------------------------------------------

// Translation by a vector.
func Translation(t geom.Vec3) geom.Mat4 {
	return geom.Mat4{
		{1, 0, 0, 0},
		{0, 1, 0, 0},
		{0, 0, 1, 0},
		{t.X, t.Y, t.Z, 1},
	}
}

//------------------------------------------------------------------------------

// Rotation around an axis.
func Rotation(angle float32, axis geom.Vec3) geom.Mat4 {
	c := math.Cos(angle)
	s := math.Sin(angle)

	return geom.Mat4{
		{c + axis.X*axis.X*(1-c), -axis.Z*s + axis.X*axis.Y*(1-c), axis.Y*s + axis.X*axis.Z*(1-c), 0},
		{axis.Z*s + axis.Y*axis.X*(1-c), c + axis.Y*axis.Y*(1-c), -axis.X*s + axis.Y*axis.Z*(1-c), 0},
		{-axis.Y*s + axis.Z*axis.X*(1-c), axis.X*s + axis.Z*axis.Y*(1-c), c + axis.Z*axis.Z*(1-c), 0},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

func EulerYXZ(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleY)
	s1 := math.Sin(angleY)
	c2 := math.Cos(angleX)
	s2 := math.Sin(angleX)
	c3 := math.Cos(angleZ)
	s3 := math.Sin(angleZ)

	return geom.Mat4{
		{c1*c3 + s1*s2*s3, c2 * s3, c1*s2*s3 - c3*s1},
		{c3*s1*s2 - c1*s3, c2 * c3, c1*c3*s2 + s1*s3},
		{c2 * s1, -s2, c1 * c2},
		{0, 0, 0, 1},
	}
}

func EulerXYZ(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleX)
	s1 := math.Sin(angleX)
	c2 := math.Cos(angleY)
	s2 := math.Sin(angleY)
	c3 := math.Cos(angleZ)
	s3 := math.Sin(angleZ)

	return geom.Mat4{
		{c2 * c3, c1*s3 + c3*s1*s2, s1*s3 - c1*c3*s2},
		{-c2 * s3, c1*c3 - s1*s2*s3, c3*s1 + c1*s2*s3},
		{s2, -c2 * s1, c1 * c2},
		{0, 0, 0, 1},
	}
}

func EulerZYX(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleZ)
	s1 := math.Sin(angleZ)
	c2 := math.Cos(angleY)
	s2 := math.Sin(angleY)
	c3 := math.Cos(angleX)
	s3 := math.Sin(angleX)

	return geom.Mat4{
		{c1 * c2, c2 * s1, -s2},
		{c1*s2*s3 - c3*s1, c1*c3 + s1*s2*s3, c2 * s3},
		{s1*s3 + c1*c3*s2, c3*s1*s2 - c1*s3, c2 * c3},
		{0, 0, 0, 1},
	}
}

func EulerXZY(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleX)
	s1 := math.Sin(angleX)
	c2 := math.Cos(angleZ)
	s2 := math.Sin(angleZ)
	c3 := math.Cos(angleY)
	s3 := math.Sin(angleY)

	return geom.Mat4{
		{c2 * c3, s1*s3 + c1*c3*s2, c3*s1*s2 - c1*s3},
		{-s2, c1 * c2, c2 * s1},
		{c2 * s3, c1*s2*s3 - c3*s1, c1*c3 + s1*s2*s3},
		{0, 0, 0, 1},
	}
}

func EulerYZX(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleY)
	s1 := math.Sin(angleY)
	c2 := math.Cos(angleZ)
	s2 := math.Sin(angleZ)
	c3 := math.Cos(angleX)
	s3 := math.Sin(angleX)

	return geom.Mat4{
		{c1 * c2, s2, -c2 * s1},
		{s1*s3 - c1*c3*s2, c2 * c3, c1*s3 + c3*s1*s2},
		{c3*s1 + c1*s2*s3, -c2 * s3, c1*c3 - s1*s2*s3},
		{0, 0, 0, 1},
	}
}

func EulerZXY(angleX, angleY, angleZ float32) geom.Mat4 {
	c1 := math.Cos(angleZ)
	s1 := math.Sin(angleZ)
	c2 := math.Cos(angleX)
	s2 := math.Sin(angleX)
	c3 := math.Cos(angleY)
	s3 := math.Sin(angleY)

	return geom.Mat4{
		{c1*c3 - s1*s2*s3, c3*s1 + c1*s2*s3, -c2 * s3},
		{-c2 * s1, c1 * c2, s2},
		{c1*s3 + c3*s1*s2, s1*s3 - c1*c3*s2, c2 * c3},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// Scaling along the 3 axis.
func Scaling(s geom.Vec3) geom.Mat4 {
	return geom.Mat4{
		{s.X, 0, 0, 0},
		{0, s.Y, 0, 0},
		{0, 0, s.Z, 0},
		{0, 0, 0, 1},
	}
}

//------------------------------------------------------------------------------

// LookAt returns a transform which put eye at origin and target along
// negative Z. In other words, if a projection matrix is applied to the result,
// target will be in the center of the viewport.
func LookAt(eye, target, up geom.Vec3) geom.Mat4 {
	f := target.Minus(eye).Normalized()
	u := up.Normalized()
	s := f.Cross(u).Normalized()
	u = s.Cross(f)

	return geom.Mat4{
		{s.X, u.X, -f.X, 0},
		{s.Y, u.Y, -f.Y, 0},
		{s.Z, u.Z, -f.Z, 0},
		{-s.Dot(eye), -u.Dot(eye), f.Dot(eye), 1},
	}
}

//------------------------------------------------------------------------------

// Perspective returns a perspective projection matrix.
func Perspective(fieldOfView, aspectRatio, near, far float32) geom.Mat4 {
	f := float32(1.0) / math.Tan(fieldOfView/float32(2.0))

	return geom.Mat4{
		{f / aspectRatio, 0, 0, 0},
		{0, f, 0, 0},
		{0, 0, (far + near) / (near - far), -1},
		{0, 0, (2 * far * near) / (near - far), 0},
	}
}

// PerspectiveFrustum returns a perspective projection matrix.
func PerspectiveFrustum(left, right, bottom, top, near, far float32) geom.Mat4 {
	return geom.Mat4{
		{(2 * near) / (right - left), 0, 0, 0},
		{0, (2 * near) / (top - bottom), 0, 0},
		{(right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1},
		{0, 0, -(2 * far * near) / (far - near), 0},
	}
}

// Orthographic returns an orthographic (parallel) projection matrix.
// (zoom is the height of the projection plane).
func Orthographic(zoom, aspectRatio, near, far float32) geom.Mat4 {
	top := zoom / 2
	right := top * aspectRatio
	return geom.Mat4{
		{1 / right, 0, 0, 0},
		{0, 1 / top, 0, 0},
		{0, 0, -2 / (far - near), 0},
		{0, 0, -(far + near) / (far - near), 1},
	}
}

// OrthographicFrustum returns an orthographic (parallel) projection matrix.
func OrthographicFrustum(left, right, bottom, top, near, far float32) geom.Mat4 {
	return geom.Mat4{
		{2 / (right - left), 0, 0, 0},
		{0, 2 / (top - bottom), 0, 0},
		{0, 0, -2 / (far - near), 0},
		{-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1},
	}
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/unders/aehello/app/pkg/health"
	"github.com/unders/aehello/pkg/signal"
)

var (
	// Version the version of the service.
	Version = "No Version Provided"

	// Buildstamp the time the service was built.
	Buildstamp = "No Buildstamp provided"

	// Githash the git commit hash
	Githash = "No Githash provided"
)

// addr is the default address for appengine services
var addr = "0.0.0.0:8080"

// log messages
const (
	started          = "info=started app=helloworld\n"
	release          = "info=version:%s buildstamp:%s githash:%s app=helloworld\n"
	stopped          = "info=stopped app=helloworld\n"
	stoppedWithError = "err=%s app=helloworld\n"
	running          = "info=listens on address %s app=helloworld\n"
	gotStopSignal    = "\ninfo=got signal %s app=helloworld\n"
	request          = "info=%s %s  [ 200 ok ] app=helloworld\n"
	notFound         = "info=%s %s  [ 404 not found ] app=helloworld\n"
)

func main() {
	if ok := run(os.Args, os.Stdout); !ok {
		os.Exit(1)
	}
}

// ENV
// GCLOUD_PROJECT
// GAE_INSTANCE
// GAE_SERVICE
// GAE_VERSION

// The following HTTP headers are now included with all requests:
// X-FORWARDED-FOR
// X-CLOUD-TRACE-CONTEXT
// X-FORWARDED-PROTO

// some requests
// Your application should handle the special country code ZZ (unknown country).
// X-AppEngine-Country        # ISO 3166-1 alpha-2 country code

// X-AppEngine-Region

// Headers to set: Strict-Transport-Security: max-age=31536000; includeSubDomains

func run(args []string, log io.Writer) bool {
	fmt.Fprint(log, started)
	fmt.Fprintf(log, release, Version, Buildstamp, Githash)
	httpAddr := parseAddr(args)

	http.HandleFunc(health.Handler())
	http.HandleFunc("/", landing(log))

	ch := make(chan error, 1)
	go func() {
		ch <- http.ListenAndServe(httpAddr, nil)
	}()

	fmt.Fprintf(log, running, httpAddr)

	select {
	case err := <-ch:
		fmt.Fprintf(log, stoppedWithError, err)
		fmt.Fprint(log, stopped)
		return false
	case sig := <-signal.Wait():
		fmt.Fprintf(log, gotStopSignal, sig)
		fmt.Fprint(log, stopped)
		return true
	}
}

func landing(log io.Writer) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			fmt.Fprintf(log, notFound, r.Method, r.RequestURI)
			return
		}
		fmt.Fprint(w, landingPage)
		fmt.Fprintf(log, request, r.Method, r.RequestURI)
	}
}

const landingPage = "Hello World\n"

func parseAddr(args []string) string {
	flag.StringVar(&addr, "http", addr, "HTTP service address.")
	flag.Parse()
	return addr
}
<commit_msg>Fix better log messages<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/unders/aehello/app/pkg/health"
	"github.com/unders/aehello/pkg/signal"
)

var (
	// Version the version of the service.
	Version = "No Version Provided"

	// Buildstamp the time the service was built.
	Buildstamp = "No Buildstamp provided"

	// Githash the git commit hash
	Githash = "No Githash provided"
)

// addr is the default address for appengine services
var addr = "0.0.0.0:8080"

// log messages
const (
	started          = "\n** STARTED **\ninfo=started app=helloworld\n"
	release          = "info=version:%s buildstamp:%s githash:%s app=helloworld\n"
	stopped          = "info=stopped app=helloworld\n** STOPPED **\n"
	stoppedWithError = "err=%s app=helloworld\n"
	running          = "info=listens on address %s app=helloworld\n"
	gotStopSignal    = "\ninfo=got signal %s app=helloworld\n"
)

func main() {
	if ok := run(os.Args, os.Stdout); !ok {
		os.Exit(1)
	}
}

// ENV
// GCLOUD_PROJECT
// GAE_INSTANCE
// GAE_SERVICE
// GAE_VERSION

// The following HTTP headers are now included with all requests:
// X-FORWARDED-FOR
// X-CLOUD-TRACE-CONTEXT
// X-FORWARDED-PROTO

// some requests
// Your application should handle the special country code ZZ (unknown country).
// X-AppEngine-Country        # ISO 3166-1 alpha-2 country code

// X-AppEngine-Region

// Headers to set: Strict-Transport-Security: max-age=31536000; includeSubDomains

func run(args []string, log io.Writer) bool {
	fmt.Fprint(log, started)
	fmt.Fprintf(log, release, Version, Buildstamp, Githash)
	httpAddr := parseAddr(args)

	http.HandleFunc(health.Handler())
	http.HandleFunc("/", landing)

	ch := make(chan error, 1)
	go func() {
		ch <- http.ListenAndServe(httpAddr, nil)
	}()

	fmt.Fprintf(log, running, httpAddr)

	select {
	case err := <-ch:
		fmt.Fprintf(log, stoppedWithError, err)
		fmt.Fprint(log, stopped)
		return false
	case sig := <-signal.Wait():
		fmt.Fprintf(log, gotStopSignal, sig)
		fmt.Fprint(log, stopped)
		return true
	}
}

func landing(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	fmt.Fprint(w, landingPage)
}

const landingPage = "Welcome to Hellow world\n"

func parseAddr(args []string) string {
	flag.StringVar(&addr, "http", addr, "HTTP service address.")
	flag.Parse()
	return addr
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/alexzorin/libvirt-go"
	"log"
)

func main() {
	vir, err := libvirt.NewVirConnection("vbox:///session")
	if err != nil {
		log.Fatalln(err.Error())
	}

	hostname, _ := vir.GetHostname()
	log.Printf("Connected to hypervisor at %s\n", hostname)

	// capabilities, err := vir.GetCapabilities()
	// if err != nil {
	// 	log.Fatalln(err)
	// }

	// definedDomains, err := vir.ListDefinedDomains()
	// if err != nil {
	// 	log.Fatalln(err.Error())
	// }
	// for k := range definedDomains {
	// 	log.Printf("Defined domain %s\n", definedDomains[k])
	// 	dom, _ := vir.LookupDomainByName(definedDomains[k])
	// 	log.Println(dom.GetName())
	// 	log.Println(dom.GetState())
	// }

	domains, err := vir.ListDomains()
	if err != nil {
		log.Fatalln(err.Error())
	}

	for k := range domains {
		log.Printf("Domain %d\n", domains[k])
		dom, err := vir.LookupDomainById(domains[k])
		if err != nil {
			log.Fatalln(err.Error())
		}
		name, _ := dom.GetName()
		state, _ := dom.GetState()
		xml, _ := dom.GetXMLDesc(0)
		log.Println(name, state, xml)
		// snapshot, err := dom.CreateSnapshotXML(`<domainsnapshot></domainsnapshot>`, 0)
		// log.Println(snapshot, err)
	}

	vir.CloseConnection()
}
<commit_msg>Remove examples as its pretty bad<commit_after><|endoftext|>