<commit_before>package main

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"

	log "github.com/Sirupsen/logrus"
)

type DBClient struct {
	cache Cache
	http  *http.Client
}

// request holds structure for request
type request struct {
	URL    string
	Method string
}

// hash returns unique hash key for request
// TODO: match on destination, request body, etc..
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, fmt.Sprintf("%s%s", r.URL, r.Method))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type res struct {
	Status  int               `json:"status"`
	Body    []byte            `json:"body"`
	Headers map[string]string `json:"headers"`
}

// recordRequest saves request for later playback
func (d *DBClient) recordRequest(req *http.Request) (*http.Response, error) {

	// forwarding request
	resp, err := d.doRequest(req)

	go d.save(req, resp)

	// return new response or error here
	return resp, err
}

func (d *DBClient) save(req *http.Request, resp *http.Response) {
	// record request here
	key := getRequestFingerprint(req)

	body, err := ioutil.ReadAll(resp.Body)

	response := res{
		Status:  resp.StatusCode,
		Body:    body,
		Headers: getHeadersMap(resp.Header),
	}

	log.WithFields(log.Fields{
		"requestURL":    req.URL.Path,
		"requestMethod": req.Method,
		"hashKey":       key,
	}).Info("Recording")

	// converting it to json bytes
	bts, err := json.Marshal(response)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to marshal json")
	} else {
		d.cache.set(key, bts)
	}

}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request) string {
	r := request{URL: req.URL.Path, Method: req.Method}
	return r.hash()
}

// getHeadersMap converts map[string][]string to map[string]string structure
func getHeadersMap(hds map[string][]string) map[string]string {
	headers := make(map[string]string)
	for key, value := range hds {
		headers[key] = value[0]
	}
	return headers
}

func (d *DBClient) getResponse(r *http.Request) *http.Response {
	log.Info("Returning response")
	return nil
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {
	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("Could not forward request.")
		return nil, err
	}

	log.WithFields(log.Fields{}).Info("Request forwarded!")

	resp.Header.Set("Gen-proxy", "Was-Here")
	return resp, nil

}
<commit_msg>memory leak fix<commit_after>package main

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"

	log "github.com/Sirupsen/logrus"
)

type DBClient struct {
	cache Cache
	http  *http.Client
}

// request holds structure for request
type request struct {
	URL    string
	Method string
}

// hash returns unique hash key for request
// TODO: match on destination, request body, etc..
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, fmt.Sprintf("%s%s", r.URL, r.Method))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type res struct {
	Status  int               `json:"status"`
	Body    []byte            `json:"body"`
	Headers map[string]string `json:"headers"`
}

// recordRequest saves request for later playback
func (d *DBClient) recordRequest(req *http.Request) (*http.Response, error) {

	// forwarding request
	resp, err := d.doRequest(req)

	go d.save(req, resp)

	// return new response or error here
	return resp, err
}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (d *DBClient) save(req *http.Request, resp *http.Response) {
	// record request here
	key := getRequestFingerprint(req)

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	response := res{
		Status:  resp.StatusCode,
		Body:    body,
		Headers: getHeadersMap(resp.Header),
	}

	log.WithFields(log.Fields{
		"requestURL":    req.URL.Path,
		"requestMethod": req.Method,
		"hashKey":       key,
	}).Info("Recording")

	// converting it to json bytes
	bts, err := json.Marshal(response)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to marshal json")
	} else {
		d.cache.set(key, bts)
	}

}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request) string {
	r := request{URL: req.URL.Path, Method: req.Method}
	return r.hash()
}

// getHeadersMap converts map[string][]string to map[string]string structure
func getHeadersMap(hds map[string][]string) map[string]string {
	headers := make(map[string]string)
	for key, value := range hds {
		headers[key] = value[0]
	}
	return headers
}

func (d *DBClient) getResponse(r *http.Request) *http.Response {
	log.Info("Returning response")
	return nil
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {
	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("Could not forward request.")
		return nil, err
	}

	log.WithFields(log.Fields{}).Info("Request forwarded!")

	resp.Header.Set("Gen-proxy", "Was-Here")
	return resp, nil

}
<|endoftext|>


<commit_before>// +build linux, arm

// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#cgo LDFLAGS: -lwiringPi

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#define nil ((void*)0)

#define GEN_INTERRUPTER(PIN) static void interrupt_handler_##PIN() { \
	context ctxt;   \
	ctxt.pin = PIN;  \
	ctxt.ret = PIN;  \
	callback_func(goCallback, &ctxt); \
}

typedef struct context context;
struct context {
	int pin;
	int ret;
};

static void(*callback_func)(void (*f)(void*), void*);

extern void goCallback(void *);

GEN_INTERRUPTER(0)
GEN_INTERRUPTER(1)
GEN_INTERRUPTER(2)
GEN_INTERRUPTER(3)
GEN_INTERRUPTER(4)
GEN_INTERRUPTER(5)
GEN_INTERRUPTER(6)
GEN_INTERRUPTER(7)
GEN_INTERRUPTER(8)
GEN_INTERRUPTER(9)
GEN_INTERRUPTER(10)
GEN_INTERRUPTER(11)
GEN_INTERRUPTER(12)
GEN_INTERRUPTER(13)
GEN_INTERRUPTER(14)
GEN_INTERRUPTER(15)
GEN_INTERRUPTER(16)
GEN_INTERRUPTER(17)
GEN_INTERRUPTER(18)
GEN_INTERRUPTER(19)
GEN_INTERRUPTER(20)

static int native_wiring_isr(int pin, int mode) {
	switch(pin) {
		case 0: return wiringPiISR(pin, mode, &interrupt_handler_0);
		case 1: return wiringPiISR(pin, mode, &interrupt_handler_1);
		case 2: return wiringPiISR(pin, mode, &interrupt_handler_2);
		case 3: return wiringPiISR(pin, mode, &interrupt_handler_3);
		case 4: return wiringPiISR(pin, mode, &interrupt_handler_4);
		case 5: return wiringPiISR(pin, mode, &interrupt_handler_5);
		case 6: return wiringPiISR(pin, mode, &interrupt_handler_6);
		case 7: return wiringPiISR(pin, mode, &interrupt_handler_7);
		case 8: return wiringPiISR(pin, mode, &interrupt_handler_8);
		case 9: return wiringPiISR(pin, mode, &interrupt_handler_9);
		case 10: return wiringPiISR(pin, mode, &interrupt_handler_10);
		case 11: return wiringPiISR(pin, mode, &interrupt_handler_11);
		case 12: return wiringPiISR(pin, mode, &interrupt_handler_12);
		case 13: return wiringPiISR(pin, mode, &interrupt_handler_13);
		case 14: return wiringPiISR(pin, mode, &interrupt_handler_14);
		case 15: return wiringPiISR(pin, mode, &interrupt_handler_15);
		case 16: return wiringPiISR(pin, mode, &interrupt_handler_16);
		case 17: return wiringPiISR(pin, mode, &interrupt_handler_17);
		case 18: return wiringPiISR(pin, mode, &interrupt_handler_18);
		case 19: return wiringPiISR(pin, mode, &interrupt_handler_19);
		case 20: return wiringPiISR(pin, mode, &interrupt_handler_20);
	}
	return -1;
}

static void init(void *p) {
	callback_func = p;
}
*/
import "C"
import "unsafe"

import (
	"github.com/henryse/go-callback"
	"sync"
)

const (
	WPI_MODE_PINS          = C.WPI_MODE_PINS
	WPI_MODE_GPIO          = C.WPI_MODE_GPIO
	WPI_MODE_GPIO_SYS      = C.WPI_MODE_GPIO_SYS
	WPI_MODE_PIFACE        = C.WPI_MODE_PIFACE
	WPI_MODE_UNINITIALISED = C.WPI_MODE_UNINITIALISED

	INPUT      = C.INPUT
	OUTPUT     = C.OUTPUT
	PWM_OUTPUT = C.PWM_OUTPUT
	GPIO_CLOCK = C.GPIO_CLOCK

	LOW  = C.LOW
	HIGH = C.HIGH

	PUD_OFF  = C.PUD_OFF
	PUD_DOWN = C.PUD_DOWN
	PUD_UP   = C.PUD_UP

	PWM_MODE_MS  = C.PWM_MODE_MS
	PWM_MODE_BAL = C.PWM_MODE_BAL

	INT_EDGE_SETUP   = C.INT_EDGE_SETUP
	INT_EDGE_FALLING = C.INT_EDGE_FALLING
	INT_EDGE_RISING  = C.INT_EDGE_RISING
	INT_EDGE_BOTH    = C.INT_EDGE_BOTH
)

var mutex = &sync.Mutex{}

func internalPinToGpio(pin int) int {
	return int(C.wpiPinToGpio(C.int(pin)))
}

func internalSetup() int {
	return int(C.wiringPiSetup())
}

func internalSetupGpio() int {
	return int(C.wiringPiSetupGpio())
}

func internalSetupPhys() int {
	return int(C.wiringPiSetupPhys())
}

func internalSetupSys() int {
	return int(C.wiringPiSetupSys())
}

func internalPinMode(pin int, mode int) {
	C.pinMode(C.int(pin), C.int(mode))
}

func internalPullUpDnControl(pin int, pud int) {
	C.pullUpDnControl(C.int(pin), C.int(pud))
}

func internalPwmWrite(pin int, value int) {
	C.pwmWrite(C.int(pin), C.int(value))
}

func internalDigitalWrite(pin int, mode int) {
	C.digitalWrite(C.int(pin), C.int(mode))
}

func internalDigitalRead(pin int) int {
	return int(C.digitalRead(C.int(pin)))
}

func internalGetMode(pin int) int {
	return int(C.getAlt(C.int(pin)))
}

func internalDelay(ms int) {
	C.delay(C.uint(ms))
}

func internalDelayMicroseconds(microSec int) {
	C.delayMicroseconds(C.uint(microSec))
}

func internalWiringISR(pin int, mode int) chan int {
	mutex.Lock()
	defer mutex.Unlock()
	if interrupt_channels[pin] == nil {
		interrupt_channels[pin] = make(chan int)
	}
	C.native_wiring_isr(C.int(pin), C.int(mode))
	return interrupt_channels[pin]
}

func init() {
	C.init(callback.Func)
}

var interrupt_channels = [64]chan int{}

//export goCallback
func goCallback(arg unsafe.Pointer) {
	ctxt := (*C.context)(arg)
	interrupt_channels[int(ctxt.pin)] <- int(ctxt.ret)
}

// This initialises the I2C system with your given device identifier.
// The ID is the I2C number of the device and you can use the i2cdetect
// program to find this out. wiringPiI2CSetup() will work out which
// revision Raspberry Pi you have and open the appropriate device in /dev.
//
// The return value is the standard Linux filehandle, or -1 if any
// error – in which case, you can consult errno as usual.
//
func internalSetupI2C(devId int) int {
	return int(C.wiringPiI2CSetup(C.int(devId)))
}

// Simple device read. Some devices present data when you read them
// without having to do any register transactions.
//
func internalI2CRead(fd int) int {
	return int(C.wiringPiI2CRead(C.int(fd)))
}
<commit_msg>Disable optimizations.<commit_after>// +build linux, arm

// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#cgo LDFLAGS: -lwiringPi
#cgo CFLAGS: -O0

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#define nil ((void*)0)

#define GEN_INTERRUPTER(PIN) static void interrupt_handler_##PIN() { \
	context ctxt;   \
	ctxt.pin = PIN;  \
	ctxt.ret = PIN;  \
	callback_func(goCallback, &ctxt); \
}

typedef struct context context;
struct context {
	int pin;
	int ret;
};

static void(*callback_func)(void (*f)(void*), void*);

extern void goCallback(void *);

GEN_INTERRUPTER(0)
GEN_INTERRUPTER(1)
GEN_INTERRUPTER(2)
GEN_INTERRUPTER(3)
GEN_INTERRUPTER(4)
GEN_INTERRUPTER(5)
GEN_INTERRUPTER(6)
GEN_INTERRUPTER(7)
GEN_INTERRUPTER(8)
GEN_INTERRUPTER(9)
GEN_INTERRUPTER(10)
GEN_INTERRUPTER(11)
GEN_INTERRUPTER(12)
GEN_INTERRUPTER(13)
GEN_INTERRUPTER(14)
GEN_INTERRUPTER(15)
GEN_INTERRUPTER(16)
GEN_INTERRUPTER(17)
GEN_INTERRUPTER(18)
GEN_INTERRUPTER(19)
GEN_INTERRUPTER(20)

