<commit_before>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// +build linux

package gpio

import (
	"errors"
	"os"
	"reflect"
	"sync"
	"syscall"
	"unsafe"
)

type Chipset int

const (
	BCM2835 Chipset = iota
	BCM2711
)

// Arrays for 8 / 32 bit access to memory and a semaphore for write locking
var (
	chipset Chipset
	// The memlock covers read/modify/write access to the mem block.
	// Individual reads and writes can skip the lock on the assumption that
	// concurrent register writes are atomic. e.g. Read, Write and Mode.
	memlock sync.Mutex
	mem     []uint32
	mem8    []uint8
)

// Open and memory map GPIO memory range from /dev/gpiomem .
// Some reflection magic is used to convert it to a unsafe []uint32 pointer
func Open() (err error) {
	if len(mem) != 0 {
		return ErrAlreadyOpen
	}
	file, err := os.OpenFile(
		"/dev/gpiomem",
		os.O_RDWR|os.O_SYNC,
		0)

	if err != nil {
		return
	}
	defer file.Close()

	memlock.Lock()
	defer memlock.Unlock()

	// Memory map GPIO registers to byte array
	mem8, err = syscall.Mmap(
		int(file.Fd()),
		0,
		memLength,
		syscall.PROT_READ|syscall.PROT_WRITE,
		syscall.MAP_SHARED)

	if err != nil {
		return
	}

	// Convert mapped byte memory to unsafe []uint32 pointer, adjust length as needed
	header := *(*reflect.SliceHeader)(unsafe.Pointer(&mem8))
	header.Len /= 4 // (32 bit = 4 bytes)
	header.Cap /= 4

	mem = *(*[]uint32)(unsafe.Pointer(&header))

	if mem[60] == 0x6770696f {
		chipset = BCM2835
	} else {
		chipset = BCM2711
	}

	return nil
}

// Close removes the interrupt handlers and unmaps GPIO memory
func Close() error {
	memlock.Lock()
	defer memlock.Unlock()
	closeInterrupts()
	mem = make([]uint32, 0)
	return syscall.Munmap(mem8)
}

var (
	// ErrAlreadyOpen indicates the mem is already open.
	ErrAlreadyOpen = errors.New("already open")
)
<commit_msg>document new types<commit_after>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// +build linux

package gpio

import (
	"errors"
	"os"
	"reflect"
	"sync"
	"syscall"
	"unsafe"
)

// Chipset identifies the GPIO chip.
type Chipset int

const (
	// BCM2835 indicates the chipset is BCM2825 or compatible.
	BCM2835 Chipset = iota

	// BCM2711 indicates the chipset is BCM2711.
	BCM2711
)

// Arrays for 8 / 32 bit access to memory and a semaphore for write locking
var (
	chipset Chipset
	// The memlock covers read/modify/write access to the mem block.
	// Individual reads and writes can skip the lock on the assumption that
	// concurrent register writes are atomic. e.g. Read, Write and Mode.
	memlock sync.Mutex
	mem     []uint32
	mem8    []uint8
)

// Open and memory map GPIO memory range from /dev/gpiomem .
// Some reflection magic is used to convert it to a unsafe []uint32 pointer
func Open() (err error) {
	if len(mem) != 0 {
		return ErrAlreadyOpen
	}
	file, err := os.OpenFile(
		"/dev/gpiomem",
		os.O_RDWR|os.O_SYNC,
		0)

	if err != nil {
		return
	}
	defer file.Close()

	memlock.Lock()
	defer memlock.Unlock()

	// Memory map GPIO registers to byte array
	mem8, err = syscall.Mmap(
		int(file.Fd()),
		0,
		memLength,
		syscall.PROT_READ|syscall.PROT_WRITE,
		syscall.MAP_SHARED)

	if err != nil {
		return
	}

	// Convert mapped byte memory to unsafe []uint32 pointer, adjust length as needed
	header := *(*reflect.SliceHeader)(unsafe.Pointer(&mem8))
	header.Len /= 4 // (32 bit = 4 bytes)
	header.Cap /= 4

	mem = *(*[]uint32)(unsafe.Pointer(&header))

	if mem[60] == 0x6770696f {
		chipset = BCM2835
	} else {
		chipset = BCM2711
	}

	return nil
}

// Close removes the interrupt handlers and unmaps GPIO memory
func Close() error {
	memlock.Lock()
	defer memlock.Unlock()
	closeInterrupts()
	mem = make([]uint32, 0)
	return syscall.Munmap(mem8)
}

var (
	// ErrAlreadyOpen indicates the mem is already open.
	ErrAlreadyOpen = errors.New("already open")
)
<|endoftext|>


<commit_before>package main

const (
	BASE         = 1024 * 1024
	UC_MEM_ALIGN = 8 * 1024
	STACK_BASE   = 0x7fff000
	STACK_SIZE   = 8 * 1024 * 1024
)

type mmap struct {
	Start, Size uint64
}

func align(addr, size uint64, growl ...bool) (uint64, uint64) {
	to := uint64(UC_MEM_ALIGN)
	right := addr + size
	right = ((right + to - 1) & ^to)
	addr &= ^(to - 1)
	size = right - addr
	if len(growl) > 0 && growl[0] {
		size = (size + (to - 1)) & (^(to - 1))
	}
	return addr, size
}
<commit_msg>change stack base<commit_after>package main

const (
	BASE         = 1024 * 1024
	UC_MEM_ALIGN = 8 * 1024
	STACK_BASE   = 0x7fff0000
	STACK_SIZE   = 8 * 1024 * 1024
)

type mmap struct {
	Start, Size uint64
}

func align(addr, size uint64, growl ...bool) (uint64, uint64) {
	to := uint64(UC_MEM_ALIGN)
	right := addr + size
	right = ((right + to - 1) & ^to)
	addr &= ^(to - 1)
	size = right - addr
	if len(growl) > 0 && growl[0] {
		size = (size + (to - 1)) & (^(to - 1))
	}
	return addr, size
}
<|endoftext|>


<commit_before>// Package mem is an example REST backend storage that stores everything in memory.
package mem

import (
	"bytes"
	"context"
	"encoding/gob"
	"sort"
	"sync"
	"time"

	"github.com/rs/rest-layer/resource"
)

// MemoryHandler is an example handler storing data in memory
type MemoryHandler struct {
	sync.RWMutex
	// If latency is set, the handler will introduce an artificial latency on
	// all operations
	Latency time.Duration
	items   map[interface{}][]byte
	ids     []interface{}
}

func init() {
	gob.Register(map[string]interface{}{})
	gob.Register(time.Time{})
}

// NewHandler creates an empty memory handler
func NewHandler() *MemoryHandler {
	return &MemoryHandler{
		items: map[interface{}][]byte{},
		ids:   []interface{}{},
	}
}

// NewSlowHandler creates an empty memory handler with specified latency
func NewSlowHandler(latency time.Duration) *MemoryHandler {
	return &MemoryHandler{
		Latency: latency,
		items:   map[interface{}][]byte{},
		ids:     []interface{}{},
	}
}

// store serialize the item using gob and store it in the handler's items map
func (m *MemoryHandler) store(item *resource.Item) error {
	var data bytes.Buffer
	enc := gob.NewEncoder(&data)
	if err := enc.Encode(*item); err != nil {
		return err
	}
	m.items[item.ID] = data.Bytes()
	return nil
}

// fetch unserialize item's data and return a new item
func (m *MemoryHandler) fetch(id interface{}) (*resource.Item, bool, error) {
	data, found := m.items[id]
	if !found {
		return nil, false, nil
	}
	dec := gob.NewDecoder(bytes.NewBuffer(data))
	var item resource.Item
	if err := dec.Decode(&item); err != nil {
		return nil, true, err
	}
	return &item, true, nil
}

// delete removes an item by this id with no look
func (m *MemoryHandler) delete(id interface{}) {
	delete(m.items, id)
	// Remove id from id list
	for i, _id := range m.ids {
		if _id == id {
			if i >= len(m.ids)-1 {
				m.ids = m.ids[:i]
			} else {
				m.ids = append(m.ids[:i], m.ids[i+1:]...)
			}
			break
		}
	}
}

// Insert inserts new items in memory
func (m *MemoryHandler) Insert(ctx context.Context, items []*resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, item := range items {
			if _, found := m.items[item.ID]; found {
				return resource.ErrConflict
			}
		}
		for _, item := range items {
			if err := m.store(item); err != nil {
				return err
			}
			// Store ids in ordered slice for sorting
			m.ids = append(m.ids, item.ID)
		}
		return nil
	})
	return err
}

// Update replace an item by a new one in memory
func (m *MemoryHandler) Update(ctx context.Context, item *resource.Item, original *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(original.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if original.ETag != o.ETag {
			return resource.ErrConflict
		}
		if err := m.store(item); err != nil {
			return err
		}
		return nil
	})
	return err
}

// Delete deletes an item from memory
func (m *MemoryHandler) Delete(ctx context.Context, item *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(item.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if item.ETag != o.ETag {
			return resource.ErrConflict
		}
		m.delete(item.ID)
		return nil
	})
	return err
}

// Clear clears all items from the memory store matching the lookup
func (m *MemoryHandler) Clear(ctx context.Context, lookup *resource.Lookup) (total int, err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		ids := make([]interface{}, len(m.ids))
		copy(ids, m.ids)
		for _, id := range ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			m.delete(item.ID)
			total++
		}
		return nil
	})
	return total, err
}

// Find items from memory matching the provided lookup
func (m *MemoryHandler) Find(ctx context.Context, lookup *resource.Lookup, offset, limit int) (list *resource.ItemList, err error) {
	m.RLock()
	defer m.RUnlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		items := []*resource.Item{}
		// Apply filter
		for _, id := range m.ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			items = append(items, item)
		}
		// Apply sort
		if len(lookup.Sort()) > 0 {
			s := sortableItems{lookup.Sort(), items}
			sort.Sort(s)
		}
		// Apply pagination
		total := len(items)
		end := total
		start := offset

		if limit > 0 {
			end = start + limit
			if end > total-1 {
				end = total
			}
		}
		if start > total-1 {
			start = 0
			end = 0
		}
		list = &resource.ItemList{Total: total, Items: items[start:end]}
		return nil
	})
	return list, err
}
<commit_msg>Support schema.Array<commit_after>// Package mem is an example REST backend storage that stores everything in memory.
package mem

