<commit_before>package main

import (
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
)

// define our game states
type State string

const IS_RUNNING State = "running"
const IS_STOPPED State = "stopped"

// define our stop reasons
type StopReason string

const FINISHED StopReason = "user finished the game"
const TIMEOUT StopReason = "game timed out"
const STOPPED StopReason = "user stoped the game"

// define the genders available in our application
type Gender string

const MALE Gender = "male"
const FEMALE Gender = "female"

// current state of the game
var GameState State

// define the time the user has to complete the game
var Timeout time.Duration

// define some communication channels
var contactChannel chan bool          // a channel to register all contacts with the wire
var contactChannelDebounced chan bool // a debouncer for our contact channel
var finishChannel chan StopReason     // a channel to register finish events (from user or timeout)

var DebounceContact time.Duration // how long should the contact channel be debounced

// lock concurrent access to the shared variables
var Mutex *sync.RWMutex

// --- EVENT HANDLERS FOR USER INTERACTION ---

// handleButtonPress will be called on every button press
// - i.e. start, stop, restart - and should be passed the gender
// that the button is allocated to (male, female)
func handleButtonPress(gender Gender) {
	log.Println("button pressed:", gender)
	currentState := getState()

	// start or stop the game
	if currentState == IS_STOPPED {
		go startGame(gender)
		return
	}

	// send a message into our finish channel
	// if the game is running
	select {
	case finishChannel <- STOPPED:
	default:
	}

}

// handleStartContact will make sure, that the users is starting from the
// beginning of the wire
func handleStartContact(s interface{}) {
	// TODO: make sure the user starts from the start area
}

// handleWireContact will be called whenever the user
// touches the wire
func handleWireContact(s interface{}) {
	log.Println("wire touched")
	currentState := getState()

	if currentState != IS_RUNNING {
		fmt.Println("the timer is currently not running")
		return
	}

	// send a contact event to our communication channel
	select {
	case contactChannelDebounced <- true:
	default:
	}
}

// handleFinishContact will be called whenever the user
// is touching the finish platform
func handleFinishContact(s interface{}) {
	log.Println("game finished")
	currentState := getState()

	if currentState != IS_RUNNING {
		fmt.Println("the timer is currently not running")
		return
	}

	// send a message into our finish channel
	select {
	case finishChannel <- FINISHED:
	default:
	}

}

// --- ACTUAL GAME ACTIONS ---

// startGame will start a new round
func startGame(gender Gender) {

	// signal the webserver that we are about to start the game
	signalChannel <- "game::start::" + string(gender)

	// initialize the start time and touch counter
	startTime := time.Now()
	touchCounter := 0

	// set the game state
	setState(IS_RUNNING)

	fmt.Print("\033[H\033[2J")

	done := make(chan struct{})

	// define the led event to use (male or female)
	var ledEvent string
	if gender == FEMALE {
		ledEvent = "enableLedWoman"
	} else {
		ledEvent = "enalbeLedMan"
	}

	// enable the led light
	select {
	case GameEvents <- ledEvent:
	default:
	}

	// create a separate go-routine for our ticker
	go func(startTime time.Time, done <-chan struct{}) {
		fmt.Println("game started")
		for {
			select {
			// create a ticker to check the time in regular timespans
			case <-time.After(200 * time.Millisecond):
				timeElapsed := time.Now().Sub(startTime)
				// fmt.Print("\rTICK: ", timeElapsed.Seconds())

				if timeElapsed >= Timeout {
					finishChannel <- TIMEOUT
				}

			case <-done:
				return
			}
		}

	}(startTime, done)

	// increase the touch counter on every touch
	go func(startTime time.Time, counter int, gender Gender, done chan struct{}) {
		for {
			select {
			case <-contactChannel:
				fmt.Println("register contact")
				counter += 1

				// signal the webserver that the wire was touched
				signalChannel <- "game::contact::" + strconv.Itoa(counter)

				// sound the buzzer
				select {
				case GameEvents <- "soundBuzzer":
				default:
				}

			case reason := <-finishChannel:

				timeElapsed := time.Now().Sub(startTime)

				// signal the webserver that the game was finished
				signalChannel <- "game::finished::" + strconv.FormatFloat(timeElapsed.Seconds(), 'f', 3, 64)

				// set the state of the game to stopped
				setState(IS_STOPPED)

				// print the results
				fmt.Printf(resultLog, gender, reason, timeElapsed.Seconds(), counter)

				// close our waiting channel
				close(done)

			case <-done:
				fmt.Println("game was finished..")
				select {
				case GameEvents <- "ledOff":
				default:
				}
				return
			}
		}

	}(startTime, touchCounter, gender, done)

}
<commit_msg>require a start signal<commit_after>package main

import (
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
)

// define our game states
type State string

const IS_RUNNING State = "running"
const IS_STOPPED State = "stopped"

// define our stop reasons
type StopReason string

const FINISHED StopReason = "user finished the game"
const TIMEOUT StopReason = "game timed out"
const STOPPED StopReason = "user stoped the game"

// define the genders available in our application
type Gender string

const MALE Gender = "male"
const FEMALE Gender = "female"

// current state of the game
var GameState State

// define the time the user has to complete the game
var Timeout time.Duration

// define some communication channels
var contactChannel chan bool          // a channel to register all contacts with the wire
var contactChannelDebounced chan bool // a debouncer for our contact channel
var startChannel chan bool            // a channel to register touching the start area
var finishChannel chan StopReason     // a channel to register finish events (from user or timeout)

var DebounceContact time.Duration // how long should the contact channel be debounced

// lock concurrent access to the shared variables
var Mutex *sync.RWMutex

// --- EVENT HANDLERS FOR USER INTERACTION ---

// handleButtonPress will be called on every button press
// - i.e. start, stop, restart - and should be passed the gender
// that the button is allocated to (male, female)
func handleButtonPress(gender Gender) {
	log.Println("button pressed:", gender)
	currentState := getState()

	// start or stop the game
	if currentState == IS_STOPPED {
		go startGame(gender)
		return
	}

	// send a message into our finish channel
	// if the game is running
	select {
	case finishChannel <- STOPPED:
	default:
	}

}

// handleStartContact will make sure, that the users is starting from the
// beginning of the wire
func handleStartContact(s interface{}) {
	// send a signal down the start channel
	select {
	case startChannel <- true:
	default:
	}
}

// handleWireContact will be called whenever the user
// touches the wire
func handleWireContact(s interface{}) {
	log.Println("wire touched")
	currentState := getState()

	if currentState != IS_RUNNING {
		fmt.Println("the timer is currently not running")
		return
	}

	// send a contact event to our communication channel
	select {
	case contactChannelDebounced <- true:
	default:
	}
}

// handleFinishContact will be called whenever the user
// is touching the finish platform
func handleFinishContact(s interface{}) {
	log.Println("game finished")
	currentState := getState()

	if currentState != IS_RUNNING {
		fmt.Println("the timer is currently not running")
		return
	}

	// send a message into our finish channel
	select {
	case finishChannel <- FINISHED:
	default:
	}

}

// --- ACTUAL GAME ACTIONS ---

// startGame will start a new round
func startGame(gender Gender) {

	// signal the webserver that we are about to start the game
	signalChannel <- "game::start::" + string(gender)

	// initialize the start time and touch counter
	startTime := time.Now()
	touchCounter := 0

	// set the game state
	setState(IS_RUNNING)

	fmt.Print("\033[H\033[2J")

	done := make(chan struct{})

	// define the led event to use (male or female)
	var ledEvent string
	if gender == FEMALE {
		ledEvent = "enableLedWoman"
	} else {
		ledEvent = "enalbeLedMan"
	}

	// enable the led light
	select {
	case GameEvents <- ledEvent:
	default:
	}

	// create a separate go-routine for our ticker
	go func(startTime time.Time, done <-chan struct{}) {
		fmt.Println("game started")
		for {
			select {
			// create a ticker to check the time in regular timespans
			case <-time.After(200 * time.Millisecond):
				timeElapsed := time.Now().Sub(startTime)
				// fmt.Print("\rTICK: ", timeElapsed.Seconds())

				if timeElapsed >= Timeout {
					finishChannel <- TIMEOUT
				}

			case <-done:
				return
			}
		}

	}(startTime, done)

	// increase the touch counter on every touch
	go func(startTime time.Time, counter int, gender Gender, done chan struct{}) {

		// check if the user touched the start of the wire
		var startTouched bool

		for {
			select {
			case <-startChannel:
				fmt.Println("start region touched")
				startTouched = true

			case <-contactChannel:
				fmt.Println("register contact")

				// check if the start region has been touched before
				if startTouched == false {
					fmt.Println("BEEP: start region not touched yet")
					break
				}

				// increase the touch counter
				counter++

				// signal the webserver that the wire was touched
				signalChannel <- "game::contact::" + strconv.Itoa(counter)

				// sound the buzzer
				select {
				case GameEvents <- "soundBuzzer":
				default:
				}

			case reason := <-finishChannel:

				timeElapsed := time.Now().Sub(startTime)

				// signal the webserver that the game was finished
				signalChannel <- "game::finished::" + string(reason) + "::" + strconv.FormatFloat(timeElapsed.Seconds(), 'f', 3, 64)

				// set the state of the game to stopped
				setState(IS_STOPPED)

				// print the results
				fmt.Printf(resultLog, gender, reason, timeElapsed.Seconds(), counter)

				// close our waiting channel
				close(done)

			case <-done:
				fmt.Println("game was finished..")
				select {
				case GameEvents <- "ledOff":
				default:
				}
				return
			}
		}

	}(startTime, touchCounter, gender, done)

}
<|endoftext|>


<commit_before>package datastructures

import "html/template"
import "fmt"

var queueTemplates = template.Must(template.ParseFiles("templates/header.html", "templates/footer.html", "templates/queue.html"))

type Queue struct {
	size, maxSize int
	elements      []int
}

func NewQueue(maxSize int) *Queue {
	return &Queue{0, maxSize, nil}
}

func (q *Queue) enqueue(val int) error {
	if q.isFull() {
		return fmt.Errorf("Can't enqueue to full queue")
	}
	q.elements = append([]int{val}, q.elements...)
	q.size++
	return nil
}

func (q *Queue) dequeue() error {
	if q.isEmpty() {
		return fmt.Errorf("Cant't dequeue from empty queue")
	}
	q.elements = q.elements[:len(q.elements)-1]
	q.size--
	return nil
}

func (q *Queue) peek() (int, error) {
	if q.isEmpty() {
		return 0, fmt.Errorf("Cant't peek into empty queue")
	}
	return q.elements[len(q.elements)-1], nil
}

func (q *Queue) isFull() bool {
	if q.size == q.maxSize {
		return true
	}
	return false
}

func (q *Queue) isEmpty() bool {
	if q.size == 0 {
		return true
	}
	return false
}
<commit_msg>also show queue size on error<commit_after>package datastructures

import "html/template"
import "fmt"

var queueTemplates = template.Must(template.ParseFiles("templates/header.html", "templates/footer.html", "templates/queue.html"))

type Queue struct {
	size, maxSize int
	elements      []int
}

func NewQueue(maxSize int) *Queue {
	return &Queue{0, maxSize, nil}
}

func (q *Queue) enqueue(val int) error {
	if q.isFull() {
		return fmt.Errorf("Can't enqueue to full queue. Size: %d", q.size)
	}
	q.elements = append([]int{val}, q.elements...)
	q.size++
	return nil
}

func (q *Queue) dequeue() error {
	if q.isEmpty() {
		return fmt.Errorf("Cant't dequeue from empty queue")
	}
	q.elements = q.elements[:len(q.elements)-1]
	q.size--
	return nil
}

func (q *Queue) peek() (int, error) {
	if q.isEmpty() {
		return 0, fmt.Errorf("Cant't peek into empty queue")
	}
	return q.elements[len(q.elements)-1], nil
}

func (q *Queue) isFull() bool {
	if q.size == q.maxSize {
		return true
	}
	return false
}

func (q *Queue) isEmpty() bool {
	if q.size == 0 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package hatchery

import (
	"crypto/rsa"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/ovh/cds/sdk"
)

// NewWorkerToken .
func NewWorkerToken(hatcheryName string, privateKey *rsa.PrivateKey, expiration time.Time, w SpawnArguments) (string, error) {
	claims := WorkerJWTClaims{
		Worker: w,
		StandardClaims: jwt.StandardClaims{
			Issuer:    hatcheryName,
			Subject:   w.WorkerName,
			Id:        sdk.UUID(),
			IssuedAt:  time.Now().Unix(),
			ExpiresAt: expiration.Unix(),
		},
	}

	jwtoken := jwt.NewWithClaims(jwt.SigningMethodRS512, claims)
	signedJWToken, err := jwtoken.SignedString(privateKey)
	if err != nil {
		return "", sdk.WithStack(err)
	}
	return signedJWToken, nil
}
<commit_msg>fix(hatchery): remove model data from worker jwt token<commit_after>package hatchery

import (
	"crypto/rsa"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/ovh/cds/sdk"
)

// NewWorkerToken .
func NewWorkerToken(hatcheryName string, privateKey *rsa.PrivateKey, expiration time.Time, w SpawnArguments) (string, error) {
	claims := WorkerJWTClaims{
		Worker: w,
		StandardClaims: jwt.StandardClaims{
			Issuer:    hatcheryName,
			Subject:   w.WorkerName,
			Id:        sdk.UUID(),
			IssuedAt:  time.Now().Unix(),
			ExpiresAt: expiration.Unix(),
		},
	}

	// FIXME create dedicated struct with only required fields for the token
	claims.Worker.Model = nil

	jwtoken := jwt.NewWithClaims(jwt.SigningMethodRS512, claims)
	signedJWToken, err := jwtoken.SignedString(privateKey)
	if err != nil {
		return "", sdk.WithStack(err)
	}
	return signedJWToken, nil
}
<|endoftext|>


<commit_before>package rrconfig

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
)

