<commit_before>// Package dyn implements a DNS provider for solving the DNS-01 challenge
// using Dyn Managed DNS.
package dyn

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/xenolf/lego/acme"
)

var dynBaseURL = "https://api.dynect.net/REST"

type dynResponse struct {
	// One of 'success', 'failure', or 'incomplete'
	Status string `json:"status"`

	// The structure containing the actual results of the request
	Data json.RawMessage `json:"data"`

	// The ID of the job that was created in response to a request.
	JobID int `json:"job_id"`

	// A list of zero or more messages
	Messages json.RawMessage `json:"msgs"`
}

// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
// Dyn's Managed DNS API to manage TXT records for a domain.
type DNSProvider struct {
	customerName string
	userName     string
	password     string
	token        string
}

// NewDNSProvider returns a DNSProvider instance configured for Dyn DNS.
// Credentials must be passed in the environment variables: DYN_CUSTOMER_NAME,
// DYN_USER_NAME and DYN_PASSWORD.
func NewDNSProvider() (*DNSProvider, error) {
	customerName := os.Getenv("DYN_CUSTOMER_NAME")
	userName := os.Getenv("DYN_USER_NAME")
	password := os.Getenv("DYN_PASSWORD")
	return NewDNSProviderCredentials(customerName, userName, password)
}

// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for Dyn DNS.
func NewDNSProviderCredentials(customerName, userName, password string) (*DNSProvider, error) {
	if customerName == "" || userName == "" || password == "" {
		return nil, fmt.Errorf("DynDNS credentials missing")
	}

	return &DNSProvider{
		customerName: customerName,
		userName:     userName,
		password:     password,
	}, nil
}

func (d *DNSProvider) sendRequest(method, resource string, payload interface{}) (*dynResponse, error) {
	url := fmt.Sprintf("%s/%s", dynBaseURL, resource)

	body, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest(method, url, bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	if len(d.token) > 0 {
		req.Header.Set("Auth-Token", d.token)
	}

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		return nil, fmt.Errorf("Dyn API request failed with HTTP status code %d", resp.StatusCode)
	} else if resp.StatusCode == 307 {
		// TODO add support for HTTP 307 response and long running jobs
		return nil, fmt.Errorf("Dyn API request returned HTTP 307. This is currently unsupported")
	}

	var dynRes dynResponse
	err = json.NewDecoder(resp.Body).Decode(&dynRes)
	if err != nil {
		return nil, err
	}

	if dynRes.Status == "failure" {
		// TODO add better error handling
		return nil, fmt.Errorf("Dyn API request failed: %s", dynRes.Messages)
	}

	return &dynRes, nil
}

// Starts a new Dyn API Session. Authenticates using customerName, userName,
// password and receives a token to be used in for subsequent requests.
func (d *DNSProvider) login() error {
	type creds struct {
		Customer string `json:"customer_name"`
		User     string `json:"user_name"`
		Pass     string `json:"password"`
	}

	type session struct {
		Token   string `json:"token"`
		Version string `json:"version"`
	}

	payload := &creds{Customer: d.customerName, User: d.userName, Pass: d.password}
	dynRes, err := d.sendRequest("POST", "Session", payload)
	if err != nil {
		return err
	}

	var s session
	err = json.Unmarshal(dynRes.Data, &s)
	if err != nil {
		return err
	}

	d.token = s.Token

	return nil
}

// Destroys Dyn Session
func (d *DNSProvider) logout() error {
	if len(d.token) == 0 {
		// nothing to do
		return nil
	}

	url := fmt.Sprintf("%s/Session", dynBaseURL)
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Auth-Token", d.token)

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Dyn API request failed to delete session with HTTP status code %d", resp.StatusCode)
	}

	d.token = ""

	return nil
}

// Present creates a TXT record using the specified parameters
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)

	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
	if err != nil {
		return err
	}

	err = d.login()
	if err != nil {
		return err
	}

	data := map[string]interface{}{
		"rdata": map[string]string{
			"txtdata": value,
		},
		"ttl": strconv.Itoa(ttl),
	}

	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
	_, err = d.sendRequest("POST", resource, data)
	if err != nil {
		return err
	}

	err = d.publish(authZone, "Added TXT record for ACME dns-01 challenge using lego client")
	if err != nil {
		return err
	}

	err = d.logout()
	if err != nil {
		return err
	}

	return nil
}

func (d *DNSProvider) publish(zone, notes string) error {
	type publish struct {
		Publish bool   `json:"publish"`
		Notes   string `json:"notes"`
	}

	pub := &publish{Publish: true, Notes: notes}
	resource := fmt.Sprintf("Zone/%s/", zone)
	_, err := d.sendRequest("PUT", resource, pub)
	if err != nil {
		return err
	}

	return nil
}

// CleanUp removes the TXT record matching the specified parameters
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)

	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
	if err != nil {
		return err
	}

	err = d.login()
	if err != nil {
		return err
	}

	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
	url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Auth-Token", d.token)

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Dyn API request failed to delete TXT record HTTP status code %d", resp.StatusCode)
	}

	err = d.publish(authZone, "Removed TXT record for ACME dns-01 challenge using lego client")
	if err != nil {
		return err
	}

	err = d.logout()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Slightly improve Dyn provider error reporting. (#473)<commit_after>// Package dyn implements a DNS provider for solving the DNS-01 challenge
// using Dyn Managed DNS.
package dyn

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/xenolf/lego/acme"
)

var dynBaseURL = "https://api.dynect.net/REST"

type dynResponse struct {
	// One of 'success', 'failure', or 'incomplete'
	Status string `json:"status"`

	// The structure containing the actual results of the request
	Data json.RawMessage `json:"data"`

	// The ID of the job that was created in response to a request.
	JobID int `json:"job_id"`

	// A list of zero or more messages
	Messages json.RawMessage `json:"msgs"`
}

// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
// Dyn's Managed DNS API to manage TXT records for a domain.
type DNSProvider struct {
	customerName string
	userName     string
	password     string
	token        string
}

// NewDNSProvider returns a DNSProvider instance configured for Dyn DNS.
// Credentials must be passed in the environment variables: DYN_CUSTOMER_NAME,
// DYN_USER_NAME and DYN_PASSWORD.
func NewDNSProvider() (*DNSProvider, error) {
	customerName := os.Getenv("DYN_CUSTOMER_NAME")
	userName := os.Getenv("DYN_USER_NAME")
	password := os.Getenv("DYN_PASSWORD")
	return NewDNSProviderCredentials(customerName, userName, password)
}

// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for Dyn DNS.
func NewDNSProviderCredentials(customerName, userName, password string) (*DNSProvider, error) {
	if customerName == "" || userName == "" || password == "" {
		return nil, fmt.Errorf("DynDNS credentials missing")
	}

	return &DNSProvider{
		customerName: customerName,
		userName:     userName,
		password:     password,
	}, nil
}

func (d *DNSProvider) sendRequest(method, resource string, payload interface{}) (*dynResponse, error) {
	url := fmt.Sprintf("%s/%s", dynBaseURL, resource)

	body, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest(method, url, bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	if len(d.token) > 0 {
		req.Header.Set("Auth-Token", d.token)
	}

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 500 {
		return nil, fmt.Errorf("Dyn API request failed with HTTP status code %d", resp.StatusCode)
	}

	var dynRes dynResponse
	err = json.NewDecoder(resp.Body).Decode(&dynRes)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 400 {
		return nil, fmt.Errorf("Dyn API request failed with HTTP status code %d: %s", resp.StatusCode, dynRes.Messages)
	} else if resp.StatusCode == 307 {
		// TODO add support for HTTP 307 response and long running jobs
		return nil, fmt.Errorf("Dyn API request returned HTTP 307. This is currently unsupported")
	}

	if dynRes.Status == "failure" {
		// TODO add better error handling
		return nil, fmt.Errorf("Dyn API request failed: %s", dynRes.Messages)
	}

	return &dynRes, nil
}

// Starts a new Dyn API Session. Authenticates using customerName, userName,
// password and receives a token to be used in for subsequent requests.
func (d *DNSProvider) login() error {
	type creds struct {
		Customer string `json:"customer_name"`
		User     string `json:"user_name"`
		Pass     string `json:"password"`
	}

	type session struct {
		Token   string `json:"token"`
		Version string `json:"version"`
	}

	payload := &creds{Customer: d.customerName, User: d.userName, Pass: d.password}
	dynRes, err := d.sendRequest("POST", "Session", payload)
	if err != nil {
		return err
	}

	var s session
	err = json.Unmarshal(dynRes.Data, &s)
	if err != nil {
		return err
	}

	d.token = s.Token

	return nil
}

// Destroys Dyn Session
func (d *DNSProvider) logout() error {
	if len(d.token) == 0 {
		// nothing to do
		return nil
	}

	url := fmt.Sprintf("%s/Session", dynBaseURL)
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Auth-Token", d.token)

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Dyn API request failed to delete session with HTTP status code %d", resp.StatusCode)
	}

	d.token = ""

	return nil
}

// Present creates a TXT record using the specified parameters
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)

	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
	if err != nil {
		return err
	}

	err = d.login()
	if err != nil {
		return err
	}

	data := map[string]interface{}{
		"rdata": map[string]string{
			"txtdata": value,
		},
		"ttl": strconv.Itoa(ttl),
	}

	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
	_, err = d.sendRequest("POST", resource, data)
	if err != nil {
		return err
	}

	err = d.publish(authZone, "Added TXT record for ACME dns-01 challenge using lego client")
	if err != nil {
		return err
	}

	err = d.logout()
	if err != nil {
		return err
	}

	return nil
}

func (d *DNSProvider) publish(zone, notes string) error {
	type publish struct {
		Publish bool   `json:"publish"`
		Notes   string `json:"notes"`
	}

	pub := &publish{Publish: true, Notes: notes}
	resource := fmt.Sprintf("Zone/%s/", zone)
	_, err := d.sendRequest("PUT", resource, pub)
	if err != nil {
		return err
	}

	return nil
}

// CleanUp removes the TXT record matching the specified parameters
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)

	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
	if err != nil {
		return err
	}

	err = d.login()
	if err != nil {
		return err
	}

	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
	url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Auth-Token", d.token)

	client := &http.Client{Timeout: time.Duration(10 * time.Second)}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Dyn API request failed to delete TXT record HTTP status code %d", resp.StatusCode)
	}

	err = d.publish(authZone, "Removed TXT record for ACME dns-01 challenge using lego client")
	if err != nil {
		return err
	}

	err = d.logout()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


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

package testutil

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