static int native_wiring_isr(int pin, int mode) {
	switch(pin) {
		case 0: return wiringPiISR(pin, mode, &interrupt_handler_0);
		case 1: return wiringPiISR(pin, mode, &interrupt_handler_1);
		case 2: return wiringPiISR(pin, mode, &interrupt_handler_2);
		case 3: return wiringPiISR(pin, mode, &interrupt_handler_3);
		case 4: return wiringPiISR(pin, mode, &interrupt_handler_4);
		case 5: return wiringPiISR(pin, mode, &interrupt_handler_5);
		case 6: return wiringPiISR(pin, mode, &interrupt_handler_6);
		case 7: return wiringPiISR(pin, mode, &interrupt_handler_7);
		case 8: return wiringPiISR(pin, mode, &interrupt_handler_8);
		case 9: return wiringPiISR(pin, mode, &interrupt_handler_9);
		case 10: return wiringPiISR(pin, mode, &interrupt_handler_10);
		case 11: return wiringPiISR(pin, mode, &interrupt_handler_11);
		case 12: return wiringPiISR(pin, mode, &interrupt_handler_12);
		case 13: return wiringPiISR(pin, mode, &interrupt_handler_13);
		case 14: return wiringPiISR(pin, mode, &interrupt_handler_14);
		case 15: return wiringPiISR(pin, mode, &interrupt_handler_15);
		case 16: return wiringPiISR(pin, mode, &interrupt_handler_16);
		case 17: return wiringPiISR(pin, mode, &interrupt_handler_17);
		case 18: return wiringPiISR(pin, mode, &interrupt_handler_18);
		case 19: return wiringPiISR(pin, mode, &interrupt_handler_19);
		case 20: return wiringPiISR(pin, mode, &interrupt_handler_20);
	}
	return -1;
}

static void init(void *p) {
	callback_func = p;
}
*/
import "C"
import "unsafe"

import (
	"sync"
)

const (
	WPI_MODE_PINS          = C.WPI_MODE_PINS
	WPI_MODE_GPIO          = C.WPI_MODE_GPIO
	WPI_MODE_GPIO_SYS      = C.WPI_MODE_GPIO_SYS
	WPI_MODE_PIFACE        = C.WPI_MODE_PIFACE
	WPI_MODE_UNINITIALISED = C.WPI_MODE_UNINITIALISED

	INPUT      = C.INPUT
	OUTPUT     = C.OUTPUT
	PWM_OUTPUT = C.PWM_OUTPUT
	GPIO_CLOCK = C.GPIO_CLOCK

	LOW  = C.LOW
	HIGH = C.HIGH

	PUD_OFF  = C.PUD_OFF
	PUD_DOWN = C.PUD_DOWN
	PUD_UP   = C.PUD_UP

	PWM_MODE_MS  = C.PWM_MODE_MS
	PWM_MODE_BAL = C.PWM_MODE_BAL

	INT_EDGE_SETUP   = C.INT_EDGE_SETUP
	INT_EDGE_FALLING = C.INT_EDGE_FALLING
	INT_EDGE_RISING  = C.INT_EDGE_RISING
	INT_EDGE_BOTH    = C.INT_EDGE_BOTH
)

var mutex = &sync.Mutex{}

func internalPinToGpio(pin int) int {
	return int(C.wpiPinToGpio(C.int(pin)))
}

func internalSetup() int {
	return int(C.wiringPiSetup())
}

func internalSetupGpio() int {
	return int(C.wiringPiSetupGpio())
}

func internalSetupPhys() int {
	return int(C.wiringPiSetupPhys())
}

func internalSetupSys() int {
	return int(C.wiringPiSetupSys())
}

func internalPinMode(pin int, mode int) {
	C.pinMode(C.int(pin), C.int(mode))
}

func internalPullUpDnControl(pin int, pud int) {
	C.pullUpDnControl(C.int(pin), C.int(pud))
}

func internalPwmWrite(pin int, value int) {
	C.pwmWrite(C.int(pin), C.int(value))
}

func internalDigitalWrite(pin int, mode int) {
	C.digitalWrite(C.int(pin), C.int(mode))
}

func internalDigitalRead(pin int) int {
	return int(C.digitalRead(C.int(pin)))
}

func internalGetMode(pin int) int {
	return int(C.getAlt(C.int(pin)))
}

func internalDelay(ms int) {
	C.delay(C.uint(ms))
}

func internalDelayMicroseconds(microSec int) {
	C.delayMicroseconds(C.uint(microSec))
}

func internalWiringISR(pin int, mode int) chan int {
	mutex.Lock()
	defer mutex.Unlock()
	if interrupt_channels[pin] == nil {
		interrupt_channels[pin] = make(chan int)
	}
	C.native_wiring_isr(C.int(pin), C.int(mode))
	return interrupt_channels[pin]
}

func init() {
	C.init(callback.Func)
}

var interrupt_channels = [64]chan int{}

//export goCallback
func goCallback(arg unsafe.Pointer) {
	ctxt := (*C.context)(arg)
	interrupt_channels[int(ctxt.pin)] <- int(ctxt.ret)
}

// This initialises the I2C system with your given device identifier.
// The ID is the I2C number of the device and you can use the i2cdetect
// program to find this out. wiringPiI2CSetup() will work out which
// revision Raspberry Pi you have and open the appropriate device in /dev.
//
// The return value is the standard Linux filehandle, or -1 if any
// error – in which case, you can consult errno as usual.
//
func internalSetupI2C(devId int) int {
	return int(C.wiringPiI2CSetup(C.int(devId)))
}

// Simple device read. Some devices present data when you read them
// without having to do any register transactions.
//
func internalI2CRead(fd int) int {
	return int(C.wiringPiI2CRead(C.int(fd)))
}
<|endoftext|>


<commit_before>package transforms

import (
	"math"

	"github.com/go-audio/audio"
)

// PCMScale converts a buffer with audio content from -1 to 1 into
// the PCM scale based on the passed bitdepth.
// Note that while the PCM data is scaled, the PCM format is not changed.
func PCMScale(buf *audio.FloatBuffer, bitDepth int) error {
	if buf == nil || buf.Format == nil {
		return audio.ErrInvalidBuffer
	}
	factor := math.Pow(2, 8*float64(bitDepth/8)-1)
	for i := 0; i < len(buf.Data); i++ {
		buf.Data[i] *= factor
	}

	return nil
}

// PCMScaleF32 converts a buffer with audio content from -1 to 1 (float32) into
// the PCM scale based on the passed bitdepth.
// Note that while the PCM data is scaled, the PCM format is not changed.
func PCMScaleF32(buf *audio.Float32Buffer, bitDepth int) error {
	if buf == nil || buf.Format == nil {
		return audio.ErrInvalidBuffer
	}
	factor := float32(math.Pow(2, float64(bitDepth)-1)) - 1.0
	for i := 0; i < len(buf.Data); i++ {
		buf.Data[i] *= factor
	}

	return nil
}
<commit_msg>update buffer source bit depth when scaling/normalizing<commit_after>package transforms

import (
	"math"

	"github.com/go-audio/audio"
)

// PCMScale converts a buffer with audio content from -1 to 1 into
// the PCM scale based on the passed bitdepth.
// Note that while the PCM data is scaled, the PCM format is not changed.
func PCMScale(buf *audio.FloatBuffer, bitDepth int) error {
	if buf == nil || buf.Format == nil {
		return audio.ErrInvalidBuffer
	}
	factor := math.Pow(2, 8*float64(bitDepth/8)-1)
	for i := 0; i < len(buf.Data); i++ {
		buf.Data[i] *= factor
	}

	return nil
}

// PCMScaleF32 converts a buffer with audio content from -1 to 1 (float32) into
// the PCM scale based on the passed bitdepth.
// Note that while the PCM data is scaled, the PCM format is not changed.
func PCMScaleF32(buf *audio.Float32Buffer, bitDepth int) error {
	if buf == nil || buf.Format == nil {
		return audio.ErrInvalidBuffer
	}
	buf.SourceBitDepth = bitDepth
	factor := float32(math.Pow(2, float64(bitDepth)-1)) - 1.0
	for i := 0; i < len(buf.Data); i++ {
		buf.Data[i] *= factor
	}

	return nil
}
<|endoftext|>


<commit_before>package rest

import (
	"bytes"
	"encoding/json"
	"net/http"
	"regexp"
	"testing"
)

var ret = "Hello world."

type BenchmarkRest struct {
	Service `prefix:"/prefix"`

	Fake FakeNode  `method:"GET" path:"/fake/:id" func:"HandleGet"`
	Get  Processor `method:"GET" path:"/processor/:id"`
	Post Processor `method:"POST" path:"/processor/:id/post"`
	Full Processor `method:"POST" path:"/processor/:id/full"`
}

func (r BenchmarkRest) HandleGet() string {
	return ret
}

func (r BenchmarkRest) HandlePost(arg string) {}

func (r BenchmarkRest) HandleFull(arg string) string {
	return arg
}

var rest *Rest

func init() {
	var err error
	rest, err = New(new(BenchmarkRest))
	if err != nil {
		panic(err)
	}
}