type JsonConfig struct {
	m     map[string]interface{}
	rb    []byte
}

func LoadJsonConfigFromFile(path string) (*JsonConfig, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return LoadJsonConfigFromBytes(b)
}

func LoadJsonConfigFromBytes(b []byte) (*JsonConfig, error) {
	var jm map[string]interface{}
	if err := json.Unmarshal(b, &jm); err != nil {
		return nil, err
	}
	s := &JsonConfig{
		m:     jm,
		rb:    b,
	}
	return s, nil
}

func (s *JsonConfig) Dump() (string, error) {
	var rj bytes.Buffer
	if err := json.Indent(&rj, s.rb, "", "\t"); err != nil {
		return "", err
	}
	return string(rj.Bytes()), nil
}

// Get("a.b.c")
func (s *JsonConfig) Get(key string) (interface{}, error) {
	nodes := strings.Split(key, ".")
	m := s.m
	for i := 0; i < len(nodes); i++ {
		if v, ok := m[nodes[i]]; ok {
			if vv, okk := v.(map[string]interface{}); okk {
				// not end
				m = vv
			} else {
				return v, nil
			}
		} else {
			return nil, fmt.Errorf("no value for key %s", key)
		}
	}
	return m, nil
}

func (s *JsonConfig) GetStringSlice(key string) ([]string, error) {
	empty := []string{}
	f, err := s.Get(key)
	if err != nil {
		return empty, err
	}
	if _, ok := f.([]interface{}); !ok {
		return empty, fmt.Errorf("value for key %s is not slice", key)
	}
	sf := f.([]interface{})
	ss := make([]string, len(sf))
	for i, v := range sf {
		if vv, ok := v.(string); ok {
			ss[i] = vv
		} else {
			return empty, fmt.Errorf("%s[%d] is not a string", key, i)
		}
	}
	return ss, nil
}

func (s *JsonConfig) GetString(key string) (string, error) {
	f, err := s.Get(key)
	if err != nil {
		return "", err
	}
	if _, ok := f.(string); !ok {
		return "", fmt.Errorf("value for key %s is not string", key)
	}
	return f.(string), nil
}

func (s *JsonConfig) GetFloat64(key string) (float64, error) {
	f, err := s.Get(key)
	if err != nil {
		return 0.0, err
	}
	if _, ok := f.(float64); !ok {
		return 0.0, fmt.Errorf("value for key %s is not float64", key)
	}
	return f.(float64), nil
}

func (s *JsonConfig) GetInterfaceSlice(key string) ([]interface{}, error) {
	f, err := s.Get(key)
	if err != nil {
		return nil, err
	}
	if _, ok := f.([]interface{}); !ok {
		return nil, fmt.Errorf("value for key %s is not []interface{}", key)
	}
	return f.([]interface{}), nil
}

<commit_msg>JsonConfig add GetInt method<commit_after>package rrconfig

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
)

type JsonConfig struct {
	m     map[string]interface{}
	rb    []byte
}

func LoadJsonConfigFromFile(path string) (*JsonConfig, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return LoadJsonConfigFromBytes(b)
}

func LoadJsonConfigFromBytes(b []byte) (*JsonConfig, error) {
	var jm map[string]interface{}
	if err := json.Unmarshal(b, &jm); err != nil {
		return nil, err
	}
	s := &JsonConfig{
		m:     jm,
		rb:    b,
	}
	return s, nil
}

func (s *JsonConfig) Dump() (string, error) {
	var rj bytes.Buffer
	if err := json.Indent(&rj, s.rb, "", "\t"); err != nil {
		return "", err
	}
	return string(rj.Bytes()), nil
}

// Get("a.b.c")
func (s *JsonConfig) Get(key string) (interface{}, error) {
	nodes := strings.Split(key, ".")
	m := s.m
	for i := 0; i < len(nodes); i++ {
		if v, ok := m[nodes[i]]; ok {
			if vv, okk := v.(map[string]interface{}); okk {
				// not end
				m = vv
			} else {
				return v, nil
			}
		} else {
			return nil, fmt.Errorf("no value for key %s", key)
		}
	}
	return m, nil
}

func (s *JsonConfig) GetStringSlice(key string) ([]string, error) {
	empty := []string{}
	f, err := s.Get(key)
	if err != nil {
		return empty, err
	}
	if _, ok := f.([]interface{}); !ok {
		return empty, fmt.Errorf("value for key %s is not slice", key)
	}
	sf := f.([]interface{})
	ss := make([]string, len(sf))
	for i, v := range sf {
		if vv, ok := v.(string); ok {
			ss[i] = vv
		} else {
			return empty, fmt.Errorf("%s[%d] is not a string", key, i)
		}
	}
	return ss, nil
}

func (s *JsonConfig) GetString(key string) (string, error) {
	f, err := s.Get(key)
	if err != nil {
		return "", err
	}
	if _, ok := f.(string); !ok {
		return "", fmt.Errorf("value for key %s is not string", key)
	}
	return f.(string), nil
}

func (s *JsonConfig) GetInt(key string) (int, error) {
	f, err := s.Get(key)
	if err != nil {
		return 0, err
	}
	if _, ok := f.(float64); !ok {
		return 0, fmt.Errorf("value for key %s is not int", key)
	}
	return int(f.(float64)), nil
}

func (s *JsonConfig) GetFloat64(key string) (float64, error) {
	f, err := s.Get(key)
	if err != nil {
		return 0.0, err
	}
	if _, ok := f.(float64); !ok {
		return 0.0, fmt.Errorf("value for key %s is not float64", key)
	}
	return f.(float64), nil
}

func (s *JsonConfig) GetInterfaceSlice(key string) ([]interface{}, error) {
	f, err := s.Get(key)
	if err != nil {
		return nil, err
	}
	if _, ok := f.([]interface{}); !ok {
		return nil, fmt.Errorf("value for key %s is not []interface{}", key)
	}
	return f.([]interface{}), nil
}

<|endoftext|>


<commit_before>/*
The topology is a data structure that implemented by application, and
used by frameework implementation to setup/manage the event according to
topology defined here. The main usage is:
a. At beginning of the framework initialization for each task, framework
   call the SetTaskID so that the singleton Topology knows which taskID it
   represents.
b. At beginning of each epoch, the framework implementation (on each task)
   will call GetParents and GetChildren with given epoch, so that it knows
   how to setup watcher for node failures.
*/
package meritop

// The Topology will be implemented by the application.
// Each Topology might have many epochs. The topology of each epoch
// might be different.
type Topology interface {
	// This method is called once by framework implementation. So that
	// we can get the local topology for each epoch later.
	SetTaskID(taskID uint64)

	// GetParents returns the parents' IDs of this task at the
	// given epoch.
	GetParents(epochID uint64) []uint64

	// GetChlidren returns the children's IDs of this task at the
	// given epoch.
	GetChildren(epochID uint64) []uint64
}
<commit_msg>add comments for topology usage<commit_after>/*
The topology is a data structure implemented by application, and
used by framework implementation to setup/manage the event according to
topology defined here. The main usage is:
a. At beginning of the framework initialization for each task, framework
   call the SetTaskID so that the singleton Topology knows which taskID it
   represents.
b. At beginning of each epoch, the framework implementation (on each task)
   will call GetParents and GetChildren with given epoch, so that it knows
   how to setup watcher for node failures.
*/
package meritop

// The Topology will be implemented by the application.
// Each Topology might have many epochs. The topology of each epoch
// might be different.
type Topology interface {
	// This method is called once by framework implementation. So that
	// we can get the local topology for each epoch later.
	SetTaskID(taskID uint64)

	// GetParents returns the parents' IDs of this task at the
	// given epoch.
	GetParents(epochID uint64) []uint64

	// GetChlidren returns the children's IDs of this task at the
	// given epoch.
	GetChildren(epochID uint64) []uint64
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"math/rand"
	"strconv"
)

type Ville struct {
	index int
	x, y  float64
}

func chooseCitie(tau [][]float64, etha [][]float64, alpha int, beta int, copyVilles []Ville, current Ville) (Ville, []Ville) {
	var prob []float64 = make([]float64, len(copyVilles))
	var i int = current.index
	var sum float64 = 0.0

	// on calcule les valeurs de tau[i][j]^alpha * etha[i][j]^beta
	for index, ville := range copyVilles {
		prob[index] = math.Pow(tau[i][ville.index], float64(alpha)) * math.Pow(etha[i][ville.index], float64(beta))
		sum += prob[index]
	}

	// on normalise pour avoir des probas
	for index, _ := range copyVilles {
		prob[index] /= sum
	}

	// probability denstiy function
	pcf := prob[0]
	// pour tout le éléments
	for index, _ := range prob {
		// si rand < élément, on le choisit,
		// si non, on calcule la distribution cumulée
		if rand.Float64() < pcf {
			res := copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)

			return res, copyVilles
		}
		if index+1 <= len(prob)+1 {
			pcf += prob[index+1]
		}
	}
	res := copyVilles[len(prob)-1]
	copyVilles = deleteItem(len(prob)-1, copyVilles)

	return res, copyVilles
}

func updateDelta(Q float64, solution []Ville, delta [][]float64) {

	n := len(solution)
	L := norm(solution)

	for index := 1; index < n; index++ {
		i := solution[index-1].index
		j := solution[index].index
		delta[i][j] += Q / L
	}
	i := solution[n-1].index
	j := solution[0].index

	delta[i][j] += Q / L

}

func updatePath(tau [][]float64, delta [][]float64, rho float64) {

	for i, _ := range tau {
		for j, _ := range tau[i] {
			tau[i][j] = (1-rho)*tau[i][j] + delta[i][j]
		}
	}
}

func ant(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.1
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes

	for t_max > 0 {
		for newM > 0 {
			// on crée une copie des villes
			var copyVilles []Ville = make([]Ville, len(villes))
			copy(copyVilles[:], villes)
			// on crée la solution
			var solution []Ville = make([]Ville, len(villes))
			var i int = 0

			// on choisit le première ville
			// et on supprime l'élément de la copie
			var index int = int(math.Mod(float64(m), float64(len(villes))))
			solution[i] = copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)
			i++

			for len(copyVilles) > 0 {
				// on choisit la ville
				solution[i], copyVilles = chooseCitie(tau, etha, alpha, beta, copyVilles, solution[i-1])
				i++
			}
			// on met à jour les phéromones
			updateDelta(Q, solution, delta)
			// on met à jour le best si il est meilleur que le courrant
			if norm(best) > norm(solution) {
				best = solution
			}
			newM--
		}
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func wrapper(file string, t_max int, m int, titre string, out string) {
	villes := readFile(file)
	solution := greedy(file)
	res := ant(t_max, m, villes, norm(solution))
	plotting(res, titre, "X", "Y", out)
}

func main() {
	fmt.Println("Start:")
	t_max := 50
	m := 50
	t_max_s := strconv.FormatInt(int64(t_max), 10)
	m_s := strconv.FormatInt(int64(m), 10)

	// wrapper("cities.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt")
	// wrapper("cities2.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt2")
	// wrapper("cities50.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt50")
	// wrapper("cities60.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt60")
	// wrapper("cities80.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt80")
	wrapper("cities100.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt100")
}
<commit_msg>ajout wrapper_ten pour les mesures<commit_after>package main

import (
	"fmt"
	"math"
	"math/rand"
	// "strconv"
)

type Ville struct {
	index int
	x, y  float64
}

func chooseCitie(tau [][]float64, etha [][]float64, alpha int, beta int, copyVilles []Ville, current Ville) (Ville, []Ville) {
	var prob []float64 = make([]float64, len(copyVilles))
	var i int = current.index
	var sum float64 = 0.0

	// on calcule les valeurs de tau[i][j]^alpha * etha[i][j]^beta
	for index, ville := range copyVilles {
		prob[index] = math.Pow(tau[i][ville.index], float64(alpha)) * math.Pow(etha[i][ville.index], float64(beta))
		sum += prob[index]
	}

	// on normalise pour avoir des probas
	for index, _ := range copyVilles {
		prob[index] /= sum
	}

	// probability denstiy function
	pcf := prob[0]
	// pour tout le éléments
	for index, _ := range prob {
		// si rand < élément, on le choisit,
		// si non, on calcule la distribution cumulée
		if rand.Float64() < pcf {
			res := copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)

			return res, copyVilles
		}
		if index+1 <= len(prob)+1 {
			pcf += prob[index+1]
		}
	}
	res := copyVilles[len(prob)-1]
	copyVilles = deleteItem(len(prob)-1, copyVilles)

	return res, copyVilles
}

