<commit_before>package config

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// ReadConfigFile reads the config from `filename` into `cfg`.
func ReadConfigFile(filename string, cfg interface{}) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	return Decode(f, cfg)
}

// WriteConfigFile writes the config from `cfg` into `filename`.
func WriteConfigFile(filename string, cfg interface{}) error {
	err := os.MkdirAll(filepath.Dir(filename), 0775)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	return Encode(f, cfg)
}

// WriteFile writes the buffer at filename
func WriteFile(filename string, buf []byte) error {
	err := os.MkdirAll(filepath.Dir(filename), 0775)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.Write(buf)
	return err
}

// HumanOutput gets a config value ready for printing
func HumanOutput(value interface{}) ([]byte, error) {
	s, ok := value.(string)
	if ok {
		return []byte(strings.Trim(s, "\n")), nil
	}
	return Marshal(value)
}

// Marshal configuration with JSON
func Marshal(value interface{}) ([]byte, error) {
	// need to prettyprint, hence MarshalIndent, instead of Encoder
	return json.MarshalIndent(value, "", "  ")
}

// Encode configuration with JSON
func Encode(w io.Writer, value interface{}) error {
	// need to prettyprint, hence MarshalIndent, instead of Encoder
	buf, err := Marshal(value)
	if err != nil {
		return err
	}

	_, err = w.Write(buf)
	return err
}

// Decode configuration with JSON
func Decode(r io.Reader, value interface{}) error {
	return json.NewDecoder(r).Decode(value)
}

// ReadConfigKey retrieves only the value of a particular key
func ReadConfigKey(filename, key string) (interface{}, error) {
	var cfg interface{}
	if err := ReadConfigFile(filename, &cfg); err != nil {
		return nil, err
	}

	var ok bool
	cursor := cfg
	parts := strings.Split(key, ".")
	for i, part := range parts {
		cursor, ok = cursor.(map[string]interface{})[part]
		if !ok {
			sofar := strings.Join(parts[:i], ".")
			return nil, fmt.Errorf("%s key has no attributes", sofar)
		}
	}
	return cursor, nil
}

// WriteConfigKey writes the value of a particular key
func WriteConfigKey(filename, key string, value interface{}) error {
	var cfg interface{}
	if err := ReadConfigFile(filename, &cfg); err != nil {
		return err
	}

	var ok bool
	var mcursor map[string]interface{}
	cursor := cfg

	parts := strings.Split(key, ".")
	for i, part := range parts {
		mcursor, ok = cursor.(map[string]interface{})
		if !ok {
			sofar := strings.Join(parts[:i], ".")
			return fmt.Errorf("%s key is not a map", sofar)
		}

		// last part? set here
		if i == (len(parts) - 1) {
			mcursor[part] = value
			break
		}

		cursor, ok = mcursor[part]
		if !ok { // create map if this is empty
			mcursor[part] = map[string]interface{}{}
			cursor = mcursor[part]
		}
	}

	return WriteConfigFile(filename, cfg)
}
<commit_msg>config: nicer error to user<commit_after>package config

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// ReadConfigFile reads the config from `filename` into `cfg`.
func ReadConfigFile(filename string, cfg interface{}) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	if err := Decode(f, cfg); err != nil {
		return fmt.Errorf("Failure to decode config: %s", err)
	}
	return nil
}

// WriteConfigFile writes the config from `cfg` into `filename`.
func WriteConfigFile(filename string, cfg interface{}) error {
	err := os.MkdirAll(filepath.Dir(filename), 0775)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	return Encode(f, cfg)
}

// WriteFile writes the buffer at filename
func WriteFile(filename string, buf []byte) error {
	err := os.MkdirAll(filepath.Dir(filename), 0775)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.Write(buf)
	return err
}

// HumanOutput gets a config value ready for printing
func HumanOutput(value interface{}) ([]byte, error) {
	s, ok := value.(string)
	if ok {
		return []byte(strings.Trim(s, "\n")), nil
	}
	return Marshal(value)
}

// Marshal configuration with JSON
func Marshal(value interface{}) ([]byte, error) {
	// need to prettyprint, hence MarshalIndent, instead of Encoder
	return json.MarshalIndent(value, "", "  ")
}

// Encode configuration with JSON
func Encode(w io.Writer, value interface{}) error {
	// need to prettyprint, hence MarshalIndent, instead of Encoder
	buf, err := Marshal(value)
	if err != nil {
		return err
	}

	_, err = w.Write(buf)
	return err
}

// Decode configuration with JSON
func Decode(r io.Reader, value interface{}) error {
	return json.NewDecoder(r).Decode(value)
}

// ReadConfigKey retrieves only the value of a particular key
func ReadConfigKey(filename, key string) (interface{}, error) {
	var cfg interface{}
	if err := ReadConfigFile(filename, &cfg); err != nil {
		return nil, err
	}

	var ok bool
	cursor := cfg
	parts := strings.Split(key, ".")
	for i, part := range parts {
		cursor, ok = cursor.(map[string]interface{})[part]
		if !ok {
			sofar := strings.Join(parts[:i], ".")
			return nil, fmt.Errorf("%s key has no attributes", sofar)
		}
	}
	return cursor, nil
}

// WriteConfigKey writes the value of a particular key
func WriteConfigKey(filename, key string, value interface{}) error {
	var cfg interface{}
	if err := ReadConfigFile(filename, &cfg); err != nil {
		return err
	}

	var ok bool
	var mcursor map[string]interface{}
	cursor := cfg

	parts := strings.Split(key, ".")
	for i, part := range parts {
		mcursor, ok = cursor.(map[string]interface{})
		if !ok {
			sofar := strings.Join(parts[:i], ".")
			return fmt.Errorf("%s key is not a map", sofar)
		}

		// last part? set here
		if i == (len(parts) - 1) {
			mcursor[part] = value
			break
		}

		cursor, ok = mcursor[part]
		if !ok { // create map if this is empty
			mcursor[part] = map[string]interface{}{}
			cursor = mcursor[part]
		}
	}

	return WriteConfigFile(filename, cfg)
}
<|endoftext|>


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

package container

import (
	"errors"
	"net/http"

	"golang.org/x/net/context"
	raw "google.golang.org/api/container/v1"
	"google.golang.org/cloud/internal"
)

// Cluster returns metadata about the specified cluster.
//
// Deprecated: please use Client.Cluster instead.
func Cluster(ctx context.Context, zone, name string) (*Resource, error) {
	s := rawService(ctx)
	resp, err := s.Projects.Zones.Clusters.Get(internal.ProjID(ctx), zone, name).Do()
	if err != nil {
		return nil, err
	}
	return resourceFromRaw(resp), nil
}

// CreateCluster creates a new cluster with the provided metadata
// in the specified zone.
//
// Deprecated: please use Client.CreateCluster instead.
func CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) {
	panic("not implemented")
}

// DeleteCluster deletes a cluster.
//
// Deprecated: please use Client.DeleteCluster instead.
func DeleteCluster(ctx context.Context, zone, name string) error {
	s := rawService(ctx)
	_, err := s.Projects.Zones.Clusters.Delete(internal.ProjID(ctx), zone, name).Do()
	return err
}

// Operations returns a list of operations from the specified zone.
// If no zone is specified, it looks up for all of the operations
// that are running under the user's project.
//
// Deprecated: please use Client.Operations instead.
func Operations(ctx context.Context, zone string) ([]*Op, error) {
	s := rawService(ctx)
	if zone == "" {
		resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), "-").Do()
		if err != nil {
			return nil, err
		}
		return opsFromRaw(resp.Operations), nil
	}
	resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), zone).Do()
	if err != nil {
		return nil, err
	}
	return opsFromRaw(resp.Operations), nil
}

// Operation returns an operation.
//
// Deprecated: please use Client.Operation instead.
func Operation(ctx context.Context, zone, name string) (*Op, error) {
	s := rawService(ctx)
	resp, err := s.Projects.Zones.Operations.Get(internal.ProjID(ctx), zone, name).Do()
	if err != nil {
		return nil, err
	}
	if resp.StatusMessage != "" {
		return nil, errors.New(resp.StatusMessage)
	}
	return opFromRaw(resp), nil
}

func rawService(ctx context.Context) *raw.Service {
	return internal.Service(ctx, "container", func(hc *http.Client) interface{} {
		svc, _ := raw.New(hc)
		return svc
	}).(*raw.Service)
}
<commit_msg>container: fix up a stray internal import<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package container

import (
	"errors"
	"net/http"

	"cloud.google.com/go/internal"
	"golang.org/x/net/context"
	raw "google.golang.org/api/container/v1"
)

// Cluster returns metadata about the specified cluster.
//
// Deprecated: please use Client.Cluster instead.
func Cluster(ctx context.Context, zone, name string) (*Resource, error) {
	s := rawService(ctx)
	resp, err := s.Projects.Zones.Clusters.Get(internal.ProjID(ctx), zone, name).Do()
	if err != nil {
		return nil, err
	}
	return resourceFromRaw(resp), nil
}

// CreateCluster creates a new cluster with the provided metadata
// in the specified zone.
//
// Deprecated: please use Client.CreateCluster instead.
func CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) {
	panic("not implemented")
}

// DeleteCluster deletes a cluster.
//
// Deprecated: please use Client.DeleteCluster instead.
func DeleteCluster(ctx context.Context, zone, name string) error {
	s := rawService(ctx)
	_, err := s.Projects.Zones.Clusters.Delete(internal.ProjID(ctx), zone, name).Do()
	return err
}

// Operations returns a list of operations from the specified zone.
// If no zone is specified, it looks up for all of the operations
// that are running under the user's project.
//
// Deprecated: please use Client.Operations instead.
func Operations(ctx context.Context, zone string) ([]*Op, error) {
	s := rawService(ctx)
	if zone == "" {
		resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), "-").Do()
		if err != nil {
			return nil, err
		}
		return opsFromRaw(resp.Operations), nil
	}
	resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), zone).Do()
	if err != nil {
		return nil, err
	}
	return opsFromRaw(resp.Operations), nil
}

// Operation returns an operation.
//
// Deprecated: please use Client.Operation instead.
func Operation(ctx context.Context, zone, name string) (*Op, error) {
	s := rawService(ctx)
	resp, err := s.Projects.Zones.Operations.Get(internal.ProjID(ctx), zone, name).Do()
	if err != nil {
		return nil, err
	}
	if resp.StatusMessage != "" {
		return nil, errors.New(resp.StatusMessage)
	}
	return opFromRaw(resp), nil
}

func rawService(ctx context.Context) *raw.Service {
	return internal.Service(ctx, "container", func(hc *http.Client) interface{} {
		svc, _ := raw.New(hc)
		return svc
	}).(*raw.Service)
}
<|endoftext|>


<commit_before>package mpb

import (
	"io"
	"sync"
	"time"
)

// ContainerOption is a func option to alter default behavior of a bar
// container. Container term refers to a Progress struct which can
// hold one or more Bars.
type ContainerOption func(*pState)

// WithWaitGroup provides means to have a single joint point. If
// *sync.WaitGroup is provided, you can safely call just p.Wait()
// without calling Wait() on provided *sync.WaitGroup. Makes sense
// when there are more than one bar to render.
func WithWaitGroup(wg *sync.WaitGroup) ContainerOption {
	return func(s *pState) {
		s.uwg = wg
	}
}

// WithWidth sets container width. If not set it defaults to terminal
// width. A bar added to the container will inherit its width, unless
// overridden by `func BarWidth(int) BarOption`.
func WithWidth(width int) ContainerOption {
	return func(s *pState) {
		s.reqWidth = width
	}
}

// WithRefreshRate overrides default 150ms refresh rate.
func WithRefreshRate(d time.Duration) ContainerOption {
	return func(s *pState) {
		s.rr = d
	}
}

// WithManualRefresh disables internal auto refresh time.Ticker.
// Refresh will occur upon receive value from provided ch.
func WithManualRefresh(ch <-chan interface{}) ContainerOption {
	return func(s *pState) {
		s.externalRefresh = ch
	}
}