func BenchmarkRestServe(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/fake/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestPost(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("POST", "http://127.0.0.1/prefix/processor/id/post", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestFull(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("POST", "http://127.0.0.1/prefix/processor/id/full", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

var handlers = []struct {
	path    *regexp.Regexp
	handler http.HandlerFunc
}{
	{regexp.MustCompile("^/prefix/processor/(.*?)$"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		encoder := json.NewEncoder(w)
		err := encoder.Encode(ret)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
	{regexp.MustCompile("^/prefix/processor/(.*?)$/post"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		decoder := json.NewDecoder(r.Body)
		var arg string
		err := decoder.Decode(&arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
	{regexp.MustCompile("^/prefix/processor/(.*?)$/full"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		decoder := json.NewDecoder(r.Body)
		var arg string
		err := decoder.Decode(&arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		encoder := json.NewEncoder(w)
		err = encoder.Encode(arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
}

func BenchmarkPlainGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}

func BenchmarkPlainPost(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}

func BenchmarkPlainFull(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}
<commit_msg>add perf<commit_after>package rest

import (
	"bytes"
	"encoding/json"
	"net/http"
	"regexp"
	"testing"
	"time"
)

var ret = "Hello world."

type BenchmarkRest struct {
	Service `prefix:"/prefix"`

	Fake FakeNode  `method:"GET" path:"/fake/:id" func:"HandleGet"`
	Get  Processor `method:"GET" path:"/processor/:id"`
	Post Processor `method:"POST" path:"/processor/:id/post"`
	Full Processor `method:"POST" path:"/processor/:id/full"`
}

func (r BenchmarkRest) HandleGet() string {
	return ret
}

func (r BenchmarkRest) HandlePost(arg string) {}

func (r BenchmarkRest) HandleFull(arg string) string {
	return arg
}

var rest *Rest

func init() {
	var err error
	rest, err = New(new(BenchmarkRest))
	if err != nil {
		panic(err)
	}
}

func BenchmarkHttpServeFull(b *testing.B) {
	b.StopTimer()
	go http.ListenAndServe("127.0.0.1:12345", rest)
	time.Sleep(time.Second / 2)
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		resp, err := http.Post("http://127.0.0.1:12345/prefix/processor/id/full", "application/json", buf)
		if err != nil {
			panic(err)
		}
		resp.Body.Close()
	}
}

func BenchmarkRestServe(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/fake/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestPost(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("POST", "http://127.0.0.1/prefix/processor/id/post", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

func BenchmarkRestFull(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("POST", "http://127.0.0.1/prefix/processor/id/full", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		rest.ServeHTTP(resp, req)
	}
}

var handlers = []struct {
	path    *regexp.Regexp
	handler http.HandlerFunc
}{
	{regexp.MustCompile("^/prefix/processor/(.*?)$"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		encoder := json.NewEncoder(w)
		err := encoder.Encode(ret)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
	{regexp.MustCompile("^/prefix/processor/(.*?)$/post"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		decoder := json.NewDecoder(r.Body)
		var arg string
		err := decoder.Decode(&arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
	{regexp.MustCompile("^/prefix/processor/(.*?)$/full"), func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Error(w, "", http.StatusNotFound)
			return
		}
		decoder := json.NewDecoder(r.Body)
		var arg string
		err := decoder.Decode(&arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		encoder := json.NewEncoder(w)
		err = encoder.Encode(arg)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}},
}

func BenchmarkPlainGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", nil)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}

func BenchmarkPlainPost(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}

func BenchmarkPlainFull(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := bytes.NewBufferString("\"post\"")
		req, err := http.NewRequest("GET", "http://127.0.0.1/prefix/processor/id", buf)
		if err != nil {
			panic(err)
		}
		resp := newWriter()
		for _, h := range handlers {
			if len(h.path.FindAllStringSubmatch(req.URL.Path, -1)) > 0 {
				h.handler(resp, req)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/igungor/quackle"
	termbox "github.com/nsf/termbox-go"
)

const (
	lexicon  = "turkish"
	alphabet = "turkish"
	datadir  = "data"
)

// hacky stuff.
// var datadir = fmt.Sprintf("%v/src/github.com/igungor/cmd/pfft/data", os.Getenv("GOPATH"))

const (
	fgcolor = termbox.ColorDefault
	bgcolor = termbox.ColorDefault
)

var dm quackle.DataManager
var flexAbc quackle.FlexibleAlphabetParameters

type game struct {
	qg      quackle.Game
	board   board
	rack1   rack
	rack2   rack
	legend  legend
	editbox editbox

	isOver     bool
	showLegend bool
}

func (g *game) draw() {
	// update board and racks
	g.board.qb = g.pos().Board()
	g.rack1.update(g.player(0).Rack().ToString())
	g.rack2.update(g.player(1).Rack().ToString())

	termbox.Clear(fgcolor, bgcolor)
	defer termbox.Flush()

	sw, sh := termbox.Size()

	// board
	boardx := (sw - g.board.w*2 + 2 + 1) / 2
	boardy := (sh - g.board.h + 1 + 1) / 2
	g.board.draw(boardx, boardy)

	// legend
	if g.showLegend {
		legendx := (sw+g.board.w)/2 + 1
		legendy := (sh-g.board.h)/2 + 1 + 1 + g.board.h
		g.legend.draw(legendx, legendy)
	}

	// racks
	rack1x := boardx
	rack1y := boardy + g.board.h + 2
	g.rack1.draw(rack1x, rack1y)
	rack2x := boardx + g.rack1.w + 2
	rack2y := boardy + g.board.h + 2
	g.rack2.draw(rack2x, rack2y)
	if g.curPlayer().Id() == 0 {
		g.rack1.highlight(rack1x, rack1y)
	} else {
		g.rack2.highlight(rack2x, rack2y)
	}

	// editbox
	boxx := (sw-g.editbox.w)/2 + 1
	boxy := (sh+g.board.h)/2 + g.rack1.h + 5
	g.editbox.draw(boxx, boxy)
}

func (g *game) loop() {
mainloop:
	for {
		if g.pos().GameOver() {
			g.isOver = true
			g.over()
			break mainloop
		}

		if g.curPlayer().Xtype() == 0 {
			g.qg.HaveComputerPlay()
			goto humanMove
		}
		g.qg.AdvanceToNoncomputerPlayer()

		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEnter:
				// new human move
				g.doHumanMove()
			case termbox.KeyCtrlS:
				g.board.showScore = !g.board.showScore
			case termbox.KeyCtrlL:
				g.showLegend = !g.showLegend
			case termbox.KeyBackspace, termbox.KeyBackspace2:
				g.editbox.DeleteRuneBackward()
			case termbox.KeySpace:
				g.editbox.InsertRune(' ')
			case termbox.KeyEsc, termbox.KeyCtrlC:
				break mainloop
			default:
				if ev.Ch != 0 {
					g.editbox.InsertRune(ev.Ch)
				}
			}
		case termbox.EventResize:
			g.draw()
		case termbox.EventMouse:
			// TODO(ig): handle mouse clicks
		case termbox.EventError:
			panic(ev.Err)
		}
	humanMove:
		g.draw()
	}
}

// FIXME(ig): print proper errors
func (g *game) doHumanMove() {
	place, word, err := g.editbox.getPlaceWord()
	if err != nil {
		return
	}
	var move quackle.Move
	if place == "-" {
		move = quackle.MoveCreatePassMove()
	} else {
		move = quackle.MoveCreatePlaceMove(place, flexAbc.Encode(word))
	}
	if g.pos().ValidateMove(move) != 0 {
		return
	}
	g.qg.CommitMove(move)
	g.editbox.clear()
}

// over draws game-over screen.
func (g *game) over() {
	termbox.Clear(fgcolor, bgcolor)
	sw, sh := termbox.Size()
	tbprint("GAME OVER", sw/2-4, sh/2, fgcolor, bgcolor)
	termbox.Flush()
	time.Sleep(1 * time.Second)
}

// pos returns current game position
func (g *game) pos() quackle.GamePosition {
	return g.qg.CurrentPosition().(quackle.GamePosition)
}

// player returns current player
func (g *game) curPlayer() quackle.Player {
	return g.pos().CurrentPlayer().(quackle.Player)
}

func (g *game) player(id int) quackle.Player {
	found := make([]bool, 1)
	return g.pos().Players().PlayerForId(id, found)
}

// newGame initializes a new game and constructs game object.
func newGame() *game {
	dm = quackle.NewDataManager()
	dm.SetComputerPlayers(quackle.ComputerPlayerCollectionFullCollection().SwigGetPlayerList())
	dm.SetBackupLexicon(lexicon)
	dm.SetAppDataDirectory(datadir)

	// set up alphabet
	abc := quackle.AlphabetParametersFindAlphabetFile(alphabet)
	qabc := quackle.UtilStdStringToQString(abc)
	flexAbc = quackle.NewFlexibleAlphabetParameters()
	flexAbc.Load(qabc)
	dm.SetAlphabetParameters(flexAbc)

	// set up board
	bp := quackle.NewBoardParameters()
	for y := 0; y < boardsize; y++ {
		for x := 0; x < boardsize; x++ {
			bp.SetLetterMultiplier(x, y, quackle.QuackleBoardParametersLetterMultiplier(boardLetterMult[x][y]))
			bp.SetWordMultiplier(x, y, quackle.QuackleBoardParametersWordMultiplier(boardWordMult[x][y]))
		}
	}
	dm.SetBoardParameters(bp)

	// find lexicon
	dawg := quackle.LexiconParametersFindDictionaryFile(lexicon + ".dawg")
	gaddag := quackle.LexiconParametersFindDictionaryFile(lexicon + ".gaddag")
	dm.LexiconParameters().LoadDawg(dawg)
	dm.LexiconParameters().LoadGaddag(gaddag)
	dm.StrategyParameters().Initialize(lexicon)

	// dm.SeedRandomNumbers(uint(time.Now().UnixNano()))
	dm.SeedRandomNumbers(42)

	newCompPlayer := func(name string, id int) quackle.Player {
		found := make([]bool, 1)
		player := dm.ComputerPlayers().PlayerForName("Speedy Player", found)
		if !found[0] {
			panic("player could not be found")
		}
		comp := player.ComputerPlayer()

		p := quackle.NewPlayer(name, int(quackle.PlayerComputerPlayerType), id)
		p.SetComputerPlayer(comp)
		return p
	}

	// set up players and game
	g := quackle.NewGame()
	player1 := quackle.NewPlayer("iby", int(quackle.PlayerHumanPlayerType), 0)
	player2 := newCompPlayer("Computer", 1)
	players := quackle.NewPlayerList()
	players.Add(player1)
	players.Add(player2)
	g.SetPlayers(players)
	g.AssociateKnownComputerPlayers()
	g.AddPosition()

	b := board{
		qb: g.CurrentPosition().(quackle.GamePosition).Board(),
		w:  boardsize,
		h:  boardsize,
	}

	return &game{
		qg:         g,
		board:      b,
		rack1:      newRack(player1.Name()),
		rack2:      newRack(player2.Name()),
		editbox:    newEditbox(),
		showLegend: true,
	}
}
<commit_msg>pfft: use relative data directory<commit_after>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/igungor/quackle"
	termbox "github.com/nsf/termbox-go"
)

const (
	lexicon  = "turkish"
	alphabet = "turkish"
)

// hacky stuff.
var datadir = fmt.Sprintf("%v/src/github.com/igungor/cmd/pfft/data", os.Getenv("GOPATH"))

const (
	fgcolor = termbox.ColorDefault
	bgcolor = termbox.ColorDefault
)

var dm quackle.DataManager
var flexAbc quackle.FlexibleAlphabetParameters

type game struct {
	qg      quackle.Game
	board   board
	rack1   rack
	rack2   rack
	legend  legend
	editbox editbox

	isOver     bool
	showLegend bool
}

func (g *game) draw() {
	// update board and racks
	g.board.qb = g.pos().Board()
	g.rack1.update(g.player(0).Rack().ToString())
	g.rack2.update(g.player(1).Rack().ToString())

	termbox.Clear(fgcolor, bgcolor)
	defer termbox.Flush()

	sw, sh := termbox.Size()

	// board
	boardx := (sw - g.board.w*2 + 2 + 1) / 2
	boardy := (sh - g.board.h + 1 + 1) / 2
	g.board.draw(boardx, boardy)

	// legend
	if g.showLegend {
		legendx := (sw+g.board.w)/2 + 1
		legendy := (sh-g.board.h)/2 + 1 + 1 + g.board.h
		g.legend.draw(legendx, legendy)
	}

	// racks
	rack1x := boardx
	rack1y := boardy + g.board.h + 2
	g.rack1.draw(rack1x, rack1y)
	rack2x := boardx + g.rack1.w + 2
	rack2y := boardy + g.board.h + 2
	g.rack2.draw(rack2x, rack2y)
	if g.curPlayer().Id() == 0 {
		g.rack1.highlight(rack1x, rack1y)
	} else {
		g.rack2.highlight(rack2x, rack2y)
	}

	// editbox
	boxx := (sw-g.editbox.w)/2 + 1
	boxy := (sh+g.board.h)/2 + g.rack1.h + 5
	g.editbox.draw(boxx, boxy)
}

func (g *game) loop() {
mainloop:
	for {
		if g.pos().GameOver() {
			g.isOver = true
			g.over()
			break mainloop
		}

		if g.curPlayer().Xtype() == 0 {
			g.qg.HaveComputerPlay()
			goto humanMove
		}
		g.qg.AdvanceToNoncomputerPlayer()

		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEnter:
				// new human move
				g.doHumanMove()
			case termbox.KeyCtrlS:
				g.board.showScore = !g.board.showScore
			case termbox.KeyCtrlL:
				g.showLegend = !g.showLegend
			case termbox.KeyBackspace, termbox.KeyBackspace2:
				g.editbox.DeleteRuneBackward()
			case termbox.KeySpace:
				g.editbox.InsertRune(' ')
			case termbox.KeyEsc, termbox.KeyCtrlC:
				break mainloop
			default:
				if ev.Ch != 0 {
					g.editbox.InsertRune(ev.Ch)
				}
			}
		case termbox.EventResize:
			g.draw()
		case termbox.EventMouse:
			// TODO(ig): handle mouse clicks
		case termbox.EventError:
			panic(ev.Err)
		}
	humanMove:
		g.draw()
	}
}

// FIXME(ig): print proper errors
func (g *game) doHumanMove() {
	place, word, err := g.editbox.getPlaceWord()
	if err != nil {
		return
	}
	var move quackle.Move
	if place == "-" {
		move = quackle.MoveCreatePassMove()
	} else {
		move = quackle.MoveCreatePlaceMove(place, flexAbc.Encode(word))
	}
	if g.pos().ValidateMove(move) != 0 {
		return
	}
	g.qg.CommitMove(move)
	g.editbox.clear()
}

// over draws game-over screen.
func (g *game) over() {
	termbox.Clear(fgcolor, bgcolor)
	sw, sh := termbox.Size()
	tbprint("GAME OVER", sw/2-4, sh/2, fgcolor, bgcolor)
	termbox.Flush()
	time.Sleep(1 * time.Second)
}

// pos returns current game position
func (g *game) pos() quackle.GamePosition {
	return g.qg.CurrentPosition().(quackle.GamePosition)
}

// player returns current player
func (g *game) curPlayer() quackle.Player {
	return g.pos().CurrentPlayer().(quackle.Player)
}

func (g *game) player(id int) quackle.Player {
	found := make([]bool, 1)
	return g.pos().Players().PlayerForId(id, found)
}

// newGame initializes a new game and constructs game object.
func newGame() *game {
	dm = quackle.NewDataManager()
	dm.SetComputerPlayers(quackle.ComputerPlayerCollectionFullCollection().SwigGetPlayerList())
	dm.SetBackupLexicon(lexicon)
	dm.SetAppDataDirectory(datadir)

	// set up alphabet
	abc := quackle.AlphabetParametersFindAlphabetFile(alphabet)
	qabc := quackle.UtilStdStringToQString(abc)
	flexAbc = quackle.NewFlexibleAlphabetParameters()
	flexAbc.Load(qabc)
	dm.SetAlphabetParameters(flexAbc)

	// set up board
	bp := quackle.NewBoardParameters()
	for y := 0; y < boardsize; y++ {
		for x := 0; x < boardsize; x++ {
			bp.SetLetterMultiplier(x, y, quackle.QuackleBoardParametersLetterMultiplier(boardLetterMult[x][y]))
			bp.SetWordMultiplier(x, y, quackle.QuackleBoardParametersWordMultiplier(boardWordMult[x][y]))
		}
	}
	dm.SetBoardParameters(bp)

	// find lexicon
	dawg := quackle.LexiconParametersFindDictionaryFile(lexicon + ".dawg")
	gaddag := quackle.LexiconParametersFindDictionaryFile(lexicon + ".gaddag")
	dm.LexiconParameters().LoadDawg(dawg)
	dm.LexiconParameters().LoadGaddag(gaddag)
	dm.StrategyParameters().Initialize(lexicon)

	// dm.SeedRandomNumbers(uint(time.Now().UnixNano()))
	dm.SeedRandomNumbers(42)

	newCompPlayer := func(name string, id int) quackle.Player {
		found := make([]bool, 1)
		player := dm.ComputerPlayers().PlayerForName("Speedy Player", found)
		if !found[0] {
			panic("player could not be found")
		}
		comp := player.ComputerPlayer()

		p := quackle.NewPlayer(name, int(quackle.PlayerComputerPlayerType), id)
		p.SetComputerPlayer(comp)
		return p
	}

	// set up players and game
	g := quackle.NewGame()
	player1 := quackle.NewPlayer("iby", int(quackle.PlayerHumanPlayerType), 0)
	player2 := newCompPlayer("Computer", 1)
	players := quackle.NewPlayerList()
	players.Add(player1)
	players.Add(player2)
	g.SetPlayers(players)
	g.AssociateKnownComputerPlayers()
	g.AddPosition()

	b := board{
		qb: g.CurrentPosition().(quackle.GamePosition).Board(),
		w:  boardsize,
		h:  boardsize,
	}

	return &game{
		qg:         g,
		board:      b,
		rack1:      newRack(player1.Name()),
		rack2:      newRack(player2.Name()),
		editbox:    newEditbox(),
		showLegend: true,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"
)

var slackToken string
var address string

type userDB struct {
	OK        bool        `json:"ok"`
	Error     string      `json:"error"`
	Members   interface{} `json:"members"`
	Timestamp time.Time   `json:"timestamp"`
	jsonOut   []byte
}

func (u *userDB) fetch() (*userDB, error) {
	rsp, err := http.Get(fmt.Sprintf("https://slack.com/api/users.list?token=%s", slackToken))
	if err != nil {
		return nil, err
	}
	defer rsp.Body.Close()
	var newudb = &userDB{}
	var decoder = json.NewDecoder(rsp.Body)
	if err := decoder.Decode(newudb); err != nil {
		return nil, err
	}
	newudb.Timestamp = time.Now()
	if newudb.jsonOut, err = json.Marshal(newudb); err != nil {
		return newudb, err
	}
	if !newudb.OK {
		return newudb, errors.New(newudb.Error)
	}
	return newudb, nil
}

var udb = &userDB{
	OK:        false,
	Error:     "just initializing",
	Timestamp: time.Now(),
}

func init() {
	flag.StringVar(&slackToken, "st", "", "Slack API Token")
	flag.StringVar(&address, "listen", "127.0.0.1:8879", "listen on")
}

func main() {
	flag.Parse()
	if newudb, err := udb.fetch(); err != nil {
		log.Fatal(err.Error())
	} else {
		udb = newudb
	}
	go func() {
		t := time.Tick(15 * time.Minute)
		for {
			select {
			case <-t:
				if newudb, err := udb.fetch(); err != nil {
					log.Println(err.Error())
				} else {
					udb = newudb
				}
			}
		}
	}()
	http.HandleFunc("/users.json", func(w http.ResponseWriter, r *http.Request) {
		w.Write(udb.jsonOut)
	})
	http.ListenAndServe(address, nil)
}
<commit_msg>add json content type header<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"
)

var slackToken string
var address string

type userDB struct {
	OK        bool        `json:"ok"`
	Error     string      `json:"error"`
	Members   interface{} `json:"members"`
	Timestamp time.Time   `json:"timestamp"`
	jsonOut   []byte
}

func (u *userDB) fetch() (*userDB, error) {
	rsp, err := http.Get(fmt.Sprintf("https://slack.com/api/users.list?token=%s", slackToken))
	if err != nil {
		return nil, err
	}
	defer rsp.Body.Close()
	var newudb = &userDB{}
	var decoder = json.NewDecoder(rsp.Body)
	if err := decoder.Decode(newudb); err != nil {
		return nil, err
	}
	newudb.Timestamp = time.Now()
	if newudb.jsonOut, err = json.Marshal(newudb); err != nil {
		return newudb, err
	}
	if !newudb.OK {
		return newudb, errors.New(newudb.Error)
	}
	return newudb, nil
}

var udb = &userDB{
	OK:        false,
	Error:     "just initializing",
	Timestamp: time.Now(),
}

func init() {
	flag.StringVar(&slackToken, "st", "", "Slack API Token")
	flag.StringVar(&address, "listen", "127.0.0.1:8879", "listen on")
}

func main() {
	flag.Parse()
	if newudb, err := udb.fetch(); err != nil {
		log.Fatal(err.Error())
	} else {
		udb = newudb
	}
	go func() {
		t := time.Tick(15 * time.Minute)
		for {
			select {
			case <-t:
				if newudb, err := udb.fetch(); err != nil {
					log.Println(err.Error())
				} else {
					udb = newudb
				}
			}
		}
	}()
	http.HandleFunc("/users.json", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write(udb.jsonOut)
	})
	http.ListenAndServe(address, nil)
}
<|endoftext|>


<commit_before>package channel

// TODO do with iota
const (
	// MIDI channel 1
	Channel0 = Channel(0)

	// MIDI channel 2
	Channel1 = Channel(1)

	// MIDI channel 3
	Channel2 = Channel(2)

	// MIDI channel 4
	Channel3 = Channel(3)

	// MIDI channel 5
	Channel4 = Channel(4)

	// MIDI channel 6
	Channel5 = Channel(5)

	// MIDI channel 7
	Channel6 = Channel(6)

	// MIDI channel 8
	Channel7 = Channel(7)

	// MIDI channel 9
	Channel8 = Channel(8)

	// MIDI channel 10
	Channel9 = Channel(9)

	// MIDI channel 11
	Channel10 = Channel(10)

	// MIDI channel 12
	Channel11 = Channel(11)

	// MIDI channel 13
	Channel12 = Channel(12)

	// MIDI channel 14
	Channel13 = Channel(13)

	// MIDI channel 15
	Channel14 = Channel(14)

	// MIDI channel 16
	Channel15 = Channel(15)
)

func SetChannel(msg Message, ch uint8) Message {
	if ch > 15 {
		panic("invalid channel number")
	}

	c := Channel(ch)

	switch v := msg.(type) {
	case Aftertouch:
		return c.Aftertouch(v.Pressure())
	case ControlChange:
		return c.ControlChange(v.Controller(), v.Value())
	case NoteOn:
		return c.NoteOn(v.Key(), v.Velocity())
	case NoteOff:
		return c.NoteOff(v.Key())
	case NoteOffVelocity:
		return c.NoteOffVelocity(v.Key(), v.Velocity())
	case Pitchbend:
		return c.Pitchbend(v.Value())
	case PolyAftertouch:
		return c.PolyAftertouch(v.Key(), v.Pressure())
	case ProgramChange:
		return c.ProgramChange(v.Program())
	}

	panic("unreachable")
}

// Channel represents a MIDI channel
// there must not be more than 16 MIDI channels (0-15)
type Channel uint8

// Channel returns the number of the MIDI channel (0-15)
func (c Channel) Channel() uint8 {
	return uint8(c)
}

// NoteOff creates a note-off message on the channel for the given key
// The note-off message is "faked" by a note-on message of velocity 0.
// This allows saving bandwidth by using running status.
// If you need a "real" note-off message with velocity, use NoteOffVelocity.
func (c Channel) NoteOff(key uint8) NoteOff {
	if key > 127 {
		key = 127
	}
	return NoteOff{channel: c.Channel(), key: key}
}

// NoteOffVelocity creates a note-off message with velocity on the channel.
func (c Channel) NoteOffVelocity(key uint8, velocity uint8) NoteOffVelocity {
	if key > 127 {
		key = 127
	}
	if velocity > 127 {
		velocity = 127
	}
	return NoteOffVelocity{NoteOff{channel: c.Channel(), key: key}, velocity}
}

// NoteOn creates a note-on message on the channel
func (c Channel) NoteOn(key uint8, velocity uint8) NoteOn {
	if key > 127 {
		key = 127
	}
	if velocity > 127 {
		velocity = 127
	}
	return NoteOn{channel: c.Channel(), key: key, velocity: velocity}
}

// PolyAftertouch creates a polyphonic aftertouch message on the channel
func (c Channel) PolyAftertouch(key uint8, pressure uint8) PolyAftertouch {
	if key > 127 {
		key = 127
	}
	if pressure > 127 {
		pressure = 127
	}
	return PolyAftertouch{channel: c.Channel(), key: key, pressure: pressure}
}

// ControlChange creates a control change message on the channel
func (c Channel) ControlChange(controller uint8, value uint8) ControlChange {
	if controller > 127 {
		controller = 127
	}
	if value > 127 {
		value = 127
	}
	return ControlChange{channel: c.Channel(), controller: controller, value: value}
}

// ProgramChange creates a program change message on the channel
func (c Channel) ProgramChange(program uint8) ProgramChange {
	if program > 127 {
		program = 127
	}
	return ProgramChange{channel: c.Channel(), program: program}
}

// Aftertouch creates an aftertouch message on the channel
func (c Channel) Aftertouch(pressure uint8) Aftertouch {
	if pressure > 127 {
		pressure = 127
	}
	return Aftertouch{channel: c.Channel(), pressure: pressure}
}

// Pitchbend creates a pitch bend message on the channel
func (c Channel) Pitchbend(value int16) Pitchbend {
	if value < PitchLowest {
		value = PitchLowest
	}

	if value > PitchHighest {
		value = PitchHighest
	}
	return Pitchbend{channel: c.Channel(), value: value}
}
<commit_msg>Cleanup: Update midimessage/channel/channel.Channel to use iota.<commit_after>package channel

// Channel represents a MIDI channel
// there must not be more than 16 MIDI channels (0-15)
type Channel uint8

const (
	// MIDI channel 1
	Channel0 Channel = iota

	// MIDI channel 2
	Channel1

	// MIDI channel 3
	Channel2

	// MIDI channel 4
	Channel3

	// MIDI channel 5
	Channel4

	// MIDI channel 6
	Channel5

	// MIDI channel 7
	Channel6

	// MIDI channel 8
	Channel7

	// MIDI channel 9
	Channel8

	// MIDI channel 10
	Channel9

	// MIDI channel 11
	Channel10

	// MIDI channel 12
	Channel11

	// MIDI channel 13
	Channel12

	// MIDI channel 14
	Channel13

	// MIDI channel 15
	Channel14

	// MIDI channel 16
	Channel15
)

func SetChannel(msg Message, ch uint8) Message {
	if ch > 15 {
		panic("invalid channel number")
	}

	c := Channel(ch)

	switch v := msg.(type) {
	case Aftertouch:
		return c.Aftertouch(v.Pressure())
	case ControlChange:
		return c.ControlChange(v.Controller(), v.Value())
	case NoteOn:
		return c.NoteOn(v.Key(), v.Velocity())
	case NoteOff:
		return c.NoteOff(v.Key())
	case NoteOffVelocity:
		return c.NoteOffVelocity(v.Key(), v.Velocity())
	case Pitchbend:
		return c.Pitchbend(v.Value())
	case PolyAftertouch:
		return c.PolyAftertouch(v.Key(), v.Pressure())
	case ProgramChange:
		return c.ProgramChange(v.Program())
	}

	panic("unreachable")
}

// Channel returns the number of the MIDI channel (0-15)
func (c Channel) Channel() uint8 {
	return uint8(c)
}

// NoteOff creates a note-off message on the channel for the given key
// The note-off message is "faked" by a note-on message of velocity 0.
// This allows saving bandwidth by using running status.
// If you need a "real" note-off message with velocity, use NoteOffVelocity.
func (c Channel) NoteOff(key uint8) NoteOff {
	if key > 127 {
		key = 127
	}
	return NoteOff{channel: c.Channel(), key: key}
}

// NoteOffVelocity creates a note-off message with velocity on the channel.
func (c Channel) NoteOffVelocity(key uint8, velocity uint8) NoteOffVelocity {
	if key > 127 {
		key = 127
	}
	if velocity > 127 {
		velocity = 127
	}
	return NoteOffVelocity{NoteOff{channel: c.Channel(), key: key}, velocity}
}

// NoteOn creates a note-on message on the channel
func (c Channel) NoteOn(key uint8, velocity uint8) NoteOn {
	if key > 127 {
		key = 127
	}
	if velocity > 127 {
		velocity = 127
	}
	return NoteOn{channel: c.Channel(), key: key, velocity: velocity}
}

// PolyAftertouch creates a polyphonic aftertouch message on the channel
func (c Channel) PolyAftertouch(key uint8, pressure uint8) PolyAftertouch {
	if key > 127 {
		key = 127
	}
	if pressure > 127 {
		pressure = 127
	}
	return PolyAftertouch{channel: c.Channel(), key: key, pressure: pressure}
}

// ControlChange creates a control change message on the channel
func (c Channel) ControlChange(controller uint8, value uint8) ControlChange {
	if controller > 127 {
		controller = 127
	}
	if value > 127 {
		value = 127
	}
	return ControlChange{channel: c.Channel(), controller: controller, value: value}
}

// ProgramChange creates a program change message on the channel
func (c Channel) ProgramChange(program uint8) ProgramChange {
	if program > 127 {
		program = 127
	}
	return ProgramChange{channel: c.Channel(), program: program}
}

// Aftertouch creates an aftertouch message on the channel
func (c Channel) Aftertouch(pressure uint8) Aftertouch {
	if pressure > 127 {
		pressure = 127
	}
	return Aftertouch{channel: c.Channel(), pressure: pressure}
}

// Pitchbend creates a pitch bend message on the channel
func (c Channel) Pitchbend(value int16) Pitchbend {
	if value < PitchLowest {
		value = PitchLowest
	}

	if value > PitchHighest {
		value = PitchHighest
	}
	return Pitchbend{channel: c.Channel(), value: value}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"image/color"
	"os"
	"strconv"
)

// DrawingMode defines the type of each drawing mode
type DrawingMode int

const (
	// DrawLineMode is a draw argument that draws 2D lines onto the Image
	DrawLineMode DrawingMode = iota
	// DrawPolygonMode is a draw argument that draws 3D polygons onto the Image
	DrawPolygonMode
)

// Parser is a script parser
type Parser struct {
	frame  *Image
	em     *Matrix
	tm     *Matrix
	cs     *Stack
	lexer  *Lexer
	backup []Token
}

// NewParser returns a new parser
func NewParser() *Parser {
	cs := NewStack()
	cs.Push(IdentityMatrix(4))
	return &Parser{
		frame:  NewImage(DefaultHeight, DefaultWidth),
		em:     NewMatrix(4, 0),
		tm:     IdentityMatrix(4),
		cs:     cs,
		backup: make([]Token, 0, 10),
	}
}

// ParseFile parses a file for commands and executes them
func (p *Parser) ParseFile(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	p.lexer = NewLexer()
	p.lexer.Lex(f)
	for {
		t := p.next()
		switch t.tt {
		case tError:
			return errors.New(t.value)
		case tEOF:
			return nil
		case tIdent:
			err := p.parseIdent(t)
			if err != nil {
				return err
			}
		case tComment:
			continue
		default:
			return fmt.Errorf("unexpected token %v", t)
		}
	}
}

func (p *Parser) parseIdent(t Token) error {
	var err error
	switch t.value {
	case "line":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		z0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		z1 := p.nextFloat()
		err = p.line(x0, y0, z0, x1, y1, z1)
	case "ident":
		p.tm = IdentityMatrix(4)
	case "scale":
		sx := p.nextFloat()
		sy := p.nextFloat()
		sz := p.nextFloat()
		err = p.scale(sx, sy, sz)
	case "move":
		x := p.nextFloat()
		y := p.nextFloat()
		z := p.nextFloat()
		err = p.move(x, y, z)
	case "rotate":
		axis := p.nextString()
		theta := p.nextFloat()
		err = p.rotate(axis, theta)
	case "save":
		filename := p.nextString()
		err = p.save(filename)
	case "display":
		err = p.display()
	case "circle":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		radius := p.nextFloat()
		err = p.circle(cx, cy, cz, radius)
	case "hermite":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		dx0 := p.nextFloat()
		dy0 := p.nextFloat()
		dx1 := p.nextFloat()
		dy1 := p.nextFloat()
		err = p.hermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1)
	case "bezier":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		x2 := p.nextFloat()
		y2 := p.nextFloat()
		x3 := p.nextFloat()
		y3 := p.nextFloat()
		err = p.bezier(x0, y0, x1, y1, x2, y2, x3, y3)
	case "box":
		x := p.nextFloat()
		y := p.nextFloat()
		z := p.nextFloat()
		width := p.nextFloat()
		height := p.nextFloat()
		depth := p.nextFloat()
		err = p.box(x, y, z, width, height, depth)
	case "clear":
		p.clear()
	case "sphere":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		radius := p.nextFloat()
		err = p.sphere(cx, cy, cz, radius)
	case "torus":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		r1 := p.nextFloat()
		r2 := p.nextFloat()
		err = p.torus(cx, cy, cz, r1, r2)
	case "push":
		top := p.cs.Peek()
		if top != nil {
			p.cs.Push(top.Copy())
		}
	case "pop":
		p.cs.Pop()
	default:
		err = fmt.Errorf("unrecognized identifier: \"%s\"", t.value)
	}
	return err
}

func (p *Parser) next() Token {
	lenBackup := len(p.backup)
	if lenBackup > 0 {
		token := p.backup[lenBackup-1]
		p.backup = p.backup[:lenBackup-1]
		return token
	}
	token := <-p.lexer.out
	return token
}

func (p *Parser) nextFloat() float64 {
	if p.requireNext(tInt) != nil && p.requireNext(tFloat) != nil {
		panic(fmt.Errorf("%s expected, got %s", tFloat, p.peek().tt))
	}
	v, _ := strconv.ParseFloat(p.next().value, 64)
	return v
}

func (p *Parser) nextString() string {
	if p.requireNext(tString) != nil {
		panic(fmt.Errorf("%s expected, got %s", tString, p.peek().tt))
	}
	return p.next().value
}

func (p *Parser) unread(token Token) {
	if p.backup == nil {
		p.backup = make([]Token, 0, 10)
	}
	p.backup = append(p.backup, token)
}

func (p *Parser) peek() Token {
	token := p.next()
	p.unread(token)
	return token
}

func (p *Parser) requireNext(tt TokenType) error {
	other := p.peek().tt
	if other != tt {
		return fmt.Errorf("unexpected %v; expected %v", other, tt)
	}
	return nil
}

func (p *Parser) line(x0, y0, z0, x1, y1, z1 float64) error {
	p.em.AddEdge(x0, y0, z0, x1, y1, z1)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) scale(sx, sy, sz float64) error {
	dilation := MakeDilation(sx, sy, sz)

	top := p.cs.Pop()
	top, err := top.Multiply(dilation)
	if err != nil {
		return err
	}
	p.cs.Push(top)
	return nil
}

func (p *Parser) move(x, y, z float64) error {
	translation := MakeTranslation(x, y, z)
	top := p.cs.Pop()
	top, err := top.Multiply(translation)
	if err != nil {
		return err
	}
	p.cs.Push(top)

	return nil
}

func (p *Parser) rotate(axis string, theta float64) error {
	var rotation *Matrix
	switch axis {
	case "x":
		rotation = MakeRotX(theta)
	case "y":
		rotation = MakeRotY(theta)
	case "z":
		rotation = MakeRotZ(theta)
	default:
		return errors.New("axis must be \"x\", \"y\", or \"z\"")
	}

	top := p.cs.Pop()
	top, err := top.Multiply(rotation)
	if err != nil {
		return err
	}
	p.cs.Push(top)

	return nil
}

func (p *Parser) apply(mode DrawingMode) error {
	product, err := p.cs.Peek().Multiply(p.em)
	if err != nil {
		return err
	}
	p.em = product
	p.draw(mode)
	p.clear()

	return nil
}

func (p *Parser) draw(mode DrawingMode) {
	switch mode {
	case DrawLineMode:
		p.frame.DrawLines(p.em, color.White)
	case DrawPolygonMode:
		p.frame.DrawPolygons(p.em, color.White)
	default:
	}
}

func (p *Parser) save(filename string) error {
	err := p.frame.Save(filename)
	return err
}

func (p *Parser) display() error {
	err := p.frame.Display()
	return err
}

func (p *Parser) circle(cx, cy, cz, radius float64) error {
	p.em.AddCircle(cx, cy, cz, radius)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) hermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1 float64) error {
	p.em.AddHermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1)
	err := p.apply(DrawLineMode)

	return err
}

func (p *Parser) bezier(x0, y0, x1, y1, x2, y2, x3, y3 float64) error {
	p.em.AddBezier(x0, y0, x1, y1, x2, y2, x3, y3)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) box(x, y, z, width, height, depth float64) error {
	p.em.AddBox(x, y, z, width, height, depth)
	err := p.apply(DrawPolygonMode)
	return err
}

func (p *Parser) clear() {
	p.em = NewMatrix(4, 0)
}

func (p *Parser) sphere(cx, cy, cz, radius float64) error {
	p.em.AddSphere(cx, cy, cz, radius)
	err := p.apply(DrawPolygonMode)
	return err
}

func (p *Parser) torus(cx, cy, cz, r1, r2 float64) error {
	p.em.AddTorus(cx, cy, cz, r1, r2)
	err := p.apply(DrawPolygonMode)

	return err
}
<commit_msg>Ignore comment tokens when parsing<commit_after>package main

import (
	"errors"
	"fmt"
	"image/color"
	"os"
	"strconv"
)

// DrawingMode defines the type of each drawing mode
type DrawingMode int

const (
	// DrawLineMode is a draw argument that draws 2D lines onto the Image
	DrawLineMode DrawingMode = iota
	// DrawPolygonMode is a draw argument that draws 3D polygons onto the Image
	DrawPolygonMode
)

// Parser is a script parser
type Parser struct {
	frame  *Image
	em     *Matrix
	tm     *Matrix
	cs     *Stack
	lexer  *Lexer
	backup []Token
}

// NewParser returns a new parser
func NewParser() *Parser {
	cs := NewStack()
	cs.Push(IdentityMatrix(4))
	return &Parser{
		frame:  NewImage(DefaultHeight, DefaultWidth),
		em:     NewMatrix(4, 0),
		tm:     IdentityMatrix(4),
		cs:     cs,
		backup: make([]Token, 0, 10),
	}
}

// ParseFile parses a file for commands and executes them
func (p *Parser) ParseFile(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	p.lexer = NewLexer()
	p.lexer.Lex(f)
	for {
		t := p.next()
		switch t.tt {
		case tError:
			return errors.New(t.value)
		case tEOF:
			return nil
		case tIdent:
			err := p.parseIdent(t)
			if err != nil {
				return err
			}
		default:
			return fmt.Errorf("unexpected token %v", t)
		}
	}
}

func (p *Parser) parseIdent(t Token) error {
	var err error
	switch t.value {
	case "line":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		z0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		z1 := p.nextFloat()
		err = p.line(x0, y0, z0, x1, y1, z1)
	case "ident":
		p.tm = IdentityMatrix(4)
	case "scale":
		sx := p.nextFloat()
		sy := p.nextFloat()
		sz := p.nextFloat()
		err = p.scale(sx, sy, sz)
	case "move":
		x := p.nextFloat()
		y := p.nextFloat()
		z := p.nextFloat()
		err = p.move(x, y, z)
	case "rotate":
		axis := p.nextString()
		theta := p.nextFloat()
		err = p.rotate(axis, theta)
	case "save":
		filename := p.nextString()
		err = p.save(filename)
	case "display":
		err = p.display()
	case "circle":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		radius := p.nextFloat()
		err = p.circle(cx, cy, cz, radius)
	case "hermite":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		dx0 := p.nextFloat()
		dy0 := p.nextFloat()
		dx1 := p.nextFloat()
		dy1 := p.nextFloat()
		err = p.hermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1)
	case "bezier":
		x0 := p.nextFloat()
		y0 := p.nextFloat()
		x1 := p.nextFloat()
		y1 := p.nextFloat()
		x2 := p.nextFloat()
		y2 := p.nextFloat()
		x3 := p.nextFloat()
		y3 := p.nextFloat()
		err = p.bezier(x0, y0, x1, y1, x2, y2, x3, y3)
	case "box":
		x := p.nextFloat()
		y := p.nextFloat()
		z := p.nextFloat()
		width := p.nextFloat()
		height := p.nextFloat()
		depth := p.nextFloat()
		err = p.box(x, y, z, width, height, depth)
	case "clear":
		p.clear()
	case "sphere":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		radius := p.nextFloat()
		err = p.sphere(cx, cy, cz, radius)
	case "torus":
		cx := p.nextFloat()
		cy := p.nextFloat()
		cz := p.nextFloat()
		r1 := p.nextFloat()
		r2 := p.nextFloat()
		err = p.torus(cx, cy, cz, r1, r2)
	case "push":
		top := p.cs.Peek()
		if top != nil {
			p.cs.Push(top.Copy())
		}
	case "pop":
		p.cs.Pop()
	default:
		err = fmt.Errorf("unrecognized identifier: \"%s\"", t.value)
	}
	return err
}

func (p *Parser) next() Token {
	lenBackup := len(p.backup)
	if lenBackup > 0 {
		token := p.backup[lenBackup-1]
		p.backup = p.backup[:lenBackup-1]
		return token
	}
	token := <-p.lexer.out
	for token.tt == tComment {
		token = <-p.lexer.out
	}
	return token
}

func (p *Parser) nextFloat() float64 {
	if p.requireNext(tInt) != nil && p.requireNext(tFloat) != nil {
		panic(fmt.Errorf("%s expected, got %s", tFloat, p.peek().tt))
	}
	v, _ := strconv.ParseFloat(p.next().value, 64)
	return v
}

func (p *Parser) nextString() string {
	if p.requireNext(tString) != nil {
		panic(fmt.Errorf("%s expected, got %s", tString, p.peek().tt))
	}
	return p.next().value
}

func (p *Parser) unread(token Token) {
	if p.backup == nil {
		p.backup = make([]Token, 0, 10)
	}
	p.backup = append(p.backup, token)
}

func (p *Parser) peek() Token {
	token := p.next()
	p.unread(token)
	return token
}

func (p *Parser) requireNext(tt TokenType) error {
	other := p.peek().tt
	if other != tt {
		return fmt.Errorf("unexpected %v; expected %v", other, tt)
	}
	return nil
}

func (p *Parser) line(x0, y0, z0, x1, y1, z1 float64) error {
	p.em.AddEdge(x0, y0, z0, x1, y1, z1)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) scale(sx, sy, sz float64) error {
	dilation := MakeDilation(sx, sy, sz)

	top := p.cs.Pop()
	top, err := top.Multiply(dilation)
	if err != nil {
		return err
	}
	p.cs.Push(top)
	return nil
}

func (p *Parser) move(x, y, z float64) error {
	translation := MakeTranslation(x, y, z)
	top := p.cs.Pop()
	top, err := top.Multiply(translation)
	if err != nil {
		return err
	}
	p.cs.Push(top)

	return nil
}

func (p *Parser) rotate(axis string, theta float64) error {
	var rotation *Matrix
	switch axis {
	case "x":
		rotation = MakeRotX(theta)
	case "y":
		rotation = MakeRotY(theta)
	case "z":
		rotation = MakeRotZ(theta)
	default:
		return errors.New("axis must be \"x\", \"y\", or \"z\"")
	}

	top := p.cs.Pop()
	top, err := top.Multiply(rotation)
	if err != nil {
		return err
	}
	p.cs.Push(top)

	return nil
}

func (p *Parser) apply(mode DrawingMode) error {
	product, err := p.cs.Peek().Multiply(p.em)
	if err != nil {
		return err
	}
	p.em = product
	p.draw(mode)
	p.clear()

	return nil
}

func (p *Parser) draw(mode DrawingMode) {
	switch mode {
	case DrawLineMode:
		p.frame.DrawLines(p.em, color.White)
	case DrawPolygonMode:
		p.frame.DrawPolygons(p.em, color.White)
	default:
	}
}

func (p *Parser) save(filename string) error {
	err := p.frame.Save(filename)
	return err
}

func (p *Parser) display() error {
	err := p.frame.Display()
	return err
}

func (p *Parser) circle(cx, cy, cz, radius float64) error {
	p.em.AddCircle(cx, cy, cz, radius)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) hermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1 float64) error {
	p.em.AddHermite(x0, y0, x1, y1, dx0, dy0, dx1, dy1)
	err := p.apply(DrawLineMode)

	return err
}

func (p *Parser) bezier(x0, y0, x1, y1, x2, y2, x3, y3 float64) error {
	p.em.AddBezier(x0, y0, x1, y1, x2, y2, x3, y3)
	err := p.apply(DrawLineMode)
	return err
}

func (p *Parser) box(x, y, z, width, height, depth float64) error {
	p.em.AddBox(x, y, z, width, height, depth)
	err := p.apply(DrawPolygonMode)
	return err
}

func (p *Parser) clear() {
	p.em = NewMatrix(4, 0)
}

func (p *Parser) sphere(cx, cy, cz, radius float64) error {
	p.em.AddSphere(cx, cy, cz, radius)
	err := p.apply(DrawPolygonMode)
	return err
}

func (p *Parser) torus(cx, cy, cz, r1, r2 float64) error {
	p.em.AddTorus(cx, cy, cz, r1, r2)
	err := p.apply(DrawPolygonMode)

	return err
}
<|endoftext|>


<commit_before>package period

import (
	"fmt"
	"time"
)

const (
	UTS               = "1136239445"          //  unixtimestamp
	ICSFORMAT         = "20060102T150405Z"    //ics date time format
	YMDHIS            = "2006-01-02 15:04:05" // Y-m-d H:i:S time format
	ICSFORMATWHOLEDAY = "20060102"            // ics date format ( describes a whole day)
)

var StartWeek time.Weekday = time.Monday
var Timezone *time.Location = time.UTC

type Period struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

// Compare DateTimeInterface objects including microseconds
func compareDate(date1, date2 time.Time) int {
	if date1.After(date2) {
		return 1
	}

	if date1.Before(date2) {
		return -1
	}

	return 0
}

func CreateFromDay(year int, month int, day int) (p Period, err error) {
	if month, err = validateRange(month, 1, 12); err != nil {
		return p, err
	}

	if day, err = validateRange(day, 1, 31); err != nil {
		return p, err
	}

	p.Start = time.Date(year, time.Month(month), day, 0, 0, 0, 0, Timezone)
	p.End = p.Start.AddDate(0, 0, 1)

	return p, nil
}

// Create a Period object from a Year and a Week.
func CreateFromWeek(year, week int) (p Period, err error) {
	if week, err = validateRange(week, 1, 53); err != nil {
		return p, err
	}

	p.Start = time.Date(year, 0, 0, 0, 0, 0, 0, Timezone)
	isoYear, isoWeek := p.Start.ISOWeek()
	for p.Start.Weekday() != time.Monday { // iterate back to Monday (ISO_8601 first day of week = Monday)
		p.Start = p.Start.AddDate(0, 0, -1)
		isoYear, isoWeek = p.Start.ISOWeek()
	}
	for isoYear < year { // iterate forward to the first day of the first week
		p.Start = p.Start.AddDate(0, 0, 1)
		isoYear, isoWeek = p.Start.ISOWeek()
		// fmt.Printf("isoYear: %s, year: %s\n", isoYear, year)
	}
	for isoWeek < week { // iterate forward to the first day of the given week
		p.Start = p.Start.AddDate(0, 0, 1)
		isoYear, isoWeek = p.Start.ISOWeek()
	}
	for p.Start.Weekday() != StartWeek { // iterate back to StartWeek
		var diff int
		diff = int(StartWeek) - int(time.Monday)
		p.Start = p.Start.AddDate(0, 0, diff)
		isoYear, isoWeek = p.Start.ISOWeek()
	}

	// add 1 week
	p.End = p.Start.AddDate(0, 0, 7)

	return p, nil
}

func validateRange(value, min, max int) (int, error) {
	if value < min || value > max {
		return value, OutOfRangeError
	}
	return value, nil
}

// Create a Period object from a Year and a Month.
func CreateFromMonth(year, month int) (p Period, err error) {
	if month, err = validateRange(month, 1, 12); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, month))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 1, 0)

	return p, nil
}

// Create a Period object from a Year and a Quarter.
func CreateFromQuarter(year, quarter int) (p Period, err error) {
	if quarter, err = validateRange(quarter, 1, 4); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, ((quarter-1)*3)+1))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 3, 0)

	return p, nil
}

// Create a Period object from a Year and a Quarter.
func CreateFromSemester(year, semester int) (p Period, err error) {
	if semester, err = validateRange(semester, 1, 2); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, ((semester-1)*6)+1))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 6, 0)

	return p, nil
}

// Create a Period object from a Year
func CreateFromYear(year int) (p Period, err error) {
	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-01-01 00:00:00", year))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(1, 0, 0)

	return p, nil
}

// Create a Period object from a starting point and an interval.
func CreateFromDuration(start time.Time, duration time.Duration) (p Period) {

	p.Start = start
	p.End = p.Start.Add(duration)

	return p
}

func CreateFromDurationBeforeEnd(end time.Time, duration time.Duration) (p Period) {
	p.Start = end.Add(-1 * duration)
	p.End = end

	return p
}

func (p *Period) Contains(index time.Time) bool {
	return (-1 < compareDate(index, p.Start)) &&
		(-1 == compareDate(index, p.End))
}

func (p *Period) WithDuration(duration time.Duration) {
	p.End = p.Start.Add(duration)
}

func (p *Period) Add(duration time.Duration) {
	p.End = p.End.Add(duration)
}

func (p *Period) Sub(duration time.Duration) {
	p.End = p.End.Add(-1 * duration)
}

func (p *Period) Next() {
	clone := *p
	duration := clone.GetDurationInterval()
	p.Start = clone.End
	p.End = clone.End.Add(duration)
}

func (p *Period) Previous() {
	clone := *p
	duration := clone.GetDurationInterval()
	p.Start = clone.Start.Add(-1 * duration)
	p.End = clone.Start
}

func (p *Period) GetDurationInterval() time.Duration {
	return p.End.Sub(p.Start)
}

func (p *Period) Overlaps(period Period) bool {
	if abuts, _ := p.Abuts(period); abuts {
		return false
	}

	return (-1 == compareDate(p.Start, period.End)) &&
		(1 == compareDate(p.End, period.Start))
}

// Tells whether a Period is entirely after the specified index
func (p *Period) After(period Period) bool {
	return p.Start.After(period.End)
}

// Tells whether a Period is entirely before the specified index
func (p *Period) Before(period Period) bool {
	return p.End.Before(period.Start)
}

// Tells whether two Period object abuts
func (p *Period) Abuts(period Period) (bool, int) {
	if p.Start.Equal(period.End) || p.End.Equal(period.Start) {
		var pos int = -1

		if compareDate(p.Start, period.End) == 0 {
			pos = 0
		} else if compareDate(p.End, period.Start) == 0 {
			pos = 1
		}

		return true, pos
	}

	return false, -1
}

func (p *Period) Diff(period Period) ([]Period, error) {
	if p.Overlaps(period) == false {
		return nil, ShouldOverlapsError
	}

	var res = []Period{}
	var period1 Period = createFromDatepoints(p.Start, period.Start)
	var period2 Period = createFromDatepoints(p.End, period.End)

	if compareDate(period1.Start, period1.End) != 0 {
		res = append(res, period1)
	}

	if compareDate(period2.Start, period2.End) != 0 {
		res = append(res, period2)
	}

	return res, nil
}

// Merges one or more Period objects to return a new Period object.
// The resultant object englobes the largest duration possible.
func (p *Period) Merge(periods ...Period) {
	// allPeriods := []Period{}
	for _, period := range periods {
		if 1 == compareDate(p.Start, period.Start) {
			p.Start = period.Start
		}

		if -1 == compareDate(p.End, period.End) {
			p.End = period.End
		}
	}
}

// Computes the intersection between two Period objects.
func (p *Period) Intersect(period Period) (Period, error) {
	var newPeriod Period
	if abuts, _ := p.Abuts(period); abuts {
		return newPeriod, BothShouldNotAbuts
	}

	if newPeriod.Start = p.Start; 1 == compareDate(period.Start, p.Start) {
		newPeriod.Start = period.Start
	}

	if newPeriod.End = p.End; -1 == compareDate(period.End, p.End) {
		newPeriod.End = period.End
	}

	return newPeriod, nil
}

func (p *Period) Gap(period Period) Period {
	var newPeriod Period
	if 1 == compareDate(period.Start, p.Start) {
		newPeriod.Start = p.End
		newPeriod.End = period.Start
		return newPeriod
	}

	newPeriod.Start = period.End
	newPeriod.End = p.Start
	return newPeriod
}

// Compares two Period objects according to their duration.
func (p *Period) CompareDuration(period Period) int {
	return compareDate(p.End, period.End)
}

// Tells whether the current Period object duration
// is greater than the submitted one.
func (p *Period) DurationGreaterThan(period Period) bool {
	return 1 == p.CompareDuration(period)
}

// Tells whether the current Period object duration
// is less than the submitted one.
func (p *Period) DurationLessThan(period Period) bool {
	return -1 == p.CompareDuration(period)
}

// Tells whether the current Period object duration
// is equal to the submitted one
func (p *Period) SameDurationAs(period Period) bool {
	return p.GetDurationInterval() == period.GetDurationInterval()
}

// Create a Period object from a Year and a Quarter.
func (p *Period) DurationDiff(period Period) time.Duration {
	return time.Duration(p.TimestampDurationDiff(period)) * time.Nanosecond
}

func (p *Period) TimestampDurationDiff(period Period) int64 {
	return p.GetDurationInterval().Nanoseconds() - period.GetDurationInterval().Nanoseconds()
}

func createFromDatepoints(date1, date2 time.Time) Period {
	if 1 == compareDate(date1, date2) {
		return Period{date2, date1}
	}

	return Period{date1, date2}
}
<commit_msg>Add new Today() constructor method<commit_after>package period

import (
	"fmt"
	"time"
)

const (
	UTS               = "1136239445"          //  unixtimestamp
	ICSFORMAT         = "20060102T150405Z"    //ics date time format
	YMDHIS            = "2006-01-02 15:04:05" // Y-m-d H:i:S time format
	ICSFORMATWHOLEDAY = "20060102"            // ics date format ( describes a whole day)
)

var StartWeek time.Weekday = time.Monday
var Timezone *time.Location = time.UTC

type Period struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

// Compare DateTimeInterface objects including microseconds
func compareDate(date1, date2 time.Time) int {
	if date1.After(date2) {
		return 1
	}

	if date1.Before(date2) {
		return -1
	}

	return 0
}

// Today create a new period for today
func Today() (p Period, err error) {
	var now = time.Now()

	p, err = CreateFromDay(now.Year(), int(now.Month()), now.Day())
	if err != nil {
		return p, err
	}

	return p, nil
}

func CreateFromDay(year int, month int, day int) (p Period, err error) {
	if month, err = validateRange(month, 1, 12); err != nil {
		return p, err
	}

	if day, err = validateRange(day, 1, 31); err != nil {
		return p, err
	}

	p.Start = time.Date(year, time.Month(month), day, 0, 0, 0, 0, Timezone)
	p.End = p.Start.AddDate(0, 0, 1)

	return p, nil
}

// Create a Period object from a Year and a Week.
func CreateFromWeek(year, week int) (p Period, err error) {
	if week, err = validateRange(week, 1, 53); err != nil {
		return p, err
	}

	p.Start = time.Date(year, 0, 0, 0, 0, 0, 0, Timezone)
	isoYear, isoWeek := p.Start.ISOWeek()
	for p.Start.Weekday() != time.Monday { // iterate back to Monday (ISO_8601 first day of week = Monday)
		p.Start = p.Start.AddDate(0, 0, -1)
		isoYear, isoWeek = p.Start.ISOWeek()
	}
	for isoYear < year { // iterate forward to the first day of the first week
		p.Start = p.Start.AddDate(0, 0, 1)
		isoYear, isoWeek = p.Start.ISOWeek()
		// fmt.Printf("isoYear: %s, year: %s\n", isoYear, year)
	}
	for isoWeek < week { // iterate forward to the first day of the given week
		p.Start = p.Start.AddDate(0, 0, 1)
		isoYear, isoWeek = p.Start.ISOWeek()
	}
	for p.Start.Weekday() != StartWeek { // iterate back to StartWeek
		var diff int
		diff = int(StartWeek) - int(time.Monday)
		p.Start = p.Start.AddDate(0, 0, diff)
		isoYear, isoWeek = p.Start.ISOWeek()
	}

	// add 1 week
	p.End = p.Start.AddDate(0, 0, 7)

	return p, nil
}

func validateRange(value, min, max int) (int, error) {
	if value < min || value > max {
		return value, OutOfRangeError
	}
	return value, nil
}

// Create a Period object from a Year and a Month.
func CreateFromMonth(year, month int) (p Period, err error) {
	if month, err = validateRange(month, 1, 12); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, month))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 1, 0)

	return p, nil
}