func updateDelta(Q float64, solution []Ville, delta [][]float64) {

	n := len(solution)
	L := norm(solution)

	for index := 1; index < n; index++ {
		i := solution[index-1].index
		j := solution[index].index
		delta[i][j] += Q / L
	}
	i := solution[n-1].index
	j := solution[0].index

	delta[i][j] += Q / L

}

func updatePath(tau [][]float64, delta [][]float64, rho float64) {

	for i, _ := range tau {
		for j, _ := range tau[i] {
			tau[i][j] = (1-rho)*tau[i][j] + delta[i][j]
		}
	}
}

func ant(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.1
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes

	for t_max > 0 {
		for newM > 0 {
			// on crée une copie des villes
			var copyVilles []Ville = make([]Ville, len(villes))
			copy(copyVilles[:], villes)
			// on crée la solution
			var solution []Ville = make([]Ville, len(villes))
			var i int = 0

			// on choisit le première ville
			// et on supprime l'élément de la copie
			var index int = int(math.Mod(float64(m), float64(len(villes))))
			solution[i] = copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)
			i++

			for len(copyVilles) > 0 {
				// on choisit la ville
				solution[i], copyVilles = chooseCitie(tau, etha, alpha, beta, copyVilles, solution[i-1])
				i++
			}
			// on met à jour les phéromones
			updateDelta(Q, solution, delta)
			// on met à jour le best si il est meilleur que le courrant
			if norm(best) > norm(solution) {
				best = solution
			}
			newM--
		}
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func wrapper(file string, t_max int, m int, titre string, out string) {
	villes := readFile(file)
	solution := greedy(file)
	res := ant(t_max, m, villes, norm(solution))
	plotting(res, titre, "X", "Y", out)
}

func wrapper_ten(file string, t_max int, m int) {
	villes := readFile(file)
	solution := greedy(file)
	res := make([]float64, 10)
	for index, _ := range res {
		res[index] = norm(ant(t_max, m, villes, norm(solution)))
	}
	fmt.Print(file + "\t->")
	fmt.Println(res)
}

func main() {
	fmt.Println("Start:")
	t_max := 50
	m := 100
	// t_max_s := strconv.FormatInt(int64(t_max), 10)
	// m_s := strconv.FormatInt(int64(m), 10)

	// wrapper("cities.dat", t_max, 50, "Cities.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt")
	// wrapper("cities2.dat", t_max, 50, "Cities2.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt2")
	// wrapper("cities50.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt50")
	// wrapper("cities60.dat", t_max, 50, "Cities60.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt60")
	// wrapper("cities80.dat", t_max, 50, "Cities80.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt80")
	// wrapper("cities100.dat", t_max, 50, "Cities100.dat with AS\n"+"t_max = "+t_max_s+"\nm = "+m_s, "citieAnt100")
	wrapper_ten("cities100.dat", t_max, m)
}
<|endoftext|>


<commit_before>package api

import (
	"testing"
	"github.com/stretchr/testify/assert"
)

func TestApi(t *testing.T) {
    // todo add api tests...
    // arrange
    var a=1
    var b=2
    // act
    var res = a+b
    // assert
	assert.Equal(t,3, res, "computer error again")
}<commit_msg>add create api test<commit_after>package api

import (
    "github.com/geodan/gost/configuration"
    "github.com/geodan/gost/mqtt"
    "github.com/geodan/gost/database/postgis"

	"testing"
	"github.com/stretchr/testify/assert"
)

func TestCreateApi(t *testing.T) {
    // arrange
	cfg := configuration.Config{}
    mqttServer := mqtt.NewMQTTServer(configuration.MQTTConfig{})
    database := postgis.NewDatabase("",123,"", "", "", "",false)
    stAPI := NewAPI(database, cfg, mqttServer)

    // act
    ep := stAPI.GetEndpoints()

    // assert
	assert.NotNil(t,ep)
}<|endoftext|>


<commit_before>package seqdiagram

import (
	"errors"
	"sort"

	"github.com/lmika/goseq/seqdiagram/graphbox"
)

// Various position offsets
const (
	posObjectLeftX = 1
	posObjectY     = 1
)

var graphboxArrowStemMapping = map[ArrowStem]graphbox.ActivityArrowStem{
	SolidArrowStem:  graphbox.SolidArrowStem,
	DashedArrowStem: graphbox.DashedArrowStem,
	ThickArrowStem:  graphbox.ThickArrowStem,
}

// Load the internal font
func mustLoadFont() *graphbox.TTFFont {
	font, err := loadInternalFont(dejaVuSansFont)
	if err != nil {
		panic(errors.New("Could not load internal font: " + dejaVuSansFont))
	}

	return font
}

// Information about a particular actor
type actorInfo struct {
	// Extra cols needed on the left or right
	ExtraLeftCol  bool
	ExtraRightCol bool

	// Actor column
	Col int
}

type graphicBuilder struct {
	Diagram *Diagram
	Graphic *graphbox.Graphic
	Style   *DiagramStyles

	actorInfos []actorInfo
}

func newGraphicBuilder(d *Diagram, style *DiagramStyles) (*graphicBuilder, error) {
	return &graphicBuilder{d, nil, style, nil}, nil
}

func (gb *graphicBuilder) buildGraphic() *graphbox.Graphic {
	rows, cols := gb.calcRowsAndCols()
	gb.Graphic = graphbox.NewGraphic(rows, cols)

	gb.Graphic.Margin = gb.Style.Margin
	gb.Graphic.ShowGrid = false

	gb.addActors()

	if len(gb.Diagram.Items) == 0 {
		gb.Graphic.Put(2, 0, &graphbox.Spacer{graphbox.Point{0, 64}})
	} else {
		row := 2
		gb.putItemsInSlice(&row, 0, gb.Diagram.Items)
	}

	// Add a title
	if gb.Diagram.Title != "" {
		gb.Graphic.Put(0, 0, graphbox.NewTitle(cols, gb.Diagram.Title, gb.Style.Title))
	}

	return gb.Graphic
}

// Place items in a slice.  This will update the rows pointer
func (gb *graphicBuilder) putItemsInSlice(row *int, depth int, items []SequenceItem) {
	for _, item := range items {
		switch itemDetails := item.(type) {
		case *Action:
			gb.putAction(*row, itemDetails)
		case *Note:
			gb.putNote(*row, itemDetails)
		case *Divider:
			gb.putDivider(*row, itemDetails)
		case *Block:
			gb.putBlock(row, depth, itemDetails)
		}

		*row += 1
	}
}

// Calculate rows in slice
func (gb *graphicBuilder) calcItemsInSlice(items []SequenceItem) int {
	rows := 0
	for _, item := range items {
		switch itemDetails := item.(type) {
		case *Block:
			if itemDetails.Concurrent() {
				maxRows := 0
				for _, seg := range itemDetails.Segments {
					rowsInSeg := gb.calcItemsInSlice(seg.SubItems) + 1
					if rowsInSeg > maxRows {
						maxRows = rowsInSeg
					}
				}
				rows += maxRows
			} else {
				for _, seg := range itemDetails.Segments {
					rows += gb.calcItemsInSlice(seg.SubItems) + 1
				}
			}
			rows += 1
		default:
			rows++
		}
	}
	return rows
}

// Places a note
func (gb *graphicBuilder) putNote(row int, note *Note) {
	if (note.Actor2 == nil) || (note.Actor1 == note.Actor2) {
		gb.putSingleActorNote(row, note.Actor1, note)
	} else {
		var leftActor, rightActor *Actor
		if gb.colOfActor(note.Actor1) < gb.colOfActor(note.Actor2) {
			leftActor, rightActor = note.Actor1, note.Actor2
		} else {
			leftActor, rightActor = note.Actor2, note.Actor1
		}

		switch note.Align {
		case OverNoteAlignment:
			gb.putMultiActorOverNote(row, leftActor, rightActor, note)
		case LeftNoteAlignment:
			gb.putSingleActorNote(row, leftActor, note)
		case RightNoteAlignment:
			gb.putSingleActorNote(row, rightActor, note)
		}
	}
}

// Places a note over a single actor
func (gb *graphicBuilder) putSingleActorNote(row int, actor *Actor, note *Note) {
	var pos graphbox.NoteBoxPos

	if note.Align == LeftNoteAlignment {
		pos = graphbox.LeftNotePos
	} else if note.Align == OverNoteAlignment {
		pos = graphbox.CenterNotePos
	} else if note.Align == RightNoteAlignment {
		pos = graphbox.RightNotePos
	}

	col := gb.colOfActor(actor)
	gb.Graphic.Put(row, col, graphbox.NewNoteBox(note.Message, gb.Style.NoteBox, pos))
}

// Places a note over a multiple actors.  This actually uses the divider graphics object
// with the style adopted from the note style
func (gb *graphicBuilder) putMultiActorOverNote(row int, leftActor *Actor, rightActor *Actor, note *Note) {
	dividerBox := graphbox.DividerStyle{
		Font:        gb.Style.NoteBox.Font,
		FontSize:    gb.Style.NoteBox.FontSize,
		Padding:     gb.Style.NoteBox.Padding,
		Margin:      gb.Style.NoteBox.Margin,
		TextPadding: graphbox.Point{0, 0},
		Shape:       graphbox.DSFramedRect,
		Overlap:     gb.Style.MultiNoteOverlap,
	}

	fromCol := gb.colOfActor(leftActor)
	toCol := gb.colOfActor(rightActor)

	// TODO: This was just to avoid bad styling of notes which reference 'left' and 'right'
	// This needs to be fixed using proper styling, instead of this hack.
	if fromCol == 0 {
		fromCol = 1
	}
	if toCol == gb.Graphic.Cols()-1 {
		toCol = gb.Graphic.Cols() - 2
	}

	gb.Graphic.Put(row, fromCol, graphbox.NewDivider(toCol, note.Message, dividerBox))
}

// Places an action
func (gb *graphicBuilder) putAction(row int, action *Action) {
	fromCol := gb.colOfActor(action.From)
	toCol := gb.colOfActor(action.To)

	style := gb.Style.ActivityLine

	style.ArrowHead = gb.Style.ArrowHeads[action.Arrow.Head] //graphboxArrowHeadMapping[action.Arrow.Head]
	style.ArrowStem = graphboxArrowStemMapping[action.Arrow.Stem]

	gb.Graphic.Put(row, fromCol, graphbox.NewActivityLine(toCol, fromCol == toCol, action.Message, style))
}

// Places a divider
func (gb *graphicBuilder) putDivider(row int, action *Divider) {
	fromCol := 0
	toCol := gb.Graphic.Cols() - 1
	style := gb.Style.Divider[action.Type]

	gb.Graphic.Put(row, fromCol, graphbox.NewDivider(toCol, action.Message, style))
}

// Places a block
func (gb *graphicBuilder) putBlock(row *int, depth int, action *Block) {
	if action.Concurrent() {
		gb.putBlockSegmentsConcurrently(row, depth, action)
	} else {
		gb.putBlockSegmentsSequentially(row, depth, action)
	}
}

func (gb *graphicBuilder) putBlockSegmentsConcurrently(row *int, depth int, action *Block) {
	startRow := *row

	for _, seg := range action.Segments {
		thisRow := startRow
		gb.putItemsInSlice(&thisRow, depth+1, seg.SubItems)
		if thisRow > *row {
			*row = thisRow
		}
	}
	*row++
}

func getInnerRanksRecursive(subItems []SequenceItem) []int {
	ranks := []int{}
	for _, subItem := range subItems {
		if action, isAction := subItem.(*Action); isAction {
			//			log.Printf("%d %#v\n", i, action)
			//			log.Printf(" From: %#v\n", action.From)
			//			log.Printf(" To  : %#v\n", action.To)
			ranks = append(ranks, action.From.rank)
			ranks = append(ranks, action.To.rank)
		} else if block, isBlock := subItem.(*Block); isBlock {
			//			log.Printf("%d %#v\n", i, block)
			for _, segment := range block.Segments {
				ranks = append(ranks, getInnerRanksRecursive(segment.SubItems)...)
			}
			//		} else {
			//			log.Printf("%d ??? %#v\n", i, subItem)
		}
	}
	return ranks
}

func (gb *graphicBuilder) putBlockSegmentsSequentially(row *int, depth int, action *Block) {
	style := gb.Style.Block

	var startRow, endRow int
	startRow = *row
	nestDepth := action.MaxNestDepth()

	for i, seg := range action.Segments {
		// default to full width of the diagram
		startCol := 0
		endCol := gb.Graphic.Cols() - 1 // This needs to be the column of the last actor

		// To outline only the inner actors of the block we need to set...
		//  - startCol to the leftmost inner actor of the block
		//  - endCol to the rightmost inner actor of the block
		innerRanks := getInnerRanksRecursive(seg.SubItems)
		sort.Ints(innerRanks)
		// log.Println(innerRanks)
		if len(innerRanks) > 0 {
			// +1 because actor rank and column values are offset by one
			startCol = innerRanks[0] + 1
			endCol = innerRanks[len(innerRanks)-1] + 1
		}

		*row++
		gb.putItemsInSlice(row, depth+1, seg.SubItems)
		endRow = *row

		segPrefix := ""
		showPrefix := true

		switch seg.Type {
		case AltSegmentType:
			segPrefix = "alt"
		case ElseSegmentType:
			segPrefix = "alt"
			showPrefix = false
		case ParSegmentType:
			segPrefix = "par"
		case ParElseSegmentType:
			segPrefix = "par"
			showPrefix = false
		case OptSegmentType:
			segPrefix = "opt"
		case LoopSegmentType:
			segPrefix = "loop"
		}

		if seg.Prefix != "" {
			segPrefix = seg.Prefix
		}

		block := graphbox.NewBlock(endRow, endCol, nestDepth, i == len(action.Segments)-1,
			segPrefix, showPrefix, seg.Message, style)
		gb.Graphic.Put(startRow, startCol, block)

		startRow = endRow
	}
}

// Count the number of rows needed in the graphic
func (gb *graphicBuilder) calcRowsAndCols() (int, int) {
	cols := gb.determineActorInfo() + 1

	// 1 for the title, object header and object footer
	if len(gb.Diagram.Items) == 0 {
		return posObjectY + 3, cols
	} else {
		return gb.calcItemsInSlice(gb.Diagram.Items) + posObjectY + 2, cols
	}
}

// Determine actor information.  Returns the number of colums required
func (gb *graphicBuilder) determineActorInfo() int {
	gb.actorInfos = make([]actorInfo, len(gb.Diagram.Actors))

	// Allocate the columns
	cols := posObjectLeftX
	for _, actor := range gb.Diagram.Actors {
		colsRequiredByActor := 1
		actorCol := cols

		if actor.rank != -1 {
			if gb.actorInfos[actor.rank].ExtraLeftCol {
				colsRequiredByActor++
				actorCol++
			}
			if gb.actorInfos[actor.rank].ExtraRightCol {
				colsRequiredByActor++
			}

			gb.actorInfos[actor.rank].Col = actorCol
			cols += colsRequiredByActor
		}
	}

	return cols
}

// Add the object headers and footers
func (gb *graphicBuilder) addActors() {
	// TODO: Proper styling
	bottomRow := gb.Graphic.Rows() - 1
	for rank, actor := range gb.Diagram.Actors {
		var actorBoxPos graphbox.ActorBoxPos

		if rank == 0 {
			actorBoxPos = graphbox.LeftActorBox
		} else if rank == len(gb.Diagram.Actors)-1 {
			actorBoxPos = graphbox.RightActorBox
		} else {
			actorBoxPos = graphbox.MiddleActorBox
		}

		col := gb.colOfActor(actor)

		if actor.Lifeline {
			gb.Graphic.Put(posObjectY, col, &graphbox.LifeLine{
				TR: bottomRow,
				TC: col,
				Style: graphbox.LifeLineStyle{
					Color: actor.Color,
				},
			})
		}

		if actor.Icon != nil {
			actorIconStyle := gb.Style.ActorIconBox
			actorIconStyle.Color = actor.Color
			actorIconStyle.TextColor = actor.TextColor

			if actor.InHeader {
				gb.Graphic.Put(posObjectY, col, graphbox.NewActorIconBox(actor.Label, actor.Icon.graphboxIcon(), actorIconStyle, actorBoxPos|graphbox.TopActorBox))
			}
		} else {
			// Configure the style
			actorStyle := gb.Style.ActorBox
			actorStyle.Color = actor.Color
			actorStyle.TextColor = actor.TextColor

			if actor.InHeader {
				gb.Graphic.Put(posObjectY, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.TopActorBox))
				if actor.InFooter {
					gb.Graphic.Put(bottomRow, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.BottomActorBox))
				}
			} else {
				if actor.InFooter {
					// Use the TopActorBox as that performs the layout
					gb.Graphic.Put(bottomRow, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.TopActorBox))
				}
			}
		}
	}
}

