<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/cubicdaiya/gonp"
)

type Target struct {
	fname string
	mtime time.Time
}

type TargetHeader struct {
	targets []Target
}

func getLines(f string) ([]string, error) {
	fp, err := os.Open(f)
	if err != nil {
		return []string{}, err
	}
	defer fp.Close()

	scanner := bufio.NewScanner(fp)
	lines := make([]string, 0)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, nil
}

func buildTargetHeader(f1, f2 string) (TargetHeader, error) {
	fi1, err := os.Stat(f1)
	if err != nil {
		return TargetHeader{}, err
	}
	fi2, err := os.Stat(f2)
	if err != nil {
		return TargetHeader{}, err
	}
	return TargetHeader{
		targets: []Target{
			Target{
				fname: f1,
				mtime: fi1.ModTime(),
			},
			Target{
				fname: f2,
				mtime: fi2.ModTime(),
			},
		},
	}, nil
}

func (th *TargetHeader) String() string {
	if len(th.targets) != 2 {
		return ""
	}
	var b bytes.Buffer
	fmt.Fprintf(&b, "--- %s\t%s\n", th.targets[0].fname, th.targets[0].mtime.Format(time.RFC3339Nano))
	fmt.Fprintf(&b, "+++ %s\t%s\n", th.targets[1].fname, th.targets[1].mtime.Format(time.RFC3339Nano))
	return b.String()
}

func main() {
	if len(os.Args) < 3 {
		log.Fatal("./unifilediff filename1 filename2")
	}

	f1 := os.Args[1]
	f2 := os.Args[2]

	var (
		a   []string
		b   []string
		err error
	)

	a, err = getLines(f1)
	if err != nil {
		log.Fatalf("%s: %s", f1, err)
	}

	b, err = getLines(f2)
	if err != nil {
		log.Fatalf("%s: %s", f2, err)
	}

	th, err := buildTargetHeader(f1, f2)
	if err != nil {
		log.Fatal(err)
	}

	diff := gonp.New(a, b)
	diff.Compose()

	fmt.Printf(th.String())
	diff.PrintUniHunks(diff.UnifiedHunks())
}
<commit_msg>style: adjusted indents.<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/cubicdaiya/gonp"
)

type Target struct {
	fname string
	mtime time.Time
}

type TargetHeader struct {
	targets []Target
}

func getLines(f string) ([]string, error) {
	fp, err := os.Open(f)
	if err != nil {
		return []string{}, err
	}
	defer fp.Close()

	scanner := bufio.NewScanner(fp)
	lines := make([]string, 0)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, nil
}

func buildTargetHeader(f1, f2 string) (TargetHeader, error) {
	fi1, err := os.Stat(f1)
	if err != nil {
		return TargetHeader{}, err
	}
	fi2, err := os.Stat(f2)
	if err != nil {
		return TargetHeader{}, err
	}
	return TargetHeader{
		targets: []Target{
			Target{fname: f1, mtime: fi1.ModTime()},
			Target{fname: f2, mtime: fi2.ModTime()},
		},
	}, nil
}

func (th *TargetHeader) String() string {
	if len(th.targets) != 2 {
		return ""
	}
	var b bytes.Buffer
	fmt.Fprintf(&b, "--- %s\t%s\n", th.targets[0].fname, th.targets[0].mtime.Format(time.RFC3339Nano))
	fmt.Fprintf(&b, "+++ %s\t%s\n", th.targets[1].fname, th.targets[1].mtime.Format(time.RFC3339Nano))
	return b.String()
}

func main() {
	if len(os.Args) < 3 {
		log.Fatal("./unifilediff filename1 filename2")
	}

	f1 := os.Args[1]
	f2 := os.Args[2]

	var (
		a   []string
		b   []string
		err error
	)

	a, err = getLines(f1)
	if err != nil {
		log.Fatalf("%s: %s", f1, err)
	}

	b, err = getLines(f2)
	if err != nil {
		log.Fatalf("%s: %s", f2, err)
	}

	th, err := buildTargetHeader(f1, f2)
	if err != nil {
		log.Fatal(err)
	}

	diff := gonp.New(a, b)
	diff.Compose()

	fmt.Printf(th.String())
	diff.PrintUniHunks(diff.UnifiedHunks())
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"code.google.com/p/go.crypto/ripemd160"
	"errors"
	"github.com/conformal/btcwire"
)

// ErrUnknownNet describes an error where the Bitcoin network is
// not recognized.
var ErrUnknownNet = errors.New("unrecognized bitcoin network")

// ErrMalformedAddress describes an error where an address is improperly
// formatted, either due to an incorrect length of the hashed pubkey or
// a non-matching checksum.
var ErrMalformedAddress = errors.New("malformed address")

// ErrMalformedPrivateKey describes an error where an address is improperly
// formatted, either due to an incorrect length of the private key or
// a non-matching checksum.
var ErrMalformedPrivateKey = errors.New("malformed private key")

// Constants used to specify which network a payment address belongs
// to.  Mainnet address cannot be used on the Testnet, and vice versa.
const (
	// MainNetAddr is the address identifier for MainNet
	MainNetAddr = 0x00

	// TestNetAddr is the address identifier for TestNet
	TestNetAddr = 0x6f

	// MainNetKey is the key identifier for MainNet
	MainNetKey = 0x80

	// TestNetKey is the key identifier for TestNet
	TestNetKey = 0xef
)

// EncodeAddress takes a 20-byte raw payment address (hash160 of a pubkey)
// and the Bitcoin network to create a human-readable payment address string.
func EncodeAddress(addrHash []byte, net btcwire.BitcoinNet) (encoded string, err error) {
	if len(addrHash) != ripemd160.Size {
		return "", ErrMalformedAddress
	}

	var netID byte
	switch net {
	case btcwire.MainNet:
		netID = MainNetAddr
	case btcwire.TestNet3:
		netID = TestNetAddr
	default:
		return "", ErrUnknownNet
	}

	tosum := append([]byte{netID}, addrHash...)
	cksum := btcwire.DoubleSha256(tosum)

	// Address before base58 encoding is 1 byte for netID, 20 bytes for
	// hash, plus 4 bytes of checksum.
	a := make([]byte, 25, 25)
	a[0] = netID
	copy(a[1:], addrHash)
	copy(a[21:], cksum[:4])

	return Base58Encode(a), nil
}

// DecodeAddress decodes a human-readable payment address string
// returning the 20-byte decoded address, along with the Bitcoin
// network for the address.
func DecodeAddress(addr string) (addrHash []byte, net btcwire.BitcoinNet, err error) {
	decoded := Base58Decode(addr)

	// Length of decoded address must be 20 bytes + 1 byte for a network
	// identifier byte + 4 bytes of checksum.
	if len(decoded) != ripemd160.Size+5 {
		return nil, 0x00, ErrMalformedAddress
	}

	switch decoded[0] {
	case MainNetAddr:
		net = btcwire.MainNet
	case TestNetAddr:
		net = btcwire.TestNet3
	default:
		return nil, 0, ErrUnknownNet
	}

	// Checksum is first four bytes of double SHA256 of the network byte
	// and addrHash.  Verify this matches the final 4 bytes of the decoded
	// address.
	tosum := decoded[:ripemd160.Size+1]
	cksum := btcwire.DoubleSha256(tosum)[:4]
	if !bytes.Equal(cksum, decoded[len(decoded)-4:]) {
		return nil, net, ErrMalformedAddress
	}

	addrHash = make([]byte, ripemd160.Size, ripemd160.Size)
	copy(addrHash, decoded[1:ripemd160.Size+1])

	return addrHash, net, nil
}

// EncodePrivateKey takes a 32-byte private key and encodes it into the
// Wallet Import Format (WIF).
func EncodePrivateKey(privKey []byte, net btcwire.BitcoinNet, compressed bool) (string, error) {
	if len(privKey) != 32 {
		return "", ErrMalformedPrivateKey
	}

	var netID byte
	switch net {
	case btcwire.MainNet:
		netID = MainNetKey
	case btcwire.TestNet3:
		netID = TestNetKey
	default:
		return "", ErrUnknownNet
	}

	tosum := append([]byte{netID}, privKey...)
	if compressed {
		tosum = append(tosum, 0x01)
	}
	cksum := btcwire.DoubleSha256(tosum)

	// Private key before base58 encoding is 1 byte for netID, 32 bytes for
	// privKey, plus an optional byte (0x01) if copressed, plus 4 bytes of checksum.
	encodeLen := 37
	if compressed {
		encodeLen += 1
	}
	a := make([]byte, encodeLen, encodeLen)
	a[0] = netID
	copy(a[1:], privKey)
	if compressed {
		copy(a[32+1:], []byte{0x01})
		copy(a[32+1+1:], cksum[:4])
	} else {
		copy(a[32+1:], cksum[:4])
	}
	return Base58Encode(a), nil
}

// DecodePrivateKey takes a Wallet Import Format (WIF) string and
// decodes into a 32-byte private key.
func DecodePrivateKey(wif string) ([]byte, btcwire.BitcoinNet, bool, error) {
	decoded := Base58Decode(wif)
	decodedLen := len(decoded)
	compressed := false

	// Length of decoded privkey must be 32 bytes + an optional 1 byte (0x01)
	// if compressed, plus 1 byte for netID + 4 bytes of checksum
	if decodedLen == 32+6 {
		compressed = true
		if decoded[33] != 0x01 {
			return nil, 0, compressed, ErrMalformedPrivateKey
		}
	} else if decodedLen != 32+5 {
		return nil, 0, compressed, ErrMalformedPrivateKey
	}

	var net btcwire.BitcoinNet
	switch decoded[0] {
	case MainNetKey:
		net = btcwire.MainNet
	case TestNetKey:
		net = btcwire.TestNet3
	default:
		return nil, 0, compressed, ErrUnknownNet
	}

	// Checksum is first four bytes of double SHA256 of the identifier byte
	// and privKey.  Verify this matches the final 4 bytes of the decoded
	// private key.
	var tosum []byte
	if compressed {
		tosum = decoded[:32+1+1]
	} else {
		tosum = decoded[:32+1]
	}
	cksum := btcwire.DoubleSha256(tosum)[:4]
	if !bytes.Equal(cksum, decoded[decodedLen-4:]) {
		return nil, 0, compressed, ErrMalformedPrivateKey
	}

	privKey := make([]byte, 32, 32)
	copy(privKey[:], decoded[1:32+1])

	return privKey, net, compressed, nil
}
<commit_msg>Added EncodeScriptHash for BIP-0013 compliance<commit_after>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"code.google.com/p/go.crypto/ripemd160"
	"errors"
	"github.com/conformal/btcwire"
)

// ErrUnknownNet describes an error where the Bitcoin network is
// not recognized.
var ErrUnknownNet = errors.New("unrecognized bitcoin network")

// ErrMalformedAddress describes an error where an address is improperly
// formatted, either due to an incorrect length of the hashed pubkey or
// a non-matching checksum.
var ErrMalformedAddress = errors.New("malformed address")

// ErrMalformedPrivateKey describes an error where an address is improperly
// formatted, either due to an incorrect length of the private key or
// a non-matching checksum.
var ErrMalformedPrivateKey = errors.New("malformed private key")

// Constants used to specify which network a payment address belongs
// to.  Mainnet address cannot be used on the Testnet, and vice versa.
const (
	// MainNetAddr is the address identifier for MainNet
	MainNetAddr = 0x00

	// TestNetAddr is the address identifier for TestNet
	TestNetAddr = 0x6f

	// MainNetKey is the key identifier for MainNet
	MainNetKey = 0x80

	// TestNetKey is the key identifier for TestNet
	TestNetKey = 0xef

	// MainNetScriptHash is the address identifier for MainNet
	MainNetScriptHash = 0x05

	// TestNetScriptHash is the address identifier for TestNet
	TestNetScriptHash = 0xC4
)