// Create a Period object from a Year and a Quarter.
func CreateFromQuarter(year, quarter int) (p Period, err error) {
	if quarter, err = validateRange(quarter, 1, 4); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, ((quarter-1)*3)+1))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 3, 0)

	return p, nil
}

// Create a Period object from a Year and a Quarter.
func CreateFromSemester(year, semester int) (p Period, err error) {
	if semester, err = validateRange(semester, 1, 2); err != nil {
		return p, err
	}

	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-%02d-01 00:00:00", year, ((semester-1)*6)+1))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(0, 6, 0)

	return p, nil
}

// Create a Period object from a Year
func CreateFromYear(year int) (p Period, err error) {
	p.Start, err = time.Parse(YMDHIS, fmt.Sprintf("%d-01-01 00:00:00", year))
	if err != nil {
		return p, err
	}

	p.End = p.Start.AddDate(1, 0, 0)

	return p, nil
}

// Create a Period object from a starting point and an interval.
func CreateFromDuration(start time.Time, duration time.Duration) (p Period) {

	p.Start = start
	p.End = p.Start.Add(duration)

	return p
}

func CreateFromDurationBeforeEnd(end time.Time, duration time.Duration) (p Period) {
	p.Start = end.Add(-1 * duration)
	p.End = end

	return p
}