// WithRenderDelay delays rendering. By default rendering starts as
// soon as bar is added, with this option it's possible to delay
// rendering process by keeping provided chan unclosed. In other words
// rendering will start as soon as provided chan is closed.
func WithRenderDelay(ch <-chan struct{}) ContainerOption {
	return func(s *pState) {
		s.renderDelay = ch
	}
}

// WithShutdownNotifier provided chanel will be closed, after all bars
// have been rendered.
func WithShutdownNotifier(ch chan struct{}) ContainerOption {
	return func(s *pState) {
		select {
		case <-ch:
		default:
			s.shutdownNotifier = ch
		}
	}
}

// WithOutput overrides default os.Stdout output. Setting it to nil
// will effectively disable auto refresh rate and discard any output,
// useful if you want to disable progress bars with little overhead.
func WithOutput(w io.Writer) ContainerOption {
	return func(s *pState) {
		if w == nil {
			s.output = io.Discard
			s.outputDiscarded = true
			return
		}
		s.output = w
	}
}

// WithDebugOutput sets debug output.
func WithDebugOutput(w io.Writer) ContainerOption {
	if w == nil {
		return nil
	}
	return func(s *pState) {
		s.debugOut = w
	}
}

// PopCompletedMode will pop and stop rendering completed bars.
func PopCompletedMode() ContainerOption {
	return func(s *pState) {
		s.popCompleted = true
	}
}

// ContainerOptional will invoke provided option only when cond is true.
func ContainerOptional(option ContainerOption, cond bool) ContainerOption {
	if cond {
		return option
	}
	return nil
}

// ContainerOptOn will invoke provided option only when higher order
// predicate evaluates to true.
func ContainerOptOn(option ContainerOption, predicate func() bool) ContainerOption {
	if predicate() {
		return option
	}
	return nil
}
<commit_msg>ContainerFuncOptional, ContainerFuncOptOn<commit_after>package mpb

import (
	"io"
	"sync"
	"time"
)

// ContainerOption is a func option to alter default behavior of a bar
// container. Container term refers to a Progress struct which can
// hold one or more Bars.
type ContainerOption func(*pState)

// WithWaitGroup provides means to have a single joint point. If
// *sync.WaitGroup is provided, you can safely call just p.Wait()
// without calling Wait() on provided *sync.WaitGroup. Makes sense
// when there are more than one bar to render.
func WithWaitGroup(wg *sync.WaitGroup) ContainerOption {
	return func(s *pState) {
		s.uwg = wg
	}
}

// WithWidth sets container width. If not set it defaults to terminal
// width. A bar added to the container will inherit its width, unless
// overridden by `func BarWidth(int) BarOption`.
func WithWidth(width int) ContainerOption {
	return func(s *pState) {
		s.reqWidth = width
	}
}

// WithRefreshRate overrides default 150ms refresh rate.
func WithRefreshRate(d time.Duration) ContainerOption {
	return func(s *pState) {
		s.rr = d
	}
}

// WithManualRefresh disables internal auto refresh time.Ticker.
// Refresh will occur upon receive value from provided ch.
func WithManualRefresh(ch <-chan interface{}) ContainerOption {
	return func(s *pState) {
		s.externalRefresh = ch
	}
}

// WithRenderDelay delays rendering. By default rendering starts as
// soon as bar is added, with this option it's possible to delay
// rendering process by keeping provided chan unclosed. In other words
// rendering will start as soon as provided chan is closed.
func WithRenderDelay(ch <-chan struct{}) ContainerOption {
	return func(s *pState) {
		s.renderDelay = ch
	}
}

// WithShutdownNotifier provided chanel will be closed, after all bars
// have been rendered.
func WithShutdownNotifier(ch chan struct{}) ContainerOption {
	return func(s *pState) {
		select {
		case <-ch:
		default:
			s.shutdownNotifier = ch
		}
	}
}

// WithOutput overrides default os.Stdout output. Setting it to nil
// will effectively disable auto refresh rate and discard any output,
// useful if you want to disable progress bars with little overhead.
func WithOutput(w io.Writer) ContainerOption {
	return func(s *pState) {
		if w == nil {
			s.output = io.Discard
			s.outputDiscarded = true
			return
		}
		s.output = w
	}
}

// WithDebugOutput sets debug output.
func WithDebugOutput(w io.Writer) ContainerOption {
	if w == nil {
		return nil
	}
	return func(s *pState) {
		s.debugOut = w
	}
}

// PopCompletedMode will pop and stop rendering completed bars.
func PopCompletedMode() ContainerOption {
	return func(s *pState) {
		s.popCompleted = true
	}
}

// ContainerOptional will return provided option only when cond is true.
func ContainerOptional(option ContainerOption, cond bool) ContainerOption {
	if cond {
		return option
	}
	return nil
}

// ContainerOptOn will return provided option only when predicate evaluates to true.
func ContainerOptOn(option ContainerOption, predicate func() bool) ContainerOption {
	if predicate() {
		return option
	}
	return nil
}

// ContainerFuncOptional will call option and return its value only when cond is true.
func ContainerFuncOptional(option func() ContainerOption, cond bool) ContainerOption {
	if cond {
		return option()
	}
	return nil
}

// ContainerFuncOptOn will call option and return its value only when predicate evaluates to true.
func ContainerFuncOptOn(option func() ContainerOption, predicate func() bool) ContainerOption {
	if predicate() {
		return option()
	}
	return nil
}
<|endoftext|>


<commit_before>package multiverse

import (
	"strings"
	"sync"
	"unicode"

	"github.com/CasualSuperman/Diorite/trie"
	"github.com/CasualSuperman/phonetics"
	"github.com/CasualSuperman/sift3"
)

func generatePhoneticsMaps(cards []*Card) trie.Trie {
	metaphoneMap := trie.Alt()

	for i, c := range cards {
		name := preventUnicode(c.Name)
		for _, word := range strings.Split(name, " ") {
			if len(word) < 4 {
				continue
			}
			mtp := phonetics.EncodeMetaphone(word)

			others, ok := metaphoneMap.Get(mtp)
			if ok {
				slice := others.([]int)
				slice = append(slice, i)
				metaphoneMap.Remove(mtp)
				metaphoneMap.Add(mtp, slice)
			} else {
				metaphoneMap.Add(mtp, []int{i})
			}
		}
	}

	return metaphoneMap
}

var phoneticsLock sync.RWMutex
var phoneticsCache = make(map[string]string)

func getMetaphone(s string) string {
	phoneticsLock.RLock()
	if cached, ok := phoneticsCache[s]; ok {
		phoneticsLock.RUnlock()
		return cached
	}
	phoneticsLock.RUnlock()

	m := phonetics.EncodeMetaphone(s)
	phoneticsLock.Lock()
	phoneticsCache[s] = m
	phoneticsLock.Unlock()
	return m
}

var unicodeLock sync.RWMutex
var unicodeCache = make(map[string]string)

func preventUnicode(name string) string {
	unicodeLock.RLock()
	if cached, ok := unicodeCache[name]; ok {
		unicodeLock.RUnlock()
		return cached
	}
	oldName := name
	name = strings.ToLower(name)
	if cached, ok := unicodeCache[name]; ok {
		unicodeLock.RUnlock()
		unicodeLock.Lock()
		unicodeCache[oldName] = cached
		unicodeLock.Unlock()
		return cached
	}

	unicodeLock.RUnlock()

	clean := ""
	for _, r := range name {
		if r > 128 {
			switch r {
			case 'á', 'à', 'â':
				clean += "a"
			case 'é':
				clean += "e"
			case 'í':
				clean += "i"
			case 'ö':
				clean += "o"
			case 'û', 'ú':
				clean += "u"

			case 'Æ', 'æ':
				clean += "ae"

			case '®':
				// We know this is an option but we're explicitly ignoring it.

			default:
			}
		} else {
			if r == ' ' || unicode.IsLetter(r) {
				clean += string(r)
			}
		}
	}

	unicodeLock.Lock()
	unicodeCache[oldName] = clean
	unicodeCache[name] = clean
	unicodeLock.Unlock()

	return clean
}

type fuzzySearchList []struct {
	index      int
	similarity float32
}

func (f *fuzzySearchList) Add(index int, similarity float32) {
	for i, item := range *f {
		if item.index == index {
			if (*f)[i].similarity < similarity {
				(*f)[i].similarity = similarity
			}
			return
		}
	}

	myLen := len(*f)

	if myLen < cap(*f) {
		(*f) = (*f)[:myLen+1]
		myLen++
	}

	for i := myLen - 1; i >= 0; i-- {
		if (*f)[i].similarity < similarity {
			if i < myLen-1 {
				(*f)[i+1] = (*f)[i]
			}
			(*f)[i].index = index
			(*f)[i].similarity = similarity
		} else {
			return
		}
	}
}

// FuzzyNameSearch searches for a card with a similar name to the searchPhrase, and returns count or less of the most likely results.
func (m Multiverse) FuzzyNameSearch(searchPhrase string, count int) []*Card {
	var aggregator = make(fuzzySearchList, 0, count)
	searchPhrase = preventUnicode(searchPhrase)
	searchGrams2 := newNGram(searchPhrase, 2)
	searchGrams3 := newNGram(searchPhrase, 3)

	for _, searchTerm := range strings.Split(searchPhrase, " ") {
		for _, result := range m.Pronunciations.Search(getMetaphone(searchTerm)) {
			for _, cardIndex := range result.([]int) {
				name := preventUnicode(m.Cards.List[cardIndex].Name)

				bestMatch := 0
				for _, word := range strings.Split(name, " ") {
					match := phonetics.DifferenceSoundex(word, searchTerm)
					if match > bestMatch {
						bestMatch = match
					}
				}

				similarity := searchGrams2.Similarity(name)
				similarity += searchGrams3.Similarity(name)
				similarity *= float32(len(name) * bestMatch)
				similarity /= float32(sift3.Sift(searchPhrase, name))

				if strings.Contains(name, searchPhrase) {
					similarity *= 50
				}

				aggregator.Add(cardIndex, similarity)
			}
		}

		for cardIndex, card := range m.Cards.List {
			for _, word := range strings.Split(preventUnicode(card.Name), " ") {
				if sift3.Sift(word, searchTerm) <= len(searchTerm)/3 {

					name := preventUnicode(card.Name)
					similarity := searchGrams2.Similarity(name)
					similarity += searchGrams3.Similarity(name)
					similarity *= float32(len(name)*phonetics.DifferenceSoundex(word, searchTerm)) / 10.0
					similarity /= float32(sift3.Sift(searchPhrase, name))

					aggregator.Add(cardIndex, similarity)
				}
			}
		}
	}

	if len(aggregator) < count {
		count = len(aggregator)
	}

	results := make([]*Card, count)

	for i, card := range aggregator {
		results[i] = m.Cards.List[card.index]
	}

	return results
}
<commit_msg>Now we use the new Split.<commit_after>package multiverse

import (
	"strings"
	"sync"
	"unicode"

	"github.com/CasualSuperman/Diorite/trie"
	"github.com/CasualSuperman/phonetics"
	"github.com/CasualSuperman/sift3"
)

func generatePhoneticsMaps(cards []*Card) trie.Trie {
	metaphoneMap := trie.Alt()

	for i, c := range cards {
		name := preventUnicode(c.Name)
		for _, word := range strings.Split(name, " ") {
			if len(word) < 4 {
				continue
			}
			mtp := phonetics.EncodeMetaphone(word)

			others, ok := metaphoneMap.Get(mtp)
			if ok {
				slice := others.([]int)
				slice = append(slice, i)
				metaphoneMap.Remove(mtp)
				metaphoneMap.Add(mtp, slice)
			} else {
				metaphoneMap.Add(mtp, []int{i})
			}
		}
	}

	return metaphoneMap
}

var phoneticsLock sync.RWMutex
var phoneticsCache = make(map[string]string)

func getMetaphone(s string) string {
	phoneticsLock.RLock()
	if cached, ok := phoneticsCache[s]; ok {
		phoneticsLock.RUnlock()
		return cached
	}
	phoneticsLock.RUnlock()

	m := phonetics.EncodeMetaphone(s)
	phoneticsLock.Lock()
	phoneticsCache[s] = m
	phoneticsLock.Unlock()
	return m
}