// Returns the column position of an actor
func (gb *graphicBuilder) colOfActor(actor *Actor) int {
	if actor == LeftOffsideActor {
		return 0
	} else if actor == RightOffsideActor {
		return gb.Graphic.Cols() - 1
	} else {
		return gb.actorInfos[actor.rank].Col
	}
}
<commit_msg>tidy up<commit_after>package seqdiagram

import (
	"errors"
	"sort"

	"github.com/lmika/goseq/seqdiagram/graphbox"
)

// Various position offsets
const (
	posObjectLeftX = 1
	posObjectY     = 1
)

var graphboxArrowStemMapping = map[ArrowStem]graphbox.ActivityArrowStem{
	SolidArrowStem:  graphbox.SolidArrowStem,
	DashedArrowStem: graphbox.DashedArrowStem,
	ThickArrowStem:  graphbox.ThickArrowStem,
}

// Load the internal font
func mustLoadFont() *graphbox.TTFFont {
	font, err := loadInternalFont(dejaVuSansFont)
	if err != nil {
		panic(errors.New("Could not load internal font: " + dejaVuSansFont))
	}

	return font
}

// Information about a particular actor
type actorInfo struct {
	// Extra cols needed on the left or right
	ExtraLeftCol  bool
	ExtraRightCol bool

	// Actor column
	Col int
}

type graphicBuilder struct {
	Diagram *Diagram
	Graphic *graphbox.Graphic
	Style   *DiagramStyles

	actorInfos []actorInfo
}

func newGraphicBuilder(d *Diagram, style *DiagramStyles) (*graphicBuilder, error) {
	return &graphicBuilder{d, nil, style, nil}, nil
}

func (gb *graphicBuilder) buildGraphic() *graphbox.Graphic {
	rows, cols := gb.calcRowsAndCols()
	gb.Graphic = graphbox.NewGraphic(rows, cols)

	gb.Graphic.Margin = gb.Style.Margin
	gb.Graphic.ShowGrid = false

	gb.addActors()

	if len(gb.Diagram.Items) == 0 {
		gb.Graphic.Put(2, 0, &graphbox.Spacer{graphbox.Point{0, 64}})
	} else {
		row := 2
		gb.putItemsInSlice(&row, 0, gb.Diagram.Items)
	}

	// Add a title
	if gb.Diagram.Title != "" {
		gb.Graphic.Put(0, 0, graphbox.NewTitle(cols, gb.Diagram.Title, gb.Style.Title))
	}

	return gb.Graphic
}

// Place items in a slice.  This will update the rows pointer
func (gb *graphicBuilder) putItemsInSlice(row *int, depth int, items []SequenceItem) {
	for _, item := range items {
		switch itemDetails := item.(type) {
		case *Action:
			gb.putAction(*row, itemDetails)
		case *Note:
			gb.putNote(*row, itemDetails)
		case *Divider:
			gb.putDivider(*row, itemDetails)
		case *Block:
			gb.putBlock(row, depth, itemDetails)
		}

		*row += 1
	}
}

// Calculate rows in slice
func (gb *graphicBuilder) calcItemsInSlice(items []SequenceItem) int {
	rows := 0
	for _, item := range items {
		switch itemDetails := item.(type) {
		case *Block:
			if itemDetails.Concurrent() {
				maxRows := 0
				for _, seg := range itemDetails.Segments {
					rowsInSeg := gb.calcItemsInSlice(seg.SubItems) + 1
					if rowsInSeg > maxRows {
						maxRows = rowsInSeg
					}
				}
				rows += maxRows
			} else {
				for _, seg := range itemDetails.Segments {
					rows += gb.calcItemsInSlice(seg.SubItems) + 1
				}
			}
			rows += 1
		default:
			rows++
		}
	}
	return rows
}

// Places a note
func (gb *graphicBuilder) putNote(row int, note *Note) {
	if (note.Actor2 == nil) || (note.Actor1 == note.Actor2) {
		gb.putSingleActorNote(row, note.Actor1, note)
	} else {
		var leftActor, rightActor *Actor
		if gb.colOfActor(note.Actor1) < gb.colOfActor(note.Actor2) {
			leftActor, rightActor = note.Actor1, note.Actor2
		} else {
			leftActor, rightActor = note.Actor2, note.Actor1
		}

		switch note.Align {
		case OverNoteAlignment:
			gb.putMultiActorOverNote(row, leftActor, rightActor, note)
		case LeftNoteAlignment:
			gb.putSingleActorNote(row, leftActor, note)
		case RightNoteAlignment:
			gb.putSingleActorNote(row, rightActor, note)
		}
	}
}

// Places a note over a single actor
func (gb *graphicBuilder) putSingleActorNote(row int, actor *Actor, note *Note) {
	var pos graphbox.NoteBoxPos

	if note.Align == LeftNoteAlignment {
		pos = graphbox.LeftNotePos
	} else if note.Align == OverNoteAlignment {
		pos = graphbox.CenterNotePos
	} else if note.Align == RightNoteAlignment {
		pos = graphbox.RightNotePos
	}

	col := gb.colOfActor(actor)
	gb.Graphic.Put(row, col, graphbox.NewNoteBox(note.Message, gb.Style.NoteBox, pos))
}

// Places a note over a multiple actors.  This actually uses the divider graphics object
// with the style adopted from the note style
func (gb *graphicBuilder) putMultiActorOverNote(row int, leftActor *Actor, rightActor *Actor, note *Note) {
	dividerBox := graphbox.DividerStyle{
		Font:        gb.Style.NoteBox.Font,
		FontSize:    gb.Style.NoteBox.FontSize,
		Padding:     gb.Style.NoteBox.Padding,
		Margin:      gb.Style.NoteBox.Margin,
		TextPadding: graphbox.Point{0, 0},
		Shape:       graphbox.DSFramedRect,
		Overlap:     gb.Style.MultiNoteOverlap,
	}

	fromCol := gb.colOfActor(leftActor)
	toCol := gb.colOfActor(rightActor)

	// TODO: This was just to avoid bad styling of notes which reference 'left' and 'right'
	// This needs to be fixed using proper styling, instead of this hack.
	if fromCol == 0 {
		fromCol = 1
	}
	if toCol == gb.Graphic.Cols()-1 {
		toCol = gb.Graphic.Cols() - 2
	}

	gb.Graphic.Put(row, fromCol, graphbox.NewDivider(toCol, note.Message, dividerBox))
}

// Places an action
func (gb *graphicBuilder) putAction(row int, action *Action) {
	fromCol := gb.colOfActor(action.From)
	toCol := gb.colOfActor(action.To)

	style := gb.Style.ActivityLine

	style.ArrowHead = gb.Style.ArrowHeads[action.Arrow.Head] //graphboxArrowHeadMapping[action.Arrow.Head]
	style.ArrowStem = graphboxArrowStemMapping[action.Arrow.Stem]

	gb.Graphic.Put(row, fromCol, graphbox.NewActivityLine(toCol, fromCol == toCol, action.Message, style))
}

// Places a divider
func (gb *graphicBuilder) putDivider(row int, action *Divider) {
	fromCol := 0
	toCol := gb.Graphic.Cols() - 1
	style := gb.Style.Divider[action.Type]

	gb.Graphic.Put(row, fromCol, graphbox.NewDivider(toCol, action.Message, style))
}

// Places a block
func (gb *graphicBuilder) putBlock(row *int, depth int, action *Block) {
	if action.Concurrent() {
		gb.putBlockSegmentsConcurrently(row, depth, action)
	} else {
		gb.putBlockSegmentsSequentially(row, depth, action)
	}
}

func (gb *graphicBuilder) putBlockSegmentsConcurrently(row *int, depth int, action *Block) {
	startRow := *row

	for _, seg := range action.Segments {
		thisRow := startRow
		gb.putItemsInSlice(&thisRow, depth+1, seg.SubItems)
		if thisRow > *row {
			*row = thisRow
		}
	}
	*row++
}

func getInnerRanksRecursive(subItems []SequenceItem) []int {
	ranks := []int{}
	for _, subItem := range subItems {
		if action, isAction := subItem.(*Action); isAction {
			ranks = append(ranks, action.From.rank)
			ranks = append(ranks, action.To.rank)
		} else if block, isBlock := subItem.(*Block); isBlock {
			for _, segment := range block.Segments {
				ranks = append(ranks, getInnerRanksRecursive(segment.SubItems)...)
			}
		}
	}
	return ranks
}

func (gb *graphicBuilder) getStartAndEndColsBasedOnContent(subItems []SequenceItem) (int, int) {
	startCol := 0
	endCol := gb.Graphic.Cols() - 1 // This needs to be the column of the last actor

	innerRanks := getInnerRanksRecursive(subItems)
	sort.Ints(innerRanks)
	// log.Println(innerRanks)
	if len(innerRanks) > 0 {
		// +1 because actor rank and column values are offset by one
		startCol = innerRanks[0] + 1
		endCol = innerRanks[len(innerRanks)-1] + 1
	}

	return startCol, endCol
}