func (p *Period) Contains(index time.Time) bool {
	return (-1 < compareDate(index, p.Start)) &&
		(-1 == compareDate(index, p.End))
}

func (p *Period) WithDuration(duration time.Duration) {
	p.End = p.Start.Add(duration)
}

func (p *Period) Add(duration time.Duration) {
	p.End = p.End.Add(duration)
}

func (p *Period) Sub(duration time.Duration) {
	p.End = p.End.Add(-1 * duration)
}

func (p *Period) Next() {
	clone := *p
	duration := clone.GetDurationInterval()
	p.Start = clone.End
	p.End = clone.End.Add(duration)
}

func (p *Period) Previous() {
	clone := *p
	duration := clone.GetDurationInterval()
	p.Start = clone.Start.Add(-1 * duration)
	p.End = clone.Start
}

func (p *Period) GetDurationInterval() time.Duration {
	return p.End.Sub(p.Start)
}

func (p *Period) Overlaps(period Period) bool {
	if abuts, _ := p.Abuts(period); abuts {
		return false
	}

	return (-1 == compareDate(p.Start, period.End)) &&
		(1 == compareDate(p.End, period.Start))
}

// Tells whether a Period is entirely after the specified index
func (p *Period) After(period Period) bool {
	return p.Start.After(period.End)
}