func PathToOSFile(relativPath string) (*os.File, error) {
	path, err := filepath.Abs(relativPath)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("failed generate absolut file path of %s", relativPath))
	}

	manifest, err := os.Open(path)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("failed to open file %s", path))
	}

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

package testutil

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

func PathToOSFile(relativPath string) (*os.File, error) {
	path, err := filepath.Abs(relativPath)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("failed generate absolut file path of %s", relativPath))
	}

	manifest, err := os.Open(path)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("failed to open file %s", path))
	}

	return manifest, nil
}
<|endoftext|>


<commit_before>package highlight

import (
	"github.com/elves/elvish/parse"
)

// Semantically applied styles.
var (
	styleForGoodCommand  = "green"
	styleForBadCommand   = "red"
	styleForGoodVariable = "magenta"
)

// Lexically applied styles.

// Styles for Primary nodes.
var styleForPrimary = map[parse.PrimaryType]string{
	parse.Bareword:     "",
	parse.SingleQuoted: "yellow",
	parse.DoubleQuoted: "yellow",
	parse.Variable:     styleForGoodVariable,
	parse.Wildcard:     "",
	parse.Tilde:        "",
}

var styleForComment = "cyan"

// Styles for Sep nodes.
var styleForSep = map[string]string{
	">":  "green",
	">>": "green",
	"<":  "green",
	"?>": "green",
	"|":  "green",

	"?(": "bold",
	"(":  "bold",
	")":  "bold",
	"[":  "bold",
	"]":  "bold",
	"{":  "bold",
	"}":  "bold",

	"&": "bold",

	"if":   "yellow",
	"then": "yellow",
	"elif": "yellow",
	"else": "yellow",
	"fi":   "yellow",

	"while": "yellow",
	"do":    "yellow",
	"done":  "yellow",

	"for": "yellow",
	"in":  "yellow",

	"try":     "yellow",
	"except":  "yellow",
	"finally": "yellow",
	"tried":   "yellow",

	"begin": "yellow",
	"end":   "yellow",
}
<commit_msg>edit/highlight: Remove styles for obsolte keywords.<commit_after>package highlight

import (
	"github.com/elves/elvish/parse"
)

// Semantically applied styles.
var (
	styleForGoodCommand  = "green"
	styleForBadCommand   = "red"
	styleForGoodVariable = "magenta"
)

// Lexically applied styles.

// Styles for Primary nodes.
var styleForPrimary = map[parse.PrimaryType]string{
	parse.Bareword:     "",
	parse.SingleQuoted: "yellow",
	parse.DoubleQuoted: "yellow",
	parse.Variable:     styleForGoodVariable,
	parse.Wildcard:     "",
	parse.Tilde:        "",
}

var styleForComment = "cyan"

// Styles for Sep nodes.
var styleForSep = map[string]string{
	">":  "green",
	">>": "green",
	"<":  "green",
	"?>": "green",
	"|":  "green",

	"?(": "bold",
	"(":  "bold",
	")":  "bold",
	"[":  "bold",
	"]":  "bold",
	"{":  "bold",
	"}":  "bold",

	"&": "bold",

	"elif":    "yellow",
	"else":    "yellow",
	"except":  "yellow",
	"finally": "yellow",
}
<|endoftext|>


<commit_before>package op

import (
	"fmt"
	"strings"

	"github.com/philharnish/forge/src/data/graph/bloom/node"
)

type operation struct {
	operator   *operator
	operands   []node.NodeIterator
	generators []node.NodeGenerator
	node       *node.Node
	formatting bool // Used to detect cycles during formatting.
}

func (op *operation) Root() *node.Node {
	if op.node == nil {
		op.node = op.operator.synthesizeNode(op.operands)
	}
	return op.node
}

func (op *operation) Items(generator node.NodeGenerator) node.NodeItems {
	return newOperatorItems(generator, op)
}

func (op *operation) String() string {
	if op.formatting {
		return "<cycle>"
	}
	op.formatting = true
	result := node.Format(
		fmt.Sprintf(op.operator.template, formatOperands(op.operator.infix, op.operands)),
		op.Root(),
	)
	op.formatting = false
	return result
}

func (op *operation) fork(alternate node.NodeIterator) *operation {
	alternate = op.substitute(0, alternate)
	exit := op.slice(1, len(op.operands))
	return &operation{
		operator:   orOperator,
		operands:   []node.NodeIterator{alternate, exit},
		generators: op.generators[0:2],
	}
}

// Return a slice of operands from [start:end].
func (op *operation) slice(start int, end int) node.NodeIterator {
	if end-start == 1 {
		return op.operands[start]
	}
	return op.sliceCopy(start, end)
}

func (op *operation) sliceCopy(start int, end int) *operation {
	operands := make([]node.NodeIterator, end-start)
	copy(operands, op.operands[start:end])
	generators := make([]node.NodeGenerator, end-start)
	copy(generators, op.generators[start:end])
	return &operation{
		operator:   op.operator,
		operands:   operands,
		generators: generators,
	}
}

// Return a copy with `position` replaced with `item`.
func (op *operation) substitute(position int, item node.NodeIterator) *operation {
	result := op.sliceCopy(0, len(op.operands))
	result.operands[0] = item
	return result
}

func (op *operation) getGenerators(generator node.NodeGenerator) []node.NodeGenerator {
	if op.generators == nil {
		op.generators = make([]node.NodeGenerator, len(op.operands))
		for i := range op.operands {
			op.generators[i] = generator.ReserveNext()
		}
	}
	return op.generators
}

func formatOperands(infix string, operands []node.NodeIterator) string {
	formatted := make([]string, len(operands))
	for i, operand := range operands {
		operandString := fmt.Sprint(operand)
		if !strings.HasPrefix("(", operandString) && strings.Contains(operandString, " ") {
			operandString = fmt.Sprintf("(%s)", operandString)
		}
		formatted[i] = operandString
	}
	return strings.Join(formatted, infix)
}
<commit_msg>Streamline small operation.String() calls.<commit_after>package op

import (
	"fmt"
	"strings"

	"github.com/philharnish/forge/src/data/graph/bloom/node"
)

type operation struct {
	operator   *operator
	operands   []node.NodeIterator
	generators []node.NodeGenerator
	node       *node.Node
	formatting bool // Used to detect cycles during formatting.
}

func (op *operation) Root() *node.Node {
	if op.node == nil {
		op.node = op.operator.synthesizeNode(op.operands)
	}
	return op.node
}

func (op *operation) Items(generator node.NodeGenerator) node.NodeItems {
	return newOperatorItems(generator, op)
}

func (op *operation) String() string {
	operands := op.operands
	if op.operator.processMethod == sequential {
		operands = operands[sequentialOffset:]
	}
	if len(operands) == 1 {
		return operands[0].iterator.String()
	}
	if op.formatting {
		return "<cycle>"
	}
	op.formatting = true
	result := node.Format(
		fmt.Sprintf(op.operator.template, formatOperands(op.operator.infix, operands)),
		op.Root(),
	)
	op.formatting = false
	return result
}

func (op *operation) fork(alternate node.NodeIterator) *operation {
	alternate = op.substitute(0, alternate)
	exit := op.slice(1, len(op.operands))
	return &operation{
		operator:   orOperator,
		operands:   []node.NodeIterator{alternate, exit},
		generators: op.generators[0:2],
	}
}

// Return a slice of operands from [start:end].
func (op *operation) slice(start int, end int) node.NodeIterator {
	if end-start == 1 {
		return op.operands[start]
	}
	return op.sliceCopy(start, end)
}

func (op *operation) sliceCopy(start int, end int) *operation {
	operands := make([]node.NodeIterator, end-start)
	copy(operands, op.operands[start:end])
	generators := make([]node.NodeGenerator, end-start)
	copy(generators, op.generators[start:end])
	return &operation{
		operator:   op.operator,
		operands:   operands,
		generators: generators,
	}
}

// Return a copy with `position` replaced with `item`.
func (op *operation) substitute(position int, item node.NodeIterator) *operation {
	result := op.sliceCopy(0, len(op.operands))
	result.operands[0] = item
	return result
}

func (op *operation) getGenerators(generator node.NodeGenerator) []node.NodeGenerator {
	if op.generators == nil {
		op.generators = make([]node.NodeGenerator, len(op.operands))
		for i := range op.operands {
			op.generators[i] = generator.ReserveNext()
		}
	}
	return op.generators
}

func formatOperands(infix string, operands []node.NodeIterator) string {
	formatted := make([]string, len(operands))
	for i, operand := range operands {
		operandString := fmt.Sprint(operand)
		if !strings.HasPrefix("(", operandString) && strings.Contains(operandString, " ") {
			operandString = fmt.Sprintf("(%s)", operandString)
		}
		formatted[i] = operandString
	}
	return strings.Join(formatted, infix)
}
<|endoftext|>


<commit_before>// +build noos

package rtos

import (
	"syscall"
)

func sleepUntil(end int64) {
	for Nanosec() < end {
		syscall.SetAlarm(end)
		syscall.Alarm.Wait()
	}
}

type eventFlag struct {
	state syscall.Event
}

func atomicInitLoadState(p *syscall.Event) syscall.Event {
	state := syscall.AtomicLoadEvent(p)
	if state == 0 {
		state = syscall.AssignEventFlag() | syscall.Alarm
		if !syscall.AtomicCompareAndSwapEvent(p, 0, state) {
			state = syscall.AtomicLoadEvent(p)
		}
	}
	return state
}

func flagSet(f *EventFlag) {
	state := atomicInitLoadState(&f.state) | 1
	syscall.AtomicStoreEvent(&f.state, state)
	state.Send()
}

func flagClear(f *EventFlag) {
	state := atomicInitLoadState(&f.state) &^ 1
	syscall.AtomicStoreEvent(&f.state, state)
	state.Send()
}

func flagVal(f *EventFlag) int {
	return int(syscall.AtomicLoadEvent(&f.state) & 1)
}

func flagWait(f *EventFlag, deadline int64) bool {
	for {
		state := atomicInitLoadState(&f.state)
		if state&1 != 0 {
			return true
		}
		if deadline != 0 && Nanosec() >= deadline {
			return false
		}
		syscall.SetAlarm(deadline)
		(state &^ 1).Wait()
	}
}