func (gb *graphicBuilder) putBlockSegmentsSequentially(row *int, depth int, action *Block) {
	style := gb.Style.Block

	var startRow, endRow int
	startRow = *row
	nestDepth := action.MaxNestDepth()

	for i, seg := range action.Segments {
		// To outline only the inner actors of the block we need to set...
		//  - startCol to the leftmost inner actor of the block
		//  - endCol to the rightmost inner actor of the block
		startCol, endCol := gb.getStartAndEndColsBasedOnContent(seg.SubItems)

		*row++
		gb.putItemsInSlice(row, depth+1, seg.SubItems)
		endRow = *row

		segPrefix := ""
		showPrefix := true

		switch seg.Type {
		case AltSegmentType:
			segPrefix = "alt"
		case ElseSegmentType:
			segPrefix = "alt"
			showPrefix = false
		case ParSegmentType:
			segPrefix = "par"
		case ParElseSegmentType:
			segPrefix = "par"
			showPrefix = false
		case OptSegmentType:
			segPrefix = "opt"
		case LoopSegmentType:
			segPrefix = "loop"
		}

		if seg.Prefix != "" {
			segPrefix = seg.Prefix
		}

		block := graphbox.NewBlock(endRow, endCol, nestDepth, i == len(action.Segments)-1,
			segPrefix, showPrefix, seg.Message, style)
		gb.Graphic.Put(startRow, startCol, block)

		startRow = endRow
	}
}

// Count the number of rows needed in the graphic
func (gb *graphicBuilder) calcRowsAndCols() (int, int) {
	cols := gb.determineActorInfo() + 1

	// 1 for the title, object header and object footer
	if len(gb.Diagram.Items) == 0 {
		return posObjectY + 3, cols
	} else {
		return gb.calcItemsInSlice(gb.Diagram.Items) + posObjectY + 2, cols
	}
}

// Determine actor information.  Returns the number of colums required
func (gb *graphicBuilder) determineActorInfo() int {
	gb.actorInfos = make([]actorInfo, len(gb.Diagram.Actors))

	// Allocate the columns
	cols := posObjectLeftX
	for _, actor := range gb.Diagram.Actors {
		colsRequiredByActor := 1
		actorCol := cols

		if actor.rank != -1 {
			if gb.actorInfos[actor.rank].ExtraLeftCol {
				colsRequiredByActor++
				actorCol++
			}
			if gb.actorInfos[actor.rank].ExtraRightCol {
				colsRequiredByActor++
			}

			gb.actorInfos[actor.rank].Col = actorCol
			cols += colsRequiredByActor
		}
	}

	return cols
}

// Add the object headers and footers
func (gb *graphicBuilder) addActors() {
	// TODO: Proper styling
	bottomRow := gb.Graphic.Rows() - 1
	for rank, actor := range gb.Diagram.Actors {
		var actorBoxPos graphbox.ActorBoxPos

		if rank == 0 {
			actorBoxPos = graphbox.LeftActorBox
		} else if rank == len(gb.Diagram.Actors)-1 {
			actorBoxPos = graphbox.RightActorBox
		} else {
			actorBoxPos = graphbox.MiddleActorBox
		}

		col := gb.colOfActor(actor)

		if actor.Lifeline {
			gb.Graphic.Put(posObjectY, col, &graphbox.LifeLine{
				TR: bottomRow,
				TC: col,
				Style: graphbox.LifeLineStyle{
					Color: actor.Color,
				},
			})
		}

		if actor.Icon != nil {
			actorIconStyle := gb.Style.ActorIconBox
			actorIconStyle.Color = actor.Color
			actorIconStyle.TextColor = actor.TextColor

			if actor.InHeader {
				gb.Graphic.Put(posObjectY, col, graphbox.NewActorIconBox(actor.Label, actor.Icon.graphboxIcon(), actorIconStyle, actorBoxPos|graphbox.TopActorBox))
			}
		} else {
			// Configure the style
			actorStyle := gb.Style.ActorBox
			actorStyle.Color = actor.Color
			actorStyle.TextColor = actor.TextColor

			if actor.InHeader {
				gb.Graphic.Put(posObjectY, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.TopActorBox))
				if actor.InFooter {
					gb.Graphic.Put(bottomRow, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.BottomActorBox))
				}
			} else {
				if actor.InFooter {
					// Use the TopActorBox as that performs the layout
					gb.Graphic.Put(bottomRow, col, graphbox.NewActorBox(actor.Label, actorStyle, actorBoxPos|graphbox.TopActorBox))
				}
			}
		}
	}
}

// Returns the column position of an actor
func (gb *graphicBuilder) colOfActor(actor *Actor) int {
	if actor == LeftOffsideActor {
		return 0
	} else if actor == RightOffsideActor {
		return gb.Graphic.Cols() - 1
	} else {
		return gb.actorInfos[actor.rank].Col
	}
}
<|endoftext|>


<commit_before>package sync

import (
	"time"

	// "github.com/coreos/etcd/client"

	"straas.io/external"
	"straas.io/pierce"
)

type Record struct {
	// ID is auto increment primary key
	ID uint64 `gorm:"primary_key,AUTO_INCREMENT"`
	// Namespace is room namespace
	Namespace string `gorm:"size:60" sql:"not null"`
	// Room is room id
	Room string `gorm:"size:100" sql:"not null"`
	// Value is json value of the room
	Value string `gorm:"size:0"`
	// Cluster is etcd cluster number, we might have multiple clusters
	// or cluster rebuild, add uniqu constrain (Cluster, Version) to
	// void etcd verion number confliction
	Cluster uint32 `sql:"not null"`
	// Version is etcd version
	Version uint64 `sql:"not null"`
	// CreateAt for gorm to insert create time
	CreatedAt time.Time
}

type sinker func(roomMeta pierce.RoomMeta, data interface{}, version uint64) error

type syncQueue chan string

type syncer struct {
	// etcd api
	api external.Etcd
	// pierce core manager
	coreMgr pierce.Core
	// named queues for better performance
	queues map[string]syncQueue
	done   chan bool
	sinker sinker
}

func (s *syncer) Start() {
	for _, q := range s.queues {
		go s.syncLoop(q)
	}
	go s.watcher()
}

func (s *syncer) Stop() {
	close(s.done)
}

func (s *syncer) Add(roomMeta pierce.RoomMeta) {
	// conver to roomid

}

func (s *syncer) watch() {
	// index out of sync

}

func (s *syncer) syncLoop(queue syncQueue) {
	for s.syncOnce(queue) {
	}
}

func (s *syncer) syncOnce(queue syncQueue) bool {
	select {
	case <-s.done:
		return false

	case resp := <-queue:
		// TODO: compare
		s.doSync(resp, false)
	}
	return true
}

// leverge namedQueue for better performance
// TODO: retry sync process or backoff unit success
func (s *syncer) doSync(etcdKey string, compare bool) error {
	// toKey ?!
	var roomMeta pierce.RoomMeta

	data, err := s.coreMgr.GetAll(roomMeta)
	if err != nil {
		// WTD ?!
		return err
	}

	// how to know it's newer or older changes ?!
	// sinker
	if err := s.sinker(roomMeta, data, 0); err != nil {
		return err
	}
	return nil
}
<commit_msg>middle<commit_after>package sync

import (
	"time"

	// "github.com/coreos/etcd/client"

	"straas.io/external"
	"straas.io/pierce"
)

type Record struct {
	// ID is auto increment primary key
	ID uint64 `gorm:"primary_key,AUTO_INCREMENT"`
	// Namespace is room namespace
	Namespace string `gorm:"size:60" sql:"not null"`
	// Room is room id
	Room string `gorm:"size:100" sql:"not null"`
	// Value is json value of the room
	Value string `gorm:"size:0"`
	// Cluster is etcd cluster number, we might have multiple clusters
	// or cluster rebuild, add uniqu constrain (Cluster, Version) to
	// void etcd verion number confliction
	Cluster uint32 `sql:"not null"`
	// Version is etcd version
	Version uint64 `sql:"not null"`
	// CreateAt for gorm to insert create time
	CreatedAt time.Time
}

type sinker func(roomMeta pierce.RoomMeta, data interface{}, version uint64) error

type syncQueue chan string

type syncer struct {
	// etcd api
	api external.Etcd
	// pierce core manager
	coreMgr pierce.Core
	// named queues for better performance
	queues map[string]syncQueue
	done   chan bool
	sinker sinker
}

func (s *syncer) Start() {
	for _, q := range s.queues {
		go s.syncLoop(q)
	}
	go s.watch()
}

func (s *syncer) Stop() {
	close(s.done)
}

func (s *syncer) Add(roomMeta pierce.RoomMeta) {
	// conver to roomid

}

func (s *syncer) watch() {
	// index out of sync

}

func (s *syncer) syncLoop(queue syncQueue) {
	for s.syncOnce(queue) {
	}
}

func (s *syncer) syncOnce(queue syncQueue) bool {
	select {
	case <-s.done:
		return false

	case resp := <-queue:
		// TODO: compare
		s.doSync(resp, false)
	}
	return true
}