// Tells whether a Period is entirely before the specified index
func (p *Period) Before(period Period) bool {
	return p.End.Before(period.Start)
}

// Tells whether two Period object abuts
func (p *Period) Abuts(period Period) (bool, int) {
	if p.Start.Equal(period.End) || p.End.Equal(period.Start) {
		var pos int = -1

		if compareDate(p.Start, period.End) == 0 {
			pos = 0
		} else if compareDate(p.End, period.Start) == 0 {
			pos = 1
		}

		return true, pos
	}

	return false, -1
}

func (p *Period) Diff(period Period) ([]Period, error) {
	if p.Overlaps(period) == false {
		return nil, ShouldOverlapsError
	}

	var res = []Period{}
	var period1 Period = createFromDatepoints(p.Start, period.Start)
	var period2 Period = createFromDatepoints(p.End, period.End)

	if compareDate(period1.Start, period1.End) != 0 {
		res = append(res, period1)
	}

	if compareDate(period2.Start, period2.End) != 0 {
		res = append(res, period2)
	}

	return res, nil
}

// Merges one or more Period objects to return a new Period object.
// The resultant object englobes the largest duration possible.
func (p *Period) Merge(periods ...Period) {
	// allPeriods := []Period{}
	for _, period := range periods {
		if 1 == compareDate(p.Start, period.Start) {
			p.Start = period.Start
		}

		if -1 == compareDate(p.End, period.End) {
			p.End = period.End
		}
	}
}