func waitEvent(deadline int64, flags []*EventFlag) uint32 {
	var sum syscall.Event
	for _, f := range flags {
		sum |= atomicInitLoadState(&f.state)
	}
	sum &^= 1
	var ret uint32
	for {
		for n, f := range flags {
			state := syscall.AtomicLoadEvent(&f.state)
			ret |= uint32(state&1) << uint(n)
		}
		if ret != 0 || deadline != 0 && Nanosec() >= deadline {
			return ret
		}
		syscall.SetAlarm(deadline)
		sum.Wait()
	}
}
<commit_msg>rtos: Fixes 3 rather harmless bugs in EventFlag implementation.<commit_after>// +build noos

package rtos

import (
	"syscall"
)

func sleepUntil(end int64) {
	for Nanosec() < end {
		syscall.SetAlarm(end)
		syscall.Alarm.Wait()
	}
}

type eventFlag struct {
	state syscall.Event
}

func atomicInitLoadState(p *syscall.Event) syscall.Event {
	state := syscall.AtomicLoadEvent(p)
	if state == 0 {
		state = syscall.AssignEventFlag() | syscall.Alarm
		if !syscall.AtomicCompareAndSwapEvent(p, 0, state) {
			state = syscall.AtomicLoadEvent(p)
		}
	}
	return state
}

func flagSet(f *EventFlag) {
	state := atomicInitLoadState(&f.state) | 1
	syscall.AtomicStoreEvent(&f.state, state)
	(state &^ 1).Send()
}

func flagClear(f *EventFlag) {
	state := atomicInitLoadState(&f.state) &^ 1
	syscall.AtomicStoreEvent(&f.state, state)
}

func flagVal(f *EventFlag) int {
	// This code rely on fact that uninitialized f is zero.
	return int(syscall.AtomicLoadEvent(&f.state) & 1)
}

func flagWait(f *EventFlag, deadline int64) bool {
	for {
		state := atomicInitLoadState(&f.state)
		if state&1 != 0 {
			return true
		}
		if deadline != 0 && Nanosec() >= deadline {
			return false
		}
		syscall.SetAlarm(deadline)
		state.Wait()
	}
}

func waitEvent(deadline int64, flags []*EventFlag) uint32 {
	var sum syscall.Event
	for _, f := range flags {
		sum |= atomicInitLoadState(&f.state)
	}
	sum &^= 1
	var ret uint32
	for {
		for n, f := range flags {
			state := syscall.AtomicLoadEvent(&f.state)
			ret |= uint32(state&1) << uint(n)
		}
		if ret != 0 || deadline != 0 && Nanosec() >= deadline {
			return ret
		}
		syscall.SetAlarm(deadline)
		sum.Wait()
	}
}
<|endoftext|>


<commit_before>package scene

import (
	"image"
	"image/color"
	"math"
	"strconv"
	"sync"
	"time"

	"github.com/pankona/gomo-simra/simra"
)

// Title represents a scene object for Title
type Title struct {
	screenWidth  int
	screenHeight int
	sprites      []*simra.Sprite
	numOfSprite  *simra.Sprite
	fps          int
	fpsText      *simra.Sprite
	mu           sync.Mutex
}

// Initialize initializes title scene
// This is called from simra.
// simra.GetInstance().SetDesiredScreenSize should be called to determine
// screen size of this scene.
func (title *Title) Initialize() {
	simra.LogDebug("[IN]")

	simra.GetInstance().SetDesiredScreenSize(1080/2, 1920/2)
	title.screenHeight = 1080 / 2
	title.screenWidth = 1920 / 2

	// initialize sprites
	title.initialize()

	title.numOfSprite = simra.NewSprite()
	title.numOfSprite.X = (float32)(title.screenWidth / 2)
	title.numOfSprite.Y = 100
	title.numOfSprite.W = (float32)(title.screenWidth)
	title.numOfSprite.H = 80
	simra.GetInstance().AddSprite(title.numOfSprite)

	tex := simra.NewTextTexture("0",
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.numOfSprite.ReplaceTexture(tex)

	title.fpsText = simra.NewSprite()
	title.fpsText.X = (float32)(title.screenWidth / 4)
	title.fpsText.Y = 100
	title.fpsText.W = (float32)(title.screenWidth)
	title.fpsText.H = 80
	simra.GetInstance().AddSprite(title.fpsText)

	tex = simra.NewTextTexture("0",
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.fpsText.ReplaceTexture(tex)
	go func() {
		for {
			<-time.After(1 * time.Second)
			tex = simra.NewTextTexture(strconv.Itoa(title.fps),
				60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
			title.fpsText.ReplaceTexture(tex)
			title.mu.Lock()
			title.fps = 0
			title.mu.Unlock()
		}
	}()

	simra.LogDebug("[OUT]")
}

func (title *Title) initialize() {
	simra.GetInstance().AddTouchListener(title)
}

var degree int

// Drive is called from simra.
// This is used to update sprites position.
// Thsi will be called 60 times per sec.
func (title *Title) Drive() {
	degree = (degree - 1) % 360
	for i := range title.sprites {
		r := float32(degree) * math.Pi / 180
		title.sprites[i].R = (float32)(r)
	}
	title.mu.Lock()
	title.fps++
	title.mu.Unlock()
	//runtime.GC()
}

// OnTouchBegin is called when Title scene is Touched.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchBegin(x, y float32) {
}

// OnTouchMove is called when Title scene is Touched and moved.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchMove(x, y float32) {
}

// OnTouchEnd is called when Title scene is Touched and it is released.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchEnd(x, y float32) {
	// scene end. go to next scene
	sprite := simra.NewSprite()
	sprite.W = 128
	sprite.H = 128
	sprite.X = x
	sprite.Y = y
	simra.GetInstance().AddSprite(sprite)

	tex := simra.NewImageTexture("sample.png", image.Rect(0, 0, 384, 384))
	sprite.ReplaceTexture(tex)

	title.sprites = append(title.sprites, sprite)

	tex = simra.NewTextTexture(strconv.Itoa(len(title.sprites)),
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.numOfSprite.ReplaceTexture(tex)
}
<commit_msg>allocate sprite's texture once. don't do every time.<commit_after>package scene

import (
	"image"
	"image/color"
	"math"
	"strconv"
	"sync"
	"time"

	"github.com/pankona/gomo-simra/simra"
)

// Title represents a scene object for Title
type Title struct {
	screenWidth  int
	screenHeight int
	sprites      []*simra.Sprite
	numOfSprite  *simra.Sprite
	fps          int
	fpsText      *simra.Sprite
	mu           sync.Mutex
	kokeshiTex   *simra.Texture
}

// Initialize initializes title scene
// This is called from simra.
// simra.GetInstance().SetDesiredScreenSize should be called to determine
// screen size of this scene.
func (title *Title) Initialize() {
	simra.LogDebug("[IN]")

	title.screenHeight = 1080 / 2
	title.screenWidth = 1920 / 2
	simra.GetInstance().SetDesiredScreenSize((float32)(title.screenHeight), (float32)(title.screenWidth))

	// initialize sprites
	title.initialize()

	title.numOfSprite = simra.NewSprite()
	title.numOfSprite.X = (float32)(title.screenWidth / 2)
	title.numOfSprite.Y = 100
	title.numOfSprite.W = (float32)(title.screenWidth)
	title.numOfSprite.H = 80
	simra.GetInstance().AddSprite(title.numOfSprite)

	tex := simra.NewTextTexture("0",
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.numOfSprite.ReplaceTexture(tex)

	title.fpsText = simra.NewSprite()
	title.fpsText.X = (float32)(title.screenWidth / 4)
	title.fpsText.Y = 100
	title.fpsText.W = (float32)(title.screenWidth)
	title.fpsText.H = 80
	simra.GetInstance().AddSprite(title.fpsText)

	tex = simra.NewTextTexture("0",
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.fpsText.ReplaceTexture(tex)
	go func() {
		for {
			<-time.After(1 * time.Second)
			tex = simra.NewTextTexture(strconv.Itoa(title.fps),
				60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
			title.fpsText.ReplaceTexture(tex)
			title.mu.Lock()
			title.fps = 0
			title.mu.Unlock()
		}
	}()

	title.kokeshiTex = simra.NewImageTexture("sample.png", image.Rect(0, 0, 384, 384))

	simra.LogDebug("[OUT]")
}

func (title *Title) initialize() {
	simra.GetInstance().AddTouchListener(title)
}

var degree int

// Drive is called from simra.
// This is used to update sprites position.
// Thsi will be called 60 times per sec.
func (title *Title) Drive() {
	degree = (degree - 1) % 360
	for i := range title.sprites {
		r := float32(degree) * math.Pi / 180
		title.sprites[i].R = (float32)(r)
	}
	title.mu.Lock()
	title.fps++
	title.mu.Unlock()
	//runtime.GC()
}

// OnTouchBegin is called when Title scene is Touched.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchBegin(x, y float32) {
}

// OnTouchMove is called when Title scene is Touched and moved.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchMove(x, y float32) {
}

// OnTouchEnd is called when Title scene is Touched and it is released.
// It is caused by calling AddtouchListener for title.background sprite.
func (title *Title) OnTouchEnd(x, y float32) {
	// scene end. go to next scene
	sprite := simra.NewSprite()
	sprite.W = 128
	sprite.H = 128
	sprite.X = x
	sprite.Y = y
	simra.GetInstance().AddSprite(sprite)
	title.sprites = append(title.sprites, sprite)
	sprite.ReplaceTexture(title.kokeshiTex)

	tex := simra.NewTextTexture(strconv.Itoa(len(title.sprites)),
		60, color.RGBA{255, 255, 255, 255}, image.Rect(0, 0, title.screenWidth, 80))
	title.numOfSprite.ReplaceTexture(tex)
}
<|endoftext|>


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

// +build js

package web

import (
	"strings"
	"sync"

	"github.com/gopherjs/gopherjs/js"
)

var (
	isNodeJSOnce sync.Once
	isNodeJS     = false
)

func IsNodeJS() bool {
	isNodeJSOnce.Do(func() {
		isNodeJS = js.Global.Get("process") != js.Undefined
	})
	return isNodeJS
}

func IsBrowser() bool {
	return !IsNodeJS()
}

func IsIOSSafari() bool {
	if IsNodeJS() {
		return false
	}
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "iPhone") {
		return false
	}
	return true
}

func IsAndroidChrome() bool {
	if IsNodeJS() {
		return false
	}
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "Android") {
		return false
	}
	if !strings.Contains(ua, "Chrome") {
		return false
	}
	return true
}

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

// +build js

package web

import (
	"strings"
	"sync"

	"github.com/hajimehoshi/gopherwasm/js"
)

var (
	isNodeJSOnce sync.Once
	isNodeJS     = false
)