import (
	"bytes"
	"context"
	"encoding/gob"
	"sort"
	"sync"
	"time"

	"github.com/rs/rest-layer/resource"
)

// MemoryHandler is an example handler storing data in memory
type MemoryHandler struct {
	sync.RWMutex
	// If latency is set, the handler will introduce an artificial latency on
	// all operations
	Latency time.Duration
	items   map[interface{}][]byte
	ids     []interface{}
}

func init() {
	gob.Register([]interface{}{})
	gob.Register(map[string]interface{}{})
	gob.Register(time.Time{})
}

// NewHandler creates an empty memory handler
func NewHandler() *MemoryHandler {
	return &MemoryHandler{
		items: map[interface{}][]byte{},
		ids:   []interface{}{},
	}
}

// NewSlowHandler creates an empty memory handler with specified latency
func NewSlowHandler(latency time.Duration) *MemoryHandler {
	return &MemoryHandler{
		Latency: latency,
		items:   map[interface{}][]byte{},
		ids:     []interface{}{},
	}
}

// store serialize the item using gob and store it in the handler's items map
func (m *MemoryHandler) store(item *resource.Item) error {
	var data bytes.Buffer
	enc := gob.NewEncoder(&data)
	if err := enc.Encode(*item); err != nil {
		return err
	}
	m.items[item.ID] = data.Bytes()
	return nil
}

// fetch unserialize item's data and return a new item
func (m *MemoryHandler) fetch(id interface{}) (*resource.Item, bool, error) {
	data, found := m.items[id]
	if !found {
		return nil, false, nil
	}
	dec := gob.NewDecoder(bytes.NewBuffer(data))
	var item resource.Item
	if err := dec.Decode(&item); err != nil {
		return nil, true, err
	}
	return &item, true, nil
}

// delete removes an item by this id with no look
func (m *MemoryHandler) delete(id interface{}) {
	delete(m.items, id)
	// Remove id from id list
	for i, _id := range m.ids {
		if _id == id {
			if i >= len(m.ids)-1 {
				m.ids = m.ids[:i]
			} else {
				m.ids = append(m.ids[:i], m.ids[i+1:]...)
			}
			break
		}
	}
}

// Insert inserts new items in memory
func (m *MemoryHandler) Insert(ctx context.Context, items []*resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, item := range items {
			if _, found := m.items[item.ID]; found {
				return resource.ErrConflict
			}
		}
		for _, item := range items {
			if err := m.store(item); err != nil {
				return err
			}
			// Store ids in ordered slice for sorting
			m.ids = append(m.ids, item.ID)
		}
		return nil
	})
	return err
}

// Update replace an item by a new one in memory
func (m *MemoryHandler) Update(ctx context.Context, item *resource.Item, original *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(original.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if original.ETag != o.ETag {
			return resource.ErrConflict
		}
		if err := m.store(item); err != nil {
			return err
		}
		return nil
	})
	return err
}

// Delete deletes an item from memory
func (m *MemoryHandler) Delete(ctx context.Context, item *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(item.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if item.ETag != o.ETag {
			return resource.ErrConflict
		}
		m.delete(item.ID)
		return nil
	})
	return err
}

// Clear clears all items from the memory store matching the lookup
func (m *MemoryHandler) Clear(ctx context.Context, lookup *resource.Lookup) (total int, err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		ids := make([]interface{}, len(m.ids))
		copy(ids, m.ids)
		for _, id := range ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			m.delete(item.ID)
			total++
		}
		return nil
	})
	return total, err
}

// Find items from memory matching the provided lookup
func (m *MemoryHandler) Find(ctx context.Context, lookup *resource.Lookup, offset, limit int) (list *resource.ItemList, err error) {
	m.RLock()
	defer m.RUnlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		items := []*resource.Item{}
		// Apply filter
		for _, id := range m.ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			items = append(items, item)
		}
		// Apply sort
		if len(lookup.Sort()) > 0 {
			s := sortableItems{lookup.Sort(), items}
			sort.Sort(s)
		}
		// Apply pagination
		total := len(items)
		end := total
		start := offset

		if limit > 0 {
			end = start + limit
			if end > total-1 {
				end = total
			}
		}
		if start > total-1 {
			start = 0
			end = 0
		}
		list = &resource.ItemList{Total: total, Items: items[start:end]}
		return nil
	})
	return list, err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"text/tabwriter"

	"github.com/GaryBoone/GoStats/stats"
	"github.com/topher200/baseutil"
)

type criterionCalculationFunction func(teams []Team) Score
type criterion struct {
	name      string                       // human readable name
	calculate criterionCalculationFunction // how to calculate the raw score
	filter    PlayerFilter                 // cull down to players that match
	weight    int                          // how much weight to give this score
	// worstCase is calculated at runtime to be the absolute worst score we can
	// see this criterion getting, calculated using random sampling
	worstCase Score
}

var criteriaToScore = [...]criterion{
	criterion{"matching baggages", baggagesMatch, nil, 10000, 0},
	criterion{"number of players", playerCountDifference, nil, 15, 0},
	criterion{"number of males", playerCountDifference, IsMale, 12, 0},
	criterion{"number of females", playerCountDifference, IsFemale, 12, 0},
	criterion{"average rating players", ratingDifference, nil, 8, 0},
	criterion{"average rating males", ratingDifference, IsMale, 7, 0},
	criterion{"average rating females", ratingDifference, IsFemale, 7, 0},
	criterion{"std dev of team player ratings", ratingStdDev, nil, 6, 0},
	criterion{"std dev of team male ratings", ratingStdDev, IsMale, 5, 0},
	criterion{"std dev of team female ratings", ratingStdDev, IsFemale, 5, 0},
}

func playerCountDifference(teams []Team) Score {
	teamLengths := make([]int, numTeams)
	for i, team := range teams {
		teamLengths[i] = len(team.players)
	}
	return Score(baseutil.StandardDeviationInt(teamLengths))
}

func ratingDifference(teams []Team) Score {
	teamAverageRatings := make([]float64, numTeams)
	for i, team := range teams {
		teamAverageRatings[i] = float64(AverageRating(team))
	}
	return Score(stats.StatsSampleStandardDeviation(teamAverageRatings))
}

func ratingStdDev(teams []Team) Score {
	teamRatingsStdDev := make([]float64, numTeams)
	for i, team := range teams {
		if len(team.players) < 2 {
			teamRatingsStdDev[i] = 0
			continue
		}
		playerRatings := make([]float64, len(team.players))
		for j, player := range team.players {
			playerRatings[j] = float64(player.rating)
		}
		teamRatingsStdDev[i] = stats.StatsSampleStandardDeviation(playerRatings)
	}
	return Score(stats.StatsSampleStandardDeviation(teamRatingsStdDev))
}

func baggagesMatch(teams []Team) Score {
	score := Score(0)
	for _, team := range teams {
		for _, player := range team.players {
			if !player.HasBaggage() {
				continue
			}
			_, err := FindPlayer(team.players, player.baggage)
			if err != nil {
				// Player desired a baggage, but they're not on the team
				score += 1
			}
		}
	}
	return score
}

func AverageRating(team Team) Score {
	if len(team.players) == 0 {
		return Score(0)
	}
	sum := float32(0.0)
	for _, player := range team.players {
		sum += player.rating
	}
	return Score(sum / float32(len(team.players)))
}

// runCriterion by filtering the input teams and running the criterion function
func runCriterion(c criterion, teams []Team) (
	rawScore Score, normalizedScore Score, weightedScore Score) {
	filteredTeams := make([]Team, len(teams))
	for i, _ := range teams {
		filteredTeams[i].players = Filter(teams[i].players, c.filter)
	}

	rawScore = c.calculate(filteredTeams)
	if c.worstCase != 0 {
		normalizedScore = rawScore / c.worstCase
	} else {
		normalizedScore = rawScore
	}
	weightedScore = normalizedScore * Score(c.weight)
	return rawScore, normalizedScore, weightedScore
}

func maxScore(a, b Score) Score {
	if a > b {
		return a
	} else {
		return b
	}
}

// PopulateWorstCases calculates the worst case of each criterion.
//
// The function has the side effect of filling in the worstCase param for each
// criterion in criteriaToScore.
func PopulateWorstCases(solutions []Solution) {
	for _, solution := range solutions {
		_, rawScores := ScoreSolution(solution.players)
		for i, criterion := range criteriaToScore {
			if math.IsNaN(float64(rawScores[i])) {
				continue
			}
			criteriaToScore[i].worstCase = maxScore(
				criterion.worstCase, rawScores[i])
		}
	}
}

// Score a solution based on all known criteria.
//
// Returns the total score for the solution, as well as the raw score found for
// each of the criteriaToScore.
func ScoreSolution(players []Player) (totalScore Score, rawScores []Score) {
	teams := splitIntoTeams(players)
	rawScores = make([]Score, len(criteriaToScore))
	for i, criterion := range criteriaToScore {
		rawScore, _, weightedScore := runCriterion(criterion, teams)
		rawScores[i] = rawScore
		totalScore += weightedScore
	}
	return totalScore, rawScores
}

func PrintSolutionScoring(solution Solution) {
	teams := splitIntoTeams(solution.players)
	totalScore := Score(0)
	writer := new(tabwriter.Writer)
	writer.Init(os.Stdout, 0, 0, 1, ' ', 0)
	for _, criterion := range criteriaToScore {
		rawScore, normalizedScore, weightedScore := runCriterion(
			criterion, teams)
		totalScore += weightedScore
		fmt.Fprintf(
			writer,
			"Balancing %s.\tScore: %.02f\t(= normalized score %.02f * weight %d)\t(raw score %0.2f, worst case %.02f)\tRunning total: %.02f\n",
			criterion.name, weightedScore, normalizedScore, criterion.weight,
			rawScore, criterion.worstCase, totalScore)
	}
	writer.Flush()
}
<commit_msg>runCriterion is now the method criterion.analyze<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"text/tabwriter"

	"github.com/GaryBoone/GoStats/stats"
	"github.com/topher200/baseutil"
)

type criterionCalculationFunction func(teams []Team) Score
type criterion struct {
	name      string                       // human readable name
	calculate criterionCalculationFunction // how to calculate the raw score
	filter    PlayerFilter                 // cull down to players that match
	weight    int                          // how much weight to give this score
	// worstCase is calculated at runtime to be the absolute worst score we can
	// see this criterion getting, calculated using random sampling
	worstCase Score
}