var unicodeLock sync.RWMutex
var unicodeCache = make(map[string]string)

func preventUnicode(name string) string {
	unicodeLock.RLock()
	if cached, ok := unicodeCache[name]; ok {
		unicodeLock.RUnlock()
		return cached
	}
	oldName := name
	name = strings.ToLower(name)
	if cached, ok := unicodeCache[name]; ok {
		unicodeLock.RUnlock()
		unicodeLock.Lock()
		unicodeCache[oldName] = cached
		unicodeLock.Unlock()
		return cached
	}

	unicodeLock.RUnlock()

	clean := ""
	for _, r := range name {
		if r > 128 {
			switch r {
			case 'á', 'à', 'â':
				clean += "a"
			case 'é':
				clean += "e"
			case 'í':
				clean += "i"
			case 'ö':
				clean += "o"
			case 'û', 'ú':
				clean += "u"

			case 'Æ', 'æ':
				clean += "ae"

			case '®':
				// We know this is an option but we're explicitly ignoring it.

			default:
			}
		} else {
			if r == ' ' || unicode.IsLetter(r) {
				clean += string(r)
			}
		}
	}

	unicodeLock.Lock()
	unicodeCache[oldName] = clean
	unicodeCache[name] = clean
	unicodeLock.Unlock()

	return clean
}

type fuzzySearchList []struct {
	index      int
	similarity float32
}

func (f *fuzzySearchList) Add(index int, similarity float32) {
	for i, item := range *f {
		if item.index == index {
			if (*f)[i].similarity < similarity {
				(*f)[i].similarity = similarity
			}
			return
		}
	}

	myLen := len(*f)

	if myLen < cap(*f) {
		(*f) = (*f)[:myLen+1]
		myLen++
	}

	for i := myLen - 1; i >= 0; i-- {
		if (*f)[i].similarity < similarity {
			if i < myLen-1 {
				(*f)[i+1] = (*f)[i]
			}
			(*f)[i].index = index
			(*f)[i].similarity = similarity
		} else {
			return
		}
	}
}

// FuzzyNameSearch searches for a card with a similar name to the searchPhrase, and returns count or less of the most likely results.
func (m Multiverse) FuzzyNameSearch(searchPhrase string, count int) []*Card {
	var aggregator = make(fuzzySearchList, 0, count)
	searchPhrase = preventUnicode(searchPhrase)
	searchGrams2 := newNGram(searchPhrase, 2)
	searchGrams3 := newNGram(searchPhrase, 3)

	for _, searchTerm := range Split(searchPhrase) {
		for _, result := range m.Pronunciations.Search(getMetaphone(searchTerm)) {
			for _, cardIndex := range result.([]int) {
				name := preventUnicode(m.Cards.List[cardIndex].Name)

				bestMatch := 0
				for _, word := range Split(name) {
					match := phonetics.DifferenceSoundex(word, searchTerm)
					if match > bestMatch {
						bestMatch = match
					}
				}

				similarity := searchGrams2.Similarity(name)
				similarity += searchGrams3.Similarity(name)
				similarity *= float32(len(name) * bestMatch)
				similarity /= float32(sift3.Sift(searchPhrase, name))

				if strings.Contains(name, searchPhrase) {
					similarity *= 50
				}

				aggregator.Add(cardIndex, similarity)
			}
		}

		for cardIndex, card := range m.Cards.List {
			for _, word := range Split(preventUnicode(card.Name)) {
				if sift3.Sift(word, searchTerm) <= len(searchTerm)/3 {

					name := preventUnicode(card.Name)
					similarity := searchGrams2.Similarity(name)
					similarity += searchGrams3.Similarity(name)
					similarity *= float32(len(name)*phonetics.DifferenceSoundex(word, searchTerm)) / 10.0
					similarity /= float32(sift3.Sift(searchPhrase, name))

					aggregator.Add(cardIndex, similarity)
				}
			}
		}
	}

	if len(aggregator) < count {
		count = len(aggregator)
	}

	results := make([]*Card, count)

	for i, card := range aggregator {
		results[i] = m.Cards.List[card.index]
	}

	return results
}
<|endoftext|>


<commit_before>package experimental_test

import (
	"testing"

	"github.com/cf-deployment/units/helpers"
)

const testDirectory = "operations/experimental"