func IsNodeJS() bool {
	isNodeJSOnce.Do(func() {
		isNodeJS = js.Global.Get("process") != js.Undefined
	})
	return isNodeJS
}

func IsBrowser() bool {
	return !IsNodeJS()
}

func IsIOSSafari() bool {
	if IsNodeJS() {
		return false
	}
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "iPhone") {
		return false
	}
	return true
}

func IsAndroidChrome() bool {
	if IsNodeJS() {
		return false
	}
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "Android") {
		return false
	}
	if !strings.Contains(ua, "Chrome") {
		return false
	}
	return true
}

func IsMobileBrowser() bool {
	return IsIOSSafari() || IsAndroidChrome()
}
<|endoftext|>


<commit_before>package keys

// ParsedInternalKey is a parsed or splited internal representation.
type ParsedInternalKey struct {
	UserKey  []byte
	Kind     Kind
	Sequence Sequence
}

// Append appends this internal key to destination buffer.
func (k *ParsedInternalKey) Append(dst []byte) []byte {
	var buf [TagBytes]byte
	CombineTag(buf[:], k.Sequence, k.Kind)
	dst = append(dst, k.UserKey...)
	return append(dst, buf[:]...)
}

// Parse parses input key as internal key and returns true for valid internal
// key. It is illegal to access other fields and methods after returning false.
func (k *ParsedInternalKey) Parse(key []byte) bool {
	i := len(key) - TagBytes
	if i < 0 {
		return false
	}
	k.UserKey = key[:i:i]
	k.Sequence, k.Kind = ExtractTag(key[i:])
	return k.Kind <= maxKind
}

// Tag returns tag of this internal key.
func (k *ParsedInternalKey) Tag() Tag {
	return PackTag(k.Sequence, k.Kind)
}
<commit_msg>Reorder methods of keys.ParsedInternalKey<commit_after>package keys

// ParsedInternalKey is a parsed or splited internal representation.
type ParsedInternalKey struct {
	UserKey  []byte
	Kind     Kind
	Sequence Sequence
}

// Parse parses input key as internal key and returns true for valid internal
// key. It is illegal to access other fields and methods after returning false.
func (k *ParsedInternalKey) Parse(key []byte) bool {
	i := len(key) - TagBytes
	if i < 0 {
		return false
	}
	k.UserKey = key[:i:i]
	k.Sequence, k.Kind = ExtractTag(key[i:])
	return k.Kind <= maxKind
}

// Tag returns tag of this internal key.
func (k *ParsedInternalKey) Tag() Tag {
	return PackTag(k.Sequence, k.Kind)
}

// Append appends this internal key to destination buffer.
func (k *ParsedInternalKey) Append(dst []byte) []byte {
	var buf [TagBytes]byte
	CombineTag(buf[:], k.Sequence, k.Kind)
	dst = append(dst, k.UserKey...)
	return append(dst, buf[:]...)
}
<|endoftext|>


<commit_before>package clockwork

import (
	"sync"
	"time"
)

// Clock provides an interface that packages can use instead of directly
// using the time module, so that chronology-related behavior can be tested
type Clock interface {
	After(d time.Duration) <-chan time.Time
	Sleep(d time.Duration)
	Now() time.Time
}

// FakeClock provides an interface for a clock which can be
// manually advanced through time
type FakeClock interface {
	Clock
	// Advance advances the FakeClock to a new point in time, ensuring any existing
	// sleepers are notified appropriately before returning
	Advance(d time.Duration)
	// BlockUntil will block until the FakeClock has the given number of
	// sleepers (callers of Sleep or After)
	BlockUntil(n int)
}

// NewRealClock returns a Clock which simply delegates calls to the actual time
// package; it should be used by packages in production.
func NewRealClock() Clock {
	return &realClock{}
}

// NewFakeClock returns a FakeClock implementation which can be
// manually advanced through time for testing. The initial time of the
// FakeClock will be an arbitrary non-zero time.
func NewFakeClock() FakeClock {
	// use a fixture that does not fulfill Time.IsZero()
	return NewFakeClockAt(time.Date(1984, time.April, 4, 0, 0, 0, 0, time.UTC))
}

// NewFakeClock returns a FakeClock initialised at the given time.Time.
func NewFakeClockAt(t time.Time) FakeClock {
	return &fakeClock{
		l:    sync.RWMutex{},
		time: t,
	}
}

type realClock struct{}

func (rc *realClock) After(d time.Duration) <-chan time.Time {
	return time.After(d)
}

func (rc *realClock) Sleep(d time.Duration) {
	time.Sleep(d)
}

func (rc *realClock) Now() time.Time {
	return time.Now()
}

type fakeClock struct {
	sleepers []*sleeper
	blockers []*blocker
	time     time.Time

	l sync.RWMutex
}

// sleeper represents a caller of After or Sleep
type sleeper struct {
	until time.Time
	done  chan time.Time
}

// blocker represents a caller of BlockUntil
type blocker struct {
	count int
	ch    chan struct{}
}

// After mimics time.After; it waits for the given duration to elapse on the
// fakeClock, then sends the current time on the returned channel.
func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	now := fc.time
	done := make(chan time.Time, 1)
	if d.Nanoseconds() == 0 {
		// special case - trigger immediately
		done <- now
	} else {
		// otherwise, add to the set of sleepers
		s := &sleeper{
			until: now.Add(d),
			done:  done,
		}
		fc.sleepers = append(fc.sleepers, s)
		// and notify any blockers
		fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	}
	return done
}

// notifyBlockers notifies all the blockers waiting until the
// given number of sleepers are waiting on the fakeClock. It
// returns an updated slice of blockers (i.e. those still waiting)
func notifyBlockers(blockers []*blocker, count int) (newBlockers []*blocker) {
	for _, b := range blockers {
		if b.count == count {
			close(b.ch)
		} else {
			newBlockers = append(newBlockers, b)
		}
	}
	return
}

// Sleep blocks until the given duration has passed on the fakeClock
func (fc *fakeClock) Sleep(d time.Duration) {
	<-fc.After(d)
}

// Time returns the current time of the fakeClock
func (fc *fakeClock) Now() time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	return fc.time
}

// Advance advances fakeClock to a new point in time, ensuring channels from any
// previous invocations of After are notified appropriately before returning
func (fc *fakeClock) Advance(d time.Duration) {
	fc.l.Lock()
	defer fc.l.Unlock()
	end := fc.time.Add(d)
	var newSleepers []*sleeper
	for _, s := range fc.sleepers {
		if end.Sub(s.until) >= 0 {
			s.done <- end
		} else {
			newSleepers = append(newSleepers, s)
		}
	}
	fc.sleepers = newSleepers
	fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	fc.time = end
}

// BlockUntil will block until the fakeClock has the given number of sleepers
// (callers of Sleep or After)
func (fc *fakeClock) BlockUntil(n int) {
	fc.l.Lock()
	// Fast path: current number of sleepers is what we're looking for
	if len(fc.sleepers) == n {
		fc.l.Unlock()
		return
	}
	// Otherwise, set up a new blocker
	b := &blocker{
		count: n,
		ch:    make(chan struct{}),
	}
	fc.blockers = append(fc.blockers, b)
	fc.l.Unlock()
	<-b.ch
}
<commit_msg>Only grab a read-lock in Now().<commit_after>package clockwork

import (
	"sync"
	"time"
)

// Clock provides an interface that packages can use instead of directly
// using the time module, so that chronology-related behavior can be tested
type Clock interface {
	After(d time.Duration) <-chan time.Time
	Sleep(d time.Duration)
	Now() time.Time
}

// FakeClock provides an interface for a clock which can be
// manually advanced through time
type FakeClock interface {
	Clock
	// Advance advances the FakeClock to a new point in time, ensuring any existing
	// sleepers are notified appropriately before returning
	Advance(d time.Duration)
	// BlockUntil will block until the FakeClock has the given number of
	// sleepers (callers of Sleep or After)
	BlockUntil(n int)
}

// NewRealClock returns a Clock which simply delegates calls to the actual time
// package; it should be used by packages in production.
func NewRealClock() Clock {
	return &realClock{}
}

// NewFakeClock returns a FakeClock implementation which can be
// manually advanced through time for testing. The initial time of the
// FakeClock will be an arbitrary non-zero time.
func NewFakeClock() FakeClock {
	// use a fixture that does not fulfill Time.IsZero()
	return NewFakeClockAt(time.Date(1984, time.April, 4, 0, 0, 0, 0, time.UTC))
}

// NewFakeClock returns a FakeClock initialised at the given time.Time.
func NewFakeClockAt(t time.Time) FakeClock {
	return &fakeClock{
		time: t,
	}
}

type realClock struct{}

func (rc *realClock) After(d time.Duration) <-chan time.Time {
	return time.After(d)
}

func (rc *realClock) Sleep(d time.Duration) {
	time.Sleep(d)
}

func (rc *realClock) Now() time.Time {
	return time.Now()
}

type fakeClock struct {
	sleepers []*sleeper
	blockers []*blocker
	time     time.Time

	l sync.RWMutex
}

// sleeper represents a caller of After or Sleep
type sleeper struct {
	until time.Time
	done  chan time.Time
}

// blocker represents a caller of BlockUntil
type blocker struct {
	count int
	ch    chan struct{}
}

// After mimics time.After; it waits for the given duration to elapse on the
// fakeClock, then sends the current time on the returned channel.
func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	now := fc.time
	done := make(chan time.Time, 1)
	if d.Nanoseconds() == 0 {
		// special case - trigger immediately
		done <- now
	} else {
		// otherwise, add to the set of sleepers
		s := &sleeper{
			until: now.Add(d),
			done:  done,
		}
		fc.sleepers = append(fc.sleepers, s)
		// and notify any blockers
		fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	}
	return done
}

// notifyBlockers notifies all the blockers waiting until the
// given number of sleepers are waiting on the fakeClock. It
// returns an updated slice of blockers (i.e. those still waiting)
func notifyBlockers(blockers []*blocker, count int) (newBlockers []*blocker) {
	for _, b := range blockers {
		if b.count == count {
			close(b.ch)
		} else {
			newBlockers = append(newBlockers, b)
		}
	}
	return
}

// Sleep blocks until the given duration has passed on the fakeClock
func (fc *fakeClock) Sleep(d time.Duration) {
	<-fc.After(d)
}

// Time returns the current time of the fakeClock
func (fc *fakeClock) Now() time.Time {
	fc.l.RLock()
	t := fc.time
	fc.l.RUnlock()
	return t
}