// Computes the intersection between two Period objects.
func (p *Period) Intersect(period Period) (Period, error) {
	var newPeriod Period
	if abuts, _ := p.Abuts(period); abuts {
		return newPeriod, BothShouldNotAbuts
	}

	if newPeriod.Start = p.Start; 1 == compareDate(period.Start, p.Start) {
		newPeriod.Start = period.Start
	}

	if newPeriod.End = p.End; -1 == compareDate(period.End, p.End) {
		newPeriod.End = period.End
	}

	return newPeriod, nil
}

func (p *Period) Gap(period Period) Period {
	var newPeriod Period
	if 1 == compareDate(period.Start, p.Start) {
		newPeriod.Start = p.End
		newPeriod.End = period.Start
		return newPeriod
	}

	newPeriod.Start = period.End
	newPeriod.End = p.Start
	return newPeriod
}

// Compares two Period objects according to their duration.
func (p *Period) CompareDuration(period Period) int {
	return compareDate(p.End, period.End)
}

// Tells whether the current Period object duration
// is greater than the submitted one.
func (p *Period) DurationGreaterThan(period Period) bool {
	return 1 == p.CompareDuration(period)
}

// Tells whether the current Period object duration
// is less than the submitted one.
func (p *Period) DurationLessThan(period Period) bool {
	return -1 == p.CompareDuration(period)
}

// Tells whether the current Period object duration
// is equal to the submitted one
func (p *Period) SameDurationAs(period Period) bool {
	return p.GetDurationInterval() == period.GetDurationInterval()
}

// Create a Period object from a Year and a Quarter.
func (p *Period) DurationDiff(period Period) time.Duration {
	return time.Duration(p.TimestampDurationDiff(period)) * time.Nanosecond
}

func (p *Period) TimestampDurationDiff(period Period) int64 {
	return p.GetDurationInterval().Nanoseconds() - period.GetDurationInterval().Nanoseconds()
}

func createFromDatepoints(date1, date2 time.Time) Period {
	if 1 == compareDate(date1, date2) {
		return Period{date2, date1}
	}

	return Period{date1, date2}
}
<|endoftext|>


<commit_before>package nio

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"testing"
)

func TestPipe(t *testing.T) {
	r, w := Pipe()

	go func() {
		for i := 0; i < 10; i++ {
			if _, err := w.Write([]byte(fmt.Sprintf("%d", i))); err != nil {
				t.Error(err.Error())
				return
			}
		}
		w.Close()
	}()

	data, err := ioutil.ReadAll(r)
	if err != nil {
		t.Error(err.Error())
	}
	if !bytes.Equal(data, []byte("0123456789")) {
		t.Error("Not equal!")
	}
}
<commit_msg>Added NewReadCloser and NewWriteCloser test<commit_after>package nio

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"testing"
)