var experimentalTests = map[string]helpers.OpsFileTestParams{
	"add-credhub-lb.yml":         {},
	"add-deployment-updater.yml": {},
	"add-deployment-updater-external-db.yml": {
		Ops:       []string{"add-deployment-updater.yml", "../use-external-dbs.yml", "add-deployment-updater-external-db.yml"},
		VarsFiles: []string{"../example-vars-files/vars-use-external-dbs.yml"},
	},
	"add-deployment-updater-postgres.yml": {
		Ops: []string{"add-deployment-updater.yml", "../use-postgres.yml", "add-deployment-updater-postgres.yml"},
	},
	"add-syslog-agent.yml": {
		Ops: []string{"deploy-forwarder-agent.yml"},
	},
	"add-syslog-agent-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "deploy-forwarder-agent.yml", "add-syslog-agent.yml", "add-syslog-agent-windows1803.yml"},
	},
	"add-system-metrics-agent.yml": {},
	"add-system-metrics-agent-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "add-system-metrics-agent.yml", "add-system-metrics-agent-windows1803.yml"},
	},
	"deploy-forwarder-agent.yml":               {},
	"disable-interpolate-service-bindings.yml": {},
	"enable-bpm-garden.yml":                    {},
	"enable-iptables-logger.yml":               {},
	"enable-mysql-tls.yml":                     {},
	"enable-nfs-volume-service-credhub.yml":    {},
	"enable-oci-phase-1.yml":                   {},
	"enable-routing-integrity-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "enable-routing-integrity-windows1803.yml"},
	},
	"enable-routing-integrity-windows2016.yml": {
		Ops: []string{"../windows2016-cell.yml", "enable-routing-integrity-windows2016.yml"},
	},
	"enable-smb-volume-service.yml":            {},
	"enable-suspect-actual-lrp-generation.yml": {},
	"enable-tls-cloud-controller-postgres.yml": {
		Ops: []string{"../use-postgres.yml", "enable-tls-cloud-controller-postgres.yml"},
	},
	"enable-traffic-to-internal-networks.yml":  {},
	"fast-deploy-with-downtime-and-danger.yml": {},
	"infrastructure-metrics.yml":               {},
	"migrate-nfsbroker-mysql-to-credhub.yml": {
		Ops:       []string{"../enable-nfs-volume-service.yml", "migrate-nfsbroker-mysql-to-credhub.yml"},
		VarsFiles: []string{"../example-vars-files/vars-migrate-nfsbroker-mysql-to-credhub.yml"},
	},
	"perm-service.yml": {
		Ops:  []string{"enable-mysql-tls.yml", "perm-service.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"perm-service-with-pxc-release.yml": {
		Ops:  []string{"perm-service.yml", "../use-pxc.yml", "perm-service-with-pxc-release.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"perm-service-with-tcp-routing.yml": {
		Ops:  []string{"perm-service.yml", "../use-pxc.yml", "perm-service-with-pxc-release.yml", "perm-service-with-tcp-routing.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"rootless-containers.yml": {},
	"set-cpu-weight.yml":      {},
	"use-compiled-releases-windows.yml": {
		Ops: []string{"../use-compiled-releases.yml", "../windows2012R2-cell.yml", "use-compiled-releases-windows.yml"},
	},
	"use-create-swap-delete-vm-strategy.yml":          {},
	"use-logcache-for-cloud-controller-app-stats.yml": {},
	"use-native-garden-runc-runner.yml":               {},
	"windows-component-syslog-ca.yml": {
		Ops:       []string{"windows-enable-component-syslog.yml", "windows-component-syslog-ca.yml"},
		VarsFiles: []string{"../addons/example-vars-files/vars-enable-component-syslog.yml"},
	},
	"windows-enable-component-syslog.yml": {
		Ops:       []string{"windows-enable-component-syslog.yml"},
		VarsFiles: []string{"../addons/example-vars-files/vars-enable-component-syslog.yml"},
	},
}

func TestExperimental(t *testing.T) {
	cfDeploymentHome, err := helpers.SetPath()
	if err != nil {
		t.Fatalf("setup: %v", err)
	}

	suite := helpers.NewSuiteTest(cfDeploymentHome, testDirectory, experimentalTests)
	suite.EnsureTestCoverage(t)
	suite.ReadmeTest(t)
	suite.InterpolateTest(t)
}
<commit_msg>Add metric store golang test<commit_after>package experimental_test

import (
	"testing"

	"github.com/cf-deployment/units/helpers"
)

const testDirectory = "operations/experimental"

var experimentalTests = map[string]helpers.OpsFileTestParams{
	"add-credhub-lb.yml":         {},
	"add-deployment-updater.yml": {},
	"add-deployment-updater-external-db.yml": {
		Ops:       []string{"add-deployment-updater.yml", "../use-external-dbs.yml", "add-deployment-updater-external-db.yml"},
		VarsFiles: []string{"../example-vars-files/vars-use-external-dbs.yml"},
	},
	"add-deployment-updater-postgres.yml": {
		Ops: []string{"add-deployment-updater.yml", "../use-postgres.yml", "add-deployment-updater-postgres.yml"},
	},
	"add-metric-store.yml": {},
	"add-syslog-agent.yml": {
		Ops: []string{"deploy-forwarder-agent.yml"},
	},
	"add-syslog-agent-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "deploy-forwarder-agent.yml", "add-syslog-agent.yml", "add-syslog-agent-windows1803.yml"},
	},
	"add-system-metrics-agent.yml": {},
	"add-system-metrics-agent-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "add-system-metrics-agent.yml", "add-system-metrics-agent-windows1803.yml"},
	},
	"deploy-forwarder-agent.yml":               {},
	"disable-interpolate-service-bindings.yml": {},
	"enable-bpm-garden.yml":                    {},
	"enable-iptables-logger.yml":               {},
	"enable-mysql-tls.yml":                     {},
	"enable-nfs-volume-service-credhub.yml":    {},
	"enable-oci-phase-1.yml":                   {},
	"enable-routing-integrity-windows1803.yml": {
		Ops: []string{"../windows1803-cell.yml", "enable-routing-integrity-windows1803.yml"},
	},
	"enable-routing-integrity-windows2016.yml": {
		Ops: []string{"../windows2016-cell.yml", "enable-routing-integrity-windows2016.yml"},
	},
	"enable-smb-volume-service.yml":            {},
	"enable-suspect-actual-lrp-generation.yml": {},
	"enable-tls-cloud-controller-postgres.yml": {
		Ops: []string{"../use-postgres.yml", "enable-tls-cloud-controller-postgres.yml"},
	},
	"enable-traffic-to-internal-networks.yml":  {},
	"fast-deploy-with-downtime-and-danger.yml": {},
	"infrastructure-metrics.yml":               {},
	"migrate-nfsbroker-mysql-to-credhub.yml": {
		Ops:       []string{"../enable-nfs-volume-service.yml", "migrate-nfsbroker-mysql-to-credhub.yml"},
		VarsFiles: []string{"../example-vars-files/vars-migrate-nfsbroker-mysql-to-credhub.yml"},
	},
	"perm-service.yml": {
		Ops:  []string{"enable-mysql-tls.yml", "perm-service.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"perm-service-with-pxc-release.yml": {
		Ops:  []string{"perm-service.yml", "../use-pxc.yml", "perm-service-with-pxc-release.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"perm-service-with-tcp-routing.yml": {
		Ops:  []string{"perm-service.yml", "../use-pxc.yml", "perm-service-with-pxc-release.yml", "perm-service-with-tcp-routing.yml"},
		Vars: []string{"perm_uaa_clients_cc_perm_secret=perm_secret", "perm_uaa_clients_perm_monitor_secret=perm_monitor_secret"},
	},
	"rootless-containers.yml": {},
	"set-cpu-weight.yml":      {},
	"use-compiled-releases-windows.yml": {
		Ops: []string{"../use-compiled-releases.yml", "../windows2012R2-cell.yml", "use-compiled-releases-windows.yml"},
	},
	"use-create-swap-delete-vm-strategy.yml":          {},
	"use-logcache-for-cloud-controller-app-stats.yml": {},
	"use-native-garden-runc-runner.yml":               {},
	"windows-component-syslog-ca.yml": {
		Ops:       []string{"windows-enable-component-syslog.yml", "windows-component-syslog-ca.yml"},
		VarsFiles: []string{"../addons/example-vars-files/vars-enable-component-syslog.yml"},
	},
	"windows-enable-component-syslog.yml": {
		Ops:       []string{"windows-enable-component-syslog.yml"},
		VarsFiles: []string{"../addons/example-vars-files/vars-enable-component-syslog.yml"},
	},
}

func TestExperimental(t *testing.T) {
	cfDeploymentHome, err := helpers.SetPath()
	if err != nil {
		t.Fatalf("setup: %v", err)
	}

	suite := helpers.NewSuiteTest(cfDeploymentHome, testDirectory, experimentalTests)
	suite.EnsureTestCoverage(t)
	suite.ReadmeTest(t)
	suite.InterpolateTest(t)
}
<|endoftext|>


<commit_before>package network

import (
	"github.com/yaricom/goNEAT/neat/genetics"
	"fmt"
	"errors"
)

// A NETWORK is a LIST of input NODEs and a LIST of output NODEs.
// The point of the network is to define a single entity which can evolve
// or learn on its own, even though it may be part of a larger framework.
type Network interface {
	// Puts the network back into an initial state
	Flush()
	// Activates the net such that all outputs are active
	Activate() (bool, error)
	// If at least one output is not active then return true
	OutputIsOff() bool

	// Prints the values of network outputs to the console
	PrintActivation()
	// Print the values of network inputs to the console
	PrintInput()
	// Verify that network was successfully flushed for debugging
	FlushCheck() error

	// Adds a new input node
	AddInputNode(node *NNode)
	// Adds a new output node
	AddOutputNode(node *NNode)

	// Takes an array of sensor values and loads it into SENSOR inputs ONLY
	LoadSensors(sensors []float64)
	// Set network name
	SetName(name string)

	// This checks a POTENTIAL link between a potential in_node
     	// and potential out_node to see if it must be recurrent.
	// Use count and thresh to jump out in the case of an infinite loop.
	IsRecurrent(potin_node, potout_node *NNode, count *int32, thresh int32) bool
	// Find the maximum number of neurons between an output and an input
	MaxDepth() (int32, error)

	// Counts the number of nodes in the net
	NodeCount() int
	// Counts the number of links in the net
	LinkCount() int
}

// Creates new network
func NewNetwork(in, out, all []*NNode, netid int32) Network {
	n := newNetwork(netid)
	n.inputs = in
	n.outputs = out
	n.all_nodes = all
	return &n
}

// The default private constructor
func newNetwork(netId int32) network {
	return network {
		numlinks:-1,
		net_id:netId,
	}
}

// The private network data holder
type network struct {
	//The number of links in the net (-1 means not yet counted)
	numlinks int

	// A list of all the nodes in the network
	all_nodes []*NNode
	// NNodes that input into the network
	inputs []*NNode
	// NNodes that output from the network
	outputs []*NNode

	// A network id
	net_id int32

	// Allows Network to be matched with its Genome
	genotype *genetics.Genome

	// Is a name of this network */
	name string
}

// The Network interface implementation
func (n *network) Flush() {
	// Flush back recursively
	for _, node := range n.all_nodes {
		node.Flushback()
	}
}
func (n *network) FlushCheck() error {
	for _, node := range n.all_nodes {
		err := node.FlushbackCheck()
		if err != nil {
			return err
		}
	}
	return nil
}
func (n *network) PrintActivation() {
	fmt.Printf("Network %s with id %d outputs: (", n.name, n.net_id)
	for i, node := range n.outputs {
		fmt.Printf("[Output #%d: %s] ", i, node)
	}
	fmt.Println(")")
}
func (n *network) PrintInput() {
	fmt.Printf("Network %s with id %d inputs: (", n.name, n.net_id)
	for i, node := range n.inputs {
		fmt.Printf("[Input #%d: %s] ", i, node)
	}
	fmt.Println(")")
}
func (n *network) OutputIsOff() bool {
	for _, node := range n.outputs {
		if node.ActivationsCount == 0 {
			return true
		}
	}
	return false
}
func (n *network) Activate() (bool, error) {
	//For adding to the activesum
	add_amount := 0.0
	//Make sure we at least activate once
	one_time := false
	//Used in case the output is somehow truncated from the network
	abort_count := 0

	// The sigmoid activator function
	sigmoid := ActivationFunc(SigmoidActivation)

	// Keep activating until all the outputs have become active
	// (This only happens on the first activation, because after that they are always active)
	for n.OutputIsOff() && !one_time {
		abort_count += 1

		if abort_count >= 20 {
			return false, errors.New("Inputs disconnected from outputa!")
		}

		// For each neuron node, compute the sum of its incoming activation
		for _, node := range n.all_nodes {
			if node.IsNeuron() {
				node.ActivationSum = 0.0 // reset activation value
				node.IsActive = false // flag node disabled

				// For each node's incoming connection, add the activity from the connection to the activesum
				for _, link := range node.Incoming {
					// Handle possible time delays
					if !link.IsTimeDelayed {
						add_amount = link.Weight * link.InNode.GetActiveOut()
						if link.InNode.IsActive && link.InNode.IsSensor() {
							link.InNode.IsActive = true
						}
					} else {
						add_amount = link.Weight * link.InNode.GetActiveOutTd()
					}
					node.ActivationSum += add_amount
				} // End {for} over incoming links
			} // End if != SENSOR
		}  // End {for} over all nodes

		// Now activate all the neuron nodes off their incoming activation
		for _, node := range n.all_nodes {
			if node.IsNeuron() {
				// Only activate if some active input came in
				if node.IsActive {
					// Keep a memory of activations for potential time delayed connections
					node.saveActivations()
					// Now run the net activation through an activation function
					if node.FType == SIGMOID {
						node.Activation = sigmoid.Activation(node, 4.924273, 2.4621365)
					} else {
						return false, errors.New(
							fmt.Sprintf("Unknown activation function type: %d", node.FType))
					}
					// Increment the activation_count
					// First activation cannot be from nothing!!
					node.ActivationsCount++
				}
			}
		}
		one_time = true
	}
	return true, nil
}
func (n *network) AddInputNode(node *NNode) {
	n.inputs = append(n.inputs, node)
}
func (n *network) AddOutputNode(node *NNode) {
	n.outputs = append(n.outputs, node)
}
func (n *network) LoadSensors(sensors []float64) {
	counter := 0
	for _, node := range n.inputs{
		if node.IsSensor() {
			node.SensorLoad(sensors[counter])
			counter += 1
		}
	}
}
func (n *network) SetName(name string) {
	n.name = name
}
func (n network) NodeCount() int {
	return len(n.all_nodes)
}
func (n network) LinkCount() int {
	n.numlinks = 0
	for _, node := range n.all_nodes {
		n.numlinks += len(node.Incoming)
	}
	return n.numlinks
}

func (n *network) IsRecurrent(potin_node, potout_node *NNode, count *int32, thresh int32) bool {
	// Count the node as visited
	*count++

	if *count > thresh {
		return false // Short out the whole thing - loop detected
	}

	if potin_node == potout_node {
		return true
	} else {
		// Check back on all links ...
		for _, link := range potin_node.Incoming {
			// But skip links that are already recurrent -
			// We want to check back through the forward flow of signals only
			if link.IsRecurrent != true {
				if n.IsRecurrent(link.InNode, potout_node, count, thresh) {
					return true
				}
			}
		}
	}
	return false
}

func (n *network) MaxDepth() (int32, error) {
	max := int32(0) // The max depth
	for _, node := range n.outputs {
		curr_depth, err := node.Depth(0)
		if err != nil {
			return curr_depth, err
		}
		if curr_depth > max {
			max = curr_depth
		}
	}
	return max, nil
}
<commit_msg>Fixed names, bug fixes in conditions, introduced AllNodes<commit_after>package network

import (
	"github.com/yaricom/goNEAT/neat/genetics"
	"fmt"
	"errors"
)

// A NETWORK is a LIST of input NODEs and a LIST of output NODEs.
// The point of the network is to define a single entity which can evolve
// or learn on its own, even though it may be part of a larger framework.
type Network interface {
	// Puts the network back into an initial state
	Flush()
	// Activates the net such that all outputs are active
	Activate() (bool, error)
	// If at least one output is not active then return true
	OutputIsOff() bool

	// Prints the values of network outputs to the console
	PrintActivation()
	// Print the values of network inputs to the console
	PrintInput()
	// Verify that network was successfully flushed for debugging
	FlushCheck() error

	// Adds a new input node
	AddInputNode(node *NNode)
	// Adds a new output node
	AddOutputNode(node *NNode)

	// Takes an array of sensor values and loads it into SENSOR inputs ONLY
	LoadSensors(sensors []float64)
	// Set network name
	SetName(name string)

	// This checks a POTENTIAL link between a potential in_node
     	// and potential out_node to see if it must be recurrent.
	// Use count and thresh to jump out in the case of an infinite loop.
	IsRecurrent(potin_node, potout_node *NNode, count *int, thresh int) bool
	// Find the maximum number of neurons between an output and an input
	MaxDepth() (int32, error)

	// Counts the number of nodes in the net
	NodeCount() int
	// Counts the number of links in the net
	LinkCount() int

	// Returns all nodes in the network
	AllNodes() []*NNode
}

// Creates new network
func NewNetwork(in, out, all []*NNode, netid int32) Network {
	n := newNetwork(netid)
	n.inputs = in
	n.outputs = out
	n.all_nodes = all
	return &n
}

// The default private constructor
func newNetwork(netId int32) network {
	return network {
		numlinks:-1,
		net_id:netId,
	}
}

// The private network data holder
type network struct {
	//The number of links in the net (-1 means not yet counted)
	numlinks int

	// A list of all the nodes in the network
	all_nodes []*NNode
	// NNodes that input into the network
	inputs []*NNode
	// NNodes that output from the network
	outputs []*NNode

	// A network id
	net_id int32

	// Allows Network to be matched with its Genome
	genotype *genetics.Genome

	// Is a name of this network */
	name string
}

// The Network interface implementation
func (n *network) Flush() {
	// Flush back recursively
	for _, node := range n.all_nodes {
		node.Flushback()
	}
}
func (n *network) FlushCheck() error {
	for _, node := range n.all_nodes {
		err := node.FlushbackCheck()
		if err != nil {
			return err
		}
	}
	return nil
}
func (n *network) PrintActivation() {
	fmt.Printf("Network %s with id %d outputs: (", n.name, n.net_id)
	for i, node := range n.outputs {
		fmt.Printf("[Output #%d: %s] ", i, node)
	}
	fmt.Println(")")
}
func (n *network) PrintInput() {
	fmt.Printf("Network %s with id %d inputs: (", n.name, n.net_id)
	for i, node := range n.inputs {
		fmt.Printf("[Input #%d: %s] ", i, node)
	}
	fmt.Println(")")
}
func (n *network) OutputIsOff() bool {
	for _, node := range n.outputs {
		if node.ActivationsCount == 0 {
			return true
		}
	}
	return false
}
func (n *network) Activate() (bool, error) {
	//For adding to the activesum
	add_amount := 0.0
	//Make sure we at least activate once
	one_time := false
	//Used in case the output is somehow truncated from the network
	abort_count := 0

	// The sigmoid activator function
	sigmoid := ActivationFunc(SigmoidActivation)

	// Keep activating until all the outputs have become active
	// (This only happens on the first activation, because after that they are always active)
	for n.OutputIsOff() || !one_time {
		abort_count += 1

		if abort_count >= 20 {
			return false, errors.New("Inputs disconnected from outputs!")
		}

		// For each neuron node, compute the sum of its incoming activation
		for _, np := range n.all_nodes {
			if np.IsNeuron() {
				np.ActivationSum = 0.0 // reset activation value
				np.IsActive = false // flag node disabled

				// For each node's incoming connection, add the activity from the connection to the activesum
				for _, link := range np.Incoming {
					// Handle possible time delays
					if !link.IsTimeDelayed {
						add_amount = link.Weight * link.InNode.GetActiveOut()
						//fmt.Printf("%f -> %f\n", link.Weight, (*link.InNode).GetActiveOut())
						if link.InNode.IsActive || link.InNode.IsSensor() {
							np.IsActive = true
						}
					} else {
						add_amount = link.Weight * link.InNode.GetActiveOutTd()
					}
					np.ActivationSum += add_amount
				} // End {for} over incoming links
			} // End if != SENSOR
		}  // End {for} over all nodes

		// Now activate all the neuron nodes off their incoming activation
		for _, np := range n.all_nodes {
			if np.IsNeuron() {
				// Only activate if some active input came in
				if np.IsActive {
					// Keep a memory of activations for potential time delayed connections
					np.saveActivations()
					// Now run the net activation through an activation function
					if np.FType == SIGMOID {
						np.Activation = sigmoid.Activation(np, 4.924273, 2.4621365)
					} else {
						return false, errors.New(
							fmt.Sprintf("Unknown activation function type: %d", np.FType))
					}
					// Increment the activation_count
					// First activation cannot be from nothing!!
					np.ActivationsCount++
				}
				//fmt.Printf("Node: %s, activation sum: %f, active: %t\n", np, np.ActivationSum, np.IsActive)
			}
		}
		one_time = true
	}
	return true, nil
}
func (n *network) AddInputNode(node *NNode) {
	n.inputs = append(n.inputs, node)
}
func (n *network) AddOutputNode(node *NNode) {
	n.outputs = append(n.outputs, node)
}
func (n *network) LoadSensors(sensors []float64) {
	counter := 0
	for _, node := range n.inputs {
		if node.IsSensor() {
			node.SensorLoad(sensors[counter])
			counter += 1
		}
	}
}
func (n *network) SetName(name string) {
	n.name = name
}
func (n network) NodeCount() int {
	return len(n.all_nodes)
}
func (n network) LinkCount() int {
	n.numlinks = 0
	for _, node := range n.all_nodes {
		n.numlinks += len(node.Incoming)
	}
	return n.numlinks
}

func (n *network) IsRecurrent(in_node, out_node *NNode, count *int, thresh int) bool {
	// Count the node as visited
	*count++

	if *count > thresh {
		return false // Short out the whole thing - loop detected
	}

	if in_node == out_node {
		return true
	} else {
		// Check back on all links ...
		for _, link := range in_node.Incoming {
			// But skip links that are already recurrent -
			// We want to check back through the forward flow of signals only
			if link.IsRecurrent != true {
				if n.IsRecurrent(link.InNode, out_node, count, thresh) {
					return true
				}
			}
		}
	}
	return false
}

func (n *network) MaxDepth() (int32, error) {
	max := int32(0) // The max depth
	for _, node := range n.outputs {
		curr_depth, err := node.Depth(0)
		if err != nil {
			return curr_depth, err
		}
		if curr_depth > max {
			max = curr_depth
		}
	}
	return max, nil
}

func (n *network) AllNodes() []*NNode {
	return n.all_nodes
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"github.com/gin-gonic/gin"

	e "github.com/techjanitor/pram-get/errors"
	"github.com/techjanitor/pram-get/models"
	u "github.com/techjanitor/pram-get/utils"
)

// UserType is the top level of the JSON response
type UserType struct {
	User u.User `json:"user"`
}

// UserController gets account info
func UserController(c *gin.Context) {

	// get userdata from session middleware
	userdata := c.MustGet("userdata").(u.User)

	// Initialize response header
	response := UserType{}

	// seet userdata from auth middleware
	response.User = userdata

	// Marshal the structs into JSON
	output, err := json.Marshal(response)
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Hand off data to cache middleware
	c.Set("data", output)

	c.Writer.Header().Set("Content-Type", "application/json")
	c.Writer.Write(output)

	return

}
<commit_msg>get userdata from auth middleware<commit_after>package controllers

import (
	"encoding/json"
	"github.com/gin-gonic/gin"

	e "github.com/techjanitor/pram-get/errors"
	u "github.com/techjanitor/pram-get/utils"
)

// UserType is the top level of the JSON response
type UserType struct {
	User u.User `json:"user"`
}

// UserController gets account info
func UserController(c *gin.Context) {

	// get userdata from session middleware
	userdata := c.MustGet("userdata").(u.User)

	// Initialize response header
	response := UserType{}

	// seet userdata from auth middleware
	response.User = userdata

	// Marshal the structs into JSON
	output, err := json.Marshal(response)
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Hand off data to cache middleware
	c.Set("data", output)

	c.Writer.Header().Set("Content-Type", "application/json")
	c.Writer.Write(output)

	return

}
<|endoftext|>


<commit_before>// +build coprocess
// +build python

package main

/*
#cgo pkg-config: python3

#include <Python.h>

#include <stdio.h>
#include <stdlib.h>

#include "coprocess/sds/sds.h"

#include "coprocess/api.h"

#include "coprocess/python/binding.h"
#include "coprocess/python/dispatcher.h"

static int Python_Init() {
  CoProcess_Log( sdsnew("Initializing interpreter, Py_Initialize()"), "info");
  Py_Initialize();

	char *k = "key";
	char *v = "value";
	int ttl = 100;

	TykStoreData(k,v,ttl);

  return Py_IsInitialized();
}

static int Python_LoadDispatcher() {
  PyObject *module_name = PyUnicode_FromString( dispatcher_module_name );
  dispatcher_module = PyImport_Import( module_name );

  if( dispatcher_module == NULL ) {
    PyErr_Print();
    return -1;
  }

  dispatcher_module_dict = PyModule_GetDict(dispatcher_module);

  if( dispatcher_module_dict == NULL ) {
    PyErr_Print();
    return -1;
  }

  dispatcher_class = PyDict_GetItemString(dispatcher_module_dict, dispatcher_class_name);

  if( dispatcher_class == NULL ) {
    PyErr_Print();
    return -1;
  }

  return 0;
}

static int Python_NewDispatcher(char* middleware_path) {
  if( PyCallable_Check(dispatcher_class) ) {
    dispatcher_args = PyTuple_Pack( 1, PyUnicode_FromString(middleware_path) );
    dispatcher = PyObject_CallObject( dispatcher_class, dispatcher_args );
    if( dispatcher == NULL) {
      PyErr_Print();
      return -1;
    }
  } else {
    PyErr_Print();
    return -1;
  }

  dispatcher_hook_name = PyUnicode_FromString( hook_name );
  dispatcher_hook = PyObject_GetAttr(dispatcher, dispatcher_hook_name);

  if( dispatcher_hook == NULL ) {
    PyErr_Print();
    return -1;
  }

  return 0;
}

static void Python_SetEnv(char* python_path) {
  CoProcess_Log( sdscatprintf(sdsempty(), "Setting PYTHONPATH to '%s'", python_path), "info");
  setenv("PYTHONPATH", python_path, 1 );
}

static char* Python_DispatchHook(char *object_json) {
  if( object_json == NULL ) {
    return NULL;
  } else {
    PyObject *args = PyTuple_Pack( 1, PyUnicode_FromString(object_json) );
    PyObject *result = PyObject_CallObject( dispatcher_hook, args );
    if( result == NULL ) {
      PyErr_Print();
      return NULL;
    } else {
      char *payload = PyUnicode_AsUTF8(result);
      return payload;
    }
  }
}
*/
import "C"

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"strings"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

const CoProcessName string = "python"

type PythonDispatcher struct {
	CoProcessDispatcher
}

func (d *PythonDispatcher) DispatchHook(objectJson []byte) CoProcessObject {
	log.WithFields(logrus.Fields{
		"prefix": "coprocess",
	}).Info("PythonDispatcher.DispatchHook")

	var CObjectStr *C.char
	CObjectStr = C.CString(string(objectJson))

	var CNewObjectStr *C.char
	CNewObjectStr = C.Python_DispatchHook(CObjectStr)

	var newObjectStr string
	newObjectStr = C.GoString(CNewObjectStr)

	var newObject CoProcessObject
	json.Unmarshal([]byte(newObjectStr), &newObject)

	return newObject

}

func PythonInit() (err error) {
	result := C.Python_Init()
	if result == 0 {
		err = errors.New("Can't Py_Initialize()")
	}
	return err
}

func PythonLoadDispatcher() (err error) {
	result := C.Python_LoadDispatcher()
	if result == -1 {
		err = errors.New("Can't load dispatcher")
	}
	return err
}

func PythonNewDispatcher(middlewarePath string) (err error, dispatcher CoProcessDispatcher) {
	var CMiddlewarePath *C.char
	CMiddlewarePath = C.CString(middlewarePath)

	result := C.Python_NewDispatcher(CMiddlewarePath)
	if result == -1 {
		err = errors.New("Can't initialize a dispatcher")
	} else {
		dispatcher = &PythonDispatcher{}
	}

	C.free(unsafe.Pointer(CMiddlewarePath))

	return err, dispatcher
}

func PythonSetEnv(pythonPaths ...string) {
	var CPythonPath *C.char
	CPythonPath = C.CString(strings.Join(pythonPaths, ":"))
	C.Python_SetEnv(CPythonPath)

	C.free(unsafe.Pointer(CPythonPath))
}

func CoProcessInit() (err error) {

	workDir, _ := os.Getwd()

	dispatcherPath := path.Join(workDir, "coprocess/python")
	middlewarePath := path.Join(workDir, "middleware/python")

	PythonSetEnv(dispatcherPath, middlewarePath)

	PythonInit()
	PythonLoadDispatcher()
	err, GlobalDispatcher = PythonNewDispatcher(middlewarePath)

	if err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "coprocess",
		}).Error(err)
	}

	return err
}
<commit_msg>Load Cython interface on Python_Init()<commit_after>// +build coprocess
// +build python