var criteriaToScore = [...]criterion{
	criterion{"matching baggages", baggagesMatch, nil, 10000, 0},
	criterion{"number of players", playerCountDifference, nil, 15, 0},
	criterion{"number of males", playerCountDifference, IsMale, 12, 0},
	criterion{"number of females", playerCountDifference, IsFemale, 12, 0},
	criterion{"average rating players", ratingDifference, nil, 8, 0},
	criterion{"average rating males", ratingDifference, IsMale, 7, 0},
	criterion{"average rating females", ratingDifference, IsFemale, 7, 0},
	criterion{"std dev of team player ratings", ratingStdDev, nil, 6, 0},
	criterion{"std dev of team male ratings", ratingStdDev, IsMale, 5, 0},
	criterion{"std dev of team female ratings", ratingStdDev, IsFemale, 5, 0},
}

func playerCountDifference(teams []Team) Score {
	teamLengths := make([]int, numTeams)
	for i, team := range teams {
		teamLengths[i] = len(team.players)
	}
	return Score(baseutil.StandardDeviationInt(teamLengths))
}

func ratingDifference(teams []Team) Score {
	teamAverageRatings := make([]float64, numTeams)
	for i, team := range teams {
		teamAverageRatings[i] = float64(AverageRating(team))
	}
	return Score(stats.StatsSampleStandardDeviation(teamAverageRatings))
}

func ratingStdDev(teams []Team) Score {
	teamRatingsStdDev := make([]float64, numTeams)
	for i, team := range teams {
		if len(team.players) < 2 {
			teamRatingsStdDev[i] = 0
			continue
		}
		playerRatings := make([]float64, len(team.players))
		for j, player := range team.players {
			playerRatings[j] = float64(player.rating)
		}
		teamRatingsStdDev[i] = stats.StatsSampleStandardDeviation(playerRatings)
	}
	return Score(stats.StatsSampleStandardDeviation(teamRatingsStdDev))
}

func baggagesMatch(teams []Team) Score {
	score := Score(0)
	for _, team := range teams {
		for _, player := range team.players {
			if !player.HasBaggage() {
				continue
			}
			_, err := FindPlayer(team.players, player.baggage)
			if err != nil {
				// Player desired a baggage, but they're not on the team
				score += 1
			}
		}
	}
	return score
}

func AverageRating(team Team) Score {
	if len(team.players) == 0 {
		return Score(0)
	}
	sum := float32(0.0)
	for _, player := range team.players {
		sum += player.rating
	}
	return Score(sum / float32(len(team.players)))
}

// analyze criterion by filtering the input teams and running the criterion's
// function
func (c criterion) analyze(teams []Team) (
	rawScore Score, normalizedScore Score, weightedScore Score) {
	filteredTeams := make([]Team, len(teams))
	for i, _ := range teams {
		filteredTeams[i].players = Filter(teams[i].players, c.filter)
	}

	rawScore = c.calculate(filteredTeams)
	if c.worstCase != 0 {
		normalizedScore = rawScore / c.worstCase
	} else {
		normalizedScore = rawScore
	}
	weightedScore = normalizedScore * Score(c.weight)
	return rawScore, normalizedScore, weightedScore
}

func maxScore(a, b Score) Score {
	if a > b {
		return a
	} else {
		return b
	}
}

// PopulateWorstCases calculates the worst case of each criterion.
//
// The function has the side effect of filling in the worstCase param for each
// criterion in criteriaToScore.
func PopulateWorstCases(solutions []Solution) {
	for _, solution := range solutions {
		_, rawScores := ScoreSolution(solution.players)
		for i, criterion := range criteriaToScore {
			if math.IsNaN(float64(rawScores[i])) {
				continue
			}
			criteriaToScore[i].worstCase = maxScore(
				criterion.worstCase, rawScores[i])
		}
	}
}

// Score a solution based on all known criteria.
//
// Returns the total score for the solution, as well as the raw score found for
// each of the criteriaToScore.
func ScoreSolution(players []Player) (totalScore Score, rawScores []Score) {
	teams := splitIntoTeams(players)
	rawScores = make([]Score, len(criteriaToScore))
	for i, criterion := range criteriaToScore {
		rawScore, _, weightedScore := criterion.analyze(teams)
		rawScores[i] = rawScore
		totalScore += weightedScore
	}
	return totalScore, rawScores
}

func PrintSolutionScoring(solution Solution) {
	teams := splitIntoTeams(solution.players)
	totalScore := Score(0)
	writer := new(tabwriter.Writer)
	writer.Init(os.Stdout, 0, 0, 1, ' ', 0)
	for _, criterion := range criteriaToScore {
		rawScore, normalizedScore, weightedScore := criterion.analyze(teams)
		totalScore += weightedScore
		fmt.Fprintf(
			writer,
			"Balancing %s.\tScore: %.02f\t(= normalized score %.02f * weight %d)\t(raw score %0.2f, worst case %.02f)\tRunning total: %.02f\n",
			criterion.name, weightedScore, normalizedScore, criterion.weight,
			rawScore, criterion.worstCase, totalScore)
	}
	writer.Flush()
}
<|endoftext|>


<commit_before>package server

import (
	"code.google.com/p/graphics-go/graphics"
	_ "crypto/sha256"
	_ "encoding/base64"
	"errors"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"image"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"io"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"net/http"
	"strconv"
	"time"
)

var Connection *mgo.Session

type GridFile struct {
	mgo.GridFile

	mimeType string
}

func (file *GridFile) SetMimeType(mimeType string) {
	file.mimeType = mimeType
}

// just a static welcome handler
func welcomeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "")
	fmt.Fprintf(w, "
Image Server.
")
	fmt.Fprintf(w, "")
}

func hasCached(etag string, md5 string, modifiedTime time.Time, updateTime time.Time) bool {
	if updateTime.After(modifiedTime) || md5 != etag {
		return false
	}

	return true
}

//
func legacyHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	database := vars["database"]

	if database == "" {
		log.Fatal("database must not be empty")
		return
	}

	port := vars["port"]

	if port == "" {
		port = "27017"
	}

	filename := vars["image"]

	if filename == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	gridfs := Connection.DB(database).GridFS("fs")
	fp, err := gridfs.Open(filename)

	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	} else {
		// if the file pointer is not set, fp.Close() throws an error.. FIX this upstream?
		defer fp.Close()
	}

	md5 := fp.MD5()

	modifiedHeader := r.Header.Get("If-Modified-Since")
	modifiedTime := time.Now()
	cachingEnabled := r.Header.Get("Cache-Control") != "no-cache"

	if modifiedHeader != "" {
		modifiedHeader = ""
	} else {
		modifiedTime, _ = time.Parse(time.RFC1123, modifiedHeader)
	}

	if hasCached(md5, r.Header.Get("If-None-Match"), modifiedTime, fp.UploadDate()) && cachingEnabled {
		w.WriteHeader(http.StatusNotModified)
		fmt.Printf("[DEBUG][304] Returning cached image for %s\n", md5)
		return
	}

	w.Header().Set("Etag", md5)
	w.Header().Set("Cache-Control", "max-age=315360000")
	d, _ := time.ParseDuration("315360000s")

	expires := fp.UploadDate().Add(d)

	w.Header().Set("Last-Modified", fp.UploadDate().Format(time.RFC1123))
	w.Header().Set("Expires", expires.Format(time.RFC1123))
	w.Header().Set("Date", fp.UploadDate().Format(time.RFC1123))

	fmt.Printf("[DEBUG][200] Returning raw image for %s\n", md5)

	_, err = io.Copy(w, fp)

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Printf("[ERROR][500] Bad Request for %s\n", md5)
		return
	}
}