// Advance advances fakeClock to a new point in time, ensuring channels from any
// previous invocations of After are notified appropriately before returning
func (fc *fakeClock) Advance(d time.Duration) {
	fc.l.Lock()
	defer fc.l.Unlock()
	end := fc.time.Add(d)
	var newSleepers []*sleeper
	for _, s := range fc.sleepers {
		if end.Sub(s.until) >= 0 {
			s.done <- end
		} else {
			newSleepers = append(newSleepers, s)
		}
	}
	fc.sleepers = newSleepers
	fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	fc.time = end
}

// BlockUntil will block until the fakeClock has the given number of sleepers
// (callers of Sleep or After)
func (fc *fakeClock) BlockUntil(n int) {
	fc.l.Lock()
	// Fast path: current number of sleepers is what we're looking for
	if len(fc.sleepers) == n {
		fc.l.Unlock()
		return
	}
	// Otherwise, set up a new blocker
	b := &blocker{
		count: n,
		ch:    make(chan struct{}),
	}
	fc.blockers = append(fc.blockers, b)
	fc.l.Unlock()
	<-b.ch
}
<|endoftext|>


<commit_before>package encoders

import (
	"fmt"
	//"github.com/cznic/mathutil"
	//"github.com/zacg/floats"
	//"github.com/nupic-community/htm"
	//"github.com/nupic-community/htm/utils"
	//"github.com/zacg/ints"
	//"math"
)

/*
	Params for the date encoder
*/
type DateEncoderParams struct {
	HolidayWidth    int
	HolidayRadius   float64
	SeasonWidth     int
	SeasonRadius    float64
	DayOfWeekWidth  int
	DayOfWeekRadius float64
	WeekendWidth    int
	WeekendRadius   float64
	TimeOfDayWidth  int
	TimeOfDayRadius float64
	//CustomDays     int
	Name string
}

func NewDateEncoderParams() *DateEncoderParams {
	p := new(DateEncoderParams)

	//set defaults
	p.SeasonRadius = 91.5 //days
	p.DayOfWeekRadius = 1
	p.TimeOfDayRadius = 4
	p.WeekendRadius = 1
	p.HolidayRadius = 1

	return p
}

/*
	Date encoder encodes a datetime to a SDR. Params allow for tuning
	for specific date attributes
*/
type DateEncoder struct {
	DateEncoderParams
	seasonEncoder    *ScalerEncoder
	holidayEncoder   *ScalerEncoder
	dayOfWeekEncoder *ScalerEncoder
	weekendEncoder   *ScalerEncoder
	timeOfDayEncoder *ScalerEncoder

	width           int
	seasonOffset    int
	weekendOffset   int
	dayOfWeekOffset int
	holidayOffset   int
	timeOfDayOffset int
	Description     string
}

/*
	Intializes a new date encoder
*/
func NewDateEncoder(params *DateEncoderParams) *DateEncoderParams {
	se := new(DateEncoder)

	se.width = 0

	if params.SeasonWidth != 0 {
		// Ignore leapyear differences -- assume 366 days in a year
		// Radius = 91.5 days = length of season
		// Value is number of days since beginning of year (0 - 355)

		sep := NewScalerEncoderParams(params.SeasonWidth, 0, 366)
		sep.Name = "Season"
		sep.Periodic = true
		se.seasonEncoder = NewScalerEncoder(sep)
		se.seasonOffset = se.params.Width
		se.width += se.seasonEncoder.params.Width
		se.Description += fmt.Sprintf("season %v", se.seasonOffset)
	}

	if params.DayOfWeekWidth != 0 {
		// Value is day of week (floating point)
		// Radius is 1 day

		sep := NewScalerEncoderParams(params.DayOfWeekWidth, 0, 7)
		sep.Radius = params.DayOfWeekRadius
		sep.Name = "day of week"
		se.dayOfWeekEncoder = NewScalerEncoder(sep)
		se.dayOfWeekOffset = se.dayOfWeekEncoder.getWidth()
		se.Description += fmt.Sprintf(" day of week: %v", se.dayOfWeekOffset)
		se.width += se.dayOfWeekEncoder.Width
	}

	if params.WeekendWidth != 0 {
		// Binary value. Not sure if this makes sense. Also is somewhat redundant
		// with dayOfWeek
		//Append radius if it was not provided

		sep := NewScalerEncoderParams(params.WeekendWidth, 0, 1)
		sep.Name = "weekend"
		sep.Radius = params.WeekendRadius
		se.weekendEncoder = NewScalerEncoder(sep)
		se.width += se.weekendEncoder.getWidth()
		se.weekendOffset = se.weekendEncoder.getWidth()
		se.Description += fmt.Sprintf("weekend: %v", se.weekendOffset)

	}

	if params.HolidayWidth > 0 {
		// A "continuous" binary value. = 1 on the holiday itself and smooth ramp
		// 0->1 on the day before the holiday and 1->0 on the day after the holiday.

		sep := NewScalerEncoderParams(params.HolidayWidth, 0, 1)
		sep.Name = "holiday"
		sep.Radius = params.HolidayRadius
		se.holidayEncoder = NewScalerEncoder(sep)
		se.width += se.holidaEncoder.getWidth()
		se.holidayOffset = se.holidayEncoder.getWidth()
		se.description += fmt.Sprintf(" holiday %v", se.holidayOffset)
	}

	if params.TimeOfDayWidth > 0 {
		// Value is time of day in hours
		// Radius = 4 hours, e.g. morning, afternoon, evening, early night,
		// late night, etc.

		sep := NewScalerEncoderParams(params.TimeOfDayWidth, 0, 24)
		sep.Name = "time of day"
		sep.Radius = params.TimeOfDayRadius
		sep.Periodic = true
		se.timeOfDayEncoder = NewScalerEncoder(sep)
		se.width += se.timeOfDayEncoder.getWidth()
		se.timeOfDayOffset = se.timeOfDayEncoder.Width
		se.Description += fmt.Sprintf(" time of day: %v ", se.timeOfDayOffset)
	}

	return se
}
<commit_msg>implement getEncodedValues()<commit_after>package encoders

import (
	"fmt"
	//"github.com/cznic/mathutil"
	//"github.com/zacg/floats"
	//"github.com/nupic-community/htm"
	"github.com/nupic-community/htm/utils"
	//"github.com/zacg/ints"
	//"math"
	"time"
)

/*
	Params for the date encoder
*/
type DateEncoderParams struct {
	HolidayWidth    int
	HolidayRadius   float64
	SeasonWidth     int
	SeasonRadius    float64
	DayOfWeekWidth  int
	DayOfWeekRadius float64
	WeekendWidth    int
	WeekendRadius   float64
	TimeOfDayWidth  int
	TimeOfDayRadius float64
	//CustomDays     int
	Name string
}

func NewDateEncoderParams() *DateEncoderParams {
	p := new(DateEncoderParams)

	//set defaults
	p.SeasonRadius = 91.5 //days
	p.DayOfWeekRadius = 1
	p.TimeOfDayRadius = 4
	p.WeekendRadius = 1
	p.HolidayRadius = 1

	return p
}

/*
	Date encoder encodes a datetime to a SDR. Params allow for tuning
	for specific date attributes
*/
type DateEncoder struct {
	DateEncoderParams
	seasonEncoder    *ScalerEncoder
	holidayEncoder   *ScalerEncoder
	dayOfWeekEncoder *ScalerEncoder
	weekendEncoder   *ScalerEncoder
	timeOfDayEncoder *ScalerEncoder

	width           int
	seasonOffset    int
	weekendOffset   int
	dayOfWeekOffset int
	holidayOffset   int
	timeOfDayOffset int
	Description     string
}

/*
	Intializes a new date encoder
*/
func NewDateEncoder(params *DateEncoderParams) *DateEncoder {
	se := new(DateEncoder)

	se.DateEncoderParams = *params

	se.width = 0

	if params.SeasonWidth != 0 {
		// Ignore leapyear differences -- assume 366 days in a year
		// Radius = 91.5 days = length of season
		// Value is number of days since beginning of year (0 - 355)

		sep := NewScalerEncoderParams(params.SeasonWidth, 0, 366)
		sep.Name = "Season"
		sep.Periodic = true
		se.seasonEncoder = NewScalerEncoder(sep)
		se.seasonOffset = se.seasonEncoder.Width
		se.width += se.seasonEncoder.Width
		se.Description += fmt.Sprintf("season %v", se.seasonOffset)
	}

	if params.DayOfWeekWidth != 0 {
		// Value is day of week (floating point)
		// Radius is 1 day

		sep := NewScalerEncoderParams(params.DayOfWeekWidth, 0, 7)
		sep.Radius = params.DayOfWeekRadius
		sep.Name = "day of week"
		se.dayOfWeekEncoder = NewScalerEncoder(sep)
		se.dayOfWeekOffset = se.dayOfWeekEncoder.Width
		se.Description += fmt.Sprintf(" day of week: %v", se.dayOfWeekOffset)
		se.width += se.dayOfWeekEncoder.Width
	}

	if params.WeekendWidth != 0 {
		// Binary value. Not sure if this makes sense. Also is somewhat redundant
		// with dayOfWeek
		//Append radius if it was not provided

		sep := NewScalerEncoderParams(params.WeekendWidth, 0, 1)
		sep.Name = "weekend"
		sep.Radius = params.WeekendRadius
		se.weekendEncoder = NewScalerEncoder(sep)
		se.width += se.weekendEncoder.Width
		se.weekendOffset = se.weekendEncoder.Width
		se.Description += fmt.Sprintf("weekend: %v", se.weekendOffset)

	}

	if params.HolidayWidth > 0 {
		// A "continuous" binary value. = 1 on the holiday itself and smooth ramp
		// 0->1 on the day before the holiday and 1->0 on the day after the holiday.

		sep := NewScalerEncoderParams(params.HolidayWidth, 0, 1)
		sep.Name = "holiday"
		sep.Radius = params.HolidayRadius
		se.holidayEncoder = NewScalerEncoder(sep)
		se.width += se.holidayEncoder.Width
		se.holidayOffset = se.holidayEncoder.Width
		se.Description += fmt.Sprintf(" holiday %v", se.holidayOffset)
	}

	if params.TimeOfDayWidth > 0 {
		// Value is time of day in hours
		// Radius = 4 hours, e.g. morning, afternoon, evening, early night,
		// late night, etc.

		sep := NewScalerEncoderParams(params.TimeOfDayWidth, 0, 24)
		sep.Name = "time of day"
		sep.Radius = params.TimeOfDayRadius
		sep.Periodic = true
		se.timeOfDayEncoder = NewScalerEncoder(sep)
		se.width += se.timeOfDayEncoder.Width
		se.timeOfDayOffset = se.timeOfDayEncoder.Width
		se.Description += fmt.Sprintf(" time of day: %v ", se.timeOfDayOffset)
	}

	return se
}