package main

/*
#cgo pkg-config: python3

#include <Python.h>

#include <stdio.h>
#include <stdlib.h>

#include "coprocess/sds/sds.h"

#include "coprocess/api.h"

#include "coprocess/python/binding.h"
#include "coprocess/python/dispatcher.h"

#include "coprocess/python/tyk/gateway.h"

static int Python_Init() {
  CoProcess_Log( sdsnew("Initializing interpreter, Py_Initialize()"), "info");
  Py_Initialize();

	// This exposes the Cython interface as "gateway"
	PyInit_gateway();

  return Py_IsInitialized();
}

static int Python_LoadDispatcher() {
  PyObject *module_name = PyUnicode_FromString( dispatcher_module_name );
  dispatcher_module = PyImport_Import( module_name );

  if( dispatcher_module == NULL ) {
    PyErr_Print();
    return -1;
  }

  dispatcher_module_dict = PyModule_GetDict(dispatcher_module);

  if( dispatcher_module_dict == NULL ) {
    PyErr_Print();
    return -1;
  }

  dispatcher_class = PyDict_GetItemString(dispatcher_module_dict, dispatcher_class_name);

  if( dispatcher_class == NULL ) {
    PyErr_Print();
    return -1;
  }

  return 0;
}

static int Python_NewDispatcher(char* middleware_path) {
  if( PyCallable_Check(dispatcher_class) ) {
    dispatcher_args = PyTuple_Pack( 1, PyUnicode_FromString(middleware_path) );
    dispatcher = PyObject_CallObject( dispatcher_class, dispatcher_args );
    if( dispatcher == NULL) {
      PyErr_Print();
      return -1;
    }
  } else {
    PyErr_Print();
    return -1;
  }

  dispatcher_hook_name = PyUnicode_FromString( hook_name );
  dispatcher_hook = PyObject_GetAttr(dispatcher, dispatcher_hook_name);

  if( dispatcher_hook == NULL ) {
    PyErr_Print();
    return -1;
  }

  return 0;
}

static void Python_SetEnv(char* python_path) {
  CoProcess_Log( sdscatprintf(sdsempty(), "Setting PYTHONPATH to '%s'", python_path), "info");
  setenv("PYTHONPATH", python_path, 1 );
}

static char* Python_DispatchHook(char *object_json) {
  if( object_json == NULL ) {
    return NULL;
  } else {
    PyObject *args = PyTuple_Pack( 1, PyUnicode_FromString(object_json) );
    PyObject *result = PyObject_CallObject( dispatcher_hook, args );
    if( result == NULL ) {
      PyErr_Print();
      return NULL;
    } else {
      char *payload = PyUnicode_AsUTF8(result);
      return payload;
    }
  }
}
*/
import "C"

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"strings"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