// leverge namedQueue for better performance
// TODO: retry sync process or backoff unit success
func (s *syncer) doSync(etcdKey string, compare bool) error {
	// toKey ?!
	var roomMeta pierce.RoomMeta

	data, version, err := s.coreMgr.GetAll(roomMeta)
	if err != nil {
		// WTD ?!
		return err
	}

	// how to know it's newer or older changes ?!
	// sinker
	if err := s.sinker(roomMeta, data, version); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Package geom implements fast and GC-efficient Open Geo Consortium-style
// geometries.
package geom

import (
	"errors"
	"fmt"
)

// A Layout describes the meaning of an N-dimensional coordinate. Layout(N) for
// N > 4 is a valid layout, in which case the first dimensions are interpreted
// to be X, Y, Z, and M and extra dimensions have no special meaning.  M values
// are considered part of a linear referencing system (e.g. classical time or
// distance along a path). 1-dimensional layouts are not supported.
type Layout int

const (
	NoLayout Layout = iota // Zero value
	XY                     // 2D
	XYZ                    // 3D
	XYM                    // 2D with an M value
	XYZM                   // 3D with an M value
)

type ErrLayoutMismatch struct {
	Got  Layout
	Want Layout
}

func (e ErrLayoutMismatch) Error() string {
	return fmt.Sprintf("geom: layout mismatch, got %s, want %s", e.Got, e.Want)
}

type ErrStrideMismatch struct {
	Got  int
	Want int
}

func (e ErrStrideMismatch) Error() string {
	return fmt.Sprintf("geom: stride mismatch, got %d, want %d", e.Got, e.Want)
}

type ErrUnsupportedLayout Layout

func (e ErrUnsupportedLayout) Error() string {
	return fmt.Sprintf("geom: unsupported layout %s", Layout(e))
}

type ErrUnsupportedType struct {
	Value interface{}
}

func (e ErrUnsupportedType) Error() string {
	return fmt.Sprintf("geom: unsupported type %T", e.Value)
}

// A Coord represents an N-dimensional coordinate.
type Coord []float64

// A T is a generic interface geomemented by all geometry types.
type T interface {
	Layout() Layout
	Stride() int
	Bounds() *Bounds
	FlatCoords() []float64
	Ends() []int
	Endss() [][]int
}

// MIndex returns the index of the M dimension, or -1 if the l does not have an M dimension.
func (l Layout) MIndex() int {
	switch l {
	case NoLayout, XY, XYZ:
		return -1
	case XYM:
		return 2
	case XYZM:
		return 3
	default:
		return 3
	}
}

// Stride returns l's number of dimensions.
func (l Layout) Stride() int {
	switch l {
	case NoLayout:
		return 0
	case XY:
		return 2
	case XYZ:
		return 3
	case XYM:
		return 3
	case XYZM:
		return 4
	default:
		return int(l)
	}
}

// String returns a human-readable string representing l.
func (l Layout) String() string {
	switch l {
	case NoLayout:
		return "NoLayout"
	case XY:
		return "XY"
	case XYZ:
		return "XYZ"
	case XYM:
		return "XYM"
	case XYZM:
		return "XYZM"
	default:
		return fmt.Sprintf("Layout(%d)", int(l))
	}
}

// ZIndex returns the index of l's Z dimension, or -1 if l does not have a Z dimension.
func (l Layout) ZIndex() int {
	switch l {
	case NoLayout, XY, XYM:
		return -1
	default:
		return 2
	}
}

// Must panics if err is not nil, otherwise it returns g.
func Must(g T, err error) T {
	if err != nil {
		panic(err)
	}
	return g
}

var (
	errIncorrectEnd         = errors.New("geom: incorrect end")
	errLengthStrideMismatch = errors.New("geom: length/stride mismatch")
	errMisalignedEnd        = errors.New("geom: misaligned end")
	errNonEmptyEnds         = errors.New("geom: non-empty ends")
	errNonEmptyEndss        = errors.New("geom: non-empty endss")
	errNonEmptyFlatCoords   = errors.New("geom: non-empty flatCoords")
	errOutOfOrderEnd        = errors.New("geom: out-of-order end")
	errStrideLayoutMismatch = errors.New("geom: stride/layout mismatch")
)
<commit_msg>Add documentation for geom<commit_after>// Package geom implements fast and GC-efficient Open Geo Consortium-style
// geometries.
package geom

import (
	"errors"
	"fmt"
)

// A Layout describes the meaning of an N-dimensional coordinate. Layout(N) for
// N > 4 is a valid layout, in which case the first dimensions are interpreted
// to be X, Y, Z, and M and extra dimensions have no special meaning.  M values
// are considered part of a linear referencing system (e.g. classical time or
// distance along a path). 1-dimensional layouts are not supported.
type Layout int

const (
	// NoLayout is an unknown layout
	NoLayout Layout = iota
	// XY is a 2D layout (X and Y)
	XY
	// XYZ is 3D layout (X, Y, and Z)
	XYZ
	// XYM is a 2D layout with an M value
	XYM
	// XYZM is a 3D layout with an M value
	XYZM
)

// An ErrLayoutMismatch is returned when geometries with different layouts
// cannot be combined.
type ErrLayoutMismatch struct {
	Got  Layout
	Want Layout
}

func (e ErrLayoutMismatch) Error() string {
	return fmt.Sprintf("geom: layout mismatch, got %s, want %s", e.Got, e.Want)
}

// An ErrStrideMismatch is returned when the stride does not match the expected
// stride.
type ErrStrideMismatch struct {
	Got  int
	Want int
}

func (e ErrStrideMismatch) Error() string {
	return fmt.Sprintf("geom: stride mismatch, got %d, want %d", e.Got, e.Want)
}

// An ErrUnsupportedLayout is returned when the requested layout is not
// supported.
type ErrUnsupportedLayout Layout

func (e ErrUnsupportedLayout) Error() string {
	return fmt.Sprintf("geom: unsupported layout %s", Layout(e))
}

// An ErrUnsupportedType is returned when the requested type is not supported.
type ErrUnsupportedType struct {
	Value interface{}
}

func (e ErrUnsupportedType) Error() string {
	return fmt.Sprintf("geom: unsupported type %T", e.Value)
}

// A Coord represents an N-dimensional coordinate.
type Coord []float64

// A T is a generic interface geomemented by all geometry types.
type T interface {
	Layout() Layout
	Stride() int
	Bounds() *Bounds
	FlatCoords() []float64
	Ends() []int
	Endss() [][]int
}

// MIndex returns the index of the M dimension, or -1 if the l does not have an M dimension.
func (l Layout) MIndex() int {
	switch l {
	case NoLayout, XY, XYZ:
		return -1
	case XYM:
		return 2
	case XYZM:
		return 3
	default:
		return 3
	}
}

// Stride returns l's number of dimensions.
func (l Layout) Stride() int {
	switch l {
	case NoLayout:
		return 0
	case XY:
		return 2
	case XYZ:
		return 3
	case XYM:
		return 3
	case XYZM:
		return 4
	default:
		return int(l)
	}
}

// String returns a human-readable string representing l.
func (l Layout) String() string {
	switch l {
	case NoLayout:
		return "NoLayout"
	case XY:
		return "XY"
	case XYZ:
		return "XYZ"
	case XYM:
		return "XYM"
	case XYZM:
		return "XYZM"
	default:
		return fmt.Sprintf("Layout(%d)", int(l))
	}
}

// ZIndex returns the index of l's Z dimension, or -1 if l does not have a Z dimension.
func (l Layout) ZIndex() int {
	switch l {
	case NoLayout, XY, XYM:
		return -1
	default:
		return 2
	}
}

// Must panics if err is not nil, otherwise it returns g.
func Must(g T, err error) T {
	if err != nil {
		panic(err)
	}
	return g
}

var (
	errIncorrectEnd         = errors.New("geom: incorrect end")
	errLengthStrideMismatch = errors.New("geom: length/stride mismatch")
	errMisalignedEnd        = errors.New("geom: misaligned end")
	errNonEmptyEnds         = errors.New("geom: non-empty ends")
	errNonEmptyEndss        = errors.New("geom: non-empty endss")
	errNonEmptyFlatCoords   = errors.New("geom: non-empty flatCoords")
	errOutOfOrderEnd        = errors.New("geom: out-of-order end")
	errStrideLayoutMismatch = errors.New("geom: stride/layout mismatch")
)
<|endoftext|>


<commit_before>package datastore

import (
	"database/sql"
	"fmt"
	"strconv"

	"github.com/rs/zerolog"

	"github.com/gilcrest/errs"
)

// NewDB returns an open database handle of 0 or more underlying PostgreSQL connections
func NewDB(n Name, logger zerolog.Logger) (*sql.DB, func(), error) {
	const op errs.Op = "datastore/NewDB"

	dbEnvMap, err := dbEnv(n)
	if err != nil {
		return nil, nil, errs.E(op, err)
	}

	// Get Database connection credentials from environment variables
	dbNme := dbEnvMap["dbname"]
	dbUser := dbEnvMap["user"]
	dbPassword := dbEnvMap["password"]
	dbHost := dbEnvMap["host"]
	dbPort, err := strconv.Atoi(dbEnvMap["port"])
	if err != nil {
		return nil, nil, errs.E(op, err)
	}

	// Craft string for database connection
	var dbinfo string
	switch dbPassword {
	case "":
		dbinfo = fmt.Sprintf("host=%s port=%d dbname=%s user=%s sslmode=disable", dbHost, dbPort, dbNme, dbUser)
	default:
		dbinfo = fmt.Sprintf("host=%s port=%d dbname=%s user=%s password=%s sslmode=disable", dbHost, dbPort, dbNme, dbUser, dbPassword)
	}

	// Open the postgres database using the postgres driver (pq)
	// func Open(driverName, dataSourceName string) (*DB, error)
	db, err := sql.Open("postgres", dbinfo)
	if err != nil {
		return nil, nil, errs.E(op, err)
	}

	logger.Log().Msgf("sql database opened for %s on port %d", dbHost, dbPort)

	err = validateDB(db, logger)
	if err != nil {
		return nil, nil, errs.E(op, err)
	}

	return db, func() { db.Close() }, nil
}

// validateDB pings the database and logs the current user and database
func validateDB(db *sql.DB, log zerolog.Logger) error {
	const op errs.Op = "datastore/validateDB"

	err := db.Ping()
	if err != nil {
		return errs.E(op, err)
	}
	log.Log().Msg("sql database Ping returned successfully")

	var (
		currentDatabase string
		currentUser     string
		dbVersion       string
	)
	sqlStatement := `select current_database(), current_user, version();`
	row := db.QueryRow(sqlStatement)
	switch err := row.Scan(&currentDatabase, &currentUser, &dbVersion); err {
	case sql.ErrNoRows:
		return errs.E(op, "No rows were returned!")
	case nil:
		log.Log().Msgf("database version: %s", dbVersion)
		log.Log().Msgf("current database user: %s", currentUser)
		log.Log().Msgf("current database: %s", currentDatabase)
	default:
		return errs.E(op, err)
	}
	return nil
}
<commit_msg>use struct instead of map for datasource name<commit_after>package datastore

import (
	"database/sql"

	"github.com/pkg/errors"
	"github.com/rs/zerolog"

	"github.com/gilcrest/go-api-basic/domain/errs"
)

// NewDB returns an open database handle of 0 or more underlying PostgreSQL connections
func NewDB(pgds PGDatasourceName, logger zerolog.Logger) (*sql.DB, func(), error) {

	// Open the postgres database using the postgres driver (pq)
	// func Open(driverName, dataSourceName string) (*DB, error)
	db, err := sql.Open("postgres", pgds.String())
	if err != nil {
		return nil, nil, errs.E(err)
	}

	logger.Log().Msgf("sql database opened for %s on port %d", pgds.Host, pgds.Port)

	err = validateDB(db, logger)
	if err != nil {
		return nil, nil, err
	}

	return db, func() { db.Close() }, nil
}

// validateDB pings the database and logs the current user and database
func validateDB(db *sql.DB, log zerolog.Logger) error {
	err := db.Ping()
	if err != nil {
		return errs.E(err)
	}
	log.Log().Msg("sql database Ping returned successfully")

	var (
		currentDatabase string
		currentUser     string
		dbVersion       string
	)
	sqlStatement := `select current_database(), current_user, version();`
	row := db.QueryRow(sqlStatement)
	switch err := row.Scan(&currentDatabase, &currentUser, &dbVersion); err {
	case sql.ErrNoRows:
		return errs.E(errors.New("No rows were returned!"))
	case nil:
		log.Log().Msgf("database version: %s", dbVersion)
		log.Log().Msgf("current database user: %s", currentUser)
		log.Log().Msgf("current database: %s", currentDatabase)
	default:
		return errs.E(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"io"
	"os/exec"
	"time"
)

type Gzipper func(w io.Writer, r io.Reader) error

// use the compress/gzip to compress the content of
// 'r'.
func GzGolang(w io.Writer, r io.Reader) error {
	gz, _ := gzip.NewWriterLevel(w, gzip.BestCompression)
	gz.Header.ModTime = time.Now()
	if _, err := io.Copy(w, r); err != nil {
		return err
	}
	gz.Close()
	return nil
}

// use a pipe to 'gzip' to create the gz in a way
// that opkg accepts the output. right now it's unclear
// why opkg explodes when it hits a golang-native-created
// gz file.
func GzGzipPipe(w io.Writer, r io.Reader) error {
	cmd := exec.Command("gzip", "-9", "-c")
	cmd.Stdin = r
	cmd.Stdout = w
	return cmd.Run()
}
<commit_msg>fix GzGolang(): write to the correct writer<commit_after>package main

import (
	"compress/gzip"
	"io"
	"os/exec"
	"time"
)

type Gzipper func(w io.Writer, r io.Reader) error

// use the compress/gzip to compress the content of
// 'r'.
func GzGolang(w io.Writer, r io.Reader) error {
	gz, _ := gzip.NewWriterLevel(w, gzip.BestCompression)
	gz.Header.ModTime = time.Now()
	if _, err := io.Copy(gz, r); err != nil {
		return err
	}
	gz.Close()
	return nil
}

// use a pipe to 'gzip' to create the gz in a way
// that opkg accepts the output. right now it's unclear
// why opkg explodes when it hits a golang-native-created
// gz file.
func GzGzipPipe(w io.Writer, r io.Reader) error {
	cmd := exec.Command("gzip", "-9", "-c")
	cmd.Stdin = r
	cmd.Stdout = w
	return cmd.Run()
}
<|endoftext|>


<commit_before>// Package hkjnweb is the personal website http://www.hkjn.me / http://blog.hkjn.me.
package hkjnweb

import (
	"appengine"

	"github.com/hkjn/autosite"
)

var baseTemplates = []string{
	"tmpl/base.tmpl",
	"tmpl/base_header.tmpl",
	"tmpl/style.tmpl",
	"tmpl/fonts.tmpl",
}

var web = autosite.New(
	"Henrik Jonsson",
	"pages/*.tmpl", // glob for pages
	"www.hkjn.me",  // live domain
	append(baseTemplates, "tmpl/page.tmpl"),
)

var blog = autosite.NewBlog(
	"Henrik Jonsson's blog",
	"blog/*/*/*.tmpl", // glob for blog entries
	"blog.hkjn.me",    // live domain
	append(baseTemplates, "tmpl/blog.tmpl"),
	append(baseTemplates, "tmpl/blog_listing.tmpl"),
)

// init initializes the app.
func init() {
	if appengine.IsDevAppServer() {
		blog.ChangeURI("/", "/blogindex")
	} else {
		web.ChangeURI("/webindex", "/")
	}

	web.Register()
	blog.Register()
}
<commit_msg>adds link to autosite<commit_after>// Package hkjnweb is the personal website http://www.hkjn.me / http://blog.hkjn.me.
//
// See https://github.com/hkjn/autosite for the framework that enables this site.
package hkjnweb

import (
	"appengine"

	"github.com/hkjn/autosite"
)

var baseTemplates = []string{
	"tmpl/base.tmpl",
	"tmpl/base_header.tmpl",
	"tmpl/style.tmpl",
	"tmpl/fonts.tmpl",
}

var web = autosite.New(
	"Henrik Jonsson",
	"pages/*.tmpl", // glob for pages
	"www.hkjn.me",  // live domain
	append(baseTemplates, "tmpl/page.tmpl"),
)

var blog = autosite.NewBlog(
	"Henrik Jonsson's blog",
	"blog/*/*/*.tmpl", // glob for blog entries
	"blog.hkjn.me",    // live domain
	append(baseTemplates, "tmpl/blog.tmpl"),
	append(baseTemplates, "tmpl/blog_listing.tmpl"),
)

// init initializes the app.
func init() {
	if appengine.IsDevAppServer() {
		blog.ChangeURI("/", "/blogindex")
	} else {
		web.ChangeURI("/webindex", "/")
	}

	web.Register()
	blog.Register()
}
<|endoftext|>


<commit_before>package lapi

// Hook acts as a middleware of processing request
type Hook interface {
	// SetUp executes Hook before handler runs
	// if one of hooks return false during process, hooking should be stopped
	SetUp(req Request, res Response) bool

	// TearDown executes Hook after handler runs
	// if one of hooks return false during process, hooking should be stopped
	TearDown(req Request, res Response) bool
}
<commit_msg>update hook<commit_after>package lapi

// Hook acts as a middleware of processing request
type Hook interface {
	// SetUp executes Hook before handler runs
	// if one of hooks return false during process, hooking should be stopped
	SetUp(req Request, res Response) bool

	// TearDown executes Hook after handler runs
	// if one of hooks return false during process, hooking should be stopped
	TearDown(req Request, res Response, result interface{}) bool
}
<|endoftext|>


<commit_before>package pg

import (
	"context"
	"fmt"
	"time"

	"github.com/go-pg/pg/v10/orm"
)

type (
	BeforeScanHook   = orm.BeforeScanHook
	AfterScanHook    = orm.AfterScanHook
	AfterSelectHook  = orm.AfterSelectHook
	BeforeInsertHook = orm.BeforeInsertHook
	AfterInsertHook  = orm.AfterInsertHook
	BeforeUpdateHook = orm.BeforeUpdateHook
	AfterUpdateHook  = orm.AfterUpdateHook
	BeforeDeleteHook = orm.BeforeDeleteHook
	AfterDeleteHook  = orm.AfterDeleteHook
)

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

type dummyFormatter struct{}

func (dummyFormatter) FormatQuery(b []byte, query string, params ...interface{}) []byte {
	return append(b, query...)
}

// QueryEvent ...
type QueryEvent struct {
	StartTime  time.Time
	DB         orm.DB
	Model      interface{}
	Query      interface{}
	Params     []interface{}
	fmtedQuery []byte
	Result     Result
	Err        error

	Stash map[interface{}]interface{}
}

// QueryHook ...
type QueryHook interface {
	BeforeQuery(context.Context, *QueryEvent) (context.Context, error)
	AfterQuery(context.Context, *QueryEvent) error
}

// UnformattedQuery returns the unformatted query of a query event.
// The query is only valid until the query Result is returned to the user.
func (e *QueryEvent) UnformattedQuery() ([]byte, error) {
	return queryString(e.Query)
}

func queryString(query interface{}) ([]byte, error) {
	switch query := query.(type) {
	case orm.TemplateAppender:
		return query.AppendTemplate(nil)
	case string:
		return dummyFormatter{}.FormatQuery(nil, query), nil
	default:
		return nil, fmt.Errorf("pg: can't append %T", query)
	}
}

// FormattedQuery returns the formatted query of a query event.
// The query is only valid until the query Result is returned to the user.
func (e *QueryEvent) FormattedQuery() ([]byte, error) {
	return e.fmtedQuery, nil
}

// AddQueryHook adds a hook into query processing.
func (db *baseDB) AddQueryHook(hook QueryHook) {
	db.queryHooks = append(db.queryHooks, hook)
}

func (db *baseDB) beforeQuery(
	ctx context.Context,
	ormDB orm.DB,
	model, query interface{},
	params []interface{},
	fmtedQuery []byte,
) (context.Context, *QueryEvent, error) {
	if len(db.queryHooks) == 0 {
		return ctx, nil, nil
	}

	event := &QueryEvent{
		StartTime:  time.Now(),
		DB:         ormDB,
		Model:      model,
		Query:      query,
		Params:     params,
		fmtedQuery: fmtedQuery,
	}

	for _, hook := range db.queryHooks {
		var err error
		ctx, err = hook.BeforeQuery(ctx, event)
		if err != nil {
			return nil, nil, err
		}
	}

	return ctx, event, nil
}

func (db *baseDB) afterQuery(
	ctx context.Context,
	event *QueryEvent,
	res Result,
	err error,
) error {
	if event == nil {
		return nil
	}

	event.Err = err
	event.Result = res

	for _, hook := range db.queryHooks {
		err := hook.AfterQuery(ctx, event)
		if err != nil {
			return err
		}
	}

	return nil
}

func copyQueryHooks(s []QueryHook) []QueryHook {
	return s[:len(s):len(s)]
}
<commit_msg>Change hooks to be LIFO<commit_after>package pg

import (
	"context"
	"fmt"
	"time"

	"github.com/go-pg/pg/v10/orm"
)

type (
	BeforeScanHook   = orm.BeforeScanHook
	AfterScanHook    = orm.AfterScanHook
	AfterSelectHook  = orm.AfterSelectHook
	BeforeInsertHook = orm.BeforeInsertHook
	AfterInsertHook  = orm.AfterInsertHook
	BeforeUpdateHook = orm.BeforeUpdateHook
	AfterUpdateHook  = orm.AfterUpdateHook
	BeforeDeleteHook = orm.BeforeDeleteHook
	AfterDeleteHook  = orm.AfterDeleteHook
)

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

type dummyFormatter struct{}

func (dummyFormatter) FormatQuery(b []byte, query string, params ...interface{}) []byte {
	return append(b, query...)
}

// QueryEvent ...
type QueryEvent struct {
	StartTime  time.Time
	DB         orm.DB
	Model      interface{}
	Query      interface{}
	Params     []interface{}
	fmtedQuery []byte
	Result     Result
	Err        error

	Stash map[interface{}]interface{}
}

// QueryHook ...
type QueryHook interface {
	BeforeQuery(context.Context, *QueryEvent) (context.Context, error)
	AfterQuery(context.Context, *QueryEvent) error
}

// UnformattedQuery returns the unformatted query of a query event.
// The query is only valid until the query Result is returned to the user.
func (e *QueryEvent) UnformattedQuery() ([]byte, error) {
	return queryString(e.Query)
}

func queryString(query interface{}) ([]byte, error) {
	switch query := query.(type) {
	case orm.TemplateAppender:
		return query.AppendTemplate(nil)
	case string:
		return dummyFormatter{}.FormatQuery(nil, query), nil
	default:
		return nil, fmt.Errorf("pg: can't append %T", query)
	}
}

// FormattedQuery returns the formatted query of a query event.
// The query is only valid until the query Result is returned to the user.
func (e *QueryEvent) FormattedQuery() ([]byte, error) {
	return e.fmtedQuery, nil
}

// AddQueryHook adds a hook into query processing.
func (db *baseDB) AddQueryHook(hook QueryHook) {
	db.queryHooks = append(db.queryHooks, hook)
}

func (db *baseDB) beforeQuery(
	ctx context.Context,
	ormDB orm.DB,
	model, query interface{},
	params []interface{},
	fmtedQuery []byte,
) (context.Context, *QueryEvent, error) {
	if len(db.queryHooks) == 0 {
		return ctx, nil, nil
	}

	event := &QueryEvent{
		StartTime:  time.Now(),
		DB:         ormDB,
		Model:      model,
		Query:      query,
		Params:     params,
		fmtedQuery: fmtedQuery,
	}

	for _, hook := range db.queryHooks {
		var err error
		ctx, err = hook.BeforeQuery(ctx, event)
		if err != nil {
			return nil, nil, err
		}
	}

	return ctx, event, nil
}

func (db *baseDB) afterQuery(
	ctx context.Context,
	event *QueryEvent,
	res Result,
	err error,
) error {
	if event == nil {
		return nil
	}

	event.Err = err
	event.Result = res

	for i := len(db.queryHooks) - 1; i >= 0; i-- {
		hook := db.queryHooks[i]
		if err := hook.AfterQuery(ctx, event); err != nil {
			return err
		}
	}

	return nil
}

func copyQueryHooks(s []QueryHook) []QueryHook {
	return s[:len(s):len(s)]
}
<|endoftext|>


<commit_before>// Package aphgrpc provides various interfaces, functions, types
// for building and working with gRPC services.
package aphgrpc

import (
	"encoding/json"
	"net/http"
	"strconv"

	context "golang.org/x/net/context"
	dat "gopkg.in/mgutz/dat.v1"

	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"github.com/manyminds/api2go"
	"github.com/pkg/errors"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

const (
	// MetaKey is the key used for storing all metadata
	MetaKey = "error"
)

var (
	//ErrDatabaseQuery represents database query related errors
	ErrDatabaseQuery = newError("Database query error")
	//ErrDatabaseInsert represents database insert related errors
	ErrDatabaseInsert = newError("Database insert error")
	//ErrDatabaseUpdate represents database update related errors
	ErrDatabaseUpdate = newError("Database update error")
	//ErrDatabaseDelete represents database update delete errors
	ErrDatabaseDelete = newError("Database delete error")
	//ErrNotFound represents the absence of an HTTP resource
	ErrNotFound = newError("Resource not found")
	//ErrJSONEncoding represents any json encoding error
	ErrJSONEncoding = newError("Json encoding error")
	//ErrStructMarshal represents any error with marshalling structure
	ErrStructMarshal = newError("Structure marshalling error")
	//ErrIncludeParam represents any error with invalid include query parameter
	ErrIncludeParam = newErrorWithParam("Invalid include query parameter", "include")
	//ErrSparseFieldSets represents any error with invalid sparse fieldsets query parameter
	ErrFields = newErrorWithParam("Invalid field query parameter", "field")
	//ErrFilterParam represents any error with invalid filter query paramter
	ErrFilterParam = newErrorWithParam("Invalid filter query parameter", "filter")
	//ErrNotAcceptable represents any error with wrong or inappropriate http Accept header
	ErrNotAcceptable = newError("Accept header is not acceptable")
	//ErrUnsupportedMedia represents any error with unsupported media type in http header
	ErrUnsupportedMedia = newError("Media type is not supported")
)

func newErrorWithParam(msg, param string) metadata.MD {
	return metadata.Pairs(MetaKey, msg, param)
}

func newError(msg string) metadata.MD {
	return metadata.Pairs(MetaKey, msg)
}

// CustomHTTPError is a custom error handler for grpc-gateway to generate
// JSONAPI formatted HTTP response.
func CustomHTTPError(ctx context.Context, _ *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if !ok {
		fallbackError(w, getgRPCStatus(errors.Wrap(err, "unable to retrieve metadata")))
		return
	}
	JSONAPIError(w, md.TrailerMD, getgRPCStatus(err))
}

func getgRPCStatus(err error) *status.Status {
	s, ok := status.FromError(err)
	if !ok {
		return status.New(codes.Unknown, err.Error())
	}
	return s
}

// JSONAPIError generates JSONAPI formatted error message
func JSONAPIError(w http.ResponseWriter, md metadata.MD, s *status.Status) {
	status := runtime.HTTPStatusFromCode(s.Code())
	jsnErr := api2go.Error{
		Status: strconv.Itoa(status),
		Title:  md["error"][0],
		Detail: s.Message(),
		Meta: map[string]interface{}{
			"creator": "api error helper",
		},
	}
	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(status)
	encErr := json.NewEncoder(w).Encode(api2go.HTTPError{Errors: []api2go.Error{jsnErr}})
	if encErr != nil {
		http.Error(w, encErr.Error(), http.StatusInternalServerError)
	}
}

func fallbackError(w http.ResponseWriter, s *status.Status) {
	status := runtime.HTTPStatusFromCode(s.Code())
	jsnErr := api2go.Error{
		Status: strconv.Itoa(status),
		Title:  "gRPC error",
		Detail: s.Message(),
		Meta: map[string]interface{}{
			"creator": "api error helper",
		},
	}
	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(status)
	encErr := json.NewEncoder(w).Encode(api2go.HTTPError{Errors: []api2go.Error{jsnErr}})
	if encErr != nil {
		http.Error(w, encErr.Error(), http.StatusInternalServerError)
	}
}

func handleError(ctx context.Context, err error) error {
	if err == dat.ErrNotFound {
		grpc.SetTrailer(ctx, ErrNotFound)
		return status.Error(codes.NotFound, err.Error())
	}
	grpc.SetTrailer(ctx, ErrDatabaseQuery)
	return status.Error(codes.Internal, err.Error())
}
<commit_msg>Added metadata and http header handling error constants Modified the handleError method accordingly to use switch case statement<commit_after>// Package aphgrpc provides various interfaces, functions, types
// for building and working with gRPC services.
package aphgrpc

import (
	"encoding/json"
	"net/http"
	"strconv"

	context "golang.org/x/net/context"
	dat "gopkg.in/mgutz/dat.v1"

	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"github.com/manyminds/api2go"
	"github.com/pkg/errors"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

const (
	// MetaKey is the key used for storing all metadata
	MetaKey = "error"
)

var (
	//ErrDatabaseQuery represents database query related errors
	ErrDatabaseQuery = newError("Database query error")
	//ErrDatabaseInsert represents database insert related errors
	ErrDatabaseInsert = newError("Database insert error")
	//ErrDatabaseUpdate represents database update related errors
	ErrDatabaseUpdate = newError("Database update error")
	//ErrDatabaseDelete represents database update delete errors
	ErrDatabaseDelete = newError("Database delete error")
	//ErrNotFound represents the absence of an HTTP resource
	ErrNotFound = newError("Resource not found")
	//ErrJSONEncoding represents any json encoding error
	ErrJSONEncoding = newError("Json encoding error")
	//ErrStructMarshal represents any error with marshalling structure
	ErrStructMarshal = newError("Structure marshalling error")
	//ErrIncludeParam represents any error with invalid include query parameter
	ErrIncludeParam = newErrorWithParam("Invalid include query parameter", "include")
	//ErrSparseFieldSets represents any error with invalid sparse fieldsets query parameter
	ErrFields = newErrorWithParam("Invalid field query parameter", "field")
	//ErrFilterParam represents any error with invalid filter query paramter
	ErrFilterParam = newErrorWithParam("Invalid filter query parameter", "filter")
	//ErrNotAcceptable represents any error with wrong or inappropriate http Accept header
	ErrNotAcceptable = newError("Accept header is not acceptable")
	//ErrUnsupportedMedia represents any error with unsupported media type in http header
	ErrUnsupportedMedia = newError("Media type is not supported")
	//ErrRetrieveMetadata represents any error to retrieve grpc metadata from the running context
	ErrRetrieveMetadata = errors.New("unable to retrieve metadata")
	//ErrXForwardedHost represents any failure or absence of x-forwarded-host HTTP header in the grpc context
	ErrXForwardedHost = errors.New("x-forwarded-host header is absent")
)

func newErrorWithParam(msg, param string) metadata.MD {
	return metadata.Pairs(MetaKey, msg, param)
}

func newError(msg string) metadata.MD {
	return metadata.Pairs(MetaKey, msg)
}

// CustomHTTPError is a custom error handler for grpc-gateway to generate
// JSONAPI formatted HTTP response.
func CustomHTTPError(ctx context.Context, _ *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if !ok {
		fallbackError(w, getgRPCStatus(errors.Wrap(err, "unable to retrieve metadata")))
		return
	}
	JSONAPIError(w, md.TrailerMD, getgRPCStatus(err))
}

func getgRPCStatus(err error) *status.Status {
	s, ok := status.FromError(err)
	if !ok {
		return status.New(codes.Unknown, err.Error())
	}
	return s
}

// JSONAPIError generates JSONAPI formatted error message
func JSONAPIError(w http.ResponseWriter, md metadata.MD, s *status.Status) {
	status := runtime.HTTPStatusFromCode(s.Code())
	jsnErr := api2go.Error{
		Status: strconv.Itoa(status),
		Title:  md["error"][0],
		Detail: s.Message(),
		Meta: map[string]interface{}{
			"creator": "api error helper",
		},
	}
	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(status)
	encErr := json.NewEncoder(w).Encode(api2go.HTTPError{Errors: []api2go.Error{jsnErr}})
	if encErr != nil {
		http.Error(w, encErr.Error(), http.StatusInternalServerError)
	}
}

func fallbackError(w http.ResponseWriter, s *status.Status) {
	status := runtime.HTTPStatusFromCode(s.Code())
	jsnErr := api2go.Error{
		Status: strconv.Itoa(status),
		Title:  "gRPC error",
		Detail: s.Message(),
		Meta: map[string]interface{}{
			"creator": "api error helper",
		},
	}
	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(status)
	encErr := json.NewEncoder(w).Encode(api2go.HTTPError{Errors: []api2go.Error{jsnErr}})
	if encErr != nil {
		http.Error(w, encErr.Error(), http.StatusInternalServerError)
	}
}

func handleError(ctx context.Context, err error) error {
	switch err {
	case dat.ErrNotFound:
		grpc.SetTrailer(ctx, ErrNotFound)
		return status.Error(codes.NotFound, err.Error())
	case ErrRetrieveMetadata:
		grpc.SetTrailer(ctx, newError(err.Error()))
		return status.Error(codes.Internal, err.Error())
	case ErrXForwardedHost:
		grpc.SetTrailer(ctx, newError(err.Error()))
		return status.Error(codes.Internal, err.Error())
	default:
		grpc.SetTrailer(ctx, ErrDatabaseQuery)
		return status.Error(codes.Internal, err.Error())
	}
}
<|endoftext|>


<commit_before>package revel

import (
	"bytes"
	"fmt"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/golang/glog"
)

type Request struct {
	*http.Request
	ContentType     string
	Format          string // "html", "xml", "json", or "txt"
	AcceptLanguages AcceptLanguages
	Locale          string
}

type Response struct {
	Status      int
	ContentType string

	Out http.ResponseWriter
}

func NewResponse(w http.ResponseWriter) *Response {
	return &Response{Out: w}
}

func NewRequest(r *http.Request) *Request {
	return &Request{
		Request:         r,
		ContentType:     ResolveContentType(r),
		Format:          ResolveFormat(r),
		AcceptLanguages: ResolveAcceptLanguage(r),
	}
}

// Write the header (for now, just the status code).
// The status may be set directly by the application (c.Response.Status = 501).
// if it isn't, then fall back to the provided status code.
func (resp *Response) WriteHeader(defaultStatusCode int, defaultContentType string) {
	if resp.Status == 0 {
		resp.Status = defaultStatusCode
	}
	if resp.ContentType == "" {
		resp.ContentType = defaultContentType
	}
	resp.Out.Header().Set("Content-Type", resp.ContentType)
	resp.Out.WriteHeader(resp.Status)
}

// Get the content type.
// e.g. From "multipart/form-data; boundary=--" to "multipart/form-data"
// If none is specified, returns "text/html" by default.
func ResolveContentType(req *http.Request) string {
	contentType := req.Header.Get("Content-Type")
	if contentType == "" {
		return "text/html"
	}
	return strings.ToLower(strings.TrimSpace(strings.Split(contentType, ";")[0]))
}

// Resolve the accept request header.
func ResolveFormat(req *http.Request) string {
	accept := req.Header.Get("accept")

	switch {
	case accept == "",
		strings.HasPrefix(accept, "*/*"),
		strings.Contains(accept, "application/xhtml"),
		strings.Contains(accept, "text/html"):
		return "html"
	case strings.Contains(accept, "application/xml"),
		strings.Contains(accept, "text/xml"):
		return "xml"
	case strings.Contains(accept, "text/plain"):
		return "txt"
	case strings.Contains(accept, "application/json"),
		strings.Contains(accept, "text/javascript"):
		return "json"
	}

	return "html"
}

// FormatToContentType returns an appropriate default content type for the
// response, given the request format.
func FormatToContentType(format string) string {
	switch format {
	case "html":
		return "text/html"
	case "txt":
		return "text/plain"
	case "xml":
		return "text/xml"
	case "json":
		return "application/json"
	}
	panic("unrecognized format: " + format)
}

// A single language from the Accept-Language HTTP header.
type AcceptLanguage struct {
	Language string
	Quality  float32
}

// A collection of sortable AcceptLanguage instances.
type AcceptLanguages []AcceptLanguage

func (al AcceptLanguages) Len() int           { return len(al) }
func (al AcceptLanguages) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AcceptLanguages) Less(i, j int) bool { return al[i].Quality > al[j].Quality }
func (al AcceptLanguages) String() string {
	output := bytes.NewBufferString("")
	for i, language := range al {
		output.WriteString(fmt.Sprintf("%s (%1.1f)", language.Language, language.Quality))
		if i != len(al)-1 {
			output.WriteString(", ")
		}
	}
	return output.String()
}

// Resolve the Accept-Language header value.
//
// The results are sorted using the quality defined in the header for each language range with the
// most qualified language range as the first element in the slice.
//
// See the HTTP header fields specification
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) for more details.
func ResolveAcceptLanguage(req *http.Request) AcceptLanguages {
	header := req.Header.Get("Accept-Language")
	if header == "" {
		return nil
	}

	acceptLanguageHeaderValues := strings.Split(header, ",")
	acceptLanguages := make(AcceptLanguages, len(acceptLanguageHeaderValues))

	for i, languageRange := range acceptLanguageHeaderValues {
		if qualifiedRange := strings.Split(languageRange, ";q="); len(qualifiedRange) == 2 {
			quality, error := strconv.ParseFloat(qualifiedRange[1], 32)
			if error != nil {
				glog.Warningf("Detected malformed Accept-Language header quality in '%s', assuming quality is 1", languageRange)
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], 1}
			} else {
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], float32(quality)}
			}
		} else {
			acceptLanguages[i] = AcceptLanguage{languageRange, 1}
		}
	}

	sort.Sort(acceptLanguages)
	return acceptLanguages
}
<commit_msg>Prefer json to txt<commit_after>package revel