//
func imageHandler(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)

	database := vars["database"]

	if database == "" {
		log.Fatal("database must not be empty")
		return
	}

	port := vars["port"]

	if port == "" {
		port = "27017"
	}

	objectId := vars["objectId"]

	if objectId == "" {
		fmt.Printf("objectId is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	width := vars["width"]

	if width == "" {
		fmt.Printf("width is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	height := vars["height"]

	if height == "" {
		fmt.Printf("height is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	var parseError error
	var intWidth, intHeight int64

	intWidth, parseError = strconv.ParseInt(width, 10, 64)

	if parseError != nil {
		fmt.Printf("parse error")
		return
	}

	intHeight, parseError = strconv.ParseInt(height, 10, 64)

	if parseError != nil {
		fmt.Printf("parse error")
		return
	}

	gridfs := Connection.DB(database).GridFS("fs")

	var fp *mgo.GridFile

	mongoId := bson.ObjectIdHex(objectId)
	query := bson.M{"parentId": mongoId, "width": intWidth, "height": intHeight}
	iter := gridfs.Find(query).Iter()
	gridfs.OpenNext(iter, &fp)

	if fp == nil {

		// schema valid? ist 130x260 erlaubt. Wenn ja: generiere und speichere und liefer aus

		// todo find via id but parentId must be null
		fp, _ = gridfs.OpenId(mongoId)

		if fp != nil {
			fmt.Printf("parent found")

			imageSrc, something, imgErr := image.Decode(fp)

			if imgErr != nil {
				fmt.Printf("Error is %s", imgErr)
				return
			}

			fmt.Printf("Something is %s", something)

			dst := image.NewRGBA(image.Rect(0, 0, int(intWidth), int(intHeight)))
			graphics.Thumbnail(dst, imageSrc)
			targetFilename := fmt.Sprintf("%d", time.Now().Nanosecond())
			fp, imgErr = gridfs.Create(targetFilename)

			if imgErr != nil {
				w.WriteHeader(http.StatusNotFound)
				return
			}

			change := bson.M{
				"$set": bson.M{
					"parentId": mongoId,
					"mimeType": "image/jpeg",
					"width":    int(intWidth),
					"height":   int(intHeight),
					"size":     fmt.Sprintf("%dx%d", intWidth, intHeight)}}

			jpeg.Encode(fp, dst, &jpeg.Options{jpeg.DefaultQuality})

			fp.Close()

			query := bson.M{"_id": fp.Id()}

			updateErr := Connection.DB(database).C("fs.files").Update(query, change)

			if updateErr != nil {
				fmt.Printf("\n - Error %s - \n", updateErr)
			}

			fp, _ = gridfs.OpenId(fp.Id())

			if fp != nil {
				defer fp.Close()
			} else {
				fmt.Printf("generated image could not be found")
				w.WriteHeader(http.StatusNotFound)
				return
			}

		} else {
			// ansonsten:
			w.WriteHeader(http.StatusNotFound)
			return
		}
	} else {
		// if the file pointer is not set, fp.Close() throws an error.. FIX this upstream?
		defer fp.Close()
	}

	md5 := fp.MD5()

	modifiedHeader := r.Header.Get("If-Modified-Since")
	modifiedTime := time.Now()
	cachingEnabled := r.Header.Get("Cache-Control") != "no-cache"

	if modifiedHeader != "" {
		modifiedHeader = ""
	} else {
		modifiedTime, _ = time.Parse(time.RFC1123, modifiedHeader)
	}

	if hasCached(md5, r.Header.Get("If-None-Match"), modifiedTime, fp.UploadDate()) && cachingEnabled {
		w.WriteHeader(http.StatusNotModified)
		fmt.Printf("[DEBUG][304] Returning cached image for %s\n", md5)
		return
	}

	w.Header().Set("Etag", md5)
	w.Header().Set("Cache-Control", "max-age=315360000")
	d, _ := time.ParseDuration("315360000s")

	expires := fp.UploadDate().Add(d)

	w.Header().Set("Last-Modified", fp.UploadDate().Format(time.RFC1123))
	w.Header().Set("Expires", expires.Format(time.RFC1123))
	w.Header().Set("Date", fp.UploadDate().Format(time.RFC1123))

	fmt.Printf("[DEBUG][200] Returning raw image for %s\n", md5)

	_, err := io.Copy(w, fp)

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Printf("[ERROR][500] Bad Request for %s\n", md5)
		return
	}
}

//
func Deliver() int {
	err := errors.New("")

	serverPort := flag.Int("port", 8000, "the server port where we will serve images")
	host := flag.String("host", "localhost", "the database host")

	flag.Parse()

	fmt.Printf("Server started. Listening on %d database host is %s\n", *serverPort, *host)

	// in order to simple configure the image server in the proxy configuration of nginx
	// we will be getting every database variable from the request
	serverRoute := "/{database}/{port}/{objectId}/{width}/{height}.jpg"

	fallbackRoute := "/{database}/{port}/{image}"

	Connection, err = mgo.Dial(*host)
	Connection.SetMode(mgo.Eventual, true)
	Connection.SetSyncTimeout(0)

	if err != nil {
		log.Fatal("Cannot connect to database")
		return -1
	}

	r := mux.NewRouter()
	r.HandleFunc("/", welcomeHandler)
	r.HandleFunc(serverRoute, imageHandler)
	r.HandleFunc(fallbackRoute, legacyHandler)

	http.Handle("/", r)

	err = http.ListenAndServe(fmt.Sprintf(":%d", *serverPort), nil)

	if err != nil {
		log.Fatal(err)
		return -1
	}

	return 0
}
<commit_msg>adds one missing defer func call<commit_after>package server

import (
	"code.google.com/p/graphics-go/graphics"
	_ "crypto/sha256"
	_ "encoding/base64"
	"errors"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"image"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"io"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"net/http"
	"strconv"
	"time"
)

var Connection *mgo.Session

type GridFile struct {
	mgo.GridFile

	mimeType string
}

func (file *GridFile) SetMimeType(mimeType string) {
	file.mimeType = mimeType
}

// just a static welcome handler
func welcomeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "")
	fmt.Fprintf(w, "
Image Server.
")
	fmt.Fprintf(w, "")
}

func hasCached(etag string, md5 string, modifiedTime time.Time, updateTime time.Time) bool {
	if updateTime.After(modifiedTime) || md5 != etag {
		return false
	}

	return true
}

//
func legacyHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	database := vars["database"]

	if database == "" {
		log.Fatal("database must not be empty")
		return
	}

	port := vars["port"]

	if port == "" {
		port = "27017"
	}

	filename := vars["image"]

	if filename == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	gridfs := Connection.DB(database).GridFS("fs")
	fp, err := gridfs.Open(filename)

	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	} else {
		// if the file pointer is not set, fp.Close() throws an error.. FIX this upstream?
		defer fp.Close()
	}

	md5 := fp.MD5()

	modifiedHeader := r.Header.Get("If-Modified-Since")
	modifiedTime := time.Now()
	cachingEnabled := r.Header.Get("Cache-Control") != "no-cache"

	if modifiedHeader != "" {
		modifiedHeader = ""
	} else {
		modifiedTime, _ = time.Parse(time.RFC1123, modifiedHeader)
	}

	if hasCached(md5, r.Header.Get("If-None-Match"), modifiedTime, fp.UploadDate()) && cachingEnabled {
		w.WriteHeader(http.StatusNotModified)
		fmt.Printf("[DEBUG][304] Returning cached image for %s\n", md5)
		return
	}

	w.Header().Set("Etag", md5)
	w.Header().Set("Cache-Control", "max-age=315360000")
	d, _ := time.ParseDuration("315360000s")

	expires := fp.UploadDate().Add(d)

	w.Header().Set("Last-Modified", fp.UploadDate().Format(time.RFC1123))
	w.Header().Set("Expires", expires.Format(time.RFC1123))
	w.Header().Set("Date", fp.UploadDate().Format(time.RFC1123))

	fmt.Printf("[DEBUG][200] Returning raw image for %s\n", md5)

	_, err = io.Copy(w, fp)

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Printf("[ERROR][500] Bad Request for %s\n", md5)
		return
	}
}