const CoProcessName string = "python"

type PythonDispatcher struct {
	CoProcessDispatcher
}

func (d *PythonDispatcher) DispatchHook(objectJson []byte) CoProcessObject {
	log.WithFields(logrus.Fields{
		"prefix": "coprocess",
	}).Info("PythonDispatcher.DispatchHook")

	var CObjectStr *C.char
	CObjectStr = C.CString(string(objectJson))

	var CNewObjectStr *C.char
	CNewObjectStr = C.Python_DispatchHook(CObjectStr)

	var newObjectStr string
	newObjectStr = C.GoString(CNewObjectStr)

	var newObject CoProcessObject
	json.Unmarshal([]byte(newObjectStr), &newObject)

	return newObject

}

func PythonInit() (err error) {
	result := C.Python_Init()
	if result == 0 {
		err = errors.New("Can't Py_Initialize()")
	}
	return err
}

func PythonLoadDispatcher() (err error) {
	result := C.Python_LoadDispatcher()
	if result == -1 {
		err = errors.New("Can't load dispatcher")
	}
	return err
}

func PythonNewDispatcher(middlewarePath string) (err error, dispatcher CoProcessDispatcher) {
	var CMiddlewarePath *C.char
	CMiddlewarePath = C.CString(middlewarePath)

	result := C.Python_NewDispatcher(CMiddlewarePath)
	if result == -1 {
		err = errors.New("Can't initialize a dispatcher")
	} else {
		dispatcher = &PythonDispatcher{}
	}

	C.free(unsafe.Pointer(CMiddlewarePath))

	return err, dispatcher
}

func PythonSetEnv(pythonPaths ...string) {
	var CPythonPath *C.char
	CPythonPath = C.CString(strings.Join(pythonPaths, ":"))
	C.Python_SetEnv(CPythonPath)

	C.free(unsafe.Pointer(CPythonPath))
}

func CoProcessInit() (err error) {

	workDir, _ := os.Getwd()

	dispatcherPath := path.Join(workDir, "coprocess/python")
	middlewarePath := path.Join(workDir, "middleware/python")

	PythonSetEnv(dispatcherPath, middlewarePath)

	PythonInit()
	PythonLoadDispatcher()
	err, GlobalDispatcher = PythonNewDispatcher(middlewarePath)

	if err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "coprocess",
		}).Error(err)
	}

	return err
}
<|endoftext|>


<commit_before>// Copyright 2019 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package core

import (
	"reflect"
	"testing"

	"github.com/issue9/assert"
)

func TestColumn_IsZero(t *testing.T) {
	a := assert.New(t)

	col, err := NewColumnFromGoType(IntType)
	a.NotError(err).NotNil(col)
	a.True(col.IsZero(reflect.ValueOf(int(0))))
	a.False(col.IsZero(reflect.ValueOf(1)))

	col, err = NewColumnFromGoType(reflect.TypeOf([]byte{}))
	a.NotError(err).NotNil(col)
	a.True(col.IsZero(reflect.ValueOf([]byte{})))
	a.True(col.IsZero(reflect.ValueOf([]byte(""))))
	a.False(col.IsZero(reflect.ValueOf([]byte{'0'})))

	col, err = NewColumnFromGoType(RawBytesType)
	a.NotError(err).NotNil(col)
	a.True(col.IsZero(reflect.ValueOf([]byte{})))
	a.True(col.IsZero(reflect.ValueOf([]byte(""))))
	a.False(col.IsZero(reflect.ValueOf([]byte{'0'})))
	a.False(col.IsZero(reflect.ValueOf(1)))

	col, err = NewColumnFromGoType(reflect.TypeOf(func() {}))
	a.ErrorType(err, ErrInvalidColumnType).Nil(col)
}

func TestColumn_Clone(t *testing.T) {
	a := assert.New(t)

	col, err := NewColumnFromGoType(IntType)
	a.NotError(err).NotNil(col)
	col.Nullable = true

	cc := col.Clone()
	a.Equal(cc, col)  // 值相同
	a.True(cc != col) // 但不是同一个实例
}

func TestColumn_Check(t *testing.T) {
	a := assert.New(t)

	col, err := NewColumnFromGoType(StringType)
	a.NotError(err).NotNil(col)
	col.Length = []int{-1}

	a.NotError(col.Check())

	col.Length[0] = 0
	a.Error(col.Check())

	col.Length[0] = -2
	a.Error(col.Check())

	col, err = NewColumnFromGoType(IntType)
	a.NotError(err).NotNil(col)
	col.Length = []int{-2}
	a.Error(col.Check())

	col.Length[0] = -1
	a.Error(col.Check())

	col.Length[0] = 0
	a.NotError(col.Check())

	col.AI = true
	col.HasDefault = true
	a.Error(col.Check())

	col.AI = true
	col.HasDefault = false
	col.Nullable = true
	a.Error(col.Check())
}
<commit_msg>test: 修正测试错误<commit_after>// Copyright 2019 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package core

import (
	"testing"

	"github.com/issue9/assert"
)

func TestColumn_Clone(t *testing.T) {
	a := assert.New(t)

	col, err := NewColumnFromGoType(IntType)
	a.NotError(err).NotNil(col)
	col.Nullable = true

	cc := col.Clone()
	a.Equal(cc, col)  // 值相同
	a.True(cc != col) // 但不是同一个实例
}

func TestColumn_Check(t *testing.T) {
	a := assert.New(t)

	col, err := NewColumnFromGoType(StringType)
	a.NotError(err).NotNil(col)
	col.Length = []int{-1}

	a.NotError(col.Check())

	col.Length[0] = 0
	a.Error(col.Check())

	col.Length[0] = -2
	a.Error(col.Check())

	col, err = NewColumnFromGoType(IntType)
	a.NotError(err).NotNil(col)
	col.Length = []int{-2}
	a.Error(col.Check())

	col.Length[0] = -1
	a.Error(col.Check())

	col.Length[0] = 0
	a.NotError(col.Check())

	col.AI = true
	col.HasDefault = true
	a.Error(col.Check())

	col.AI = true
	col.HasDefault = false
	col.Nullable = true
	a.Error(col.Check())
}
<|endoftext|>


<commit_before>package tuple

import (
	"errors"
	"fmt"
	"github.com/ugorji/go/codec"
	"math"
	"reflect"
	"time"
)

// Value is the generic interface for all data that can be stored
// inside a Tuple. Since we assume the data not to conform to any
// schema, data can have any shape and it can also change within a
// stream from one Tuple to the next. Therefore we need to be
// careful with respect to type conversions. A Value obtained, e.g.,
// by Map.Get should always be converted using the appropriate method
// and error checking must be done.
//
// Example:
//  i, err := val.AsInt()
//  if err != nil { ... }
type Value interface {
	Type() TypeID
	AsBool() (bool, error)
	AsInt() (int64, error)
	AsFloat() (float64, error)
	AsString() (string, error)
	AsBlob() ([]byte, error)
	AsTimestamp() (time.Time, error)
	AsArray() (Array, error)
	AsMap() (Map, error)
	clone() Value
}

func castError(from TypeID, to TypeID) error {
	return errors.New(fmt.Sprintf("unsupported cast %v from %v", to.String(), from.String()))
}

type TypeID int

const (
	TypeUnknown TypeID = iota
	TypeNull
	TypeBool
	TypeInt
	TypeFloat
	TypeString
	TypeBlob
	TypeTimestamp
	TypeArray
	TypeMap
)

func (t TypeID) String() string {
	switch t {
	case TypeNull:
		return "null"
	case TypeBool:
		return "bool"
	case TypeInt:
		return "int"
	case TypeFloat:
		return "float"
	case TypeString:
		return "string"
	case TypeBlob:
		return "blob"
	case TypeTimestamp:
		return "timestamp"
	case TypeArray:
		return "array"
	case TypeMap:
		return "map"
	default:
		return "unknown"
	}
}

var msgpackHandle = &codec.MsgpackHandle{}

func init() {
	msgpackHandle.MapType = reflect.TypeOf(map[string]interface{}(nil))
	msgpackHandle.RawToString = true
	msgpackHandle.WriteExt = false
}

// UnmarshalMsgpack returns a Map object from a byte array encoded
// by msgpack serialization. The byte is expected to decode key-value
// style map. Returns an error when value type is not supported in SensorBee.
func UnmarshalMsgpack(b []byte) (Map, error) {
	var m map[string]interface{}
	dec := codec.NewDecoderBytes(b, msgpackHandle)
	dec.Decode(&m)

	return NewMap(m)
}

// NewMap returns a Map object from map[string]interface{}.
// Returns an error when value type is not supported in SensorBee.
//
// Example:
// The following sample interface{} will be changed to mapSample Map.
//   var sample = map[string]interface{}{
//  	"bool":   true,
//  	"int":    int64(1),
//  	"float":  float64(0.1),
//  	"string": "homhom",
//  	"time":   time.Date(2015, time.May, 1, 14, 27, 0, 0, time.UTC),
//  	"array": []interface{}{true, 10, "inarray",
//  		map[string]interface{}{
//  			"mapinarray": "arraymap",
//  		}},
//  	"map": map[string]interface{}{
//  		"map_a": "a",
//  		"map_b": 2,
//  	},
//  	"byte": []byte("test byte"),
//  	"null": nil,
//  }
//  var mapSample = Map{
//  	"bool":   Bool(true),
//  	"int":    Int(1),
//  	"float":  Float(0.1),
//  	"string": String("homhom"),
//  	"time":   Timestamp(time.Date(2015, time.May, 1, 14, 27, 0, 0, time.UTC)),
//  	"array": Array([]Value{Bool(true), Int(10), String("inarray"),
//  		Map{
//  			"mapinarray": String("arraymap"),
//  		}}),
//  	"map": Map{
//  		"map_a": String("a"),
//  		"map_b": Int(2),
//  	},
//  	"byte": Blob([]byte("test byte")),
//  	"null": Null{},
//  }
//
func NewMap(m map[string]interface{}) (Map, error) {
	result := Map{}
	for k, v := range m {
		value, err := newValue(v)
		if err != nil {
			return nil, err
		}
		result[k] = value
	}
	return result, nil
}

func newArray(a []interface{}) (Array, error) {
	result := make([]Value, len(a))
	for i, v := range a {
		value, err := newValue(v)
		if err != nil {
			return nil, err
		}
		result[i] = value
	}
	return result, nil
}

func newValue(v interface{}) (result Value, err error) {
	switch vt := v.(type) {
	case []interface{}:
		a, err := newArray(vt)
		if err != nil {
			return nil, err
		}
		result = a
	case map[string]interface{}:
		m, err := NewMap(vt)
		if err != nil {
			return nil, err
		}
		result = m
	case bool:
		result = Bool(vt)
	case int:
		result = Int(vt)
	case int8:
		result = Int(vt)
	case int16:
		result = Int(vt)
	case int32:
		result = Int(vt)
	case int64:
		result = Int(vt)
	case uint:
		if vt > math.MaxInt64 {
			err = errors.New(fmt.Sprintf("over 64 bit int value is not supported"))
			break
		}
		result = Int(vt)
	case uint8:
		result = Int(vt)
	case uint16:
		result = Int(vt)
	case uint32:
		result = Int(vt)
	case uint64:
		if vt > math.MaxInt64 {
			err = errors.New(fmt.Sprintf("over 64 bit int value is not supported"))
			break
		}
		result = Int(vt)
	case float32:
		result = Float(vt)
	case float64:
		result = Float(vt)
	case time.Time:
		result = Timestamp(vt)
	case string:
		result = String(vt)
	case []byte:
		result = Blob(vt)
	case nil:
		result = Null{}
	default:
		err = errors.New(fmt.Sprintf("unsupported type %T", v))
	}
	return result, err
}