// EncodeAddress takes a 20-byte raw payment address (hash160 of a pubkey)
// and the Bitcoin network to create a human-readable payment address string.
func EncodeAddress(addrHash []byte, net btcwire.BitcoinNet) (encoded string, err error) {
	if len(addrHash) != ripemd160.Size {
		return "", ErrMalformedAddress
	}

	var netID byte
	switch net {
	case btcwire.MainNet:
		netID = MainNetAddr
	case btcwire.TestNet3:
		netID = TestNetAddr
	default:
		return "", ErrUnknownNet
	}

	return encodeHashWithNetId(netID, addrHash)
}

// EncodeScriptHash takes a 20-byte raw script hash (hash160 of a pubkey)
// and the Bitcoin network to create a human-readable payment address string.
func EncodeScriptHash(addrHash []byte, net btcwire.BitcoinNet) (encoded string, err error) {
	if len(addrHash) != ripemd160.Size {
		return "", ErrMalformedAddress
	}

	var netID byte
	switch net {
	case btcwire.MainNet:
		netID = MainNetScriptHash
	case btcwire.TestNet3:
		netID = TestNetScriptHash
	default:
		return "", ErrUnknownNet
	}

	return encodeHashWithNetId(netID, addrHash)
}

func encodeHashWithNetId(netID byte, addrHash []byte) (encoded string, err error) {
	tosum := append([]byte{netID}, addrHash...)
	cksum := btcwire.DoubleSha256(tosum)

	// Address before base58 encoding is 1 byte for netID, 20 bytes for
	// hash, plus 4 bytes of checksum.
	a := make([]byte, 25, 25)
	a[0] = netID
	copy(a[1:], addrHash)
	copy(a[21:], cksum[:4])

	return Base58Encode(a), nil
}

// DecodeAddress decodes a human-readable payment address string
// returning the 20-byte decoded address, along with the Bitcoin
// network for the address.
func DecodeAddress(addr string) (addrHash []byte, net btcwire.BitcoinNet, err error) {
	decoded := Base58Decode(addr)

	// Length of decoded address must be 20 bytes + 1 byte for a network
	// identifier byte + 4 bytes of checksum.
	if len(decoded) != ripemd160.Size+5 {
		return nil, 0x00, ErrMalformedAddress
	}

	switch decoded[0] {
	case MainNetAddr:
		net = btcwire.MainNet
	case TestNetAddr:
		net = btcwire.TestNet3
	default:
		return nil, 0, ErrUnknownNet
	}

	// Checksum is first four bytes of double SHA256 of the network byte
	// and addrHash.  Verify this matches the final 4 bytes of the decoded
	// address.
	tosum := decoded[:ripemd160.Size+1]
	cksum := btcwire.DoubleSha256(tosum)[:4]
	if !bytes.Equal(cksum, decoded[len(decoded)-4:]) {
		return nil, net, ErrMalformedAddress
	}

	addrHash = make([]byte, ripemd160.Size, ripemd160.Size)
	copy(addrHash, decoded[1:ripemd160.Size+1])

	return addrHash, net, nil
}

// EncodePrivateKey takes a 32-byte private key and encodes it into the
// Wallet Import Format (WIF).
func EncodePrivateKey(privKey []byte, net btcwire.BitcoinNet, compressed bool) (string, error) {
	if len(privKey) != 32 {
		return "", ErrMalformedPrivateKey
	}

	var netID byte
	switch net {
	case btcwire.MainNet:
		netID = MainNetKey
	case btcwire.TestNet3:
		netID = TestNetKey
	default:
		return "", ErrUnknownNet
	}

	tosum := append([]byte{netID}, privKey...)
	if compressed {
		tosum = append(tosum, 0x01)
	}
	cksum := btcwire.DoubleSha256(tosum)

	// Private key before base58 encoding is 1 byte for netID, 32 bytes for
	// privKey, plus an optional byte (0x01) if copressed, plus 4 bytes of checksum.
	encodeLen := 37
	if compressed {
		encodeLen += 1
	}
	a := make([]byte, encodeLen, encodeLen)
	a[0] = netID
	copy(a[1:], privKey)
	if compressed {
		copy(a[32+1:], []byte{0x01})
		copy(a[32+1+1:], cksum[:4])
	} else {
		copy(a[32+1:], cksum[:4])
	}
	return Base58Encode(a), nil
}

// DecodePrivateKey takes a Wallet Import Format (WIF) string and
// decodes into a 32-byte private key.
func DecodePrivateKey(wif string) ([]byte, btcwire.BitcoinNet, bool, error) {
	decoded := Base58Decode(wif)
	decodedLen := len(decoded)
	compressed := false

	// Length of decoded privkey must be 32 bytes + an optional 1 byte (0x01)
	// if compressed, plus 1 byte for netID + 4 bytes of checksum
	if decodedLen == 32+6 {
		compressed = true
		if decoded[33] != 0x01 {
			return nil, 0, compressed, ErrMalformedPrivateKey
		}
	} else if decodedLen != 32+5 {
		return nil, 0, compressed, ErrMalformedPrivateKey
	}

	var net btcwire.BitcoinNet
	switch decoded[0] {
	case MainNetKey:
		net = btcwire.MainNet
	case TestNetKey:
		net = btcwire.TestNet3
	default:
		return nil, 0, compressed, ErrUnknownNet
	}

	// Checksum is first four bytes of double SHA256 of the identifier byte
	// and privKey.  Verify this matches the final 4 bytes of the decoded
	// private key.
	var tosum []byte
	if compressed {
		tosum = decoded[:32+1+1]
	} else {
		tosum = decoded[:32+1]
	}
	cksum := btcwire.DoubleSha256(tosum)[:4]
	if !bytes.Equal(cksum, decoded[decodedLen-4:]) {
		return nil, 0, compressed, ErrMalformedPrivateKey
	}

	privKey := make([]byte, 32, 32)
	copy(privKey[:], decoded[1:32+1])

	return privKey, net, compressed, nil
}
<|endoftext|>


<commit_before>package translation

import (
	"os"
	"log"
	"fmt"
	"math"
	// "bufio"
	"github.com/thomaspeugeot/tkv/barnes-hut"
	"github.com/thomaspeugeot/tkv/quadtree"
	"github.com/thomaspeugeot/tkv/grump"
	// "path/filepath"
	"encoding/json"

	convexhull "github.com/thomaspeugeot/go-convexhull/convexhull"
)

type Country struct {
	grump.Country

	NbBodies int // nb of bodies according to the filename

	bodiesOrig * []quadtree.Body // original bodies position in the quatree
	bodiesSpread * []quadtree.Body // bodies position in the quatree after the spread simulation
	VilCoordinates [][]int
	Step int // step when the simulation stopped

	villages [][]Village
}

type BodySetChoice string
const (
	ORIGINAL_CONFIGURATION = "ORIGINAL_CONFIGURATION"
	SPREAD_CONFIGURATION = "SPREAD_CONFIGURATION"
)

// number of village per X or Y axis. For 10 000 villages, this number is 100
// this value can be set interactively during the run
var nbVillagePerAxe int = 100

// init variables
func (country * Country) Init() {

	// unserialize from conf-<country trigram>.coord
	// store step because the unseralize set it to a wrong value
	step := country.Step
	country.Unserialize()
	country.Step = step

	Info.Printf("Init after Unserialize name %s", country.Name)
	Info.Printf("Init after Unserialize step %d", country.Step)

	country.LoadConfig( true ) // load config at the end  of the simulation
	country.LoadConfig( false ) // load config at the start of the simulation

	// init village array
	country.villages = make( [][]Village, nbVillagePerAxe )
	for x,_  := range country.villages {
		country.villages[x] = make([]Village, nbVillagePerAxe)
	}

	country.VilCoordinates = make( [][]int, country.NbBodies)
	for idx, _ := range country.VilCoordinates {
		country.VilCoordinates[idx] = make( []int, 2)
	}

	country.ComputeBaryCenters()

}

// load configuration from filename into counry
// check that it matches the
func (country * Country) LoadConfig( isOriginal bool) bool {

	Info.Printf( "Load Config begin : Country is %s, step %d", country.Name, country.Step)

	// computing the file name from the step
	step := 0

	// if isOrignal load the file with the step number 0, else use spread
	if ! isOriginal { step = country.Step }

	filename := fmt.Sprintf( barnes_hut.CountryBodiesNamePattern, country.Name, country.NbBodies, step)
	Info.Printf( "LoadConfig original %t file %s for country %s at step %d", isOriginal, filename, country.Name, step)

	file, err := os.Open(filename)
	if( err != nil) {
		log.Fatal(err)
		return false
	}

	jsonParser := json.NewDecoder(file)

	bodies := (make([]quadtree.Body, 0))
	if isOriginal {
		country.bodiesOrig = & bodies
		if err = jsonParser.Decode( country.bodiesOrig); err != nil {
			log.Fatal( fmt.Sprintf( "parsing config file %s", err.Error()))
		}
		Info.Printf( "nb item parsed in file for orig %d\n", len( *country.bodiesOrig))
	} else {
		country.bodiesSpread = & bodies
		if err = jsonParser.Decode( country.bodiesSpread); err != nil {
			log.Fatal( fmt.Sprintf( "parsing config file %s", err.Error()))
		}
		Info.Printf( "nb item parsed in file for spread %d\n", len( *country.bodiesSpread))
	}

	file.Close()

	Info.Printf( "Load Config end : Country is %s, step %d", country.Name, country.Step)

	return true
}

// compute villages barycenters
func (country * Country) ComputeBaryCenters() {
	Info.Printf("ComputeBaryCenters begins for country %s", country.Name)

	// parse bodiesSpread to compute bary centers
	// use bodiesOrig to compute bary centers
	for index,b := range *country.bodiesSpread {

		// compute village coordinate (from 0 to nbVillagePerAxe-1)
		villageX := int( math.Floor(float64( nbVillagePerAxe) * b.X))
		villageY := int( math.Floor(float64( nbVillagePerAxe) * b.Y))

		Trace.Printf("Adding body index %d to village %d %d", index, villageX, villageY)

		// add body (original) to the barycenter of the village
		bOrig := (*country.bodiesOrig)[index]
		country.villages[villageX][villageY].addBody( bOrig)

		country.VilCoordinates[index][0] = villageX
		country.VilCoordinates[index][1] = villageY
	}
}