//
func imageHandler(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)

	database := vars["database"]

	if database == "" {
		log.Fatal("database must not be empty")
		return
	}

	port := vars["port"]

	if port == "" {
		port = "27017"
	}

	objectId := vars["objectId"]

	if objectId == "" {
		fmt.Printf("objectId is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	width := vars["width"]

	if width == "" {
		fmt.Printf("width is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	height := vars["height"]

	if height == "" {
		fmt.Printf("height is empty.")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	var parseError error
	var intWidth, intHeight int64

	intWidth, parseError = strconv.ParseInt(width, 10, 64)

	if parseError != nil {
		fmt.Printf("parse error")
		return
	}

	intHeight, parseError = strconv.ParseInt(height, 10, 64)

	if parseError != nil {
		fmt.Printf("parse error")
		return
	}

	gridfs := Connection.DB(database).GridFS("fs")

	var fp *mgo.GridFile

	mongoId := bson.ObjectIdHex(objectId)
	query := bson.M{"parentId": mongoId, "width": intWidth, "height": intHeight}
	iter := gridfs.Find(query).Iter()
	gridfs.OpenNext(iter, &fp)

	if fp == nil {

		// schema valid? ist 130x260 erlaubt. Wenn ja: generiere und speichere und liefer aus

		// todo find via id but parentId must be null
		fp, _ = gridfs.OpenId(mongoId)

		if fp != nil {
			fmt.Printf("parent found")

			imageSrc, something, imgErr := image.Decode(fp)

			if imgErr != nil {
				fmt.Printf("Error is %s", imgErr)
				return
			}

			fmt.Printf("Something is %s", something)

			dst := image.NewRGBA(image.Rect(0, 0, int(intWidth), int(intHeight)))
			graphics.Thumbnail(dst, imageSrc)
			targetFilename := fmt.Sprintf("%d", time.Now().Nanosecond())
			fp, imgErr = gridfs.Create(targetFilename)

			if imgErr != nil {
				defer fp.Close()
				w.WriteHeader(http.StatusNotFound)
				return
			}

			change := bson.M{
				"$set": bson.M{
					"parentId": mongoId,
					"mimeType": "image/jpeg",
					"width":    int(intWidth),
					"height":   int(intHeight),
					"size":     fmt.Sprintf("%dx%d", intWidth, intHeight)}}

			jpeg.Encode(fp, dst, &jpeg.Options{jpeg.DefaultQuality})

			fp.Close()

			query := bson.M{"_id": fp.Id()}

			// add aditional fields
			updateErr := Connection.DB(database).C("fs.files").Update(query, change)

			if updateErr != nil {
				fmt.Printf("\n - Error %s - \n", updateErr)
			}

			fp, _ = gridfs.OpenId(fp.Id())

			if fp != nil {
				defer fp.Close()
			} else {
				fmt.Printf("generated image could not be found")
				w.WriteHeader(http.StatusNotFound)
				return
			}

		} else {
			// ansonsten:
			w.WriteHeader(http.StatusNotFound)
			return
		}
	} else {
		// if the file pointer is not set, fp.Close() throws an error.. FIX this upstream?
		defer fp.Close()
	}

	md5 := fp.MD5()

	modifiedHeader := r.Header.Get("If-Modified-Since")
	modifiedTime := time.Now()
	cachingEnabled := r.Header.Get("Cache-Control") != "no-cache"

	if modifiedHeader != "" {
		modifiedHeader = ""
	} else {
		modifiedTime, _ = time.Parse(time.RFC1123, modifiedHeader)
	}

	if hasCached(md5, r.Header.Get("If-None-Match"), modifiedTime, fp.UploadDate()) && cachingEnabled {
		w.WriteHeader(http.StatusNotModified)
		fmt.Printf("[DEBUG][304] Returning cached image for %s\n", md5)
		return
	}

	w.Header().Set("Etag", md5)
	w.Header().Set("Cache-Control", "max-age=315360000")
	d, _ := time.ParseDuration("315360000s")

	expires := fp.UploadDate().Add(d)

	w.Header().Set("Last-Modified", fp.UploadDate().Format(time.RFC1123))
	w.Header().Set("Expires", expires.Format(time.RFC1123))
	w.Header().Set("Date", fp.UploadDate().Format(time.RFC1123))

	fmt.Printf("[DEBUG][200] Returning raw image for %s\n", md5)

	_, err := io.Copy(w, fp)

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Printf("[ERROR][500] Bad Request for %s\n", md5)
		return
	}
}

//
func Deliver() int {
	err := errors.New("")

	serverPort := flag.Int("port", 8000, "the server port where we will serve images")
	host := flag.String("host", "localhost", "the database host")

	flag.Parse()

	fmt.Printf("Server started. Listening on %d database host is %s\n", *serverPort, *host)

	// in order to simple configure the image server in the proxy configuration of nginx
	// we will be getting every database variable from the request
	serverRoute := "/{database}/{port}/{objectId}/{width}/{height}.jpg"

	fallbackRoute := "/{database}/{port}/{image}"

	Connection, err = mgo.Dial(*host)
	Connection.SetMode(mgo.Eventual, true)
	Connection.SetSyncTimeout(0)

	if err != nil {
		log.Fatal("Cannot connect to database")
		return -1
	}

	r := mux.NewRouter()
	r.HandleFunc("/", welcomeHandler)
	r.HandleFunc(serverRoute, imageHandler)
	r.HandleFunc(fallbackRoute, legacyHandler)

	http.Handle("/", r)

	err = http.ListenAndServe(fmt.Sprintf(":%d", *serverPort), nil)

	if err != nil {
		log.Fatal(err)
		return -1
	}

	return 0
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

package helper

import (
	"fmt"

	"github.com/op/go-logging"
	"github.com/spf13/viper"
	"golang.org/x/net/context"

	"github.com/openblockchain/obc-peer/openchain/chaincode"
	"github.com/openblockchain/obc-peer/openchain/consensus"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/openchain/peer"
	pb "github.com/openblockchain/obc-peer/protos"
)

// =============================================================================
// Init
// =============================================================================

var logger *logging.Logger // package-level logger

func init() {
	logger = logging.MustGetLogger("consensus/helper")
}

// =============================================================================
// Structure definitions go here
// =============================================================================

// Helper contains the reference to coordinator for broadcasts/unicasts.
type Helper struct {
	coordinator peer.MessageHandlerCoordinator
}

// =============================================================================
// Constructors go here
// =============================================================================

// NewHelper constructs the consensus helper object.
func NewHelper(mhc peer.MessageHandlerCoordinator) consensus.CPI {
	return &Helper{coordinator: mhc}
}

// =============================================================================
// Stack-facing implementation goes here
// =============================================================================

// GetReplicaHash returns the crypto IDs of the current replica and the whole network
// func (h *Helper) GetReplicaHash() (self []byte, network [][]byte, err error) {
// ATTN: Until the crypto package is integrated, this functions returns
// the <IP:port>s of the current replica and the whole network instead
func (h *Helper) GetReplicaHash() (self string, network []string, err error) {
	// v, _ := h.coordinator.GetValidator()
	// self = v.GetID()
	peer, err := peer.GetPeerEndpoint()
	if err != nil {
		return "", nil, err
	}
	self = peer.Address

	config := viper.New()
	config.SetConfigName("openchain")
	config.AddConfigPath("./")
	err = config.ReadInConfig()
	if err != nil {
		err = fmt.Errorf("Fatal error reading root config: %s", err)
		return self, nil, err
	}

	// encodedHashes := config.GetStringSlice("peer.validator.replicas.hashes")
	/* network = make([][]byte, len(encodedHashes))
	for i, v := range encodedHashes {
		network[i], _ = base64.StdEncoding.DecodeString(v)
	} */
	network = config.GetStringSlice("peer.validator.replicas.ips")

	return self, network, nil
}

// GetReplicaID returns the uint handle corresponding to a replica address
// func (h *Helper) GetReplicaID(hash []byte) (id uint64, err error) {
func (h *Helper) GetReplicaID(addr string) (id uint64, err error) {
	_, network, err := h.GetReplicaHash()
	if err != nil {
		return uint64(0), err
	}
	for i, v := range network {
		// if bytes.Equal(v, hash) {
		if v == addr {
			return uint64(i), nil
		}
	}

	//err = fmt.Errorf("Couldn't find crypto ID in list of VP IDs given in config")
	err = fmt.Errorf("Couldn't find IP:port in list of VP addresses given in config")
	return uint64(0), err
}

// Broadcast sends a message to all validating peers.
func (h *Helper) Broadcast(msg *pb.OpenchainMessage) error {
	_ = h.coordinator.Broadcast(msg) // TODO process the errors
	return nil
}

// Unicast sends a message to a specified receiver.
func (h *Helper) Unicast(msgPayload []byte, receiver string) error {
	// TODO Call a function in the comms layer; wait for Jeff's implementation.
	return nil
}

// ExecTXs executes all the transactions listed in the txs array one-by-one.
// If all the executions are successful, it returns the candidate global state hash, and nil error array.
func (h *Helper) ExecTXs(txs []*pb.Transaction) ([]byte, []error) {
	return chaincode.ExecuteTransactions(context.Background(), chaincode.DefaultChain, txs)
}

// BeginTxBatch gets invoked when next round of transaction-batch
// execution begins.
func (h *Helper) BeginTxBatch(id interface{}) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.BeginTxBatch(id); err != nil {
		return fmt.Errorf("Fail to begin transaction with the ledger: %v", err)
	}
	return nil
}

// CommitTxBatch gets invoked when the current transaction-batch needs
// to be committed.  This function returns successfully iff the
// transactions details and state changes (that may have happened
// during execution of this transaction-batch) have been committed to
// permanent storage
func (h *Helper) CommitTxBatch(id interface{}, transactions []*pb.Transaction, proof []byte) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.CommitTxBatch(id, transactions, proof); err != nil {
		return fmt.Errorf("Fail to commit transaction to the ledger: %v", err)
	}
	return nil
}

// RollbackTxBatch discards all the state changes that may have taken
// place during the execution of current transaction-batch.
func (h *Helper) RollbackTxBatch(id interface{}) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.RollbackTxBatch(id); err != nil {
		return fmt.Errorf("Fail to rollback transaction with the ledger: %v", err)
	}
	return nil
}
<commit_msg>Add TODOs for GetReplica*<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

package helper

import (
	"fmt"

	"github.com/op/go-logging"
	"github.com/spf13/viper"
	"golang.org/x/net/context"

	"github.com/openblockchain/obc-peer/openchain/chaincode"
	"github.com/openblockchain/obc-peer/openchain/consensus"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/openchain/peer"
	pb "github.com/openblockchain/obc-peer/protos"
)

// =============================================================================
// Init
// =============================================================================

var logger *logging.Logger // package-level logger

func init() {
	logger = logging.MustGetLogger("consensus/helper")
}

// =============================================================================
// Structure definitions go here
// =============================================================================

// Helper contains the reference to coordinator for broadcasts/unicasts.
type Helper struct {
	coordinator peer.MessageHandlerCoordinator
}

// =============================================================================
// Constructors go here
// =============================================================================

// NewHelper constructs the consensus helper object.
func NewHelper(mhc peer.MessageHandlerCoordinator) consensus.CPI {
	return &Helper{coordinator: mhc}
}

// =============================================================================
// Stack-facing implementation goes here
// =============================================================================

// GetReplicaHash returns the crypto IDs of the current replica and the whole network
// TODO func (h *Helper) GetReplicaHash() (self []byte, network [][]byte, err error) {
// ATTN: Until the crypto package is integrated, this functions returns
// the <IP:port>s of the current replica and the whole network instead
func (h *Helper) GetReplicaHash() (self string, network []string, err error) {
	// v, _ := h.coordinator.GetValidator()
	// self = v.GetID()
	peer, err := peer.GetPeerEndpoint()
	if err != nil {
		return "", nil, err
	}
	self = peer.Address

	config := viper.New()
	config.SetConfigName("openchain")
	config.AddConfigPath("./")
	err = config.ReadInConfig()
	if err != nil {
		err = fmt.Errorf("Fatal error reading root config: %s", err)
		return self, nil, err
	}

	// encodedHashes := config.GetStringSlice("peer.validator.replicas.hashes")
	/* network = make([][]byte, len(encodedHashes))
	for i, v := range encodedHashes {
		network[i], _ = base64.StdEncoding.DecodeString(v)
	} */
	network = config.GetStringSlice("peer.validator.replicas.ips")

	return self, network, nil
}

// GetReplicaID returns the uint handle corresponding to a replica address
// TODO func (h *Helper) GetReplicaID(hash []byte) (id uint64, err error) {
func (h *Helper) GetReplicaID(addr string) (id uint64, err error) {
	_, network, err := h.GetReplicaHash()
	if err != nil {
		return uint64(0), err
	}
	for i, v := range network {
		// if bytes.Equal(v, hash) {
		if v == addr {
			return uint64(i), nil
		}
	}

	//err = fmt.Errorf("Couldn't find crypto ID in list of VP IDs given in config")
	err = fmt.Errorf("Couldn't find IP:port in list of VP addresses given in config")
	return uint64(0), err
}

// Broadcast sends a message to all validating peers.
func (h *Helper) Broadcast(msg *pb.OpenchainMessage) error {
	_ = h.coordinator.Broadcast(msg) // TODO process the errors
	return nil
}

// Unicast sends a message to a specified receiver.
func (h *Helper) Unicast(msgPayload []byte, receiver string) error {
	// TODO Call a function in the comms layer; wait for Jeff's implementation.
	return nil
}

// BeginTxBatch gets invoked when the next round of transaction-batch
// execution begins.
func (h *Helper) BeginTxBatch(id interface{}) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.BeginTxBatch(id); err != nil {
		return fmt.Errorf("Fail to begin transaction with the ledger: %v", err)
	}
	return nil
}

// ExecTXs executes all the transactions listed in the txs array
// one-by-one. If all the executions are successful, it returns
// the candidate global state hash, and nil error array.
func (h *Helper) ExecTXs(txs []*pb.Transaction) ([]byte, []error) {
	return chaincode.ExecuteTransactions(context.Background(), chaincode.DefaultChain, txs)
}

// CommitTxBatch gets invoked when the current transaction-batch needs
// to be committed. This function returns successfully iff the
// transactions details and state changes (that may have happened
// during execution of this transaction-batch) have been committed to
// permanent storage.
func (h *Helper) CommitTxBatch(id interface{}, transactions []*pb.Transaction, proof []byte) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.CommitTxBatch(id, transactions, proof); err != nil {
		return fmt.Errorf("Fail to commit transaction to the ledger: %v", err)
	}
	return nil
}

// RollbackTxBatch discards all the state changes that may have taken
// place during the execution of current transaction-batch.
func (h *Helper) RollbackTxBatch(id interface{}) error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}
	if err := ledger.RollbackTxBatch(id); err != nil {
		return fmt.Errorf("Fail to rollback transaction with the ledger: %v", err)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"golang.org/x/net/html"
)