func TestPipe(t *testing.T) {
	r, w := Pipe()

	r = NewReadCloser(r)
	w = NewWriteCloser(w)

	go func() {
		for i := 0; i < 10; i++ {
			if _, err := w.Write([]byte(fmt.Sprintf("%d", i))); err != nil {
				t.Error(err.Error())
				return
			}
		}
		w.Close()
	}()

	data, err := ioutil.ReadAll(r)
	if err != nil {
		t.Error(err.Error())
	}
	if !bytes.Equal(data, []byte("0123456789")) {
		t.Error("Not equal!")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/appleboy/drone-git-push/repo"
	"github.com/pkg/errors"
)

type (
	Repo struct {
		Clone string
	}

	Build struct {
		Path string
	}

	Author struct {
		Name  string
		Email string
	}

	Commit struct {
		Author Author
	}

	Netrc struct {
		Machine  string
		Login    string
		Password string
	}

	Config struct {
		Key            string
		UpstreamName   string
		TargetBranch   string
		TemporaryBase  string
		PagesDirectory string
		WorkDirectory  string
	}

	Plugin struct {
		Repo   Repo
		Build  Build
		Commit Commit
		Netrc  Netrc
		Config Config
	}
)

func (p Plugin) Exec() error {
	if err := p.prepare(); err != nil {
		return err
	}

	if err := p.process(); err != nil {
		return err
	}

	return nil
}

func (p Plugin) prepare() error {
	if p.Netrc.Login != "" {
		if err := repo.WriteNetrc(p.Netrc.Machine, p.Netrc.Login, p.Netrc.Password); err != nil {
			return errors.Wrap(err, "failed to write netrc")
		}
	}

	if p.Config.Key != "" {
		if err := repo.WriteKey(p.Config.Key); err != nil {
			return errors.Wrap(err, "failed to write sshkey")
		}
	}

	if err := repo.GlobalUser(p.Commit.Author.Email).Run(); err != nil {
		return errors.Wrap(err, "failed to set email")
	}

	if err := repo.GlobalName(p.Commit.Author.Name).Run(); err != nil {
		return errors.Wrap(err, "failed to set author")
	}

	return nil
}

func (p Plugin) process() error {
	defer os.RemoveAll(p.Config.TemporaryBase)

	if err := p.cloneTarget(); err != nil {
		return errors.Wrap(err, "failed to clone target")
	}

	if err := p.rsyncPages(); err != nil {
		return errors.Wrap(err, "failed to sync pages")
	}

	if p.dirtyRepo() {
		if err := p.stageChanges(); err != nil {
			return errors.Wrap(err, "failed to stage changes")
		}

		if err := p.commitChanges(); err != nil {
			return errors.Wrap(err, "failed to commit changes")
		}

		if err := p.pushChanges(); err != nil {
			return errors.Wrap(err, "failed to push changes")
		}
	}

	return nil
}

func (p Plugin) cloneTarget() error {
	cmd := exec.Command(
		"git",
		"clone",
		"-b",
		p.Config.TargetBranch,
		"--single-branch",
		p.Repo.Clone,
		p.Config.WorkDirectory,
	)

	cmd.Dir = p.Build.Path
	return runCommand(cmd)
}

func (p Plugin) rsyncPages() error {
	cmd := exec.Command(
		"rsync",
		"--delete",
		"--exclude",
		".git",
		"--exclude",
		"CNAME",
		"-r",
		p.Config.PagesDirectory,
		p.Config.TemporaryBase,
	)

	cmd.Dir = p.Build.Path
	return runCommand(cmd)
}

func (p Plugin) stageChanges() error {
	cmd := exec.Command(
		"git",
		"add",
		".",
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) commitChanges() error {
	message, err := p.commitMessage()

	if err != nil {
		return err
	}

	cmd := exec.Command(
		"git",
		"commit",
		"-m",
		string(message),
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) pushChanges() error {
	cmd := repo.RemotePush(
		p.Config.UpstreamName,
		p.Config.TargetBranch,
		false,
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) dirtyRepo() bool {
	cmd := exec.Command(
		"git",
		"status",
		"--porcelain",
	)

	res := bytes.NewBufferString("")
	cmd.Dir = p.Config.WorkDirectory
	cmd.Stdout = res
	cmd.Stderr = res

	err := runCommand(cmd)

	if err != nil {
		return false
	}

	if res.Len() > 0 {
		fmt.Print(res.String())
		return true
	}

	return false
}

func (p Plugin) commitMessage() ([]byte, error) {
	cmd := exec.Command(
		"git",
		"show",
		"-q",
	)

	cmd.Dir = p.Build.Path
	return cmd.Output()
}

func trace(cmd *exec.Cmd) {
	fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
}

func runCommand(cmd *exec.Cmd) error {
	if cmd.Stdout == nil {
		cmd.Stdout = os.Stdout
	}

	if cmd.Stderr == nil {
		cmd.Stderr = os.Stderr
	}

	trace(cmd)
	return cmd.Run()
}
<commit_msg>update<commit_after>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/appleboy/drone-git-push/repo"
	"github.com/pkg/errors"
)

type (
	Repo struct {
		Clone string
	}

	Build struct {
		Path string
	}

	Author struct {
		Name  string
		Email string
	}

	Commit struct {
		Author Author
	}

	Netrc struct {
		Machine  string
		Login    string
		Password string
	}

	Config struct {
		Key            string
		UpstreamName   string
		TargetBranch   string
		TemporaryBase  string
		PagesDirectory string
		WorkDirectory  string
	}

	Plugin struct {
		Repo   Repo
		Build  Build
		Commit Commit
		Netrc  Netrc
		Config Config
	}
)

func (p Plugin) Exec() error {
	if err := p.prepare(); err != nil {
		return err
	}

	if err := p.process(); err != nil {
		return err
	}

	return nil
}

func (p Plugin) prepare() error {
	if p.Netrc.Login != "" {
		if err := repo.WriteNetrc(p.Netrc.Machine, p.Netrc.Login, p.Netrc.Password); err != nil {
			return errors.Wrap(err, "failed to write netrc")
		}
	}

	if p.Config.Key != "" {
		if err := repo.WriteKey(p.Config.Key); err != nil {
			return errors.Wrap(err, "failed to write sshkey")
		}
	}

	if err := repo.GlobalUser(p.Commit.Author.Email).Run(); err != nil {
		return errors.Wrap(err, "failed to set email")
	}

	if err := repo.GlobalName(p.Commit.Author.Name).Run(); err != nil {
		return errors.Wrap(err, "failed to set author")
	}

	return nil
}

func (p Plugin) process() error {
	defer os.RemoveAll(p.Config.TemporaryBase)

	if err := p.cloneTarget(); err != nil {
		return errors.Wrap(err, "failed to clone target")
	}

	if err := p.rsyncPages(); err != nil {
		return errors.Wrap(err, "failed to sync pages")
	}

	if p.dirtyRepo() {
		if err := p.stageChanges(); err != nil {
			return errors.Wrap(err, "failed to stage changes")
		}

		if err := p.commitChanges(); err != nil {
			return errors.Wrap(err, "failed to commit changes")
		}

		if err := p.pushChanges(); err != nil {
			return errors.Wrap(err, "failed to push changes")
		}
	}

	return nil
}

func (p Plugin) cloneTarget() error {
	cmd := exec.Command(
		"git",
		"clone",
		"-b",
		p.Config.TargetBranch,
		"--single-branch",
		p.Repo.Clone,
		p.Config.WorkDirectory,
	)

	cmd.Dir = p.Build.Path
	return runCommand(cmd)
}

func (p Plugin) rsyncPages() error {
	cmd := exec.Command(
		"rsync",
		"--delete",
		"--exclude",
		".git",
		"--exclude",
		"CNAME",
		"-r",
		p.Config.PagesDirectory,
		p.Config.TemporaryBase,
	)

	cmd.Dir = p.Build.Path
	return runCommand(cmd)
}

func (p Plugin) stageChanges() error {
	cmd := exec.Command(
		"git",
		"add",
		".",
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) commitChanges() error {
	message, err := p.commitMessage()

	if err != nil {
		return err
	}

	cmd := exec.Command(
		"git",
		"commit",
		"-m",
		string(message),
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) pushChanges() error {
	cmd := repo.RemotePush(
		p.Config.UpstreamName,
		p.Config.TargetBranch,
		false,
		false,
	)

	cmd.Dir = p.Config.WorkDirectory
	return runCommand(cmd)
}

func (p Plugin) dirtyRepo() bool {
	cmd := exec.Command(
		"git",
		"status",
		"--porcelain",
	)

	res := bytes.NewBufferString("")
	cmd.Dir = p.Config.WorkDirectory
	cmd.Stdout = res
	cmd.Stderr = res

	err := runCommand(cmd)

	if err != nil {
		return false
	}

	if res.Len() > 0 {
		fmt.Print(res.String())
		return true
	}

	return false
}

func (p Plugin) commitMessage() ([]byte, error) {
	cmd := exec.Command(
		"git",
		"show",
		"-q",
	)

	cmd.Dir = p.Build.Path
	return cmd.Output()
}

func trace(cmd *exec.Cmd) {
	fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
}

func runCommand(cmd *exec.Cmd) error {
	if cmd.Stdout == nil {
		cmd.Stdout = os.Stdout
	}

	if cmd.Stderr == nil {
		cmd.Stderr = os.Stderr
	}

	trace(cmd)
	return cmd.Run()
}
<|endoftext|>


<commit_before>package nr

import (
	"log"

	newrelic "github.com/newrelic/go-agent"
)

// ReportNewRelicError reports errors to newrelic.
func ReportNewRelicError(txn newrelic.Transaction, err error, isDev bool) {
	if !isDev {
		log.Println("Reporting error to newrelic: ", err)
		txn.NoticeError(err)
	}
}
<commit_msg>log the tnx error log<commit_after>package nr

import (
	"log"

	newrelic "github.com/newrelic/go-agent"
)

// ReportNewRelicError reports errors to newrelic.
func ReportNewRelicError(txn newrelic.Transaction, err error, isDev bool) {
	if !isDev {
		log.Println("Reporting error to newrelic: ", err)
		newRelicErr := txn.NoticeError(err)
		if newRelicErr != nil {
			log.Println("New relic error occured: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package session

import (
	"fmt"
	"io"
	"net/http"
	"sort"
	"sync"
	"sync/atomic"
	"text/tabwriter"
	"time"

	"golang.org/x/text/language"
	"golang.org/x/text/message"

	"github.com/eycorsican/go-tun2socks/common/log"
	"github.com/eycorsican/go-tun2socks/common/stats"
)

const maxCompletedSessions = 50

type simpleSessionStater struct {
	sessions          sync.Map
	completedSessions []stats.Session
	server            *http.Server
}

func NewSimpleSessionStater() stats.SessionStater {
	return &simpleSessionStater{}
}

func (s *simpleSessionStater) Start() error {
	log.Infof("Start session stater.")
	sessionStatsHandler := func(respw http.ResponseWriter, req *http.Request) {
		// Make a snapshot.
		var sessions []stats.Session
		s.sessions.Range(func(key, value interface{}) bool {
			sess := value.(*stats.Session)
			sessions = append(sessions, *sess)
			return true
		})

		// Sort by session start time.
		sort.Slice(sessions, func(i, j int) bool {
			return sessions[i].SessionStart.Sub(sessions[j].SessionStart) < 0
		})

		p := message.NewPrinter(language.English)
		tablePrint := func(w io.Writer, sessions []stats.Session) {
			fmt.Fprintf(w, "Process Name\tNetwork\tDuration\tLocal Addr\tRemote Addr\tUpload Bytes\tDownload Bytes\t\n")
			for _, sess := range sessions {
				fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t\n",
					sess.ProcessName,
					sess.Network,
					time.Now().Sub(sess.SessionStart),
					sess.LocalAddr,
					sess.RemoteAddr,
					p.Sprintf("%d", atomic.LoadInt64(&sess.UploadBytes)),
					p.Sprintf("%d", atomic.LoadInt64(&sess.DownloadBytes)),
				)
			}
		}

		w := tabwriter.NewWriter(respw, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug)
		fmt.Fprintf(w, "Active sessions %d\n", len(sessions))
		tablePrint(w, sessions)
		fmt.Fprintf(w, "\n\n")
		fmt.Fprintf(w, "Recently completed sessions %d\n", len(s.completedSessions))
		tablePrint(w, s.completedSessions)
		w.Flush()
	}
	http.HandleFunc("/stats/session/plain", sessionStatsHandler)
	server := &http.Server{Addr: "127.0.0.1:6001"}
	go func() {
		s.server.ListenAndServe()
	}()
	s.server = server
	return nil
}

func (s *simpleSessionStater) Stop() error {
	log.Infof("Stop session stater.")
	return s.server.Close()
}

func (s *simpleSessionStater) AddSession(key interface{}, session *stats.Session) {
	s.sessions.Store(key, session)
}

func (s *simpleSessionStater) GetSession(key interface{}) *stats.Session {
	if sess, ok := s.sessions.Load(key); ok {
		return sess.(*stats.Session)
	}
	return nil
}

func (s *simpleSessionStater) RemoveSession(key interface{}) {
	if sess, ok := s.sessions.Load(key); ok {
		s.completedSessions = append(s.completedSessions, *(sess.(*stats.Session)))
		if len(s.completedSessions) > maxCompletedSessions {
			s.completedSessions = s.completedSessions[1:]
		}
	}
	s.sessions.Delete(key)
}
<commit_msg>fix multiple handler registration<commit_after>package session

import (
	"fmt"
	"io"
	"net/http"
	"sort"
	"sync"
	"sync/atomic"
	"text/tabwriter"
	"time"

	"golang.org/x/text/language"
	"golang.org/x/text/message"

	"github.com/eycorsican/go-tun2socks/common/log"
	"github.com/eycorsican/go-tun2socks/common/stats"
)

const maxCompletedSessions = 50

type simpleSessionStater struct {
	sessions          sync.Map
	completedSessions []stats.Session
	server            *http.Server
}

func NewSimpleSessionStater() stats.SessionStater {
	return &simpleSessionStater{}
}

func (s *simpleSessionStater) Start() error {
	log.Infof("Start session stater.")
	sessionStatsHandler := func(respw http.ResponseWriter, req *http.Request) {
		// Make a snapshot.
		var sessions []stats.Session
		s.sessions.Range(func(key, value interface{}) bool {
			sess := value.(*stats.Session)
			sessions = append(sessions, *sess)
			return true
		})

		// Sort by session start time.
		sort.Slice(sessions, func(i, j int) bool {
			return sessions[i].SessionStart.Sub(sessions[j].SessionStart) < 0
		})

		p := message.NewPrinter(language.English)
		tablePrint := func(w io.Writer, sessions []stats.Session) {
			fmt.Fprintf(w, "Process Name\tNetwork\tDuration\tLocal Addr\tRemote Addr\tUpload Bytes\tDownload Bytes\t\n")
			for _, sess := range sessions {
				fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t\n",
					sess.ProcessName,
					sess.Network,
					time.Now().Sub(sess.SessionStart),
					sess.LocalAddr,
					sess.RemoteAddr,
					p.Sprintf("%d", atomic.LoadInt64(&sess.UploadBytes)),
					p.Sprintf("%d", atomic.LoadInt64(&sess.DownloadBytes)),
				)
			}
		}

		w := tabwriter.NewWriter(respw, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug)
		fmt.Fprintf(w, "Active sessions %d\n", len(sessions))
		tablePrint(w, sessions)
		fmt.Fprintf(w, "\n\n")
		fmt.Fprintf(w, "Recently completed sessions %d\n", len(s.completedSessions))
		tablePrint(w, s.completedSessions)
		w.Flush()
	}
	mux := http.NewServeMux()
	mux.HandleFunc("/stats/session/plain", sessionStatsHandler)
	server := &http.Server{Addr: "127.0.0.1:6001", Handler: mux}
	go func() {
		s.server.ListenAndServe()
	}()
	s.server = server
	return nil
}

func (s *simpleSessionStater) Stop() error {
	log.Infof("Stop session stater.")
	return s.server.Close()
}

func (s *simpleSessionStater) AddSession(key interface{}, session *stats.Session) {
	s.sessions.Store(key, session)
}

func (s *simpleSessionStater) GetSession(key interface{}) *stats.Session {
	if sess, ok := s.sessions.Load(key); ok {
		return sess.(*stats.Session)
	}
	return nil
}

func (s *simpleSessionStater) RemoveSession(key interface{}) {
	if sess, ok := s.sessions.Load(key); ok {
		s.completedSessions = append(s.completedSessions, *(sess.(*stats.Session)))
		if len(s.completedSessions) > maxCompletedSessions {
			s.completedSessions = s.completedSessions[1:]
		}
	}
	s.sessions.Delete(key)
}
<|endoftext|>