func (country * Country) VillageCoordinates( lat, lng float64) (x, y, distance, latClosest, lngClosest, xSpread, ySpread float64, closestIndex int) {

	// compute relative coordinates within the square
	xRel, yRel := country.LatLng2XY( lat, lng)
	Info.Printf("VillageCoordinates lat %f,  lng %f", lat, lng)
	Info.Printf("VillageCoordinates Rel x %f, Rel y %f", xRel, yRel)

	// parse all bodies and get closest body
	closestIndex = -1
	minDistance := 1000000000.0 // we start from away
	for index,b := range *country.bodiesOrig {
		distanceX := b.X - xRel
		distanceY := b.Y - yRel
		distance := math.Sqrt( (distanceX*distanceX) + (distanceY*distanceY))

		if( distance < minDistance ) {
			closestIndex = index
			minDistance = distance
		}
	}
	Info.Printf("VillageCoordinates closestIndex %d, minDistance %f", closestIndex, minDistance)

	villageX := country.VilCoordinates[closestIndex][0]
	villageY := country.VilCoordinates[closestIndex][1]
	xRelClosest := (*country.bodiesOrig)[closestIndex].X
	yRelClosest := (*country.bodiesOrig)[closestIndex].Y

	latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

	Info.Printf( "VillageCoordinates %f %f relative to country %f %f", lat, lng, xRel, yRel)
	Info.Printf( "VillageCoordinates rel closest %f %f lat lng closest %f %f", xRelClosest, yRelClosest, latOptimClosest, lngOptimClosest)
	Info.Printf( "VillageCoordinates village %d %d", villageX, villageY)

	// compute x, y in spread bodies
	xSpread = (*country.bodiesSpread)[closestIndex].X
	ySpread = (*country.bodiesSpread)[closestIndex].Y

	Info.Printf( "VillageCoordinates village %f %f index %d", xSpread, ySpread, closestIndex)

	return xRelClosest, yRelClosest, minDistance, latOptimClosest, lngOptimClosest, xSpread, ySpread, closestIndex
}

func (country * Country) XYSpreadToLatLngOrig( x, y float64) (lat, lng float64) {

	Info.Printf( "XYSpreadToLatLngOrig input x %f y %f", x, y)

	// parse all bodies and get closest body
	closestIndex := -1
	minDistance := 1000000000.0 // we start from away
	for index,b := range *country.bodiesSpread {
		distanceX := b.X - x
		distanceY := b.Y - y
		distance := math.Sqrt( (distanceX*distanceX) + (distanceY*distanceY))

		if( distance < minDistance ) {
			closestIndex = index
			minDistance = distance
		}
	}

	xRelClosest := (*country.bodiesOrig)[closestIndex].X
	yRelClosest := (*country.bodiesOrig)[closestIndex].Y
	latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)
	Info.Printf("XYSpreadToLatLngOrig target x %f y %f index %d distance %f", xRelClosest, yRelClosest, closestIndex, minDistance)

	Info.Printf("XYSpreadToLatLngOrig target lat %f lng %f", latOptimClosest, lngOptimClosest)

	return latOptimClosest, lngOptimClosest
}