/*
	Get the scalar values for each subfield of the date encoder
*/
func (de *DateEncoder) getEncodedValues(date time.Time) []float64 {

	values := make([]float64, 0, 5)

	timeOfDay := date.Hour() + date.Minute()/60.0
	dayOfWeek := date.Weekday()

	if de.seasonEncoder != nil {
		//make year 0 based
		dayOfYear := float64(date.YearDay() - 1)
		values = append(values, dayOfYear)
	}

	if de.dayOfWeekEncoder != nil {

		values = append(values, float64(dayOfWeek))
	}

	if de.weekendEncoder != nil {
		// saturday, sunday or friday evening
		weekend := 0.0
		if dayOfWeek == time.Saturday ||
			dayOfWeek == time.Sunday ||
			(dayOfWeek == time.Friday && timeOfDay > 18) {
			weekend = 1.0
		}
		values = append(values, weekend)
	}

	if de.holidayEncoder != nil {
		// A "continuous" binary value. = 1 on the holiday itself and smooth ramp
		// 0->1 on the day before the holiday and 1->0 on the day after the holiday.
		// Currently the only holiday we know about is December 25
		// holidays is a list of holidays that occur on a fixed date every year
		val := 0.0
		holidays := []utils.TupleInt{{12, 25}}

		for _, h := range holidays {
			// hdate is midnight on the holiday
			hDate := time.Date(date.Year(), time.Month(h.A), h.B, 0, 0, 0, 0, nil)
			if date.After(hDate) {
				diff := date.Sub(hDate)
				if (diff/time.Hour)/24 == 0 {
					val = 1
					break
				} else if (diff/time.Hour)/24 == 1 {
					// ramp smoothly from 1 -> 0 on the next day
					val = 1.0 - (float64(diff/time.Second) / (86400))
					break
				}
			} else {
				diff := hDate.Sub(date)
				if (diff/time.Hour)/24 == 1 {
					// ramp smoothly from 0 -> 1 on the previous day
					val = 1.0 - (float64(diff/time.Second) / 86400)
				}

			}
		}

		values = append(values, val)
	}

	if de.timeOfDayEncoder != nil {
		values = append(values, float64(timeOfDay))
	}

	return values
}
<|endoftext|>


<commit_before>package cmd

import (
	"log"
	"os"

	"github.com/bkittelmann/pinboard-checker/pinboard"
	"github.com/spf13/cobra"
)

var token string
var inputFile string
var inputFormat string
var outputFile string
var outputFormat string
var verbose bool
var noColor bool

func init() {
	checkCmd.Flags().StringVarP(&token, "token", "t", "", "The pinboard API token")
	checkCmd.Flags().StringVarP(&inputFile, "inputFile", "i", "", "File containing links to check")
	checkCmd.Flags().StringVar(&inputFormat, "inputFormat", "json", "Format of file with links. Can be either 'json' (default) or 'txt'")
	checkCmd.Flags().StringVarP(&outputFile, "outputFile", "o", "-", "Where the report should be written to")
	checkCmd.Flags().StringVar(&outputFormat, "outputFormat", "txt", "Allowed values are 'txt' (default) or 'json'")
	checkCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Verbose logging, will report successful link lookups")
	checkCmd.Flags().BoolVar(&noColor, "noColor", false, "Do not use colorized status output")

	RootCmd.AddCommand(checkCmd)
}

func makeReporter(format string) pinboard.Reporter {
	var reporter pinboard.Reporter
	switch format {
	case "json":
		reporter = pinboard.NewJSONReporter(verbose)
	case "txt":
		reporter = pinboard.NewSimpleFailureReporter(verbose, !noColor)
	default:
		log.Fatalf("'%s' is not a valid value for 'outputFormat'", format)
	}
	return reporter
}

var checkCmd = &cobra.Command{
	Use:   "check",
	Short: "Check for stale links",
	Long:  "...",

	Run: func(cmd *cobra.Command, args []string) {
		reporter := makeReporter(outputFormat)

		var bookmarks []pinboard.Bookmark
		if len(inputFile) > 0 {
			file, _ := os.Open(inputFile)
			bookmarks = pinboard.GetBookmarksFromFile(file, inputFormat)
		} else {
			bookmarks, _ = pinboard.GetAllBookmarks(token)
		}

		pinboard.CheckAll(bookmarks, reporter)
	},
}
<commit_msg>Read from stdin if input file name is '-'<commit_after>package cmd

import (
	"io"
	"log"
	"os"

	"github.com/bkittelmann/pinboard-checker/pinboard"
	"github.com/spf13/cobra"
)

var token string
var inputFile string
var inputFormat string
var outputFile string
var outputFormat string
var verbose bool
var noColor bool

func init() {
	checkCmd.Flags().StringVarP(&token, "token", "t", "", "The pinboard API token")
	checkCmd.Flags().StringVarP(&inputFile, "inputFile", "i", "", "File containing links to check. To read stdin use '-'.")
	checkCmd.Flags().StringVar(&inputFormat, "inputFormat", "json", "Format of file with links. Can be either 'json' (default) or 'txt'")
	checkCmd.Flags().StringVarP(&outputFile, "outputFile", "o", "-", "Where the report should be written to")
	checkCmd.Flags().StringVar(&outputFormat, "outputFormat", "txt", "Allowed values are 'txt' (default) or 'json'")
	checkCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Verbose logging, will report successful link lookups")
	checkCmd.Flags().BoolVar(&noColor, "noColor", false, "Do not use colorized status output")

	RootCmd.AddCommand(checkCmd)
}

func makeReporter(format string) pinboard.Reporter {
	var reporter pinboard.Reporter
	switch format {
	case "json":
		reporter = pinboard.NewJSONReporter(verbose)
	case "txt":
		reporter = pinboard.NewSimpleFailureReporter(verbose, !noColor)
	default:
		log.Fatalf("'%s' is not a valid value for 'outputFormat'", format)
	}
	return reporter
}