// MarshalMsgpack returns a byte array encoded by msgpack serialization
// from a Map object. Returns an error when msgpack serialization failed.
func MarshalMsgpack(m Map) ([]byte, error) {
	iMap := newIMap(m)
	var out []byte
	enc := codec.NewEncoderBytes(&out, msgpackHandle)
	err := enc.Encode(iMap)

	return out, err
}

func newIMap(m Map) map[string]interface{} {
	result := map[string]interface{}{}
	for k, v := range m {
		value := newIValue(v)
		result[k] = value
	}
	return result
}

func newIArray(a Array) []interface{} {
	result := make([]interface{}, len(a))
	for i, v := range a {
		value := newIValue(v)
		result[i] = value
	}
	return result
}

func newIValue(v Value) interface{} {
	var result interface{}
	switch v.Type() {
	case TypeBool:
		result, _ = v.AsBool()
	case TypeInt:
		result, _ = v.AsInt()
	case TypeFloat:
		result, _ = v.AsFloat()
	case TypeString:
		result, _ = v.AsString()
	case TypeBlob:
		result, _ = v.AsBlob()
	case TypeTimestamp:
		result, _ = ToInt(v)
	case TypeArray:
		innerArray, _ := v.AsArray()
		result = newIArray(innerArray)
	case TypeMap:
		innerMap, _ := v.AsMap()
		result = newIMap(innerMap)
	case TypeNull:
		result = nil
	default:
		//do nothing
	}
	return result
}
<commit_msg>change public NewArray / NewValue<commit_after>package tuple

import (
	"errors"
	"fmt"
	"github.com/ugorji/go/codec"
	"math"
	"reflect"
	"time"
)

// Value is the generic interface for all data that can be stored
// inside a Tuple. Since we assume the data not to conform to any
// schema, data can have any shape and it can also change within a
// stream from one Tuple to the next. Therefore we need to be
// careful with respect to type conversions. A Value obtained, e.g.,
// by Map.Get should always be converted using the appropriate method
// and error checking must be done.
//
// Example:
//  i, err := val.AsInt()
//  if err != nil { ... }
type Value interface {
	Type() TypeID
	AsBool() (bool, error)
	AsInt() (int64, error)
	AsFloat() (float64, error)
	AsString() (string, error)
	AsBlob() ([]byte, error)
	AsTimestamp() (time.Time, error)
	AsArray() (Array, error)
	AsMap() (Map, error)
	clone() Value
}

func castError(from TypeID, to TypeID) error {
	return errors.New(fmt.Sprintf("unsupported cast %v from %v", to.String(), from.String()))
}

type TypeID int

const (
	TypeUnknown TypeID = iota
	TypeNull
	TypeBool
	TypeInt
	TypeFloat
	TypeString
	TypeBlob
	TypeTimestamp
	TypeArray
	TypeMap
)

func (t TypeID) String() string {
	switch t {
	case TypeNull:
		return "null"
	case TypeBool:
		return "bool"
	case TypeInt:
		return "int"
	case TypeFloat:
		return "float"
	case TypeString:
		return "string"
	case TypeBlob:
		return "blob"
	case TypeTimestamp:
		return "timestamp"
	case TypeArray:
		return "array"
	case TypeMap:
		return "map"
	default:
		return "unknown"
	}
}

var msgpackHandle = &codec.MsgpackHandle{}

func init() {
	msgpackHandle.MapType = reflect.TypeOf(map[string]interface{}(nil))
	msgpackHandle.RawToString = true
	msgpackHandle.WriteExt = false
}

// UnmarshalMsgpack returns a Map object from a byte array encoded
// by msgpack serialization. The byte is expected to decode key-value
// style map. Returns an error when value type is not supported in SensorBee.
func UnmarshalMsgpack(b []byte) (Map, error) {
	var m map[string]interface{}
	dec := codec.NewDecoderBytes(b, msgpackHandle)
	dec.Decode(&m)

	return NewMap(m)
}

// NewMap returns a Map object from map[string]interface{}.
// Returns an error when value type is not supported in SensorBee.
//
// Example:
// The following sample interface{} will be converted to mapSample Map.
//   var sample = map[string]interface{}{
//  	"bool":   true,
//  	"int":    int64(1),
//  	"float":  float64(0.1),
//  	"string": "homhom",
//  	"time":   time.Date(2015, time.May, 1, 14, 27, 0, 0, time.UTC),
//  	"array": []interface{}{true, 10, "inarray",
//  		map[string]interface{}{
//  			"mapinarray": "arraymap",
//  		}},
//  	"map": map[string]interface{}{
//  		"map_a": "a",
//  		"map_b": 2,
//  	},
//  	"byte": []byte("test byte"),
//  	"null": nil,
//  }
//  var mapSample = Map{
//  	"bool":   Bool(true),
//  	"int":    Int(1),
//  	"float":  Float(0.1),
//  	"string": String("homhom"),
//  	"time":   Timestamp(time.Date(2015, time.May, 1, 14, 27, 0, 0, time.UTC)),
//  	"array": Array([]Value{Bool(true), Int(10), String("inarray"),
//  		Map{
//  			"mapinarray": String("arraymap"),
//  		}}),
//  	"map": Map{
//  		"map_a": String("a"),
//  		"map_b": Int(2),
//  	},
//  	"byte": Blob([]byte("test byte")),
//  	"null": Null{},
//  }
//
func NewMap(m map[string]interface{}) (Map, error) {
	result := Map{}
	for k, v := range m {
		value, err := NewValue(v)
		if err != nil {
			return nil, err
		}
		result[k] = value
	}
	return result, nil
}

// NewArray returns a Array object from []interface{}.
// Returns an error when value type is not supported in SensorBee.
func NewArray(a []interface{}) (Array, error) {
	result := make([]Value, len(a))
	for i, v := range a {
		value, err := NewValue(v)
		if err != nil {
			return nil, err
		}
		result[i] = value
	}
	return result, nil
}

// NewValue returns a Value object from interface{}.
// Returns an error when value type is not supported in SensorBee.
func NewValue(v interface{}) (result Value, err error) {
	switch vt := v.(type) {
	case []interface{}:
		a, err := NewArray(vt)
		if err != nil {
			return nil, err
		}
		result = a
	case map[string]interface{}:
		m, err := NewMap(vt)
		if err != nil {
			return nil, err
		}
		result = m
	case bool:
		result = Bool(vt)
	case int:
		result = Int(vt)
	case int8:
		result = Int(vt)
	case int16:
		result = Int(vt)
	case int32:
		result = Int(vt)
	case int64:
		result = Int(vt)
	case uint:
		if vt > math.MaxInt64 {
			err = errors.New(fmt.Sprintf("over 64 bit int value is not supported"))
			break
		}
		result = Int(vt)
	case uint8:
		result = Int(vt)
	case uint16:
		result = Int(vt)
	case uint32:
		result = Int(vt)
	case uint64:
		if vt > math.MaxInt64 {
			err = errors.New(fmt.Sprintf("over 64 bit int value is not supported"))
			break
		}
		result = Int(vt)
	case float32:
		result = Float(vt)
	case float64:
		result = Float(vt)
	case time.Time:
		result = Timestamp(vt)
	case string:
		result = String(vt)
	case []byte:
		result = Blob(vt)
	case nil:
		result = Null{}
	default:
		err = errors.New(fmt.Sprintf("unsupported type %T", v))
	}
	return result, err
}

// MarshalMsgpack returns a byte array encoded by msgpack serialization
// from a Map object. Returns an error when msgpack serialization failed.
func MarshalMsgpack(m Map) ([]byte, error) {
	iMap := newIMap(m)
	var out []byte
	enc := codec.NewEncoderBytes(&out, msgpackHandle)
	err := enc.Encode(iMap)

	return out, err
}

func newIMap(m Map) map[string]interface{} {
	result := map[string]interface{}{}
	for k, v := range m {
		value := newIValue(v)
		result[k] = value
	}
	return result
}

func newIArray(a Array) []interface{} {
	result := make([]interface{}, len(a))
	for i, v := range a {
		value := newIValue(v)
		result[i] = value
	}
	return result
}

func newIValue(v Value) interface{} {
	var result interface{}
	switch v.Type() {
	case TypeBool:
		result, _ = v.AsBool()
	case TypeInt:
		result, _ = v.AsInt()
	case TypeFloat:
		result, _ = v.AsFloat()
	case TypeString:
		result, _ = v.AsString()
	case TypeBlob:
		result, _ = v.AsBlob()
	case TypeTimestamp:
		result, _ = ToInt(v)
	case TypeArray:
		innerArray, _ := v.AsArray()
		result = newIArray(innerArray)
	case TypeMap:
		innerMap, _ := v.AsMap()
		result = newIMap(innerMap)
	case TypeNull:
		result = nil
	default:
		//do nothing
	}
	return result
}
<|endoftext|>


<commit_before>package utils

import (
	"io/ioutil"
	"log"
	"math/rand"
	"os/exec"
	"strings"
	"time"

	"github.com/DanielRenne/GoCore/core/serverSettings"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func ReplaceTokenInFile(file string, find string, replaceWith string) {
	input, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatalln(err)
	}

	lines := strings.Split(string(input), "\n")

	for i, line := range lines {
		if strings.Contains(line, find) {
			lines[i] = strings.Replace(lines[i], find, replaceWith, -1)
		}
	}
	output := strings.Join(lines, "\n")
	err = ioutil.WriteFile(file, []byte(output), 0644)
	if err != nil {
		log.Fatalln(err)
	}
}

func TalkDirtyToMe(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		go exec.Command("say", sayWhat).Output()
	}
}

func TalkDirty(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		go exec.Command("say", sayWhat).Output()
	}
}

func TalkDirtySlowly(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		exec.Command("say", sayWhat).Output()
	}
}

func InArray(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func Array(values ...string) []string {
	var out []string
	for _, value := range values {
		out = append(out, value)
	}
	return out
}

func ArrayRemove(s []string, r string) []string {
	for i, v := range s {
		if v == r {
			return append(s[:i], s[i+1:]...)
		}
	}
	return s
}

func Dict(k string, v string) (ret map[string]string) {
	ret = make(map[string]string, 0)
	if k != "" && v != "" {
		ret[k] = v
	}
	return ret
}

func InterfaceMap() (ret map[string]interface{}) {
	ret = make(map[string]interface{}, 1)
	return ret
}
<commit_msg>add randomfloat function<commit_after>package utils

import (
	"io/ioutil"
	"log"
	"math/rand"
	"os/exec"
	"strings"
	"time"

	"github.com/DanielRenne/GoCore/core/serverSettings"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func ReplaceTokenInFile(file string, find string, replaceWith string) {
	input, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatalln(err)
	}

	lines := strings.Split(string(input), "\n")

	for i, line := range lines {
		if strings.Contains(line, find) {
			lines[i] = strings.Replace(lines[i], find, replaceWith, -1)
		}
	}
	output := strings.Join(lines, "\n")
	err = ioutil.WriteFile(file, []byte(output), 0644)
	if err != nil {
		log.Fatalln(err)
	}
}

func TalkDirtyToMe(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		go exec.Command("say", sayWhat).Output()
	}
}

func TalkDirty(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		go exec.Command("say", sayWhat).Output()
	}
}

func TalkDirtySlowly(sayWhat string) {
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		exec.Command("say", sayWhat).Output()
	}
}