func (country * Country) XYSpreadToLatLngOrigVillage( x, y float64) convexhull.PointList {

	Info.Printf( "XYSpreadToLatLngOrig input x %f y %f", x, y)

	points := make(convexhull.PointList, 0)

	// compute village min & max coord
	numberOfVillagePerAxe := 10.0
	xMinVillage := float64( int( x*numberOfVillagePerAxe))/numberOfVillagePerAxe
	xMaxVillage := float64( int( x*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe
	yMinVillage := float64( int( y*numberOfVillagePerAxe))/numberOfVillagePerAxe
	yMaxVillage := float64( int( y*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe

	Info.Printf( "XYSpreadToLatLngOrig input village Min x %f Max x %f", xMinVillage, xMaxVillage)

	// parse all bodies and get closest body
	for index,b := range *country.bodiesSpread {
		if (xMinVillage <= b.X) && (b.X < xMaxVillage) && (yMinVillage <= b.Y) && (b.Y < yMaxVillage) {

			xRelClosest := (*country.bodiesOrig)[index].X
			yRelClosest := (*country.bodiesOrig)[index].Y
			latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

			points = append(points, convexhull.MakePoint(latOptimClosest, lngOptimClosest))
		}
	}

	return points
}

// given x, y of a point, return the border in the country
func (country * Country) VillageBorder( lat, lng float64) convexhull.PointList {

	Info.Printf( "")
	Info.Printf( "VillageBorder country %s input lat %f lng %f", country.Name, lat, lng)

	// from input lat, lng, get the xSpread, ySpread
	_, _, _, _, _, xSpread, ySpread, _ := country.VillageCoordinates(lat, lng)
	Info.Printf( "VillageBorder country %s input xSpread %f ySpread %f", country.Name, xSpread, ySpread)

	// compute village min & max coord
	numberOfVillagePerAxe := 10.0
	xMinVillage := float64( int( xSpread*numberOfVillagePerAxe))/numberOfVillagePerAxe
	xMaxVillage := float64( int( xSpread*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe
	yMinVillage := float64( int( ySpread*numberOfVillagePerAxe))/numberOfVillagePerAxe
	yMaxVillage := float64( int( ySpread*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe

	Info.Printf( "VillageBorder input village Min x %f Max x %f", xMinVillage, xMaxVillage)

	// parse all bodies and if bodies has x & y spead close to input spread, include them in point list
	points := make(convexhull.PointList, 0)
	for index,b := range *country.bodiesSpread {
		if (xMinVillage <= b.X) && (b.X < xMaxVillage) && (yMinVillage <= b.Y) && (b.Y < yMaxVillage) {

			xRelClosest := (*country.bodiesOrig)[index].X
			yRelClosest := (*country.bodiesOrig)[index].Y
			latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

			points = append(points, convexhull.MakePoint(latOptimClosest, lngOptimClosest))
		}
	}

	Info.Printf( "VillageBorder nb of border points %d", len(points))
	Info.Printf( "")

	return points
}
<commit_msg>facotring nb of village per axes for rendering<commit_after>package translation

import (
	"os"
	"log"
	"fmt"
	"math"
	// "bufio"
	"github.com/thomaspeugeot/tkv/barnes-hut"
	"github.com/thomaspeugeot/tkv/quadtree"
	"github.com/thomaspeugeot/tkv/grump"
	// "path/filepath"
	"encoding/json"

	convexhull "github.com/thomaspeugeot/go-convexhull/convexhull"
)

type Country struct {
	grump.Country

	NbBodies int // nb of bodies according to the filename

	bodiesOrig * []quadtree.Body // original bodies position in the quatree
	bodiesSpread * []quadtree.Body // bodies position in the quatree after the spread simulation
	VilCoordinates [][]int
	Step int // step when the simulation stopped

	villages [][]Village
}

type BodySetChoice string
const (
	ORIGINAL_CONFIGURATION = "ORIGINAL_CONFIGURATION"
	SPREAD_CONFIGURATION = "SPREAD_CONFIGURATION"
)

// number of village per X or Y axis. For 10 000 villages, this number is 100
// this value can be set interactively during the run
var nbVillagePerAxe int = 100
var numberOfVillagePerAxe float64 = 50.0

// init variables
func (country * Country) Init() {

	// unserialize from conf-<country trigram>.coord
	// store step because the unseralize set it to a wrong value
	step := country.Step
	country.Unserialize()
	country.Step = step

	Info.Printf("Init after Unserialize name %s", country.Name)
	Info.Printf("Init after Unserialize step %d", country.Step)

	country.LoadConfig( true ) // load config at the end  of the simulation
	country.LoadConfig( false ) // load config at the start of the simulation

	// init village array
	country.villages = make( [][]Village, nbVillagePerAxe )
	for x,_  := range country.villages {
		country.villages[x] = make([]Village, nbVillagePerAxe)
	}

	country.VilCoordinates = make( [][]int, country.NbBodies)
	for idx, _ := range country.VilCoordinates {
		country.VilCoordinates[idx] = make( []int, 2)
	}

	country.ComputeBaryCenters()

}

// load configuration from filename into counry
// check that it matches the
func (country * Country) LoadConfig( isOriginal bool) bool {

	Info.Printf( "Load Config begin : Country is %s, step %d", country.Name, country.Step)

	// computing the file name from the step
	step := 0

	// if isOrignal load the file with the step number 0, else use spread
	if ! isOriginal { step = country.Step }

	filename := fmt.Sprintf( barnes_hut.CountryBodiesNamePattern, country.Name, country.NbBodies, step)
	Info.Printf( "LoadConfig original %t file %s for country %s at step %d", isOriginal, filename, country.Name, step)

	file, err := os.Open(filename)
	if( err != nil) {
		log.Fatal(err)
		return false
	}

	jsonParser := json.NewDecoder(file)

	bodies := (make([]quadtree.Body, 0))
	if isOriginal {
		country.bodiesOrig = & bodies
		if err = jsonParser.Decode( country.bodiesOrig); err != nil {
			log.Fatal( fmt.Sprintf( "parsing config file %s", err.Error()))
		}
		Info.Printf( "nb item parsed in file for orig %d\n", len( *country.bodiesOrig))
	} else {
		country.bodiesSpread = & bodies
		if err = jsonParser.Decode( country.bodiesSpread); err != nil {
			log.Fatal( fmt.Sprintf( "parsing config file %s", err.Error()))
		}
		Info.Printf( "nb item parsed in file for spread %d\n", len( *country.bodiesSpread))
	}

	file.Close()

	Info.Printf( "Load Config end : Country is %s, step %d", country.Name, country.Step)

	return true
}

// compute villages barycenters
func (country * Country) ComputeBaryCenters() {
	Info.Printf("ComputeBaryCenters begins for country %s", country.Name)

	// parse bodiesSpread to compute bary centers
	// use bodiesOrig to compute bary centers
	for index,b := range *country.bodiesSpread {

		// compute village coordinate (from 0 to nbVillagePerAxe-1)
		villageX := int( math.Floor(float64( nbVillagePerAxe) * b.X))
		villageY := int( math.Floor(float64( nbVillagePerAxe) * b.Y))

		Trace.Printf("Adding body index %d to village %d %d", index, villageX, villageY)

		// add body (original) to the barycenter of the village
		bOrig := (*country.bodiesOrig)[index]
		country.villages[villageX][villageY].addBody( bOrig)

		country.VilCoordinates[index][0] = villageX
		country.VilCoordinates[index][1] = villageY
	}
}

func (country * Country) VillageCoordinates( lat, lng float64) (x, y, distance, latClosest, lngClosest, xSpread, ySpread float64, closestIndex int) {

	// compute relative coordinates within the square
	xRel, yRel := country.LatLng2XY( lat, lng)
	Info.Printf("VillageCoordinates lat %f,  lng %f", lat, lng)
	Info.Printf("VillageCoordinates Rel x %f, Rel y %f", xRel, yRel)

	// parse all bodies and get closest body
	closestIndex = -1
	minDistance := 1000000000.0 // we start from away
	for index,b := range *country.bodiesOrig {
		distanceX := b.X - xRel
		distanceY := b.Y - yRel
		distance := math.Sqrt( (distanceX*distanceX) + (distanceY*distanceY))

		if( distance < minDistance ) {
			closestIndex = index
			minDistance = distance
		}
	}
	Info.Printf("VillageCoordinates closestIndex %d, minDistance %f", closestIndex, minDistance)

	villageX := country.VilCoordinates[closestIndex][0]
	villageY := country.VilCoordinates[closestIndex][1]
	xRelClosest := (*country.bodiesOrig)[closestIndex].X
	yRelClosest := (*country.bodiesOrig)[closestIndex].Y

	latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

	Info.Printf( "VillageCoordinates %f %f relative to country %f %f", lat, lng, xRel, yRel)
	Info.Printf( "VillageCoordinates rel closest %f %f lat lng closest %f %f", xRelClosest, yRelClosest, latOptimClosest, lngOptimClosest)
	Info.Printf( "VillageCoordinates village %d %d", villageX, villageY)

	// compute x, y in spread bodies
	xSpread = (*country.bodiesSpread)[closestIndex].X
	ySpread = (*country.bodiesSpread)[closestIndex].Y

	Info.Printf( "VillageCoordinates village %f %f index %d", xSpread, ySpread, closestIndex)

	return xRelClosest, yRelClosest, minDistance, latOptimClosest, lngOptimClosest, xSpread, ySpread, closestIndex
}

func (country * Country) XYSpreadToLatLngOrig( x, y float64) (lat, lng float64) {

	Info.Printf( "XYSpreadToLatLngOrig input x %f y %f", x, y)

	// parse all bodies and get closest body
	closestIndex := -1
	minDistance := 1000000000.0 // we start from away
	for index,b := range *country.bodiesSpread {
		distanceX := b.X - x
		distanceY := b.Y - y
		distance := math.Sqrt( (distanceX*distanceX) + (distanceY*distanceY))

		if( distance < minDistance ) {
			closestIndex = index
			minDistance = distance
		}
	}

	xRelClosest := (*country.bodiesOrig)[closestIndex].X
	yRelClosest := (*country.bodiesOrig)[closestIndex].Y
	latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)
	Info.Printf("XYSpreadToLatLngOrig target x %f y %f index %d distance %f", xRelClosest, yRelClosest, closestIndex, minDistance)

	Info.Printf("XYSpreadToLatLngOrig target lat %f lng %f", latOptimClosest, lngOptimClosest)

	return latOptimClosest, lngOptimClosest
}

func (country * Country) XYSpreadToLatLngOrigVillage( x, y float64) convexhull.PointList {

	Info.Printf( "XYSpreadToLatLngOrig input x %f y %f", x, y)

	points := make(convexhull.PointList, 0)

	// compute village min & max coord
	xMinVillage := float64( int( x*numberOfVillagePerAxe))/numberOfVillagePerAxe
	xMaxVillage := float64( int( x*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe
	yMinVillage := float64( int( y*numberOfVillagePerAxe))/numberOfVillagePerAxe
	yMaxVillage := float64( int( y*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe

	Info.Printf( "XYSpreadToLatLngOrig input village Min x %f Max x %f", xMinVillage, xMaxVillage)

	// parse all bodies and get closest body
	for index,b := range *country.bodiesSpread {
		if (xMinVillage <= b.X) && (b.X < xMaxVillage) && (yMinVillage <= b.Y) && (b.Y < yMaxVillage) {

			xRelClosest := (*country.bodiesOrig)[index].X
			yRelClosest := (*country.bodiesOrig)[index].Y
			latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

			points = append(points, convexhull.MakePoint(latOptimClosest, lngOptimClosest))
		}
	}

	return points
}

// given x, y of a point, return the border in the country
func (country * Country) VillageBorder( lat, lng float64) convexhull.PointList {

	Info.Printf( "")
	Info.Printf( "VillageBorder country %s input lat %f lng %f", country.Name, lat, lng)

	// from input lat, lng, get the xSpread, ySpread
	_, _, _, _, _, xSpread, ySpread, _ := country.VillageCoordinates(lat, lng)
	Info.Printf( "VillageBorder country %s input xSpread %f ySpread %f", country.Name, xSpread, ySpread)

	// compute village min & max coord
	xMinVillage := float64( int( xSpread*numberOfVillagePerAxe))/numberOfVillagePerAxe
	xMaxVillage := float64( int( xSpread*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe
	yMinVillage := float64( int( ySpread*numberOfVillagePerAxe))/numberOfVillagePerAxe
	yMaxVillage := float64( int( ySpread*numberOfVillagePerAxe + 1.0))/numberOfVillagePerAxe

	Info.Printf( "VillageBorder input village Min x %f Max x %f", xMinVillage, xMaxVillage)

	// parse all bodies and if bodies has x & y spead close to input spread, include them in point list
	points := make(convexhull.PointList, 0)
	for index,b := range *country.bodiesSpread {
		if (xMinVillage <= b.X) && (b.X < xMaxVillage) && (yMinVillage <= b.Y) && (b.Y < yMaxVillage) {

			xRelClosest := (*country.bodiesOrig)[index].X
			yRelClosest := (*country.bodiesOrig)[index].Y
			latOptimClosest, lngOptimClosest := country.XY2LatLng( xRelClosest, yRelClosest)

			points = append(points, convexhull.MakePoint(latOptimClosest, lngOptimClosest))
		}
	}

	Info.Printf( "VillageBorder nb of border points %d", len(points))
	Info.Printf( "")

	return points
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/ryanbressler/CloudForest"
	"log"
	"math"
	"math/rand"
	"os"
	"runtime"
	"runtime/pprof"
)

func main() {
	fm := flag.String("train",
		"featurematrix.afm", "AFM formated feature matrix containing training data.")
	rf := flag.String("rfpred",
		"rface.sf", "File name to output predictor forest in sf format.")
	targetname := flag.String("target",
		"", "The row header of the target in the feature matrix.")
	imp := flag.String("importance",
		"", "File name to output importance.")
	costs := flag.String("cost",
		"", "For categorical targets, a json string to float map of the cost of falsely identifying each category.")

	var nCores int
	flag.IntVar(&nCores, "nCores", 1, "The number of cores to use.")

	var nSamples int
	flag.IntVar(&nSamples, "nSamples", 0, "The number of cases to sample (with replacement) for each tree grow. If <=0 set to total number of cases")

	var leafSize int
	flag.IntVar(&leafSize, "leafSize", 0, "The minimum number of cases on a leaf node. If <=0 will be inferred to 1 for classification 4 for regression.")

	var nTrees int
	flag.IntVar(&nTrees, "nTrees", 100, "Number of trees to grow in the predictor.")

	var mTry int
	flag.IntVar(&mTry, "mTry", 0, "Number of candidate features for each split. Inferred to ceil(swrt(nFeatures)) if <=0.")

	var nContrasts int
	flag.IntVar(&nContrasts, "nContrasts", 0, "The number of randomized artificial contrast features to include in the feature matrix.")

	var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

	var contrastAll bool
	flag.BoolVar(&contrastAll, "contrastall", false, "Include a shuffled artificial contrast copy of every feature.")

	var impute bool
	flag.BoolVar(&impute, "impute", false, "Impute missing values to feature mean/mode instead of filtering them out when splitting.")

	var splitmissing bool
	flag.BoolVar(&splitmissing, "splitmissing", false, "Split missing values onto a third branch at each node (experimental).")

	var l1 bool
	flag.BoolVar(&l1, "l1", false, "Use l1 norm regression (target must be numeric).")

	var entropy bool
	flag.BoolVar(&entropy, "entropy", false, "Use entropy minimizing classification (target must be categorical).")

	flag.Parse()

	fmt.Printf("nTrees : %v\n", nTrees)

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if nCores > 1 {
		runtime.GOMAXPROCS(nCores)
	}
	//Parse Data
	datafile, err := os.Open(*fm)
	if err != nil {
		log.Fatal(err)
	}

	data := CloudForest.ParseAFM(datafile)
	datafile.Close()

	//infer nSamples and mTry from data if they are 0
	if nSamples <= 0 {
		nSamples = len(data.Data[0].Missing)
	}
	fmt.Printf("nSamples : %v\n", nSamples)

	if mTry <= 0 {
		mTry = int(math.Ceil(math.Sqrt(float64(len(data.Data)))))
	}
	fmt.Printf("mTry : %v\n", mTry)

	if nContrasts > 0 {
		fmt.Printf("Adding %v Random Contrasts\n", nContrasts)
		data.AddContrasts(nContrasts)
	}
	if contrastAll {
		fmt.Printf("Adding Random Contrasts for All Features.\n")
		data.ContrastAll()
	}
	if impute {
		fmt.Println("Imputing missing values to feature mean/mode.")
		data.ImputeMissing()
	}

	//find the target feature
	targeti, ok := data.Map[*targetname]
	if !ok {
		log.Fatal("Target not found in data.")
	}

	targetf := data.Data[targeti]
	if leafSize <= 0 {
		if targetf.NCats() == 0 {
			//regression
			leafSize = 4
		} else {
			//classification
			leafSize = 1
		}
	}
	fmt.Printf("leafSize : %v\n", leafSize)

	//****** Set up Target for Alternative Impurity  if needed *******//
	var target CloudForest.Target

	switch {
	case l1:
		fmt.Println("Using l1 regression.")
		target = &CloudForest.L1Target{&targetf}
	case *costs != "":
		fmt.Println("Using cost weighted classification: ", *costs)
		costmap := make(map[string]float64)
		err := json.Unmarshal([]byte(*costs), &costmap)
		if err != nil {
			log.Fatal(err)
		}

		regTarg := CloudForest.NewRegretTarget(&targetf)
		regTarg.SetCosts(costmap)
		target = regTarg

	case entropy:
		fmt.Println("Using entropy minimizing classification.")
		target = &CloudForest.EntropyTarget{&targetf}

	default:
		target = &targetf
	}

	forestfile, err := os.Create(*rf)
	if err != nil {
		log.Fatal(err)
	}
	defer forestfile.Close()
	forestwriter := CloudForest.NewForestWriter(forestfile)
	//forestwriter.WriteForestHeader(*targetname, nTrees)

	//****************** Needed Collections and vars ******************//

	var imppnt *[]*CloudForest.RunningMean
	if *imp != "" {
		fmt.Println("Recording Importance Scores.")

		imppnt = CloudForest.NewRunningMeans(len(data.Data))
	}

	treechan := make(chan *CloudForest.Tree, 0)

	//****************** Good Stuff Stars Here ;) ******************//
	for core := 0; core < nCores; core++ {
		go func() {
			canidates := make([]int, 0, len(data.Data))
			for i := 0; i < len(data.Data); i++ {
				if i != targeti {
					canidates = append(canidates, i)
				}
			}
			tree := CloudForest.NewTree()
			tree.Target = targetf.Name
			cases := make([]int, 0, nSamples)
			allocs := CloudForest.NewBestSplitAllocs(nSamples, target)
			for i := 0; i < nTrees; i++ {
				//sample nCases case with replacement
				cases = cases[0:0]
				nCases := len(data.Data[0].Missing)
				for j := 0; j < nSamples; j++ {
					cases = append(cases, rand.Intn(nCases))
				}

				tree.Grow(data, target, cases, canidates, mTry, leafSize, splitmissing, imppnt, allocs)
				treechan <- tree
				tree = <-treechan
			}
		}()

	}

	for i := 0; i < nTrees; i++ {
		tree := <-treechan
		forestwriter.WriteTree(tree, i)
		if i < nTrees-1 {
			treechan <- tree
		}

	}

	if *imp != "" {
		impfile, err := os.Create(*imp)
		if err != nil {
			log.Fatal(err)
		}
		defer impfile.Close()
		for i, v := range *imppnt {
			mean, count := v.Read()
			fmt.Fprintf(impfile, "%v\t%v\t%v\n", data.Data[i].Name, mean, count)

		}
	}

}
<commit_msg>added support for blacklist<commit_after>package main

import (
	"encoding/csv"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/ryanbressler/CloudForest"
	"io"
	"log"
	"math"
	"math/rand"
	"os"
	"runtime"
	"runtime/pprof"
)

func main() {
	fm := flag.String("train",
		"featurematrix.afm", "AFM formated feature matrix containing training data.")
	rf := flag.String("rfpred",
		"rface.sf", "File name to output predictor forest in sf format.")
	targetname := flag.String("target",
		"", "The row header of the target in the feature matrix.")
	imp := flag.String("importance",
		"", "File name to output importance.")
	costs := flag.String("cost",
		"", "For categorical targets, a json string to float map of the cost of falsely identifying each category.")

	blacklist := flag.String("blacklist",
		"", "A list of feature id's to exclude from the set of predictors.")

	var nCores int
	flag.IntVar(&nCores, "nCores", 1, "The number of cores to use.")

	var nSamples int
	flag.IntVar(&nSamples, "nSamples", 0, "The number of cases to sample (with replacement) for each tree grow. If <=0 set to total number of cases")

	var leafSize int
	flag.IntVar(&leafSize, "leafSize", 0, "The minimum number of cases on a leaf node. If <=0 will be inferred to 1 for classification 4 for regression.")

	var nTrees int
	flag.IntVar(&nTrees, "nTrees", 100, "Number of trees to grow in the predictor.")

	var mTry int
	flag.IntVar(&mTry, "mTry", 0, "Number of candidate features for each split. Inferred to ceil(swrt(nFeatures)) if <=0.")

	var nContrasts int
	flag.IntVar(&nContrasts, "nContrasts", 0, "The number of randomized artificial contrast features to include in the feature matrix.")

	var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

	var contrastAll bool
	flag.BoolVar(&contrastAll, "contrastall", false, "Include a shuffled artificial contrast copy of every feature.")

	var impute bool
	flag.BoolVar(&impute, "impute", false, "Impute missing values to feature mean/mode instead of filtering them out when splitting.")

	var splitmissing bool
	flag.BoolVar(&splitmissing, "splitmissing", false, "Split missing values onto a third branch at each node (experimental).")

	var l1 bool
	flag.BoolVar(&l1, "l1", false, "Use l1 norm regression (target must be numeric).")

	var entropy bool
	flag.BoolVar(&entropy, "entropy", false, "Use entropy minimizing classification (target must be categorical).")

	flag.Parse()

	fmt.Printf("nTrees : %v\n", nTrees)

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if nCores > 1 {
		runtime.GOMAXPROCS(nCores)
	}
	//Parse Data
	datafile, err := os.Open(*fm)
	if err != nil {
		log.Fatal(err)
	}

	data := CloudForest.ParseAFM(datafile)
	datafile.Close()

	//infer nSamples and mTry from data if they are 0
	if nSamples <= 0 {
		nSamples = len(data.Data[0].Missing)
	}
	fmt.Printf("nSamples : %v\n", nSamples)

	if mTry <= 0 {
		mTry = int(math.Ceil(math.Sqrt(float64(len(data.Data)))))
	}
	fmt.Printf("mTry : %v\n", mTry)

	if nContrasts > 0 {
		fmt.Printf("Adding %v Random Contrasts\n", nContrasts)
		data.AddContrasts(nContrasts)
	}
	if contrastAll {
		fmt.Printf("Adding Random Contrasts for All Features.\n")
		data.ContrastAll()
	}

	blacklistis := make([]bool, len(data.Data))
	if *blacklist != "" {
		blackfile, err := os.Open(*blacklist)
		if err != nil {
			log.Fatal(err)
		}
		tsv := csv.NewReader(blackfile)
		tsv.Comma = '\t'
		for {
			id, err := tsv.Read()
			if err == io.EOF {
				break
			} else if err != nil {
				log.Fatal(err)
			}
			blacklistis[data.Map[id[0]]] = true
		}
		blackfile.Close()

	}

	if impute {
		fmt.Println("Imputing missing values to feature mean/mode.")
		data.ImputeMissing()
	}

	//find the target feature
	targeti, ok := data.Map[*targetname]
	if !ok {
		log.Fatal("Target not found in data.")
	}

	targetf := data.Data[targeti]
	if leafSize <= 0 {
		if targetf.NCats() == 0 {
			//regression
			leafSize = 4
		} else {
			//classification
			leafSize = 1
		}
	}
	fmt.Printf("leafSize : %v\n", leafSize)

	//****** Set up Target for Alternative Impurity  if needed *******//
	var target CloudForest.Target

	switch {
	case l1:
		fmt.Println("Using l1 regression.")
		target = &CloudForest.L1Target{&targetf}
	case *costs != "":
		fmt.Println("Using cost weighted classification: ", *costs)
		costmap := make(map[string]float64)
		err := json.Unmarshal([]byte(*costs), &costmap)
		if err != nil {
			log.Fatal(err)
		}

		regTarg := CloudForest.NewRegretTarget(&targetf)
		regTarg.SetCosts(costmap)
		target = regTarg

	case entropy:
		fmt.Println("Using entropy minimizing classification.")
		target = &CloudForest.EntropyTarget{&targetf}

	default:
		target = &targetf
	}

	forestfile, err := os.Create(*rf)
	if err != nil {
		log.Fatal(err)
	}
	defer forestfile.Close()
	forestwriter := CloudForest.NewForestWriter(forestfile)
	//forestwriter.WriteForestHeader(*targetname, nTrees)

	//****************** Needed Collections and vars ******************//

	var imppnt *[]*CloudForest.RunningMean
	if *imp != "" {
		fmt.Println("Recording Importance Scores.")

		imppnt = CloudForest.NewRunningMeans(len(data.Data))
	}

	treechan := make(chan *CloudForest.Tree, 0)

	//****************** Good Stuff Stars Here ;) ******************//
	for core := 0; core < nCores; core++ {
		go func() {
			canidates := make([]int, 0, len(data.Data))
			for i := 0; i < len(data.Data); i++ {
				if i != targeti && !blacklistis[i] {
					canidates = append(canidates, i)
				}
			}
			tree := CloudForest.NewTree()
			tree.Target = targetf.Name
			cases := make([]int, 0, nSamples)
			allocs := CloudForest.NewBestSplitAllocs(nSamples, target)
			for i := 0; i < nTrees; i++ {
				//sample nCases case with replacement
				cases = cases[0:0]
				nCases := len(data.Data[0].Missing)
				for j := 0; j < nSamples; j++ {
					cases = append(cases, rand.Intn(nCases))
				}

				tree.Grow(data, target, cases, canidates, mTry, leafSize, splitmissing, imppnt, allocs)
				treechan <- tree
				tree = <-treechan
			}
		}()

	}

	for i := 0; i < nTrees; i++ {
		tree := <-treechan
		forestwriter.WriteTree(tree, i)
		if i < nTrees-1 {
			treechan <- tree
		}

	}

	if *imp != "" {
		impfile, err := os.Create(*imp)
		if err != nil {
			log.Fatal(err)
		}
		defer impfile.Close()
		for i, v := range *imppnt {
			mean, count := v.Read()
			fmt.Fprintf(impfile, "%v\t%v\t%v\n", data.Data[i].Name, mean, count)

		}
	}

}
<|endoftext|>


<commit_before>package element

import (
	"bytes"
	"errors"
	"io"
	"reflect"
	"testing"
)

func TestElementWrite(t *testing.T) {
	t.Parallel()

	var want, got string
	var n int64
	var err error
	var el Element
	var buf bytes.Buffer
	var b []byte

	// Should be able to write element into an io.Writer.
	el = Element{
		Space: "namespace",
		Tag:   "foo",
		Attr: []Attr{
			{Space: "foo", Key: "bar", Value: "val"},
			{Key: "bar2", Value: "val2"},
		},
		Child: []Token{
			Element{
				Tag:   "foobar",
				Child: []Token{CharData{Data: "Random Data Whee"}},
			},
		},
	}
	want = `<namespace:foo foo:bar="val" bar2="val2">`
	want += `<foobar>Random Data Whee</foobar></namespace:foo>`
	n, err = el.WriteTo(&buf)
	if err != nil {
		t.Errorf("Unexpected Error: %s", err)
	}
	if len(want) != int(n) {
		t.Error("Incorrect number of bytes written to io.Writer.")
		t.Errorf("\nWant:%d\nGot :%d", len(want), got)
	}
	got = buf.String()
	if got != want {
		t.Error("Should be able to write element into an io.Writer.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should be able to write element into a slice of bytes.
	b = el.WriteBytes()
	got = string(b)
	if want != got {
		t.Error("Should be able to write element into a slice of bytes.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}
}

func TestElementWriterError(t *testing.T) {
	t.Parallel()

	var want, got error
	var writer io.Writer
	var el Element
	var n int64

	el = Element{Tag: "foo"}

	// Should return error from underlying io.Writer.
	want = errors.New("io.Writer error")
	writer = errWriter{err: want}
	n, got = el.WriteTo(writer)
	if n != 0 {
		t.Error("Incorrect number of bytes written to io.Writer.")
		t.Errorf("\nWant:%d\nGot :%d", 0, n)
	}

	if !reflect.DeepEqual(want, got) {
		t.Errorf("Should return error from underlying io.Writer.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
}

func TestElementText(t *testing.T) {
	t.Parallel()

	var want, got string
	var el Element

	// Should return empty text if there are no children.
	el = Element{Tag: "foo"}
	want = ""
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should return empty text if no children are CharData.
	el = Element{Tag: "foo", Child: []Token{Element{Tag: "bar"}}}
	want = ""
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should return text if first element is CharData.
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "barbaz"}}}
	want = "barbaz"
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}
}

func TestElementSetText(t *testing.T) {
	t.Parallel()

	var el, want, got Element

	// Should be able to set text on an element with children, with first child CharData.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}, Element{Tag: "bar"}}}
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "wrongdata"}, Element{Tag: "bar"}}}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with children, with first child CharData.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
	// Should be able to set text on an element with children.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}, Element{Tag: "bar"}}}
	el = Element{Tag: "foo", Child: []Token{Element{Tag: "bar"}}}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with children.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should be able to set text on an element with no children.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}}}
	el = Element{Tag: "foo"}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with no children.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

}

func TestElementSelectAttr(t *testing.T) {
	t.Parallel()

	var want, got Attr
	var el Element

	// Should be able to get Attr which exists on element.
	want = Attr{Key: "baz", Value: "quux"}
	el = Element{Tag: "foo", Attr: []Attr{want}}
	got = el.SelectAttr("baz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to get Attr which exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should get NoAttrExists when the attribute key does not exist on element.
	got = el.SelectAttr("doesn't exist")
	if got != NoAttrExists {
		t.Error("Should get NoAttrexists when the attribute key does not exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", NoAttrExists, got)
	}
}

func TestElementSelectAttrValue(t *testing.T) {
	t.Parallel()

	var want, got string
	var el Element

	// Should be able to get Attr value for Attr which exists on element.
	want = "quux"
	el = Element{Tag: "foo", Attr: []Attr{{Key: "baz", Value: "quux"}}}
	got = el.SelectAttrValue("baz", "wrong")
	if want != got {
		t.Error("Should be able to get Attr value for Attr which exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should get default value for Attr which doesn't exist on element.
	want = "default value wheee"
	got = el.SelectAttrValue("doesn't exist", want)
	if want != got {
		t.Error("Should get default value for Attr which doesn't exist on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
}

func TestElementChildElements(t *testing.T) {
	t.Parallel()

	var want, got []Element
	var el Element

	// Should return elements if the element has child elements.
	el = Element{Tag: "foo",
		Child: []Token{
			CharData{Data: "Random Data"},
			Element{Tag: "bar"},
			Element{Space: "namespace", Tag: "baz"},
		},
	}
	want = []Element{{Tag: "bar"}, {Space: "namespace", Tag: "baz"}}
	got = el.ChildElements()
	if !reflect.DeepEqual(want, got) {
		t.Error("Should return elements if the element has child elements.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should return no elements if the element has no child elements.
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "Random Data"}}}
	want = []Element{}
	got = el.ChildElements()
	if len(got) != len(want) {
		t.Error("Should return no elements if the element hasno child elements.")
		t.Errorf("\nWant:%d\nGot :%d", len(want), len(got))
	}
}

func TestSelectElement(t *testing.T) {
	t.Parallel()

	var el, want, got Element

	// Should return child element if the child element exists.
	el = Element{Tag: "foo", Child: []Token{
		Element{Tag: "bar"},
		Element{Space: "namespace", Tag: "bar"},
	}}
	want = Element{Tag: "bar"}
	got = el.SelectElement("bar")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should return child element if the child element exists.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should properly decompose tag string to retrieve child element.
	want = Element{Space: "namespace", Tag: "bar"}
	got = el.SelectElement("namespace:bar")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should propery decompose tag string to retrieve child element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should return NoElementExists if the child element doesn't exist.
	got = el.SelectElement("doesn't exist")
	if !reflect.DeepEqual(NoElementExists, got) {
		t.Error("Should return NoElementExists if the child element doesn't exist.")
		t.Errorf("\nWant:%+v\nGot :%+v", NoElementExists, got)
	}
}

func TestDecompose(t *testing.T) {
	t.Parallel()

	var space, key string

	// Should decompose non-namespaced tag into empty space with string as key.
	space, key = decompose("nonnamedspacedtagfoo")
	if space != "" {
		t.Error("Should decompose non-namspaced tag into empty space with string as key")
		t.Errorf("\nWant:%s\nGot :%s", "", space)
	}
	if key != "nonnamedspacedtagfoo" {
		t.Error("Should decompose non-namspaced tag into empty space with string as key")
		t.Errorf("\nWant:%s\nGot :%s", "nonnamespacedtagfoo", key)
	}

	// Should decompose namespaced tag into tag and key.
	space, key = decompose("namespaced:tagfoo")
	if space != "namespaced" {
		t.Error("Should decompose namespaced tag into tag and key")
		t.Errorf("\nWant:%s\nGot :%s", "namespaced", space)
	}
	if key != "tagfoo" {
		t.Error("Should decompose namespaced tag into tag and key")
		t.Errorf("\nWant:%s\nGot :%s", "tagfoo", key)
	}
}

type errWriter struct{ err error }

func (ew errWriter) Write(_ []byte) (int, error) { return 0, ew.err }
<commit_msg>Fixing broken tests and incorrect printf variable.<commit_after>package element

import (
	"bytes"
	"errors"
	"io"
	"reflect"
	"testing"
)

func TestElementWrite(t *testing.T) {
	t.Parallel()

	var want, got string
	var n int64
	var err error
	var el Element
	var buf bytes.Buffer
	var b []byte

	// Should be able to write element into an io.Writer.
	el = Element{
		Space: "namespace",
		Tag:   "foo",
		Attr: []Attr{
			{Space: "foo", Key: "bar", Value: "val"},
			{Key: "bar2", Value: "val2"},
		},
		Child: []Token{
			Element{
				Tag:   "foobar",
				Child: []Token{CharData{Data: "Random Data Whee"}},
			},
		},
	}
	want = `<namespace:foo foo:bar='val' bar2='val2'>`
	want += `<foobar>Random Data Whee</foobar></namespace:foo>`
	n, err = el.WriteTo(&buf)
	if err != nil {
		t.Errorf("Unexpected Error: %s", err)
	}
	if len(want) != int(n) {
		t.Error("Incorrect number of bytes written to io.Writer.")
		t.Errorf("\nWant:%d\nGot :%d", len(want), n)
	}
	got = buf.String()
	if got != want {
		t.Error("Should be able to write element into an io.Writer.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should be able to write element into a slice of bytes.
	b = el.WriteBytes()
	got = string(b)
	if want != got {
		t.Error("Should be able to write element into a slice of bytes.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}
}

func TestElementWriterError(t *testing.T) {
	t.Parallel()

	var want, got error
	var writer io.Writer
	var el Element
	var n int64

	el = Element{Tag: "foo"}

	// Should return error from underlying io.Writer.
	want = errors.New("io.Writer error")
	writer = errWriter{err: want}
	n, got = el.WriteTo(writer)
	if n != 0 {
		t.Error("Incorrect number of bytes written to io.Writer.")
		t.Errorf("\nWant:%d\nGot :%d", 0, n)
	}

	if !reflect.DeepEqual(want, got) {
		t.Errorf("Should return error from underlying io.Writer.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
}

func TestElementText(t *testing.T) {
	t.Parallel()

	var want, got string
	var el Element

	// Should return empty text if there are no children.
	el = Element{Tag: "foo"}
	want = ""
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should return empty text if no children are CharData.
	el = Element{Tag: "foo", Child: []Token{Element{Tag: "bar"}}}
	want = ""
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}

	// Should return text if first element is CharData.
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "barbaz"}}}
	want = "barbaz"
	got = el.Text()
	if want != got {
		t.Error("Should return empty text if there are no children.")
		t.Errorf("\nWant:%s\nGot :%s", want, got)
	}
}

func TestElementSetText(t *testing.T) {
	t.Parallel()

	var el, want, got Element

	// Should be able to set text on an element with children, with first child CharData.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}, Element{Tag: "bar"}}}
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "wrongdata"}, Element{Tag: "bar"}}}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with children, with first child CharData.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
	// Should be able to set text on an element with children.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}, Element{Tag: "bar"}}}
	el = Element{Tag: "foo", Child: []Token{Element{Tag: "bar"}}}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with children.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should be able to set text on an element with no children.
	want = Element{Tag: "foo", Child: []Token{CharData{Data: "foobarbaz"}}}
	el = Element{Tag: "foo"}
	got = el.SetText("foobarbaz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to set text on an element with no children.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

}

func TestElementSelectAttr(t *testing.T) {
	t.Parallel()

	var want, got Attr
	var el Element

	// Should be able to get Attr which exists on element.
	want = Attr{Key: "baz", Value: "quux"}
	el = Element{Tag: "foo", Attr: []Attr{want}}
	got = el.SelectAttr("baz")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should be able to get Attr which exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should get NoAttrExists when the attribute key does not exist on element.
	got = el.SelectAttr("doesn't exist")
	if got != NoAttrExists {
		t.Error("Should get NoAttrexists when the attribute key does not exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", NoAttrExists, got)
	}
}

func TestElementSelectAttrValue(t *testing.T) {
	t.Parallel()

	var want, got string
	var el Element

	// Should be able to get Attr value for Attr which exists on element.
	want = "quux"
	el = Element{Tag: "foo", Attr: []Attr{{Key: "baz", Value: "quux"}}}
	got = el.SelectAttrValue("baz", "wrong")
	if want != got {
		t.Error("Should be able to get Attr value for Attr which exists on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should get default value for Attr which doesn't exist on element.
	want = "default value wheee"
	got = el.SelectAttrValue("doesn't exist", want)
	if want != got {
		t.Error("Should get default value for Attr which doesn't exist on element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}
}

func TestElementChildElements(t *testing.T) {
	t.Parallel()

	var want, got []Element
	var el Element

	// Should return elements if the element has child elements.
	el = Element{Tag: "foo",
		Child: []Token{
			CharData{Data: "Random Data"},
			Element{Tag: "bar"},
			Element{Space: "namespace", Tag: "baz"},
		},
	}
	want = []Element{{Tag: "bar"}, {Space: "namespace", Tag: "baz"}}
	got = el.ChildElements()
	if !reflect.DeepEqual(want, got) {
		t.Error("Should return elements if the element has child elements.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should return no elements if the element has no child elements.
	el = Element{Tag: "foo", Child: []Token{CharData{Data: "Random Data"}}}
	want = []Element{}
	got = el.ChildElements()
	if len(got) != len(want) {
		t.Error("Should return no elements if the element hasno child elements.")
		t.Errorf("\nWant:%d\nGot :%d", len(want), len(got))
	}
}

func TestSelectElement(t *testing.T) {
	t.Parallel()

	var el, want, got Element

	// Should return child element if the child element exists.
	el = Element{Tag: "foo", Child: []Token{
		Element{Tag: "bar"},
		Element{Space: "namespace", Tag: "bar"},
	}}
	want = Element{Tag: "bar"}
	got = el.SelectElement("bar")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should return child element if the child element exists.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should properly decompose tag string to retrieve child element.
	want = Element{Space: "namespace", Tag: "bar"}
	got = el.SelectElement("namespace:bar")
	if !reflect.DeepEqual(want, got) {
		t.Error("Should propery decompose tag string to retrieve child element.")
		t.Errorf("\nWant:%+v\nGot :%+v", want, got)
	}

	// Should return NoElementExists if the child element doesn't exist.
	got = el.SelectElement("doesn't exist")
	if !reflect.DeepEqual(NoElementExists, got) {
		t.Error("Should return NoElementExists if the child element doesn't exist.")
		t.Errorf("\nWant:%+v\nGot :%+v", NoElementExists, got)
	}
}

func TestDecompose(t *testing.T) {
	t.Parallel()

	var space, key string

	// Should decompose non-namespaced tag into empty space with string as key.
	space, key = decompose("nonnamedspacedtagfoo")
	if space != "" {
		t.Error("Should decompose non-namspaced tag into empty space with string as key")
		t.Errorf("\nWant:%s\nGot :%s", "", space)
	}
	if key != "nonnamedspacedtagfoo" {
		t.Error("Should decompose non-namspaced tag into empty space with string as key")
		t.Errorf("\nWant:%s\nGot :%s", "nonnamespacedtagfoo", key)
	}

	// Should decompose namespaced tag into tag and key.
	space, key = decompose("namespaced:tagfoo")
	if space != "namespaced" {
		t.Error("Should decompose namespaced tag into tag and key")
		t.Errorf("\nWant:%s\nGot :%s", "namespaced", space)
	}
	if key != "tagfoo" {
		t.Error("Should decompose namespaced tag into tag and key")
		t.Errorf("\nWant:%s\nGot :%s", "tagfoo", key)
	}
}

type errWriter struct{ err error }

func (ew errWriter) Write(_ []byte) (int, error) { return 0, ew.err }
<|endoftext|>


<commit_before>package evaluation

import (
	"fmt"
	"math"
	"strings"

	"github.com/Zac-Garby/pluto/ast"
)

type args map[string]Object
type builtinFn func(args, *Context) Object

type Builtin struct {
	Pattern []string
	Fn      builtinFn
}

func NewBuiltin(ptn string, fn builtinFn, types map[string]Type) Builtin {
	pattern := strings.Split(ptn, " ")

	typedFn := func(args args, ctx *Context) Object {
		for key, t := range types {
			val := args[key]

			if !is(val, t) {
				return Err(
					ctx,
					"the $%s parameter of %s must be of type %s, not %s",
					"TypeError",
					key, ptn,
					t, val.Type(),
				)
			}
		}

		return fn(args, ctx)
	}

	return Builtin{
		Pattern: pattern,
		Fn:      typedFn,
	}
}

var empty = make(map[string]Type)

var builtins = []Builtin{}

func GetBuiltins() []Builtin {
	if len(builtins) == 0 {
		builtins = []Builtin{
			NewBuiltin("print $obj", printObj, empty),

			NewBuiltin("do $block", doBlock, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("do $block with $args", doBlockWithArgs, map[string]Type{
				"block": BLOCK,
				"args":  COLLECTION,
			}),

			NewBuiltin("do $block on $arg", doBlockOnArg, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("map $block over $collection", mapBlockOverCollection, map[string]Type{
				"block":      BLOCK,
				"collection": COLLECTION,
			}),

			NewBuiltin("format $format with $args", formatWithArgs, map[string]Type{
				"format": STRING,
				"args":   COLLECTION,
			}),

			NewBuiltin("$start to $end", startToEnd, map[string]Type{
				"start": NUMBER,
				"end":   NUMBER,
			}),

			NewBuiltin(
				"slice $collection from $start to $end",
				sliceCollectionFromStartToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
					"end":        NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection from $start",
				sliceCollectionFromStart,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection to $end",
				sliceCollectionToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"end":        NUMBER,
				},
			),

			NewBuiltin(
				"filter $collection by $predicate",
				filterCollectionByPredicate,
				map[string]Type{
					"collection": COLLECTION,
					"predicate":  BLOCK,
				},
			),

			NewBuiltin("round $number", roundNumber, map[string]Type{
				"number": NUMBER,
			}),

			NewBuiltin("floor $number", floorNumber, map[string]Type{
				"number": NUMBER,
			}),

			NewBuiltin("ceil $number", ceilNumber, map[string]Type{
				"number": NUMBER,
			}),
		}
	}

	return builtins
}

// print $obj
func printObj(args args, ctx *Context) Object {
	fmt.Println(args["obj"])

	return O_NULL
}

// format $format with $args
func formatWithArgs(args args, ctx *Context) Object {
	var (
		format  = args["format"].(*String)
		formats = args["args"].(Collection)
	)

	// if format = "Hello, {}!" and args = ["world"]
	// the result will be "Hello, world!"

	result := format.Value

	for _, f := range formats.Elements() {
		result = strings.Replace(result, "{}", f.String(), 1)
	}

	return &String{Value: result}
}

func evalBlock(block *Block, args []Object, ctx *Context) Object {
	if len(block.Params) != len(args) {
		return err(
			ctx,
			"wrong number of arguments applied to a block. expected %d, got %d", "TypeError",
			len(block.Params),
			len(args),
		)
	}

	apArgs := make(map[string]Object)

	for i, param := range block.Params {
		apArgs[param.(*ast.Identifier).Value] = args[i]
	}

	return eval(block.Body, ctx.EncloseWith(apArgs))
}

// do $block
func doBlock(args args, ctx *Context) Object {
	block := args["block"].(*Block)

	return evalBlock(block, []Object{}, ctx)
}

// do $block with $args
func doBlockWithArgs(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["args"].(Collection)
	)

	return evalBlock(block, col.Elements(), ctx)
}

// do $block on $arg
func doBlockOnArg(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		arg   = args["arg"]
	)

	return evalBlock(block, []Object{arg}, ctx)
}

// map $block over $collection
func mapBlockOverCollection(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["collection"].(Collection)
	)

	var result []Object

	for i, item := range col.Elements() {
		mapped := evalBlock(block, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(mapped) {
			return mapped
		}

		result = append(result, mapped)
	}

	return MakeCollection(col.Type(), result, ctx)
}

// $start to $end
func startToEnd(args args, ctx *Context) Object {
	var (
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		sVal = int(start.Value)
		eVal = int(end.Value)
	)

	if eVal < sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i >= eVal; i-- {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	} else if eVal > sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i < eVal+1; i++ {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	}

	return &Array{Value: []Object{start}}
}

// slice $collection from $start to $end
func sliceCollectionFromStartToEnd(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		elems = col.Elements()
		sVal  = int(start.Value)
		eVal  = int(end.Value)
	)

	if sVal >= eVal {
		return err(ctx, "$start must be less than $end", "OutOfBoundsError")
	}

	if sVal < 0 || eVal < 0 {
		return err(ctx, "neither $start nor $end can be less than 0", "OutOfBoundsError")
	}

	if eVal >= len(elems) {
		return err(ctx, "$end must be contained by $collection", "OutOfBoundsError")
	}

	return &Array{Value: elems[sVal:eVal]}
}

// slice $collection from $start
func sliceCollectionFromStart(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)

		elems = col.Elements()
		index = int(start.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$start is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[index:]}
}

// slice $collection to $end
func sliceCollectionToEnd(args args, ctx *Context) Object {
	var (
		col = args["collection"].(Collection)
		end = args["end"].(*Number)

		elems = col.Elements()
		index = int(end.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$end is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[:index]}
}

// filter $collection by $predicate
func filterCollectionByPredicate(args args, ctx *Context) Object {
	var (
		col  = args["collection"].(Collection)
		pred = args["predicate"].(*Block)

		filtered = []Object{}
	)

	for i, item := range col.Elements() {
		result := evalBlock(pred, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(result) {
			return result
		}

		if isTruthy(result) {
			filtered = append(filtered, item)
		}
	}

	return MakeCollection(col.Type(), filtered, ctx)
}

// round $number
func roundNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Floor(num + 0.5)}
}

// floor $number
func floorNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Floor(num)}
}

// ceil $number
func ceilNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Ceil(num)}
}
<commit_msg>Add map builtins<commit_after>package evaluation

import (
	"fmt"
	"math"
	"strings"

	"github.com/Zac-Garby/pluto/ast"
)

type args map[string]Object
type builtinFn func(args, *Context) Object

type Builtin struct {
	Pattern []string
	Fn      builtinFn
}

func NewBuiltin(ptn string, fn builtinFn, types map[string]Type) Builtin {
	pattern := strings.Split(ptn, " ")

	typedFn := func(args args, ctx *Context) Object {
		for key, t := range types {
			val := args[key]

			if !is(val, t) {
				return Err(
					ctx,
					"the $%s parameter of %s must be of type %s, not %s",
					"TypeError",
					key, ptn,
					t, val.Type(),
				)
			}
		}

		return fn(args, ctx)
	}

	return Builtin{
		Pattern: pattern,
		Fn:      typedFn,
	}
}

var empty = make(map[string]Type)

var builtins = []Builtin{}

func GetBuiltins() []Builtin {
	if len(builtins) == 0 {
		builtins = []Builtin{
			NewBuiltin("print $obj", printObj, empty),

			NewBuiltin("do $block", doBlock, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("do $block with $args", doBlockWithArgs, map[string]Type{
				"block": BLOCK,
				"args":  COLLECTION,
			}),

			NewBuiltin("do $block on $arg", doBlockOnArg, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("map $block over $collection", mapBlockOverCollection, map[string]Type{
				"block":      BLOCK,
				"collection": COLLECTION,
			}),

			NewBuiltin("format $format with $args", formatWithArgs, map[string]Type{
				"format": STRING,
				"args":   COLLECTION,
			}),

			NewBuiltin("$start to $end", startToEnd, map[string]Type{
				"start": NUMBER,
				"end":   NUMBER,
			}),

			NewBuiltin(
				"slice $collection from $start to $end",
				sliceCollectionFromStartToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
					"end":        NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection from $start",
				sliceCollectionFromStart,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection to $end",
				sliceCollectionToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"end":        NUMBER,
				},
			),

			NewBuiltin(
				"filter $collection by $predicate",
				filterCollectionByPredicate,
				map[string]Type{
					"collection": COLLECTION,
					"predicate":  BLOCK,
				},
			),

			NewBuiltin("round $number", roundNumber, map[string]Type{
				"number": NUMBER,
			}),

			NewBuiltin("floor $number", floorNumber, map[string]Type{
				"number": NUMBER,
			}),

			NewBuiltin("ceil $number", ceilNumber, map[string]Type{
				"number": NUMBER,
			}),

			NewBuiltin("keys of $map", keysOfMap, map[string]Type{
				"map": MAP,
			}),

			NewBuiltin("values of $map", valuesOfMap, map[string]Type{
				"map": MAP,
			}),

			NewBuiltin("pairs of $map", pairsOfMap, map[string]Type{
				"map": MAP,
			}),
		}
	}

	return builtins
}

// print $obj
func printObj(args args, ctx *Context) Object {
	fmt.Println(args["obj"])

	return O_NULL
}

// format $format with $args
func formatWithArgs(args args, ctx *Context) Object {
	var (
		format  = args["format"].(*String)
		formats = args["args"].(Collection)
	)

	// if format = "Hello, {}!" and args = ["world"]
	// the result will be "Hello, world!"

	result := format.Value

	for _, f := range formats.Elements() {
		result = strings.Replace(result, "{}", f.String(), 1)
	}

	return &String{Value: result}
}

func evalBlock(block *Block, args []Object, ctx *Context) Object {
	if len(block.Params) != len(args) {
		return err(
			ctx,
			"wrong number of arguments applied to a block. expected %d, got %d", "TypeError",
			len(block.Params),
			len(args),
		)
	}

	apArgs := make(map[string]Object)

	for i, param := range block.Params {
		apArgs[param.(*ast.Identifier).Value] = args[i]
	}

	return eval(block.Body, ctx.EncloseWith(apArgs))
}

// do $block
func doBlock(args args, ctx *Context) Object {
	block := args["block"].(*Block)

	return evalBlock(block, []Object{}, ctx)
}

// do $block with $args
func doBlockWithArgs(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["args"].(Collection)
	)

	return evalBlock(block, col.Elements(), ctx)
}

// do $block on $arg
func doBlockOnArg(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		arg   = args["arg"]
	)

	return evalBlock(block, []Object{arg}, ctx)
}

// map $block over $collection
func mapBlockOverCollection(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["collection"].(Collection)
	)

	var result []Object

	for i, item := range col.Elements() {
		mapped := evalBlock(block, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(mapped) {
			return mapped
		}

		result = append(result, mapped)
	}

	return MakeCollection(col.Type(), result, ctx)
}

// $start to $end
func startToEnd(args args, ctx *Context) Object {
	var (
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		sVal = int(start.Value)
		eVal = int(end.Value)
	)

	if eVal < sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i >= eVal; i-- {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	} else if eVal > sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i < eVal+1; i++ {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	}

	return &Array{Value: []Object{start}}
}

// slice $collection from $start to $end
func sliceCollectionFromStartToEnd(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		elems = col.Elements()
		sVal  = int(start.Value)
		eVal  = int(end.Value)
	)

	if sVal >= eVal {
		return err(ctx, "$start must be less than $end", "OutOfBoundsError")
	}

	if sVal < 0 || eVal < 0 {
		return err(ctx, "neither $start nor $end can be less than 0", "OutOfBoundsError")
	}

	if eVal >= len(elems) {
		return err(ctx, "$end must be contained by $collection", "OutOfBoundsError")
	}

	return &Array{Value: elems[sVal:eVal]}
}

// slice $collection from $start
func sliceCollectionFromStart(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)

		elems = col.Elements()
		index = int(start.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$start is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[index:]}
}

// slice $collection to $end
func sliceCollectionToEnd(args args, ctx *Context) Object {
	var (
		col = args["collection"].(Collection)
		end = args["end"].(*Number)

		elems = col.Elements()
		index = int(end.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$end is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[:index]}
}

// filter $collection by $predicate
func filterCollectionByPredicate(args args, ctx *Context) Object {
	var (
		col  = args["collection"].(Collection)
		pred = args["predicate"].(*Block)

		filtered = []Object{}
	)

	for i, item := range col.Elements() {
		result := evalBlock(pred, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(result) {
			return result
		}

		if isTruthy(result) {
			filtered = append(filtered, item)
		}
	}

	return MakeCollection(col.Type(), filtered, ctx)
}

// round $number
func roundNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Floor(num + 0.5)}
}

// floor $number
func floorNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Floor(num)}
}

// ceil $number
func ceilNumber(args args, ctx *Context) Object {
	num := args["number"].(*Number).Value

	return &Number{Value: math.Ceil(num)}
}

// keys of $map
func keysOfMap(args args, ctx *Context) Object {
	var (
		m    = args["map"].(*Map)
		keys = []Object{}
	)

	for _, k := range m.Keys {
		keys = append(keys, k)
	}

	return &Array{Value: keys}
}

// values of $map
func valuesOfMap(args args, ctx *Context) Object {
	var (
		m    = args["map"].(*Map)
		vals = []Object{}
	)

	for _, v := range m.Values {
		vals = append(vals, v)
	}

	return &Array{Value: vals}
}

// pairs of $map
func pairsOfMap(args args, ctx *Context) Object {
	var (
		m     = args["map"].(*Map)
		keys  = m.Keys
		vals  = m.Values
		pairs = []Object{}
	)

	for hash, key := range keys {
		val := vals[hash]

		pairs = append(pairs, &Tuple{Value: []Object{key, val}})
	}

	return &Array{Value: pairs}
}
<|endoftext|>


<commit_before>package contractor

import (
	"errors"
	"fmt"
	"strings"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/proto"
	"github.com/NebulousLabs/Sia/types"
)

var (
	// the contractor will not form contracts above this price
	maxStoragePrice = types.SiacoinPrecision.Mul64(500e3).Mul(modules.BlockBytesPerMonthTerabyte) // 500k SC / TB / Month
	// the contractor will not download data above this price (3x the maximum monthly storage price)
	maxDownloadPrice = maxStoragePrice.Mul64(3 * 4320)

	errInsufficientAllowance = errors.New("allowance is not large enough to perform contract creation")
	errTooExpensive          = errors.New("host price was too high")
)

// maxSectors is the estimated maximum number of sectors that the allowance
// can support.
func maxSectors(a modules.Allowance, hdb hostDB) (uint64, error) {
	if a.Hosts == 0 || a.Period == 0 {
		return 0, errors.New("invalid allowance")
	}

	// Sample at least 10 hosts.
	nRandomHosts := int(a.Hosts)
	if nRandomHosts < 10 {
		nRandomHosts = 10
	}
	hosts := hdb.RandomHosts(nRandomHosts, nil)
	if len(hosts) < int(a.Hosts) {
		return 0, errors.New("not enough hosts")
	}

	// Calculate cost of storing 1 sector per host for the allowance period.
	var sum types.Currency
	for _, h := range hosts {
		sum = sum.Add(h.StoragePrice)
	}
	averagePrice := sum.Div64(uint64(len(hosts)))
	costPerSector := averagePrice.Mul64(a.Hosts).Mul64(modules.SectorSize).Mul64(uint64(a.Period))

	// Divide total funds by cost per sector.
	numSectors, err := a.Funds.Div(costPerSector).Uint64()
	if err != nil {
		// if there was an overflow, something is definitely wrong
		return 0, errors.New("allowance can fund suspiciously large number of sectors")
	}
	return numSectors, nil
}

// managedNewContract negotiates an initial file contract with the specified
// host, saves it, and returns it.
func (c *Contractor) managedNewContract(host modules.HostDBEntry, numSectors uint64, endHeight types.BlockHeight) (modules.RenterContract, error) {
	// reject hosts that are too expensive
	if host.StoragePrice.Cmp(maxStoragePrice) > 0 {
		return modules.RenterContract{}, errTooExpensive
	}

	// get an address to use for negotiation
	uc, err := c.wallet.NextAddress()
	if err != nil {
		return modules.RenterContract{}, err
	}

	// create contract params
	c.mu.RLock()
	params := proto.ContractParams{
		Host:          host,
		Filesize:      numSectors * modules.SectorSize,
		StartHeight:   c.blockHeight,
		EndHeight:     endHeight,
		RefundAddress: uc.UnlockHash(),
	}
	c.mu.RUnlock()

	// create transaction builder
	txnBuilder := c.wallet.StartTransaction()

	contract, err := proto.FormContract(params, txnBuilder, c.tpool)
	if err != nil {
		txnBuilder.Drop()
		return modules.RenterContract{}, err
	}
	contractValue := contract.RenterFunds()

	c.mu.Lock()
	c.contracts[contract.ID] = contract
	c.financialMetrics.ContractSpending = c.financialMetrics.ContractSpending.Add(contractValue)
	c.saveSync()
	c.mu.Unlock()

	c.log.Printf("Formed contract with %v for %v SC", host.NetAddress, contractValue.Div(types.SiacoinPrecision))

	return contract, nil
}

// managedFormContracts forms contracts with n hosts using the allowance
// parameters.
func (c *Contractor) managedFormContracts(n int, a modules.Allowance) error {
	// Sample at least 10 hosts.
	nRandomHosts := 2 * n
	if nRandomHosts < 10 {
		nRandomHosts = 10
	}
	// Don't select from hosts we've already formed contracts with
	c.mu.RLock()
	var exclude []modules.NetAddress
	for _, contract := range c.contracts {
		exclude = append(exclude, contract.NetAddress)
	}
	c.mu.RUnlock()
	hosts := c.hdb.RandomHosts(nRandomHosts, exclude)
	if len(hosts) < n/2 { // TODO: /2 is temporary until more hosts are online
		return errors.New("not enough hosts")
	}

	// Check that allowance is sufficient to store at least one sector per
	// host for the specified duration.
	c.mu.RLock()
	endHeight := c.blockHeight + a.Period
	numSectors, err := maxSectors(a, c.hdb)
	c.mu.RUnlock()
	if err != nil {
		return err
	} else if numSectors == 0 {
		return errInsufficientAllowance
	}

	// Form contracts with each host.
	var numContracts int
	var errs []string
	for _, h := range hosts {
		_, err := c.managedNewContract(h, numSectors, endHeight)
		if err != nil {
			errs = append(errs, fmt.Sprintf("\t%v: %v", h.NetAddress, err))
			continue
		}
		if numContracts++; numContracts >= n {
			break
		}
	}
	// If we couldn't form any contracts, return an error. Otherwise, just log
	// the failures.
	// TODO: is there a better way to handle failure here? Should we prefer an
	// all-or-nothing approach? We can't pick new hosts to negotiate with
	// because they'll probably be more expensive than we can afford.
	if numContracts == 0 {
		return errors.New("could not form any contracts:\n" + strings.Join(errs, "\n"))
	} else if numContracts < n {
		c.log.Printf("WARN: failed to form desired number of contracts (wanted %v, got %v):\n%v", n, numContracts, strings.Join(errs, "\n"))
	}

	return nil
}
<commit_msg>move maxSectors outside lock<commit_after>package contractor

import (
	"errors"
	"fmt"
	"strings"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/proto"
	"github.com/NebulousLabs/Sia/types"
)

var (
	// the contractor will not form contracts above this price
	maxStoragePrice = types.SiacoinPrecision.Mul64(500e3).Mul(modules.BlockBytesPerMonthTerabyte) // 500k SC / TB / Month
	// the contractor will not download data above this price (3x the maximum monthly storage price)
	maxDownloadPrice = maxStoragePrice.Mul64(3 * 4320)

	errInsufficientAllowance = errors.New("allowance is not large enough to perform contract creation")
	errTooExpensive          = errors.New("host price was too high")
)

// maxSectors is the estimated maximum number of sectors that the allowance
// can support.
func maxSectors(a modules.Allowance, hdb hostDB) (uint64, error) {
	if a.Hosts == 0 || a.Period == 0 {
		return 0, errors.New("invalid allowance")
	}

	// Sample at least 10 hosts.
	nRandomHosts := int(a.Hosts)
	if nRandomHosts < 10 {
		nRandomHosts = 10
	}
	hosts := hdb.RandomHosts(nRandomHosts, nil)
	if len(hosts) < int(a.Hosts) {
		return 0, errors.New("not enough hosts")
	}

	// Calculate cost of storing 1 sector per host for the allowance period.
	var sum types.Currency
	for _, h := range hosts {
		sum = sum.Add(h.StoragePrice)
	}
	averagePrice := sum.Div64(uint64(len(hosts)))
	costPerSector := averagePrice.Mul64(a.Hosts).Mul64(modules.SectorSize).Mul64(uint64(a.Period))

	// Divide total funds by cost per sector.
	numSectors, err := a.Funds.Div(costPerSector).Uint64()
	if err != nil {
		// if there was an overflow, something is definitely wrong
		return 0, errors.New("allowance can fund suspiciously large number of sectors")
	}
	return numSectors, nil
}

// managedNewContract negotiates an initial file contract with the specified
// host, saves it, and returns it.
func (c *Contractor) managedNewContract(host modules.HostDBEntry, numSectors uint64, endHeight types.BlockHeight) (modules.RenterContract, error) {
	// reject hosts that are too expensive
	if host.StoragePrice.Cmp(maxStoragePrice) > 0 {
		return modules.RenterContract{}, errTooExpensive
	}

	// get an address to use for negotiation
	uc, err := c.wallet.NextAddress()
	if err != nil {
		return modules.RenterContract{}, err
	}

	// create contract params
	c.mu.RLock()
	params := proto.ContractParams{
		Host:          host,
		Filesize:      numSectors * modules.SectorSize,
		StartHeight:   c.blockHeight,
		EndHeight:     endHeight,
		RefundAddress: uc.UnlockHash(),
	}
	c.mu.RUnlock()

	// create transaction builder
	txnBuilder := c.wallet.StartTransaction()

	contract, err := proto.FormContract(params, txnBuilder, c.tpool)
	if err != nil {
		txnBuilder.Drop()
		return modules.RenterContract{}, err
	}
	contractValue := contract.RenterFunds()

	c.mu.Lock()
	c.contracts[contract.ID] = contract
	c.financialMetrics.ContractSpending = c.financialMetrics.ContractSpending.Add(contractValue)
	c.saveSync()
	c.mu.Unlock()

	c.log.Printf("Formed contract with %v for %v SC", host.NetAddress, contractValue.Div(types.SiacoinPrecision))

	return contract, nil
}

// managedFormContracts forms contracts with n hosts using the allowance
// parameters.
func (c *Contractor) managedFormContracts(n int, a modules.Allowance) error {
	// Sample at least 10 hosts.
	nRandomHosts := 2 * n
	if nRandomHosts < 10 {
		nRandomHosts = 10
	}
	// Don't select from hosts we've already formed contracts with
	c.mu.RLock()
	var exclude []modules.NetAddress
	for _, contract := range c.contracts {
		exclude = append(exclude, contract.NetAddress)
	}
	c.mu.RUnlock()
	hosts := c.hdb.RandomHosts(nRandomHosts, exclude)
	if len(hosts) < n/2 { // TODO: /2 is temporary until more hosts are online
		return errors.New("not enough hosts")
	}

	// Check that allowance is sufficient to store at least one sector per
	// host for the specified duration.
	numSectors, err := maxSectors(a, c.hdb)
	if err != nil {
		return err
	} else if numSectors == 0 {
		return errInsufficientAllowance
	}

	// Form contracts with each host.
	c.mu.RLock()
	endHeight := c.blockHeight + a.Period
	c.mu.RUnlock()
	var numContracts int
	var errs []string
	for _, h := range hosts {
		_, err := c.managedNewContract(h, numSectors, endHeight)
		if err != nil {
			errs = append(errs, fmt.Sprintf("\t%v: %v", h.NetAddress, err))
			continue
		}
		if numContracts++; numContracts >= n {
			break
		}
	}
	// If we couldn't form any contracts, return an error. Otherwise, just log
	// the failures.
	// TODO: is there a better way to handle failure here? Should we prefer an
	// all-or-nothing approach? We can't pick new hosts to negotiate with
	// because they'll probably be more expensive than we can afford.
	if numContracts == 0 {
		return errors.New("could not form any contracts:\n" + strings.Join(errs, "\n"))
	} else if numContracts < n {
		c.log.Printf("WARN: failed to form desired number of contracts (wanted %v, got %v):\n%v", n, numContracts, strings.Join(errs, "\n"))
	}

	return nil
}
<|endoftext|>