var checkCmd = &cobra.Command{
	Use:   "check",
	Short: "Check for stale links",
	Long:  "...",

	Run: func(cmd *cobra.Command, args []string) {
		reporter := makeReporter(outputFormat)

		var bookmarks []pinboard.Bookmark
		if len(inputFile) > 0 {
			var file io.Reader
			if inputFile == "-" {
				file = os.Stdin
			} else {
				file, _ = os.Open(inputFile)
			}
			bookmarks = pinboard.GetBookmarksFromFile(file, inputFormat)
		} else {
			bookmarks, _ = pinboard.GetAllBookmarks(token)
		}

		pinboard.CheckAll(bookmarks, reporter)
	},
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package main

import (
        `fmt`
        `time`
        `github.com/michaeldv/donna`
)

func repl() {
        var game *donna.Game
        var move *donna.Move
        var position *donna.Position

        for command := ``; ; command = `` {
                fmt.Print(`donna> `)
                fmt.Scanf(`%s`, &command)
                switch command {
                case ``:
                case `bench`:
                        benchmark()
                case `perft`:
                        perft(5)
                case `exit`, `quit`:
                        return
                case `help`:
                        fmt.Println(`help: not implemented yet.`)
                case `new`:
                        game = donna.NewGame().InitialPosition()
                        position = game.Start(donna.White)
                        fmt.Printf("%s\n", position)
                case `go`:
                        if game == nil || position == nil {
                                game = donna.NewGame().InitialPosition()
                                position = game.Start(donna.White)
                        }
                        move = game.Think(3, position)
                        position = position.MakeMove(move)
                        fmt.Printf("%s\n", position)
                default:
                        if game == nil || position == nil {
                                game = donna.NewGame().InitialPosition()
                                position = game.Start(donna.White)
                        }
                        move = donna.NewMoveFromString(command, position)
                        if move != nil {
                                position = position.MakeMove(move)
                                fmt.Printf("%s\n", position)
                                move = game.Think(3, position)
                                position = position.MakeMove(move)
                                fmt.Printf("%s\n", position)
                        } else {
                                fmt.Printf("%s appears to be an invalid move.\n", command)
                        }
                }
        }
}

func main() {
        donna.Settings.Log = false//true
        donna.Settings.Fancy = true

        // donna.NewGame().Setup(`Ka7,Qb1,Bg2`, `Ka5,b3,g3`).Think(4, nil) // Qb2
        // donna.NewGame().Setup(`Kh5,Qg7,Be5,f2,f3`, `Kh1`).Think(4, nil) // Bh2
        // donna.NewGame().Setup(`Kd3,Rd8,a5,b2,f2,g5`, `Kd1`).Think(4, nil) // Rd4
        repl()
}

//
// Bobby Fischer vs. James Sherwin, New Jersey Open 1957 after 16 moves.
// http://www.chessgames.com/perl/chessgame?gid=1008366
// Fischer played 17. h2-h4
//
func benchmark() {
        game := donna.NewGame().Setup(`Kg1,Qc2,Ra1,Re1,Bc1,Bg2,Ng5,a2,b2,c3,d4,f2,g3,h2`,
                                      `Kg8,Qd6,Ra8,Rf8,Bc8,Nd5,Ng6,a7,b6,c4,e6,f7,g7,h7`)

        fmt.Printf("%s\n", game)
        for i := 0;  i < 3; i++ {
                game.Think(3, nil)
        }
}

func perft(depth int) (total int64){
        p := donna.NewGame().InitialPosition().Start(donna.White)

        start := time.Now()
        gen := p.StartMoveGen(depth).GenerateMoves()
        for move := gen.NextMove(); move != nil; move = gen.NextMove() {
                if position := p.MakeMove(move); position != nil {
                        delta := position.Perft(depth - 1)
                        total += delta
                        position.TakeBack(move)
                        fmt.Printf("%7s - %d\n", move, delta)
                }
        }
        finish := time.Since(start).Seconds()
        fmt.Printf("\n  Nodes: %d\n", total)
        fmt.Printf("Elapsed: %.2fs\n", finish)
        fmt.Printf("Nodes/s: %.2f\n", float64(total) / finish)
        return
}
<commit_msg>Made perft run again<commit_after>// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package main

import (
        `fmt`
        `time`
        `github.com/michaeldv/donna`
)

func repl() {
        var game *donna.Game
        var position *donna.Position
        var move donna.Move

        for command := ``; ; command = `` {
                fmt.Print(`donna> `)
                fmt.Scanf(`%s`, &command)
                switch command {
                case ``:
                case `bench`:
                        benchmark()
                case `perft`:
                        perft(5)
                case `exit`, `quit`:
                        return
                case `help`:
                        fmt.Println(`help: not implemented yet.`)
                case `new`:
                        game = donna.NewGame().InitialPosition()
                        position = game.Start(donna.White)
                        fmt.Printf("%s\n", position)
                case `go`:
                        if game == nil || position == nil {
                                game = donna.NewGame().InitialPosition()
                                position = game.Start(donna.White)
                        }
                        move = game.Think(3, position)
                        position = position.MakeMove(move)
                        fmt.Printf("%s\n", position)
                default:
                        if game == nil || position == nil {
                                game = donna.NewGame().InitialPosition()
                                position = game.Start(donna.White)
                        }
                        move = donna.NewMoveFromString(command, position)
                        if move != 0 {
                                position = position.MakeMove(move)
                                fmt.Printf("%s\n", position)
                                move = game.Think(3, position)
                                position = position.MakeMove(move)
                                fmt.Printf("%s\n", position)
                        } else {
                                fmt.Printf("%s appears to be an invalid move.\n", command)
                        }
                }
        }
}

func main() {
        donna.Settings.Log = false//true
        donna.Settings.Fancy = true

        // donna.NewGame().Setup(`Ka7,Qb1,Bg2`, `Ka5,b3,g3`).Think(4, nil) // Qb2
        // donna.NewGame().Setup(`Kh5,Qg7,Be5,f2,f3`, `Kh1`).Think(4, nil) // Bh2
        // donna.NewGame().Setup(`Kd3,Rd8,a5,b2,f2,g5`, `Kd1`).Think(4, nil) // Rd4
        repl()
}

//
// Bobby Fischer vs. James Sherwin, New Jersey Open 1957 after 16 moves.
// http://www.chessgames.com/perl/chessgame?gid=1008366
// Fischer played 17. h2-h4
//
func benchmark() {
        game := donna.NewGame().Setup(`Kg1,Qc2,Ra1,Re1,Bc1,Bg2,Ng5,a2,b2,c3,d4,f2,g3,h2`,
                                      `Kg8,Qd6,Ra8,Rf8,Bc8,Nd5,Ng6,a7,b6,c4,e6,f7,g7,h7`)

        fmt.Printf("%s\n", game)
        for i := 0;  i < 3; i++ {
                game.Think(3, nil)
        }
}

func perft(depth int) (total int64){
        p := donna.NewGame().InitialPosition().Start(donna.White)

        start := time.Now()
        gen := p.StartMoveGen(depth).GenerateMoves()
        for move := gen.NextMove(); move != 0; move = gen.NextMove() {
                if position := p.MakeMove(move); position != nil {
                        delta := position.Perft(depth - 1)
                        total += delta
                        position.TakeBack(move)
                        fmt.Printf("%7s - %d\n", move, delta)
                }
        }
        finish := time.Since(start).Seconds()
        fmt.Printf("\n  Nodes: %d\n", total)
        fmt.Printf("Elapsed: %.2fs\n", finish)
        fmt.Printf("Nodes/s: %.2f\n", float64(total) / finish)
        return
}
<|endoftext|>


<commit_before>// Copyright © 2017 Norwegian Tax Authority
//
// 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 cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

const SPEC_ILLEGAL = -1
const MISSING_FILE_REFERENCE = -2
const MISSING_CONFIGURATION = -3
const ILLEGAL_JSON_CONFIGURATION = -4
const CONFIGURATION_FILE_IN_ROOT = -5
const ERROR_READING_FILE = -6
const BOOBER_ERROR = -7
const ILLEGAL_FILE = -8
const INTERNAL_ERROR = -9

const SPEC_IS_FILE = 1
const SPEC_IS_FOLDER = 2

// Cobra Flag variables
var overrideFiles []string
var overrideValues []string
var dryRun bool
var showConfig bool

// Struct to represent data to the Boober interface
type BooberInferface struct {
	Env         string                     `json:"env"`
	App         string                     `json:"app"`
	Affiliation string                     `json:"affiliation"`
	Files       map[string]json.RawMessage `json:"files"`
	Overrides   map[string]json.RawMessage `json:"overrides"`
}

// Struct to represent return data from the Boober interface
type BooberReturn struct {
	Sources json.RawMessage `json:"sources"`
	Errors  []string        `json:"errors"`
	Valid   bool            `json:"valid"`
	Config  json.RawMessage `json:"config"`
}

// setupCmd represents the setup command
var setupCmd = &cobra.Command{
	Use:   `setup folder | file [-f file 'JSON Configuration String']`,
	Short: "Deploys an application to OpenShift based upon local configuration files",
	Long: `When used with a .json file as an argument, it will deploy the application referred to in the
file merged with about.json in the same folder, and about.json and aos-features.json in the parent folder`,
	Run: func(cmd *cobra.Command, args []string) {
		executeSetup(args)
	},
}

func executeSetup(args []string) {
	validateCode := validateCommand(args)

	var absolutePath string

	absolutePath, _ = filepath.Abs(args[0])

	var envFile string      // Filename for app
	var envFolder string    // Short folder name (Env)
	var folder string       // Absolute path of folder
	var parentFolder string // Absolute path of parent

	switch validateCode {
	case SPEC_IS_FILE:
		folder = filepath.Dir(absolutePath)
		envFile = filepath.Base(absolutePath)
	case SPEC_IS_FOLDER:
		folder = absolutePath
		envFile = ""
	}
	parentFolder = filepath.Dir(folder)
	envFolder = filepath.Base(folder)

	if folder == parentFolder {
		fmt.Println("Application configuration file cannot reside in root directory")
		os.Exit(CONFIGURATION_FILE_IN_ROOT)
	}

	// Initialize JSON

	var booberData BooberInferface
	booberData.App = strings.TrimSuffix(envFile, filepath.Ext(envFile)) //envFile
	booberData.Env = envFolder
	booberData.Affiliation = ""

	var returnMap = folder2map(folder, envFolder+"/")
	var returnMap2 = folder2map(parentFolder, "")

	booberData.Files = combineMaps(returnMap, returnMap2)
	booberData.Overrides = overrides2map(args)

	jsonByte, ok := json.Marshal(booberData)
	if !(ok == nil) {
		fmt.Println("Internal error in marshalling Boober data: " + ok.Error())
		os.Exit(INTERNAL_ERROR)
	}

	jsonStr := string(jsonByte)
	if dryRun {
		fmt.Println(string(prettyPrintJson(jsonStr)))
	} else {
		callBoober(jsonStr)
	}
}

func overrides2map(args []string) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)
	for i := 0; i < len(overrideFiles); i++ {
		returnMap[overrideFiles[i]] = json.RawMessage(args[i+1])
	}
	return returnMap
}

func folder2map(folder string, prefix string) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)
	var allFilesOK bool = true

	files, _ := ioutil.ReadDir(folder)
	var filesProcessed = 0
	for _, f := range files {
		absolutePath := filepath.Join(folder, f.Name())
		if isLegalFileFolder(absolutePath) == SPEC_IS_FILE { // Ignore folders
			matched, _ := filepath.Match("*.json", strings.ToLower(f.Name()))
			if matched {
				fileJson, err := ioutil.ReadFile(absolutePath)
				if err != nil {
					fmt.Println("Error in reading file " + absolutePath)
					os.Exit(ERROR_READING_FILE)
				}
				if isLegalJson(string(fileJson)) {
					filesProcessed++
					returnMap[prefix+f.Name()] = fileJson
				} else {
					fmt.Println("Illegal JSON in configuration file " + absolutePath)
					allFilesOK = false
				}
				filesProcessed++
			}
		}

	}
	if !allFilesOK {
		os.Exit(ILLEGAL_JSON_CONFIGURATION)
	}
	return returnMap
}

func combineMaps(map1 map[string]json.RawMessage, map2 map[string]json.RawMessage) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)

	for k, v := range map1 {
		returnMap[k] = v
	}
	for k, v := range map2 {
		returnMap[k] = v
	}
	return returnMap
}

func validateCommand(args []string) int {
	var errorString = ""
	var returnCode int

	if len(args) == 0 {
		returnCode = -1
		errorString += "Missing file/folder "
	} else {
		// Chceck argument 0 for legal file / folder
		returnCode = isLegalFileFolder(args[0])
		if returnCode < 0 {
			errorString += "Illegal file / folder: " + args[0]
			returnCode = ILLEGAL_FILE
		}

		// We have at least one argument, now there should be a correlation between the number of args
		// and the number of override (-f) flags
		if len(overrideFiles) < (len(args) - 1) {
			returnCode = MISSING_FILE_REFERENCE
			errorString += "Configuration override specified without file reference flag "
		}
		if len(overrideFiles) > (len(args) - 1) {
			returnCode = MISSING_CONFIGURATION
			errorString += "Configuration overide file reference flag specified without configuration "
		}

		// Check for legal JSON argument for each overrideFiles flag
		for i := 1; i < len(args); i++ {
			if !isLegalJson(args[i]) {
				errorString = "Illegal JSON configuration override: " + args[i] + " "
				returnCode = ILLEGAL_JSON_CONFIGURATION
			}
		}
	}

	if returnCode < 0 {
		fmt.Println(errorString)
		os.Exit(returnCode)
	}
	return returnCode

}

func isLegalFileFolder(filespec string) int {
	var err error
	var absolutePath string
	var fi os.FileInfo

	absolutePath, err = filepath.Abs(filespec)
	fi, err = os.Stat(absolutePath)
	if os.IsNotExist(err) {
		return SPEC_ILLEGAL
	} else {
		switch mode := fi.Mode(); {
		case mode.IsDir():
			return SPEC_IS_FOLDER
		case mode.IsRegular():
			return SPEC_IS_FILE
		}
	}
	return SPEC_ILLEGAL
}

func isLegalJson(jsonString string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(jsonString), &js) == nil
}

func prettyPrintJson(jsonString string) string {
	var out bytes.Buffer
	err := json.Indent(&out, []byte(jsonString), "", "\t")
	if err != nil {
		return jsonString
	}
	return out.String()
}