// Results -- struct returned by Crawl() to represent the entire crawl process
type Results struct {
	// Inherit the Resource struct
	Resource

	// Body represents a string implementation of the byte array returned by
	// http.Response
	Body string

	// Slice of Resource structs containing the needed resources for the given URL
	Resources []*Resource

	// ResourceTime shows how long it took to fetch all resources
	ResourceTime *TimerResult

	// TotalTime represents the time it took to crawl the site
	TotalTime *TimerResult
}

// Resource represents a single entity of many within a given crawl. These should
// only be of type css, js, jpg, png, etc (static resources).
type Resource struct {
	// connURL is the initial URL received by input
	connURL string

	// connIP is the initial IP address received by input
	connIP string

	// connHostname represents the original requested hostname for the resource
	connHostname string

	// URL represents the resulting static URL derived by the original result page
	URL string

	// Hostname represents the resulting hostname derived by the original returned
	// resource
	Hostname string

	// Remote represents if the resulting resource is remote to the original domain
	Remote bool

	// Error represents any errors that may have occurred when fetching the resource
	Error error

	// Code represents the numeric HTTP based status code
	Code int

	// Proto represents the end protocol used to fetch the page. For example, HTTP/2.0
	Proto string

	// Scheme represents the end scheme used to fetch the page. For example, https
	Scheme string

	// ContentLength represents the number of bytes in the body of the response
	ContentLength int64

	// TLS represents the SSL/TLS handshake/session if the resource was loaded over
	// SSL.
	TLS *tls.ConnectionState

	// Time represents the time it took to complete the request
	Time *TimerResult
}

var resourcePool sync.WaitGroup

// getSrc crawls the body of the Results page, yielding all img/script/link resources
// so they can later be fetched.
func getSrc(b io.ReadCloser, req *http.Request) (urls []string) {
	urls = []string{}

	z := html.NewTokenizer(b)

	for {
		// loop through all tokens in the html body response
		tt := z.Next()

		switch {
		case tt == html.ErrorToken:
			// this assumes that there are no further tokens -- end of document
			return
		case tt == html.StartTagToken:
			t := z.Token()

			// the tokens that we are pulling resources from, and the attribute we are
			// pulling from
			allowed := map[string]string{
				"link":   "href",
				"script": "src",
				"img":    "src",
			}
			var isInAllowed bool
			var checkType string
			var src string

			// loop through all allowed elements, and see if the current element is
			// allowed
			for key := range allowed {
				if t.Data == key {
					isInAllowed = true
					checkType = allowed[key]
					break
				}
			}

			if !isInAllowed {
				continue
			}

			for _, a := range t.Attr {
				if a.Key == checkType {
					src = a.Val
					break
				}
			}

			// this assumes that the resource is something along the lines of:
			//   http://something.com/ -- which we don't care about
			if len(src) == 0 || strings.HasSuffix(src, "/") {
				continue
			}

			// add trailing slash to the end of the path
			if len(req.URL.Path) == 0 {
				req.URL.Path = "/"
			}

			// site was developed using relative paths. E.g:
			//  - url: http://domain.com/sub/path and resource: ./something/main.js
			//    would equal http://domain.com/sub/path/something/main.js
			if strings.HasPrefix(src, "./") {
				src = req.URL.Scheme + "://" + req.URL.Host + req.URL.Path + strings.SplitN(src, "./", 2)[1]
			}

			// site is loading resources from a remote location that supports both
			// http and https. browsers should natively tack on the current sites
			// protocol to the url. E.g:
			//  - url: http://domain.com/ and resource: //other.com/some-resource.js
			//    generates: http://other.com/some-resource.js
			//  - url: https://domain.com/ and resource: //other.com/some-resource.js
			//    generates: https://other.com/some-resource.js
			if strings.HasPrefix(src, "//") {
				src = req.URL.Scheme + ":" + src
			}

			// non-host-absolute resource. E.g. resource is loaded based on the docroot
			// of the domain. E.g:
			//  - url: http://domain.com/ and resource: /some-resource.js
			//    generates: http://domain.com/some-resource.js
			//  - url: https://domain.com/sub/resource and resource: /some-resource.js
			//    generates: https://domain.com/some-resource.js
			if strings.HasPrefix(src, "/") {
				src = req.URL.Scheme + "://" + req.URL.Host + src
			}

			// ignore anything else that isn't http based. E.g. ftp://, and other svg-like
			// data urls, as we really can't fetch those.
			if !strings.HasPrefix(src, "http") {
				continue
			}

			urls = append(urls, src)
		}
	}
}

func connHostname(URL string) (host string, err error) {
	tmp, err := url.Parse(URL)

	if err != nil {
		return
	}

	host = tmp.Host
	return
}

// FetchResource fetches a singular resource from a page, returning a *Resource struct.
// As we don't care much about the body of the resource, that can safely be ignored. We
// must still close the body object, however.
func (rsrc *Resource) FetchResource() {
	var err error

	defer resourcePool.Done()

	// calculate the time it takes to fetch the request
	timer := NewTimer()
	resp, err := Get(rsrc.connURL, rsrc.connIP)
	rsrc.Time = timer.End()
	resp.Body.Close()

	if err != nil {
		rsrc.Error = err
		return
	}

	rsrc.connHostname, err = connHostname(rsrc.connURL)
	if err != nil {
		rsrc.Error = err
		return
	}

	rsrc.Hostname = resp.Request.Host
	rsrc.URL = resp.Request.URL.String()
	rsrc.Code = resp.StatusCode
	rsrc.Proto = resp.Proto
	rsrc.Scheme = resp.Request.URL.Scheme
	rsrc.ContentLength = resp.ContentLength
	rsrc.TLS = resp.TLS

	if rsrc.Hostname != rsrc.connHostname {
		rsrc.Remote = true
	}

	fmt.Printf("[%d] [%s] %s\n", rsrc.Code, rsrc.Proto, rsrc.URL)

	return
}

// Crawl manages the fetching of the main resource, as well as all child resources,
// providing a Results struct containing the entire crawl data needed
func Crawl(URL string, IP string) (res *Results) {
	res = &Results{}

	crawlTimer := NewTimer()
	reqTimer := NewTimer()

	// actually fetch the request
	resp, err := Get(URL, IP)
	defer resp.Body.Close()

	res.Time = reqTimer.End()

	if err != nil {
		res.Error = err
		return
	}

	res.connHostname, err = connHostname(URL)
	if err != nil {
		res.Error = err
		return
	}

	res.connURL = URL
	res.connIP = IP
	res.Hostname = resp.Request.Host
	res.URL = URL
	res.Code = resp.StatusCode
	res.Proto = resp.Proto
	res.Scheme = resp.Request.URL.Scheme
	res.ContentLength = resp.ContentLength
	res.TLS = resp.TLS

	if res.Hostname != res.connHostname {
		res.Remote = true
	}

	buf, _ := ioutil.ReadAll(resp.Body)
	b := ioutil.NopCloser(bytes.NewReader(buf))
	defer b.Close()

	bbytes, err := ioutil.ReadAll(bytes.NewBuffer(buf))
	if len(bbytes) != 0 {
		res.Body = string(bbytes[:])
	}

	urls := getSrc(b, resp.Request)

	fmt.Printf("[%d] [%s] %s\n", res.Code, res.Proto, res.URL)

	resourceTime := NewTimer()

	for i := range urls {
		resourcePool.Add(1)

		rsrc := &Resource{connURL: urls[i], connIP: ""}
		res.Resources = append(res.Resources, rsrc)
		go res.Resources[i].FetchResource()
	}

	resourcePool.Wait()

	res.ResourceTime = resourceTime.End()
	res.TotalTime = crawlTimer.End()

	return
}
<commit_msg>close body only if opened<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"golang.org/x/net/html"
)

// Results -- struct returned by Crawl() to represent the entire crawl process
type Results struct {
	// Inherit the Resource struct
	Resource

	// Body represents a string implementation of the byte array returned by
	// http.Response
	Body string

	// Slice of Resource structs containing the needed resources for the given URL
	Resources []*Resource

	// ResourceTime shows how long it took to fetch all resources
	ResourceTime *TimerResult

	// TotalTime represents the time it took to crawl the site
	TotalTime *TimerResult
}

// Resource represents a single entity of many within a given crawl. These should
// only be of type css, js, jpg, png, etc (static resources).
type Resource struct {
	// connURL is the initial URL received by input
	connURL string

	// connIP is the initial IP address received by input
	connIP string

	// connHostname represents the original requested hostname for the resource
	connHostname string

	// URL represents the resulting static URL derived by the original result page
	URL string

	// Hostname represents the resulting hostname derived by the original returned
	// resource
	Hostname string

	// Remote represents if the resulting resource is remote to the original domain
	Remote bool

	// Error represents any errors that may have occurred when fetching the resource
	Error error

	// Code represents the numeric HTTP based status code
	Code int

	// Proto represents the end protocol used to fetch the page. For example, HTTP/2.0
	Proto string

	// Scheme represents the end scheme used to fetch the page. For example, https
	Scheme string

	// ContentLength represents the number of bytes in the body of the response
	ContentLength int64

	// TLS represents the SSL/TLS handshake/session if the resource was loaded over
	// SSL.
	TLS *tls.ConnectionState

	// Time represents the time it took to complete the request
	Time *TimerResult
}

var resourcePool sync.WaitGroup