import (
	"bytes"
	"fmt"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/golang/glog"
)

type Request struct {
	*http.Request
	ContentType     string
	Format          string // "html", "xml", "json", or "txt"
	AcceptLanguages AcceptLanguages
	Locale          string
}

type Response struct {
	Status      int
	ContentType string

	Out http.ResponseWriter
}

func NewResponse(w http.ResponseWriter) *Response {
	return &Response{Out: w}
}

func NewRequest(r *http.Request) *Request {
	return &Request{
		Request:         r,
		ContentType:     ResolveContentType(r),
		Format:          ResolveFormat(r),
		AcceptLanguages: ResolveAcceptLanguage(r),
	}
}

// Write the header (for now, just the status code).
// The status may be set directly by the application (c.Response.Status = 501).
// if it isn't, then fall back to the provided status code.
func (resp *Response) WriteHeader(defaultStatusCode int, defaultContentType string) {
	if resp.Status == 0 {
		resp.Status = defaultStatusCode
	}
	if resp.ContentType == "" {
		resp.ContentType = defaultContentType
	}
	resp.Out.Header().Set("Content-Type", resp.ContentType)
	resp.Out.WriteHeader(resp.Status)
}

// Get the content type.
// e.g. From "multipart/form-data; boundary=--" to "multipart/form-data"
// If none is specified, returns "text/html" by default.
func ResolveContentType(req *http.Request) string {
	contentType := req.Header.Get("Content-Type")
	if contentType == "" {
		return "text/html"
	}
	return strings.ToLower(strings.TrimSpace(strings.Split(contentType, ";")[0]))
}