func callBoober(combindedJson string) {
	//url := "http://localhost:8080/api/setupMock/env/app"
	url := "http://localhost:8080/setup"
	var jsonStr = []byte(combindedJson)

	req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Content-Type", "application/json")
	if err != nil {
		fmt.Println("Internal error in NewRequest: ", err)
		os.Exit(INTERNAL_ERROR)
	}

	req.Header.Set("Authentication", "mydirtysecret")
	client := &http.Client{}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error connecting to the Boober service on "+url+": ", err)
		os.Exit(BOOBER_ERROR)
	}

	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		fmt.Println("Error from the Boober service on " + url + ":")
		body, _ := ioutil.ReadAll(resp.Body)
		fmt.Println(string(body))
		os.Exit(BOOBER_ERROR)
	}
	body, _ := ioutil.ReadAll(resp.Body)

	// Check return for error
	var booberReturn BooberReturn
	err = json.Unmarshal(body, &booberReturn)
	if err != nil {
		fmt.Println("Error unmashalling Boober return: " + err.Error())
		os.Exit(BOOBER_ERROR)
	}

	if !(booberReturn.Valid) {
		fmt.Println("Error in configuration: ")
		for _, message := range booberReturn.Errors {
			fmt.Println("  " + message)
		}
	}

	if showConfig {
		fmt.Println(prettyPrintJson(string(booberReturn.Config)))
	}

}

func init() {
	RootCmd.AddCommand(setupCmd)

	// File flag, supports multiple instances of the flag
	setupCmd.Flags().StringArrayVarP(&overrideFiles, "file",
		"f", overrideValues, "File to override")
	setupCmd.Flags().BoolVarP(&dryRun, "dryrun",
		"d", false,
		"Do not perform a setup, just collect and print the configuration files")
	setupCmd.Flags().BoolVarP(&showConfig, "showconfig",
		"s", false, "Send merged config from Boober to standard out")
}
<commit_msg>Code cleanup<commit_after>// Copyright © 2017 Norwegian Tax Authority
//
// 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 cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/spf13/cobra"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

const SPEC_ILLEGAL = -1
const MISSING_FILE_REFERENCE = -2
const MISSING_CONFIGURATION = -3
const ILLEGAL_JSON_CONFIGURATION = -4
const CONFIGURATION_FILE_IN_ROOT = -5
const ERROR_READING_FILE = -6
const BOOBER_ERROR = -7
const ILLEGAL_FILE = -8
const INTERNAL_ERROR = -9

const SPEC_IS_FILE = 1
const SPEC_IS_FOLDER = 2

// Cobra Flag variables
var overrideFiles []string
var overrideValues []string
var dryRun bool
var showConfig bool

// Struct to represent data to the Boober interface
type BooberInferface struct {
	Env         string                     `json:"env"`
	App         string                     `json:"app"`
	Affiliation string                     `json:"affiliation"`
	Files       map[string]json.RawMessage `json:"files"`
	Overrides   map[string]json.RawMessage `json:"overrides"`
}

// Struct to represent return data from the Boober interface
type BooberReturn struct {
	Sources json.RawMessage `json:"sources"`
	Errors  []string        `json:"errors"`
	Valid   bool            `json:"valid"`
	Config  json.RawMessage `json:"config"`
}

// setupCmd represents the setup command
var setupCmd = &cobra.Command{
	Use:   `setup folder | file [-f file 'JSON Configuration String']`,
	Short: "Deploys an application to OpenShift based upon local configuration files",
	Long: `When used with a .json file as an argument, it will deploy the application referred to in the
file merged with about.json in the same folder, and about.json and aos-features.json in the parent folder`,
	Run: func(cmd *cobra.Command, args []string) {
		executeSetup(args)
	},
}

func executeSetup(args []string) {
	validateCode := validateCommand(args)

	var absolutePath string

	absolutePath, _ = filepath.Abs(args[0])

	var envFile string      // Filename for app
	var envFolder string    // Short folder name (Env)
	var folder string       // Absolute path of folder
	var parentFolder string // Absolute path of parent

	switch validateCode {
	case SPEC_IS_FILE:
		folder = filepath.Dir(absolutePath)
		envFile = filepath.Base(absolutePath)
	case SPEC_IS_FOLDER:
		folder = absolutePath
		envFile = ""
	}
	parentFolder = filepath.Dir(folder)
	envFolder = filepath.Base(folder)

	if folder == parentFolder {
		fmt.Println("Application configuration file cannot reside in root directory")
		os.Exit(CONFIGURATION_FILE_IN_ROOT)
	}

	// Initialize JSON

	var booberData BooberInferface
	booberData.App = strings.TrimSuffix(envFile, filepath.Ext(envFile)) //envFile
	booberData.Env = envFolder
	booberData.Affiliation = ""

	var returnMap = folder2map(folder, envFolder+"/")
	var returnMap2 = folder2map(parentFolder, "")

	booberData.Files = combineMaps(returnMap, returnMap2)
	booberData.Overrides = overrides2map(args)

	jsonByte, ok := json.Marshal(booberData)
	if !(ok == nil) {
		fmt.Println("Internal error in marshalling Boober data: " + ok.Error())
		os.Exit(INTERNAL_ERROR)
	}

	jsonStr := string(jsonByte)
	if dryRun {
		fmt.Println(string(prettyPrintJson(jsonStr)))
	} else {
		callBoober(jsonStr)
	}
}

func overrides2map(args []string) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)
	for i := 0; i < len(overrideFiles); i++ {
		returnMap[overrideFiles[i]] = json.RawMessage(args[i+1])
	}
	return returnMap
}

func folder2map(folder string, prefix string) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)
	var allFilesOK bool = true

	files, _ := ioutil.ReadDir(folder)
	var filesProcessed = 0
	for _, f := range files {
		absolutePath := filepath.Join(folder, f.Name())
		if isLegalFileFolder(absolutePath) == SPEC_IS_FILE { // Ignore folders
			matched, _ := filepath.Match("*.json", strings.ToLower(f.Name()))
			if matched {
				fileJson, err := ioutil.ReadFile(absolutePath)
				if err != nil {
					fmt.Println("Error in reading file " + absolutePath)
					os.Exit(ERROR_READING_FILE)
				}
				if isLegalJson(string(fileJson)) {
					filesProcessed++
					returnMap[prefix+f.Name()] = fileJson
				} else {
					fmt.Println("Illegal JSON in configuration file " + absolutePath)
					allFilesOK = false
				}
				filesProcessed++
			}
		}

	}
	if !allFilesOK {
		os.Exit(ILLEGAL_JSON_CONFIGURATION)
	}
	return returnMap
}

func combineMaps(map1 map[string]json.RawMessage, map2 map[string]json.RawMessage) map[string]json.RawMessage {
	var returnMap = make(map[string]json.RawMessage)

	for k, v := range map1 {
		returnMap[k] = v
	}
	for k, v := range map2 {
		returnMap[k] = v
	}
	return returnMap
}

func validateCommand(args []string) int {
	var errorString = ""
	var returnCode int

	if len(args) == 0 {
		returnCode = -1
		errorString += "Missing file/folder "
	} else {
		// Chceck argument 0 for legal file / folder
		returnCode = isLegalFileFolder(args[0])
		if returnCode < 0 {
			errorString += "Illegal file / folder: " + args[0]
			returnCode = ILLEGAL_FILE
		}

		// We have at least one argument, now there should be a correlation between the number of args
		// and the number of override (-f) flags
		if len(overrideFiles) < (len(args) - 1) {
			returnCode = MISSING_FILE_REFERENCE
			errorString += "Configuration override specified without file reference flag "
		}
		if len(overrideFiles) > (len(args) - 1) {
			returnCode = MISSING_CONFIGURATION
			errorString += "Configuration overide file reference flag specified without configuration "
		}

		// Check for legal JSON argument for each overrideFiles flag
		for i := 1; i < len(args); i++ {
			if !isLegalJson(args[i]) {
				errorString = "Illegal JSON configuration override: " + args[i] + " "
				returnCode = ILLEGAL_JSON_CONFIGURATION
			}
		}
	}

	if returnCode < 0 {
		fmt.Println(errorString)
		os.Exit(returnCode)
	}
	return returnCode

}

func isLegalFileFolder(filespec string) int {
	var err error
	var absolutePath string
	var fi os.FileInfo

	absolutePath, err = filepath.Abs(filespec)
	fi, err = os.Stat(absolutePath)
	if os.IsNotExist(err) {
		return SPEC_ILLEGAL
	} else {
		switch mode := fi.Mode(); {
		case mode.IsDir():
			return SPEC_IS_FOLDER
		case mode.IsRegular():
			return SPEC_IS_FILE
		}
	}
	return SPEC_ILLEGAL
}

func isLegalJson(jsonString string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(jsonString), &js) == nil
}

func prettyPrintJson(jsonString string) string {
	var out bytes.Buffer
	err := json.Indent(&out, []byte(jsonString), "", "\t")
	if err != nil {
		return jsonString
	}
	return out.String()
}

func callBoober(combindedJson string) {
	//url := "http://localhost:8080/api/setupMock/env/app"
	url := "http://localhost:8080/setup"
	var jsonStr = []byte(combindedJson)

	req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Content-Type", "application/json")
	if err != nil {
		fmt.Println("Internal error in NewRequest: ", err)
		os.Exit(INTERNAL_ERROR)
	}

	req.Header.Set("Authentication", "mydirtysecret")
	client := &http.Client{}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error connecting to the Boober service on "+url+": ", err)
		os.Exit(BOOBER_ERROR)
	}

	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		fmt.Println("Error from the Boober service on " + url + ":")
		body, _ := ioutil.ReadAll(resp.Body)
		fmt.Println(string(body))
		os.Exit(BOOBER_ERROR)
	}
	body, _ := ioutil.ReadAll(resp.Body)

	// Check return for error
	var booberReturn BooberReturn
	err = json.Unmarshal(body, &booberReturn)
	if err != nil {
		fmt.Println("Error unmashalling Boober return: " + err.Error())
		os.Exit(BOOBER_ERROR)
	}

	if !(booberReturn.Valid) {
		fmt.Println("Error in configuration: ")
		for _, message := range booberReturn.Errors {
			fmt.Println("  " + message)
		}
	}

	if showConfig {
		fmt.Println(prettyPrintJson(string(booberReturn.Config)))
	}

}

func init() {
	RootCmd.AddCommand(setupCmd)

	// File flag, supports multiple instances of the flag
	setupCmd.Flags().StringArrayVarP(&overrideFiles, "file",
		"f", overrideValues, "File to override")
	setupCmd.Flags().BoolVarP(&dryRun, "dryrun",
		"d", false,
		"Do not perform a setup, just collect and print the configuration files")
	setupCmd.Flags().BoolVarP(&showConfig, "showconfig",
		"s", false, "Send merged config from Boober to standard out")
}
<|endoftext|>