// getSrc crawls the body of the Results page, yielding all img/script/link resources
// so they can later be fetched.
func getSrc(b io.ReadCloser, req *http.Request) (urls []string) {
	urls = []string{}

	z := html.NewTokenizer(b)

	for {
		// loop through all tokens in the html body response
		tt := z.Next()

		switch {
		case tt == html.ErrorToken:
			// this assumes that there are no further tokens -- end of document
			return
		case tt == html.StartTagToken:
			t := z.Token()

			// the tokens that we are pulling resources from, and the attribute we are
			// pulling from
			allowed := map[string]string{
				"link":   "href",
				"script": "src",
				"img":    "src",
			}
			var isInAllowed bool
			var checkType string
			var src string

			// loop through all allowed elements, and see if the current element is
			// allowed
			for key := range allowed {
				if t.Data == key {
					isInAllowed = true
					checkType = allowed[key]
					break
				}
			}

			if !isInAllowed {
				continue
			}

			for _, a := range t.Attr {
				if a.Key == checkType {
					src = a.Val
					break
				}
			}

			// this assumes that the resource is something along the lines of:
			//   http://something.com/ -- which we don't care about
			if len(src) == 0 || strings.HasSuffix(src, "/") {
				continue
			}

			// add trailing slash to the end of the path
			if len(req.URL.Path) == 0 {
				req.URL.Path = "/"
			}

			// site was developed using relative paths. E.g:
			//  - url: http://domain.com/sub/path and resource: ./something/main.js
			//    would equal http://domain.com/sub/path/something/main.js
			if strings.HasPrefix(src, "./") {
				src = req.URL.Scheme + "://" + req.URL.Host + req.URL.Path + strings.SplitN(src, "./", 2)[1]
			}

			// site is loading resources from a remote location that supports both
			// http and https. browsers should natively tack on the current sites
			// protocol to the url. E.g:
			//  - url: http://domain.com/ and resource: //other.com/some-resource.js
			//    generates: http://other.com/some-resource.js
			//  - url: https://domain.com/ and resource: //other.com/some-resource.js
			//    generates: https://other.com/some-resource.js
			if strings.HasPrefix(src, "//") {
				src = req.URL.Scheme + ":" + src
			}

			// non-host-absolute resource. E.g. resource is loaded based on the docroot
			// of the domain. E.g:
			//  - url: http://domain.com/ and resource: /some-resource.js
			//    generates: http://domain.com/some-resource.js
			//  - url: https://domain.com/sub/resource and resource: /some-resource.js
			//    generates: https://domain.com/some-resource.js
			if strings.HasPrefix(src, "/") {
				src = req.URL.Scheme + "://" + req.URL.Host + src
			}

			// ignore anything else that isn't http based. E.g. ftp://, and other svg-like
			// data urls, as we really can't fetch those.
			if !strings.HasPrefix(src, "http") {
				continue
			}

			urls = append(urls, src)
		}
	}
}

func connHostname(URL string) (host string, err error) {
	tmp, err := url.Parse(URL)

	if err != nil {
		return
	}

	host = tmp.Host
	return
}

// FetchResource fetches a singular resource from a page, returning a *Resource struct.
// As we don't care much about the body of the resource, that can safely be ignored. We
// must still close the body object, however.
func (rsrc *Resource) FetchResource() {
	var err error

	defer resourcePool.Done()

	// calculate the time it takes to fetch the request
	timer := NewTimer()
	resp, err := Get(rsrc.connURL, rsrc.connIP)
	rsrc.Time = timer.End()
	resp.Body.Close()

	if err != nil {
		rsrc.Error = err
		return
	}

	rsrc.connHostname, err = connHostname(rsrc.connURL)
	if err != nil {
		rsrc.Error = err
		return
	}

	rsrc.Hostname = resp.Request.Host
	rsrc.URL = resp.Request.URL.String()
	rsrc.Code = resp.StatusCode
	rsrc.Proto = resp.Proto
	rsrc.Scheme = resp.Request.URL.Scheme
	rsrc.ContentLength = resp.ContentLength
	rsrc.TLS = resp.TLS

	if rsrc.Hostname != rsrc.connHostname {
		rsrc.Remote = true
	}

	fmt.Printf("[%d] [%s] %s\n", rsrc.Code, rsrc.Proto, rsrc.URL)

	return
}

// Crawl manages the fetching of the main resource, as well as all child resources,
// providing a Results struct containing the entire crawl data needed
func Crawl(URL string, IP string) (res *Results) {
	res = &Results{}

	crawlTimer := NewTimer()
	reqTimer := NewTimer()

	// actually fetch the request
	resp, err := Get(URL, IP)

	res.Time = reqTimer.End()

	if err != nil {
		res.Error = err
		return
	}

	defer resp.Body.Close()

	res.connHostname, err = connHostname(URL)
	if err != nil {
		res.Error = err
		return
	}

	res.connURL = URL
	res.connIP = IP
	res.Hostname = resp.Request.Host
	res.URL = URL
	res.Code = resp.StatusCode
	res.Proto = resp.Proto
	res.Scheme = resp.Request.URL.Scheme
	res.ContentLength = resp.ContentLength
	res.TLS = resp.TLS

	if res.Hostname != res.connHostname {
		res.Remote = true
	}

	buf, _ := ioutil.ReadAll(resp.Body)
	b := ioutil.NopCloser(bytes.NewReader(buf))
	defer b.Close()

	bbytes, err := ioutil.ReadAll(bytes.NewBuffer(buf))
	if len(bbytes) != 0 {
		res.Body = string(bbytes[:])
	}

	urls := getSrc(b, resp.Request)

	fmt.Printf("[%d] [%s] %s\n", res.Code, res.Proto, res.URL)

	resourceTime := NewTimer()

	for i := range urls {
		resourcePool.Add(1)

		rsrc := &Resource{connURL: urls[i], connIP: ""}
		res.Resources = append(res.Resources, rsrc)
		go res.Resources[i].FetchResource()
	}

	resourcePool.Wait()

	res.ResourceTime = resourceTime.End()
	res.TotalTime = crawlTimer.End()

	return
}
<|endoftext|>


<commit_before>// Sequence-based Go-native audio mixer for music apps
//
// Go-native audio mixer for Music apps
//
// See `demo/demo.go`:
//
//     package main
//
//     import (
//       "fmt"
//       "os"
//       "time"
//
//       "github.com/go-mix/mix"
//       "github.com/go-mix/mix/bind"
//     )
//
//     var (
//       sampleHz   = float64(48000)
//       spec = bind.AudioSpec{
//         Freq:     sampleHz,
//         Format:   bind.AudioF32,
//         Channels: 2,
//         }
//       bpm        = 120
//       step       = time.Minute / time.Duration(bpm*4)
//       loops      = 16
//       prefix     = "sound/808/"
//       kick1      = "kick1.wav"
//       kick2      = "kick2.wav"
//       marac      = "maracas.wav"
//       snare      = "snare.wav"
//       hitom      = "hightom.wav"
//       clhat      = "cl_hihat.wav"
//       pattern    = []string{
//         kick2,
//         marac,
//         clhat,
//         marac,
//         snare,
//         marac,
//         clhat,
//         kick2,
//         marac,
//         marac,
//         hitom,
//         marac,
//         snare,
//         kick1,
//         clhat,
//         marac,
//       }
//     )
//
//     func main() {
//       defer mix.Teardown()
//
//       mix.Debug(true)
//       mix.Configure(spec)
//       mix.SetSoundsPath(prefix)
//       mix.StartAt(time.Now().Add(1 * time.Second))
//
//       t := 2 * time.Second // padding before music
//       for n := 0; n < loops; n++ {
//         for s := 0; s < len(pattern); s++ {
//           mix.SetFire(pattern[s], t+time.Duration(s)*step, 0, 1.0, 0)
//         }
//         t += time.Duration(len(pattern)) * step
//       }
//
//       fmt.Printf("Mix, pid:%v, spec:%v\n", os.Getpid(), spec)
//       for mix.FireCount() > 0 {
//         time.Sleep(1 * time.Second)
//       }
//     }
//
// Play this Demo from the root of the project, with no actual audio playback
//
//     make demo
//
// Or export WAV via stdout `> demo/output.wav`:
//
//     make demo.wav
//
// What
//
// Game audio mixers are designed to play audio spontaneously, but when the timing is known in advance (e.g. sequence-based music apps) there is a demand for much greater accuracy in playback timing.
//
// Read the API documentation at https://godoc.org/github.com/go-mix/mix
//
// Mix seeks to solve the problem of audio mixing for the purpose of the playback of sequences where audio files and their playback timing is known in advance.
//
// Mix stores and mixes audio in native Go `[]float64` and natively implements Paul Vögler's "Loudness Normalization by Logarithmic Dynamic Range Compression" (details below)
//
// Credit
//
// Charney Kaye
// <hiya@charney.io>
// http://w.charney.io
//
// Outright Mental
// http://w.outright.io
//
// Why
//
// Even after selecting a hardware interface library such as http://www.portaudio.com/ or https://www.libsdl.org/, there remains a critical design problem to be solved.
//
// This design is a music application mixer. Most available options are geared towards Game development.
//
// Game audio mixers offer playback timing accuracy +/- 2 milliseconds. But that's totally unacceptable for music, specifically sequence-based sample playback.
//
// The design pattern particular to Game design is that the timing of the audio is not know in advance- the timing that really matters is that which is assembled in near-real-time in response to user interaction.
//
// In the field of Music development, often the timing is known in advance, e.g. a sequencer, the composition of music by specifying exactly how, when and which audio files will be played relative to the beginning of playback.
//
// Ergo, mix seeks to solve the problem of audio mixing for the purpose of the playback of sequences where audio files and their playback timing is known in advance. It seeks to do this with the absolute minimal logical overhead on top of the audio interface.
//
// Mix takes maximum advantage of Go by storing and mixing audio in native Go `[]float64` and natively implementing Paul Vögler's "Loudness Normalization by Logarithmic Dynamic Range Compression" (see The Mixing Algorithm below)
//
// Time
//
// To the Mix API, time is specified as a time.Duration-since-epoch, where the epoch is the moment that mix.Start() was called.
//
// Internally, time is tracked as samples-since-epoch at the master out playback frequency (e.g. 48000 Hz). This is most efficient because source audio is pre-converted to the master out playback frequency, and all audio maths are performed in terms of samples.
//
// The Mixing Algorithm
//
// Inspired by the theory paper "Mixing two digital audio streams with on the fly Loudness Normalization by Logarithmic Dynamic Range Compression" by Paul Vögler, 2012-04-20. This paper is published at http://www.voegler.eu/pub/audio/digital-audio-mixing-and-normalization.html.
//
// Usage
//
// There's a demo implementation of **mix** included in the `demo/` folder in this repository. Run it using the defaults:
//
//     cd demo && go get && go run demo.go
//
// Or specify options, e.g. using WAV bytes to stdout for playback (piped to system native `aplay`)
//
//     go run demo.go --out wav | aplay
//
// To show the help screen:
//
//     go run demo.go --help
//
// Best efforts will be made to preserve each API version in a release tag that can be parsed, e.g. http://github.com/go-mix/mix
//
// Mix in good health!
//
package mix