// Resolve the accept request header.
func ResolveFormat(req *http.Request) string {
	accept := req.Header.Get("accept")

	switch {
	case accept == "",
		strings.HasPrefix(accept, "*/*"),
		strings.Contains(accept, "application/xhtml"),
		strings.Contains(accept, "text/html"):
		return "html"
	case strings.Contains(accept, "application/json"),
		strings.Contains(accept, "text/javascript"):
		return "json"
	case strings.Contains(accept, "application/xml"),
		strings.Contains(accept, "text/xml"):
		return "xml"
	case strings.Contains(accept, "text/plain"):
		return "txt"
	}

	return "html"
}

// FormatToContentType returns an appropriate default content type for the
// response, given the request format.
func FormatToContentType(format string) string {
	switch format {
	case "html":
		return "text/html"
	case "txt":
		return "text/plain"
	case "xml":
		return "text/xml"
	case "json":
		return "application/json"
	}
	panic("unrecognized format: " + format)
}

// A single language from the Accept-Language HTTP header.
type AcceptLanguage struct {
	Language string
	Quality  float32
}

// A collection of sortable AcceptLanguage instances.
type AcceptLanguages []AcceptLanguage

func (al AcceptLanguages) Len() int           { return len(al) }
func (al AcceptLanguages) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AcceptLanguages) Less(i, j int) bool { return al[i].Quality > al[j].Quality }
func (al AcceptLanguages) String() string {
	output := bytes.NewBufferString("")
	for i, language := range al {
		output.WriteString(fmt.Sprintf("%s (%1.1f)", language.Language, language.Quality))
		if i != len(al)-1 {
			output.WriteString(", ")
		}
	}
	return output.String()
}

// Resolve the Accept-Language header value.
//
// The results are sorted using the quality defined in the header for each language range with the
// most qualified language range as the first element in the slice.
//
// See the HTTP header fields specification
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) for more details.
func ResolveAcceptLanguage(req *http.Request) AcceptLanguages {
	header := req.Header.Get("Accept-Language")
	if header == "" {
		return nil
	}

	acceptLanguageHeaderValues := strings.Split(header, ",")
	acceptLanguages := make(AcceptLanguages, len(acceptLanguageHeaderValues))

	for i, languageRange := range acceptLanguageHeaderValues {
		if qualifiedRange := strings.Split(languageRange, ";q="); len(qualifiedRange) == 2 {
			quality, error := strconv.ParseFloat(qualifiedRange[1], 32)
			if error != nil {
				glog.Warningf("Detected malformed Accept-Language header quality in '%s', assuming quality is 1", languageRange)
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], 1}
			} else {
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], float32(quality)}
			}
		} else {
			acceptLanguages[i] = AcceptLanguage{languageRange, 1}
		}
	}

	sort.Sort(acceptLanguages)
	return acceptLanguages
}
<|endoftext|>