func InArray(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func Array(values ...string) []string {
	var out []string
	for _, value := range values {
		out = append(out, value)
	}
	return out
}

func ArrayRemove(s []string, r string) []string {
	for i, v := range s {
		if v == r {
			return append(s[:i], s[i+1:]...)
		}
	}
	return s
}

func Dict(k string, v string) (ret map[string]string) {
	ret = make(map[string]string, 0)
	if k != "" && v != "" {
		ret[k] = v
	}
	return ret
}

func InterfaceMap() (ret map[string]interface{}) {
	ret = make(map[string]interface{}, 1)
	return ret
}

func RandomFloat() float32 {
	return rand.Float32() // Intn(max-min) + min
}
<|endoftext|>


<commit_before>package notify

import (
	"encoding/json"
	"errors"
	"strings"
	"testing"

	"github.com/gansoi/gansoi/boltdb"
	"github.com/gansoi/gansoi/checks"
	"github.com/gansoi/gansoi/database"
	"github.com/gansoi/gansoi/eval"
	"github.com/gansoi/gansoi/plugins"
)

type (
	mock struct {
		Err bool `json:"err"`
	}

	mockNotifier struct {
	}
)

var (
	notifyMessage string
)

func init() {
	plugins.RegisterAgent("mock", mock{})
	plugins.RegisterNotifier("mockn", mockNotifier{})
}

func (m *mock) Check(result plugins.AgentResult) error {
	if m.Err {
		return errors.New("error")
	}

	return nil
}

func (m mockNotifier) Notify(text string) error {
	notifyMessage = text

	return nil
}

func TestGotEvaluation(t *testing.T) {
	db := boltdb.NewTestStore()

	contact := &Contact{
		Name:     "testcontact",
		Notifier: "mockn",
	}
	err := db.Save(contact)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	group := &ContactGroup{
		Name:    "testgroup",
		Members: []string{contact.GetID()},
	}
	err = db.Save(group)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	check := &checks.Check{
		Name:          "test",
		AgentID:       "mock",
		ContactGroups: []string{group.GetID(), "nonexisting"},
	}
	err = db.Save(check)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	e := eval.NewEvaluator(db)
	n, _ := NewNotifier(db)

	// This should not fail :)
	n.PostApply(false, database.CommandSave, nil)

	timeline := []struct {
		err             bool
		expectedMessage string
	}{
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{true, ""},
		{true, ""},
		{true, "Down"},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{false, ""},
		{false, ""},
		{false, "Up"},
		{false, ""},
		{false, ""},
		{true, ""},
		{false, ""},
		{false, ""},
		{true, ""},
		{false, ""},
		{false, ""},
	}

	for i, c := range timeline {
		if c.err {
			check.Arguments = json.RawMessage(`{"err": true}`)
		} else {
			check.Arguments = json.RawMessage(`{}`)
		}

		result := checks.RunCheck(nil, check)
		result.CheckHostID = checks.CheckHostID(check.GetID(), "")
		result.CheckID = check.GetID()

		err = db.Save(result)
		if err != nil {
			t.Fatalf("Save() failed: %s", err.Error())
		}

		evaluation, err := e.Evaluate(result)
		if err != nil {
			t.Fatalf("Evaluate() failed: %s", err.Error())
		}

		n.PostApply(true, database.CommandSave, evaluation)
		//		err = n.gotEvaluation(evaluation)
		if err != nil {
			t.Fatalf("gotEvaluation() failed: %s", err.Error())
		}

		if c.expectedMessage != "" && !strings.Contains(notifyMessage, c.expectedMessage) {
			t.Errorf("%d: Notification '%s' did not contain '%s' as expected", i, notifyMessage, c.expectedMessage)
		}

		if c.expectedMessage == "" && notifyMessage != "" {
			t.Errorf("%d: Got unexpected notoification: %s", i, notifyMessage)
		}

		notifyMessage = ""
	}

	result := checks.RunCheck(nil, check)
	result.CheckHostID = checks.CheckHostID(check.GetID(), "")
	result.CheckID = check.GetID()
	e.Evaluate(result)
	evaluation, _ := eval.LatestEvaluation(db, result)
	evaluation.CheckID = "nonexisting"
	e.Evaluate(result)
}

var _ database.Listener = (*Notifier)(nil)
<commit_msg>Added a test of errorpath.<commit_after>package notify

import (
	"encoding/json"
	"errors"
	"strings"
	"testing"

	"github.com/gansoi/gansoi/boltdb"
	"github.com/gansoi/gansoi/checks"
	"github.com/gansoi/gansoi/database"
	"github.com/gansoi/gansoi/eval"
	"github.com/gansoi/gansoi/plugins"
)

type (
	mock struct {
		Err bool `json:"err"`
	}

	mockNotifier struct {
	}
)

var (
	notifyMessage string
)

func init() {
	plugins.RegisterAgent("mock", mock{})
	plugins.RegisterNotifier("mockn", mockNotifier{})
}

func (m *mock) Check(result plugins.AgentResult) error {
	if m.Err {
		return errors.New("error")
	}

	return nil
}

func (m mockNotifier) Notify(text string) error {
	notifyMessage = text

	return nil
}

func TestGotEvaluation(t *testing.T) {
	db := boltdb.NewTestStore()

	contact := &Contact{
		Name:     "testcontact",
		Notifier: "mockn",
	}
	err := db.Save(contact)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	group := &ContactGroup{
		Name:    "testgroup",
		Members: []string{contact.GetID()},
	}
	err = db.Save(group)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	check := &checks.Check{
		Name:          "test",
		AgentID:       "mock",
		ContactGroups: []string{group.GetID(), "nonexisting"},
	}
	err = db.Save(check)
	if err != nil {
		t.Fatalf("Save() failed: %s", err.Error())
	}

	e := eval.NewEvaluator(db)
	n, _ := NewNotifier(db)

	// This should not fail :)
	n.PostApply(false, database.CommandSave, nil)

	timeline := []struct {
		err             bool
		expectedMessage string
	}{
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{false, ""},
		{true, ""},
		{true, ""},
		{true, "Down"},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{true, ""},
		{false, ""},
		{false, ""},
		{false, "Up"},
		{false, ""},
		{false, ""},
		{true, ""},
		{false, ""},
		{false, ""},
		{true, ""},
		{false, ""},
		{false, ""},
	}

	for i, c := range timeline {
		if c.err {
			check.Arguments = json.RawMessage(`{"err": true}`)
		} else {
			check.Arguments = json.RawMessage(`{}`)
		}

		result := checks.RunCheck(nil, check)
		result.CheckHostID = checks.CheckHostID(check.GetID(), "")
		result.CheckID = check.GetID()

		err = db.Save(result)
		if err != nil {
			t.Fatalf("Save() failed: %s", err.Error())
		}

		evaluation, err := e.Evaluate(result)
		if err != nil {
			t.Fatalf("Evaluate() failed: %s", err.Error())
		}

		n.PostApply(true, database.CommandSave, evaluation)
		//		err = n.gotEvaluation(evaluation)
		if err != nil {
			t.Fatalf("gotEvaluation() failed: %s", err.Error())
		}

		if c.expectedMessage != "" && !strings.Contains(notifyMessage, c.expectedMessage) {
			t.Errorf("%d: Notification '%s' did not contain '%s' as expected", i, notifyMessage, c.expectedMessage)
		}

		if c.expectedMessage == "" && notifyMessage != "" {
			t.Errorf("%d: Got unexpected notoification: %s", i, notifyMessage)
		}

		notifyMessage = ""
	}

	result := checks.RunCheck(nil, check)
	result.CheckHostID = checks.CheckHostID(check.GetID(), "")
	result.CheckID = check.GetID()
	e.Evaluate(result)
	evaluation, _ := eval.LatestEvaluation(db, result)
	evaluation.CheckID = "nonexisting"
	e.Evaluate(result)
}

func TestPostApply(t *testing.T) {
	db := boltdb.NewTestStore()

	n, _ := NewNotifier(db)
	n.PostApply(true, database.CommandSave, &eval.Evaluation{})

	err := n.gotEvaluation(&eval.Evaluation{})
	if err == nil {
		t.Fatalf("gotEvaluation() failed to detect null-valued input")
	}
}

var _ database.Listener = (*Notifier)(nil)
<|endoftext|>


<commit_before>package gosolar

import "fmt"

// BulkSetCustomProperty sets a custom property on a series of URIs.
func (c *Client) BulkSetCustomProperty(uris []string, name string, value interface{}) error {
	// load up the uris that are going to be affected
	var cpuris []string
	for _, uri := range uris {
		cpuris = append(cpuris, uri+"/CustomProperties")
	}

	bulkRequest := struct {
		URIs       []string               `json:"uris"`
		Properties map[string]interface{} `json:"properties"`
	}{
		URIs: cpuris,
		Properties: map[string]interface{}{
			name: value,
		},
	}

	_, err := c.post("BulkUpdate", &bulkRequest)
	if err != nil {
		return fmt.Errorf("failed to post bulk update: %v", err)
	}

	return nil
}

// SetCustomProperty sets a custom property value on a specific URI.
func (c *Client) SetCustomProperty(uri, name string, value interface{}) error {
	property := map[string]interface{}{
		name: value,
	}

	_, err := c.post(uri+"/CustomProperties", &property)
	if err != nil {
		return fmt.Errorf("failed to update custom property: %v", err)
	}

	return nil
}

// SetCustomProperties sets multiple properties on an entity.
func (c *Client) SetCustomProperties(uri string, properties map[string]string) error {
	_, err := c.post(uri+"/CustomProperties", &properties)
	if err != nil {
		return fmt.Errorf("failed to update custom property: %v", err)
	}

	return nil
}

// CreateCustomProperty creates a new custom property of a specified type.
func (c *Client) CreateCustomProperty(cpEntity, cpType, cpName, cpDesc string) error {
	var cpLength string

	if cpType == "string" {
		cpLength = "400"
	} else {
		cpLength = "0"
	}

	props := []string{
		cpName,
		cpDesc,
		cpType,
		cpLength,
		"",
		"",
		"",
		"",
		"",
		"",
		"",
		"false",
		"",
	}

	endpoint := fmt.Sprintf("Invoke/%s/CreateCustomProperty", cpEntity)

	_, err := c.post(endpoint, &props)
	if err != nil {
		return fmt.Errorf("failed to create custom property: %v", err)
	}

	return nil
}
<commit_msg>Change type to map[string]interface{}<commit_after>package gosolar

import "fmt"

// BulkSetCustomProperty sets a custom property on a series of URIs.
func (c *Client) BulkSetCustomProperty(uris []string, name string, value interface{}) error {
	// load up the uris that are going to be affected
	var cpuris []string
	for _, uri := range uris {
		cpuris = append(cpuris, uri+"/CustomProperties")
	}

	bulkRequest := struct {
		URIs       []string               `json:"uris"`
		Properties map[string]interface{} `json:"properties"`
	}{
		URIs: cpuris,
		Properties: map[string]interface{}{
			name: value,
		},
	}

	_, err := c.post("BulkUpdate", &bulkRequest)
	if err != nil {
		return fmt.Errorf("failed to post bulk update: %v", err)
	}

	return nil
}

// SetCustomProperty sets a custom property value on a specific URI.
func (c *Client) SetCustomProperty(uri, name string, value interface{}) error {
	property := map[string]interface{}{
		name: value,
	}

	_, err := c.post(uri+"/CustomProperties", &property)
	if err != nil {
		return fmt.Errorf("failed to update custom property: %v", err)
	}

	return nil
}

// SetCustomProperties sets multiple properties on an entity.
func (c *Client) SetCustomProperties(uri string, properties map[string]interface{}) error {
	_, err := c.post(uri+"/CustomProperties", &properties)
	if err != nil {
		return fmt.Errorf("failed to update custom property: %v", err)
	}

	return nil
}

// CreateCustomProperty creates a new custom property of a specified type.
func (c *Client) CreateCustomProperty(cpEntity, cpType, cpName, cpDesc string) error {
	var cpLength string

	if cpType == "string" {
		cpLength = "400"
	} else {
		cpLength = "0"
	}

	props := []string{
		cpName,
		cpDesc,
		cpType,
		cpLength,
		"",
		"",
		"",
		"",
		"",
		"",
		"",
		"false",
		"",
	}

	endpoint := fmt.Sprintf("Invoke/%s/CreateCustomProperty", cpEntity)

	_, err := c.post(endpoint, &props)
	if err != nil {
		return fmt.Errorf("failed to create custom property: %v", err)
	}

	return nil
}
<|endoftext|>