import (
	"io"
	"time"

	"github.com/go-mix/mix/bind"
	"github.com/go-mix/mix/bind/debug"
	"github.com/go-mix/mix/bind/spec"

	"github.com/go-mix/mix/lib/fire"
	"github.com/go-mix/mix/lib/mix"
)

// VERSION # of this mix source code
// const VERSION = "0.0.3"

// Debug ON/OFF (ripples down to all sub-modules)
func Debug(isOn bool) {
	debug.Configure(isOn)
}

// Configure the mixer frequency, format, channels & sample rate.
func Configure(s spec.AudioSpec) {
	s.Validate()
	bind.SetOutputCallback(mix.NextSample)
	bind.Configure(s)
	mix.Configure(s)
}

// Teardown everything and release all memory.
func Teardown() {
	mix.Teardown()
	bind.Teardown()
}

// Spec for the mixer, which may include callback functions, e.g. portaudio
func Spec() *spec.AudioSpec {
	return mix.Spec()
}

// SetFire to represent a single audio source playing at a specific time in the future (in time.Duration from play start), with sustain time.Duration, volume from 0 to 1, and pan from -1 to +1
func SetFire(source string, begin time.Duration, sustain time.Duration, volume float64, pan float64) *fire.Fire {
	return mix.SetFire(source, begin, sustain, volume, pan)
}

// FireCount to check the number of fires currently scheduled for playback
func FireCount() int {
	return mix.FireCount()
}

// ClearAllFires to clear all fires currently ready, or live
func ClearAllFires() {
	mix.ClearAllFires()
}

// SetSoundsPath prefix
func SetSoundsPath(prefix string) {
	mix.SetSoundsPath(prefix)
}

// Set the duration between "mix cycles", wherein garbage collection is performed.
func SetMixCycleDuration(d time.Duration) {
	mix.SetCycleDuration(d)
}

// Start the mixer now
func Start() {
	mix.StartAt(time.Now())
}

// StartAt a specific time in the future
func StartAt(t time.Time) {
	mix.StartAt(t)
}

// GetStartTime the mixer was started at
func GetStartTime() time.Time {
	return mix.GetStartTime()
}

// GetNowAt returns current mix position
func GetNowAt() time.Duration {
	return mix.GetNowAt()
}

// OutputStart requires a known length
func OutputStart(length time.Duration, out io.Writer) {
	mix.OutputStart(length, out)
}

// OutputContinueTo output as []byte via stdout, up to a specified duration-since-start
func OutputContinueTo(t time.Duration) {
	mix.OutputContinueTo(t)
}

// OutputBegin to output WAV closer as []byte via stdout
func OutputClose() {
	mix.OutputClose()
}
<commit_msg>Fix credits<commit_after>// Sequence-based Go-native audio mixer for music apps
//
// Go-native audio mixer for Music apps
//
// See `demo/demo.go`:
//
//     package main
//
//     import (
//       "fmt"
//       "os"
//       "time"
//
//       "github.com/go-mix/mix"
//       "github.com/go-mix/mix/bind"
//     )
//
//     var (
//       sampleHz   = float64(48000)
//       spec = bind.AudioSpec{
//         Freq:     sampleHz,
//         Format:   bind.AudioF32,
//         Channels: 2,
//         }
//       bpm        = 120
//       step       = time.Minute / time.Duration(bpm*4)
//       loops      = 16
//       prefix     = "sound/808/"
//       kick1      = "kick1.wav"
//       kick2      = "kick2.wav"
//       marac      = "maracas.wav"
//       snare      = "snare.wav"
//       hitom      = "hightom.wav"
//       clhat      = "cl_hihat.wav"
//       pattern    = []string{
//         kick2,
//         marac,
//         clhat,
//         marac,
//         snare,
//         marac,
//         clhat,
//         kick2,
//         marac,
//         marac,
//         hitom,
//         marac,
//         snare,
//         kick1,
//         clhat,
//         marac,
//       }
//     )
//
//     func main() {
//       defer mix.Teardown()
//
//       mix.Debug(true)
//       mix.Configure(spec)
//       mix.SetSoundsPath(prefix)
//       mix.StartAt(time.Now().Add(1 * time.Second))
//
//       t := 2 * time.Second // padding before music
//       for n := 0; n < loops; n++ {
//         for s := 0; s < len(pattern); s++ {
//           mix.SetFire(pattern[s], t+time.Duration(s)*step, 0, 1.0, 0)
//         }
//         t += time.Duration(len(pattern)) * step
//       }
//
//       fmt.Printf("Mix, pid:%v, spec:%v\n", os.Getpid(), spec)
//       for mix.FireCount() > 0 {
//         time.Sleep(1 * time.Second)
//       }
//     }
//
// Play this Demo from the root of the project, with no actual audio playback
//
//     make demo
//
// Or export WAV via stdout `> demo/output.wav`:
//
//     make demo.wav
//
//
// What
//
// Game audio mixers are designed to play audio spontaneously, but when the timing is known in advance (e.g. sequence-based music apps) there is a demand for much greater accuracy in playback timing.
//
// Read the API documentation at https://godoc.org/github.com/go-mix/mix
//
// Mix seeks to solve the problem of audio mixing for the purpose of the playback of sequences where audio files and their playback timing is known in advance.
//
// Mix stores and mixes audio in native Go `[]float64` and natively implements Paul Vögler's "Loudness Normalization by Logarithmic Dynamic Range Compression" (details below)
//
//
// Credit
//
// Charney Kaye
// https://charneykaye.com
//
// XJ Music Inc.
// https://xj.io
//
//
// Why
//
// Even after selecting a hardware interface library such as http://www.portaudio.com/ or https://www.libsdl.org/, there remains a critical design problem to be solved.
//
// This design is a music application mixer. Most available options are geared towards Game development.
//
// Game audio mixers offer playback timing accuracy +/- 2 milliseconds. But that's totally unacceptable for music, specifically sequence-based sample playback.
//
// The design pattern particular to Game design is that the timing of the audio is not know in advance- the timing that really matters is that which is assembled in near-real-time in response to user interaction.
//
// In the field of Music development, often the timing is known in advance, e.g. a sequencer, the composition of music by specifying exactly how, when and which audio files will be played relative to the beginning of playback.
//
// Ergo, mix seeks to solve the problem of audio mixing for the purpose of the playback of sequences where audio files and their playback timing is known in advance. It seeks to do this with the absolute minimal logical overhead on top of the audio interface.
//
// Mix takes maximum advantage of Go by storing and mixing audio in native Go `[]float64` and natively implementing Paul Vögler's "Loudness Normalization by Logarithmic Dynamic Range Compression" (see The Mixing Algorithm below)
//
//
// Time
//
// To the Mix API, time is specified as a time.Duration-since-epoch, where the epoch is the moment that mix.Start() was called.
//
// Internally, time is tracked as samples-since-epoch at the master out playback frequency (e.g. 48000 Hz). This is most efficient because source audio is pre-converted to the master out playback frequency, and all audio maths are performed in terms of samples.
//
// The Mixing Algorithm
//
// Inspired by the theory paper "Mixing two digital audio streams with on the fly Loudness Normalization by Logarithmic Dynamic Range Compression" by Paul Vögler, 2012-04-20. This paper is published at http://www.voegler.eu/pub/audio/digital-audio-mixing-and-normalization.html.
//
//
// Usage
//
// There's a demo implementation of **mix** included in the `demo/` folder in this repository. Run it using the defaults:
//
//     cd demo && go get && go run demo.go
//
// Or specify options, e.g. using WAV bytes to stdout for playback (piped to system native `aplay`)
//
//     go run demo.go --out wav | aplay
//
// To show the help screen:
//
//     go run demo.go --help
//
// Best efforts will be made to preserve each API version in a release tag that can be parsed, e.g. http://github.com/go-mix/mix
//
// Mix in good health!
//
package mix

import (
	"io"
	"time"

	"github.com/go-mix/mix/bind"
	"github.com/go-mix/mix/bind/debug"
	"github.com/go-mix/mix/bind/spec"

	"github.com/go-mix/mix/lib/fire"
	"github.com/go-mix/mix/lib/mix"
)

// VERSION # of this mix source code
// const VERSION = "0.0.3"

// Debug ON/OFF (ripples down to all sub-modules)
func Debug(isOn bool) {
	debug.Configure(isOn)
}

// Configure the mixer frequency, format, channels & sample rate.
func Configure(s spec.AudioSpec) {
	s.Validate()
	bind.SetOutputCallback(mix.NextSample)
	bind.Configure(s)
	mix.Configure(s)
}

// Teardown everything and release all memory.
func Teardown() {
	mix.Teardown()
	bind.Teardown()
}

// Spec for the mixer, which may include callback functions, e.g. portaudio
func Spec() *spec.AudioSpec {
	return mix.Spec()
}

// SetFire to represent a single audio source playing at a specific time in the future (in time.Duration from play start), with sustain time.Duration, volume from 0 to 1, and pan from -1 to +1
func SetFire(source string, begin time.Duration, sustain time.Duration, volume float64, pan float64) *fire.Fire {
	return mix.SetFire(source, begin, sustain, volume, pan)
}

// FireCount to check the number of fires currently scheduled for playback
func FireCount() int {
	return mix.FireCount()
}

// ClearAllFires to clear all fires currently ready, or live
func ClearAllFires() {
	mix.ClearAllFires()
}

// SetSoundsPath prefix
func SetSoundsPath(prefix string) {
	mix.SetSoundsPath(prefix)
}

// Set the duration between "mix cycles", wherein garbage collection is performed.
func SetMixCycleDuration(d time.Duration) {
	mix.SetCycleDuration(d)
}

// Start the mixer now
func Start() {
	mix.StartAt(time.Now())
}

// StartAt a specific time in the future
func StartAt(t time.Time) {
	mix.StartAt(t)
}

// GetStartTime the mixer was started at
func GetStartTime() time.Time {
	return mix.GetStartTime()
}

// GetNowAt returns current mix position
func GetNowAt() time.Duration {
	return mix.GetNowAt()
}

// OutputStart requires a known length
func OutputStart(length time.Duration, out io.Writer) {
	mix.OutputStart(length, out)
}

// OutputContinueTo output as []byte via stdout, up to a specified duration-since-start
func OutputContinueTo(t time.Duration) {
	mix.OutputContinueTo(t)
}

// OutputBegin to output WAV closer as []byte via stdout
func OutputClose() {
	mix.OutputClose()
}
<|endoftext|>