<commit_before>package pddl

import (
	"fmt"
	"io"
)

// A Domain represents a PDDL domain definition.
type Domain struct {
	// Name is the name of the domain.
	Name

	// Requirements is the requirement definitions.
	Requirements []Name

	// Types is the type definitions.
	Types []Type

	// Constants is the constant definitions.
	Constants []TypedEntry

	// Predicates is the predicate definitions.
	Predicates []Predicate

	// Functions is the function definitions.
	Functions []Function

	// Actions is the action definitions.
	Actions []Action
}

// A Problem represents a PDDL planning
// problem definition
type Problem struct {
	// Name is the problem name.
	Name

	// Domain is the name of the domain for
	// which this is a problem.
	Domain Name

	// Requirements is the requirement definitions.
	Requirements []Name

	// Objects is the object definitions.
	Objects []TypedEntry

	// Init is a conjunction of initial conditions
	// for the problem.
	Init []Formula

	// Goal is the problem goal formula.
	Goal Formula

	// Metric is the metric that must be optimized.
	Metric Metric
}

// A Metric represents planning metric that
// must be optimized.
type Metric int

const (
	// MetricMakespan asks the planner to
	// optimize the number of actions in
	// the plan.
	MetricMakespan Metric = iota

	// MetricMinCost asks the planner to
	// minimize the total-cost function.
	MetricMinCost
)

// A Name represents the name of an entity.
type Name struct {
	Str string
	Location
}

func (n Name) String() string {
	return n.Str
}

// A Type represents a type definition.
type Type struct {
	TypedEntry

	// Supers is all of the predecessor types,
	// including this current type.
	Supers []*Type

	// Domain is a pointer to the definition
	// of each object of this type.
	Domain []*TypedEntry
}

// A TypedEntry is the entry of a typed list.
type TypedEntry struct {
	// Name is the name of the entry.
	Name

	// Num is a number assigned to this
	// entry.  The number is unique within
	// the class of the entry: constants,
	// variables, function, etc.
	Num int

	// Types is the disjunctive set of types
	// for this entry.
	Types []TypeName
}

// A TypeName represents a name that is
// referring to a type.
type TypeName struct {
	// Name is the name of the type.
	Name

	// Definition is a pointer to the definition
	// of the type to which this name refers.
	Definition *Type
}

// An Action represents an action definition.
type Action struct {
	// Name is the name of the action.
	Name

	// Parameters is a typed list of the parameter
	// names for the action.
	Parameters []TypedEntry

	// Precondition is the action precondition
	// formula.
	Precondition Formula

	// Effect is the action effect formula.
	Effect Formula
}

// A Predicates represents a predicate definition.
type Predicate struct {
	// Name is the name of the predicate.
	Name

	// Num is a unique number assigned
	// the predicate.
	Num int

	// Parameters is a typed list of the predicate
	// parameters.
	Parameters []TypedEntry

	// PosEffect and NegEffect are true if the predicate
	// appears positively or negatively (respectively)
	// in an unconditional effect or as the consequent
	// of a conditional effect.
	PosEffect, NegEffect bool
}

// A Functions represents a function definition.
type Function struct {
	// Name is the name of the function.
	Name

	// Num is a unique number assigned to the
	// function.
	Num int

	// Types is a disjunctive list of the types
	// for the evaluation of this function.
	Types []TypeName

	// Parameters is a typed list of the function
	// parameters.
	Parameters []TypedEntry
}

// A Formula represents either a PDDL goal
// description (GD), or an expression.
type Formula interface {
	// print prints the formula as valid PDDL
	// to an io.Writed, prefixed with a string
	// for indentation purposes.
	print(io.Writer, string)

	// check panicks an error if there is a
	// semantic error in the formula.
	check(defs, *errors)
}

// A Node is a node in the formula tree.
type Node struct{ Location }

// A UnaryNode is a node with only a
// single successor.
type UnaryNode struct {
	Node
	Formula Formula
}

// A BinaryNode is a node with two successors.
type BinaryNode struct {
	Node
	Left, Right Formula
}

// A MultiNode is a node with a slice of successors.
type MultiNode struct {
	Node
	Formula []Formula
}

// A QuantNode is a node with a single successor
// that also declares a typed list of variables.
type QuantNode struct {
	Variables []TypedEntry
	UnaryNode
}

// A LiteralNode represents the instantiation of
// a predicate.
type LiteralNode struct {
	Node

	// Predicate is the name of the predicate.
	Predicate Name

	// Negative is true if this literal is negative,
	// or it is false if the predicate is positive.
	Negative bool

	// Arguments are the terms that are passed
	// as the arguments to this instantiation.
	Arguments []Term

	// IsEffect is true if the literal is appearing
	// in an unconditional effect or as a
	// consequent of a conditional effect.
	// This is used to determine inertia for
	// the literal's predicate.
	IsEffect bool

	// Definition is a pointer to the definition
	// of the predicate to which this literal refers.
	Definition *Predicate
}

// A Term represents either a constant or a variable.
type Term struct {
	// Name is the name of the term.
	Name

	// Variable is true if this term is referring
	// to a variable and it is false if this term
	// is referring to a constant.
	Variable bool

	// Definition points to the variable
	// or constant definition for this term.
	Definition *TypedEntry
}

// An AndNode represents a conjunction of its
// successors.
type AndNode struct{ MultiNode }

// An OrNode represents a disjunction of its
// successors.
type OrNode struct{ MultiNode }

// A NotNode represents the negation of its
// successor.
type NotNode struct{ UnaryNode }

// An ImplyNode represents an antecedent and
// its consequent.
type ImplyNode struct{ BinaryNode }

// A ForallNode represents a universal quantifier.
type ForallNode struct {
	QuantNode

	// IsEffect is true if the literal is appearing
	// in an unconditional effect or as a
	// consequent of a conditional effect.
	// This is used to distinguish between
	// the need to require :universal-preconditions
	// and :conditional-effects.
	IsEffect bool
}

// An ExistsNode represents an existential quantifier.
type ExistsNode struct{ QuantNode }

// A WhenNode represents a conditional effect.
type WhenNode struct {
	// Condition is the condition of the
	// conditional effect.
	Condition Formula

	// The Formula of the UnaryNode is the
	// consequent of the conditional effect.
	UnaryNode
}

var (
	// AssignOps is the set of valid assignment operators.
	AssignOps = map[string]bool{
		"=":        true,
		"assign":   true,
		"increase": true,
	}
)

// An AssignNode represents the assingment of a
// value to a function.
type AssignNode struct {
	Node

	// Op is the assignment operation.
	Op Name

	// Lval is the function to which a value is
	// being assigned.
	Lval Fhead

	// IsNumber is true if the right-hand-side
	// is a number, in which case the Number
	// field is valid and the Fhead field is not.
	// If IsNumber is false, then the opposite
	// is the case.
	IsNumber bool

	// Number is valid if IsNumber is true, in
	// which case it is a string representing
	// the number being assigned.
	Number string

	// Fhead is valid if IsNumber is false, in
	// which case it is the function instantiation
	// being assigned.
	Fhead Fhead

	// IsInit is true if the assignment is appearing
	// in the :init section of a problem.
	IsInit bool
}

// Fhead represents a function instantiation.
type Fhead struct {
	// Name is the name of the function.
	Name

	// Arguments is the slice of terms used as
	// the arguments to the function's parameters.
	Arguments []Term

	// Definition is a pointer to the definition
	// of the function to which this Fhead refers.
	Definition *Function
}

// Locer wraps the Loc method.
type Locer interface {
	Loc() Location
}

// A Location is a location in a PDDL input file.
type Location struct {
	// File is the file name.
	File string
	// Line is the line number.
	Line int
}

func (l Location) Loc() Location {
	return l
}

func (l Location) String() string {
	if l.Line < 0 {
		return l.File
	}
	return fmt.Sprintf("%s:%d", l.File, l.Line)
}

// An Error holds information about errors
// assocated with locations in a PDDL file.
type Error struct {
	// Location is the location of the cause of the error.
	Location

	// msg is the error's message.
	msg string
}

func (e Error) Error() string {
	return e.Location.String() + ": " + e.msg
}

// errorf panicks with an error at a location
// in a PDDL file with the message set  by a
// format string.
func errorf(l Locer, f string, vls ...interface{}) Error {
	panic(Error{l.Loc(), fmt.Sprintf(f, vls...)})
}
<commit_msg>Add comments to to exported functions.<commit_after>package pddl

import (
	"fmt"
	"io"
)

// A Domain represents a PDDL domain definition.
type Domain struct {
	// Name is the name of the domain.
	Name

	// Requirements is the requirement definitions.
	Requirements []Name

	// Types is the type definitions.
	Types []Type

	// Constants is the constant definitions.
	Constants []TypedEntry

	// Predicates is the predicate definitions.
	Predicates []Predicate

	// Functions is the function definitions.
	Functions []Function

	// Actions is the action definitions.
	Actions []Action
}

// A Problem represents a PDDL planning
// problem definition
type Problem struct {
	// Name is the problem name.
	Name

	// Domain is the name of the domain for
	// which this is a problem.
	Domain Name

	// Requirements is the requirement definitions.
	Requirements []Name

	// Objects is the object definitions.
	Objects []TypedEntry

	// Init is a conjunction of initial conditions
	// for the problem.
	Init []Formula

	// Goal is the problem goal formula.
	Goal Formula

	// Metric is the metric that must be optimized.
	Metric Metric
}

// A Metric represents planning metric that
// must be optimized.
type Metric int

const (
	// MetricMakespan asks the planner to
	// optimize the number of actions in
	// the plan.
	MetricMakespan Metric = iota

	// MetricMinCost asks the planner to
	// minimize the total-cost function.
	MetricMinCost
)

// A Name represents the name of an entity.
type Name struct {
	Str string
	Location
}

func (n Name) String() string {
	return n.Str
}

// A Type represents a type definition.
type Type struct {
	TypedEntry

	// Supers is all of the predecessor types,
	// including this current type.
	Supers []*Type

	// Domain is a pointer to the definition
	// of each object of this type.
	Domain []*TypedEntry
}

// A TypedEntry is the entry of a typed list.
type TypedEntry struct {
	// Name is the name of the entry.
	Name

	// Num is a number assigned to this
	// entry.  The number is unique within
	// the class of the entry: constants,
	// variables, function, etc.
	Num int

	// Types is the disjunctive set of types
	// for this entry.
	Types []TypeName
}

// A TypeName represents a name that is
// referring to a type.
type TypeName struct {
	// Name is the name of the type.
	Name

	// Definition is a pointer to the definition
	// of the type to which this name refers.
	Definition *Type
}

// An Action represents an action definition.
type Action struct {
	// Name is the name of the action.
	Name

	// Parameters is a typed list of the parameter
	// names for the action.
	Parameters []TypedEntry

	// Precondition is the action precondition
	// formula.
	Precondition Formula

	// Effect is the action effect formula.
	Effect Formula
}

// A Predicate represents a predicate definition.
type Predicate struct {
	// Name is the name of the predicate.
	Name

	// Num is a unique number assigned
	// the predicate.
	Num int

	// Parameters is a typed list of the predicate
	// parameters.
	Parameters []TypedEntry

	// PosEffect and NegEffect are true if the predicate
	// appears positively or negatively (respectively)
	// in an unconditional effect or as the consequent
	// of a conditional effect.
	PosEffect, NegEffect bool
}

// A Function represents a function definition.
type Function struct {
	// Name is the name of the function.
	Name

	// Num is a unique number assigned to the
	// function.
	Num int

	// Types is a disjunctive list of the types
	// for the evaluation of this function.
	Types []TypeName

	// Parameters is a typed list of the function
	// parameters.
	Parameters []TypedEntry
}

// A Formula represents either a PDDL goal
// description (GD), or an expression.
type Formula interface {
	// print prints the formula as valid PDDL
	// to an io.Writed, prefixed with a string
	// for indentation purposes.
	print(io.Writer, string)

	// check panicks an error if there is a
	// semantic error in the formula.
	check(defs, *errors)
}

// A Node is a node in the formula tree.
type Node struct{ Location }

// A UnaryNode is a node with only a
// single successor.
type UnaryNode struct {
	Node
	Formula Formula
}

// A BinaryNode is a node with two successors.
type BinaryNode struct {
	Node
	Left, Right Formula
}

// A MultiNode is a node with a slice of successors.
type MultiNode struct {
	Node
	Formula []Formula
}

// A QuantNode is a node with a single successor
// that also declares a typed list of variables.
type QuantNode struct {
	Variables []TypedEntry
	UnaryNode
}

// A LiteralNode represents the instantiation of
// a predicate.
type LiteralNode struct {
	Node

	// Predicate is the name of the predicate.
	Predicate Name

	// Negative is true if this literal is negative,
	// or it is false if the predicate is positive.
	Negative bool

	// Arguments are the terms that are passed
	// as the arguments to this instantiation.
	Arguments []Term

	// IsEffect is true if the literal is appearing
	// in an unconditional effect or as a
	// consequent of a conditional effect.
	// This is used to determine inertia for
	// the literal's predicate.
	IsEffect bool

	// Definition is a pointer to the definition
	// of the predicate to which this literal refers.
	Definition *Predicate
}

// A Term represents either a constant or a variable.
type Term struct {
	// Name is the name of the term.
	Name

	// Variable is true if this term is referring
	// to a variable and it is false if this term
	// is referring to a constant.
	Variable bool

	// Definition points to the variable
	// or constant definition for this term.
	Definition *TypedEntry
}

// An AndNode represents a conjunction of its
// successors.
type AndNode struct{ MultiNode }

// An OrNode represents a disjunction of its
// successors.
type OrNode struct{ MultiNode }

// A NotNode represents the negation of its
// successor.
type NotNode struct{ UnaryNode }

// An ImplyNode represents an antecedent and
// its consequent.
type ImplyNode struct{ BinaryNode }

// A ForallNode represents a universal quantifier.
type ForallNode struct {
	QuantNode

	// IsEffect is true if the literal is appearing
	// in an unconditional effect or as a
	// consequent of a conditional effect.
	// This is used to distinguish between
	// the need to require :universal-preconditions
	// and :conditional-effects.
	IsEffect bool
}

// An ExistsNode represents an existential quantifier.
type ExistsNode struct{ QuantNode }

// A WhenNode represents a conditional effect.
type WhenNode struct {
	// Condition is the condition of the
	// conditional effect.
	Condition Formula

	// The Formula of the UnaryNode is the
	// consequent of the conditional effect.
	UnaryNode
}

var (
	// AssignOps is the set of valid assignment operators.
	AssignOps = map[string]bool{
		"=":        true,
		"assign":   true,
		"increase": true,
	}
)

// An AssignNode represents the assingment of a
// value to a function.
type AssignNode struct {
	Node

	// Op is the assignment operation.
	Op Name

	// Lval is the function to which a value is
	// being assigned.
	Lval Fhead

	// IsNumber is true if the right-hand-side
	// is a number, in which case the Number
	// field is valid and the Fhead field is not.
	// If IsNumber is false, then the opposite
	// is the case.
	IsNumber bool

	// Number is valid if IsNumber is true, in
	// which case it is a string representing
	// the number being assigned.
	Number string

	// Fhead is valid if IsNumber is false, in
	// which case it is the function instantiation
	// being assigned.
	Fhead Fhead

	// IsInit is true if the assignment is appearing
	// in the :init section of a problem.
	IsInit bool
}

// Fhead represents a function instantiation.
type Fhead struct {
	// Name is the name of the function.
	Name

	// Arguments is the slice of terms used as
	// the arguments to the function's parameters.
	Arguments []Term

	// Definition is a pointer to the definition
	// of the function to which this Fhead refers.
	Definition *Function
}

// Locer wraps the Loc method.
type Locer interface {
	Loc() Location
}

// A Location is a location in a PDDL input file.
type Location struct {
	// File is the file name.
	File string
	// Line is the line number.
	Line int
}

// Loc returns the Location, implementing the Locer interface.
func (l Location) Loc() Location {
	return l
}

// String returns a human-readable string representation of the location.
func (l Location) String() string {
	if l.Line < 0 {
		return l.File
	}
	return fmt.Sprintf("%s:%d", l.File, l.Line)
}

// An Error holds information about errors
// assocated with locations in a PDDL file.
type Error struct {
	// Location is the location of the cause of the error.
	Location

	// msg is the error's message.
	msg string
}

func (e Error) Error() string {
	return e.Location.String() + ": " + e.msg
}

// errorf panicks with an error at a location
// in a PDDL file with the message set  by a
// format string.
func errorf(l Locer, f string, vls ...interface{}) Error {
	panic(Error{l.Loc(), fmt.Sprintf(f, vls...)})
}
<|endoftext|>


<commit_before>// Package ripe provides ASN and IP information
package ripe

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"sort"
	"strings"
	"sync"

	"github.com/mehrdadrad/mylg/data"
	"github.com/olekukonko/tablewriter"
)

const (
	// RIPEAPI holds RIPE API URL
	RIPEAPI = "https://stat.ripe.net"
	// RIPEPrefixURL holds RIPE prefix path
	RIPEPrefixURL = "/data/prefix-overview/data.json?max_related=50&resource="
	// RIPEASNURL holds RIPE ASN path
	RIPEASNURL = "/data/as-overview/data.json?resource=AS"
	// RIPEGeoURL holds Geo path
	RIPEGeoURL = "/data/geoloc/data.json?resource=AS"
)

// ASN represents ASN information
type ASN struct {
	Number  string
	Data    map[string]interface{}
	GeoData map[string]interface{}
}

// Prefix represents prefix information
type Prefix struct {
	Resource string
	Data     map[string]interface{}
}

// kv represents key/value(float64) in sort func
type kv struct {
	key   string
	value float64
}

// location represents location information
type location struct {
	City    string `json:"city"`
	Country string `json:"country"`
}

// Set sets the resource value
func (p *Prefix) Set(r string) {
	p.Resource = r
}

// GetData gets prefix information from RIPE NCC
func (p *Prefix) GetData() bool {
	if len(p.Resource) < 6 {
		println("error: prefix invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEPrefixURL + p.Resource)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		println("error: check your prefix")
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &p.Data)
	return true
}

// PrettyPrint print ASN information (holder)
func (p *Prefix) PrettyPrint() {
	data, ok := p.Data["data"].(map[string]interface{})
	if ok {
		println("prefix:", data["resource"].(string))
		asns := data["asns"].([]interface{})
		for _, h := range asns {
			println("holder:", h.(map[string]interface{})["holder"].(string))
		}
	}
}

// Set ASN
func (a *ASN) Set(r string) {
	a.Number = r
}

// GetData gets ASN information from RIPE NCC
func (a *ASN) GetData() bool {
	var (
		wg        sync.WaitGroup
		rOV, rGeo bool
	)

	wg.Add(1)
	go func() {
		defer wg.Done()
		rOV = a.GetOVData()
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		rGeo = a.GetGeoData()
	}()
	wg.Wait()
	return rOV || rGeo
}

// GetOVData gets ASN overview information from RIPE NCC
func (a *ASN) GetOVData() bool {
	if len(a.Number) < 2 {
		println("error: AS number invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEASNURL + a.Number)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.Data)
	return true
}

// GetGeoData gets Geo information from RIPE NCC
func (a *ASN) GetGeoData() bool {
	if len(a.Number) < 2 {
		println("error: AS number invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEGeoURL + a.Number)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		println("error: check your AS number")
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.GeoData)
	return true
}

// PrettyPrint print ASN information (holder)
func (a *ASN) PrettyPrint() {
	var cols = make(map[string]float64)
	overviewData, ok := a.Data["data"].(map[string]interface{})
	if ok {
		println(string(overviewData["holder"].(string)))
	}
	geoLocData, ok := a.GeoData["data"].(map[string]interface{})
	if !ok {
		return
	}
	locs := geoLocData["locations"].([]interface{})
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Location", "Covered %"})
	for _, loc := range locs {
		geoInfo := loc.(map[string]interface{})
		cols[geoInfo["country"].(string)] = geoInfo["covered_percentage"].(float64)
	}
	for _, v := range sortMapFloat(cols) {
		name := v.key
		percent := v.value
		uc := strings.Split(name, "-")
		if country, ok := data.Country[uc[0]]; ok {
			name = country
		}
		if len(uc) == 2 {
			name = fmt.Sprintf("%s - %s", name, uc[1])
		}
		table.Append([]string{name, fmt.Sprintf("%.4f", percent)})
	}
	table.Render()
}

// IsASN checks if the key is a number
func IsASN(key string) bool {
	m, err := regexp.MatchString(`^\d+$`, key)
	if err != nil {
		return false
	}
	return m
}

// sortMapFloat sorts map[string]float64 w/ value
func sortMapFloat(m map[string]float64) []kv {
	n := map[float64][]string{}
	var (
		a []float64
		r []kv
	)
	for k, v := range m {
		n[v] = append(n[v], k)
	}
	for k := range n {
		a = append(a, k)
	}
	sort.Sort(sort.Reverse(sort.Float64Slice(a)))
	for _, k := range a {
		for _, s := range n[k] {
			r = append(r, kv{s, k})
		}
	}
	return r
}
<commit_msg>added two funcs to evaluate ip v4 and v6<commit_after>// Package ripe provides ASN and IP information
package ripe

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"sort"
	"strings"
	"sync"

	"github.com/mehrdadrad/mylg/data"
	"github.com/olekukonko/tablewriter"
)

const (
	// RIPEAPI holds RIPE API URL
	RIPEAPI = "https://stat.ripe.net"
	// RIPEPrefixURL holds RIPE prefix path
	RIPEPrefixURL = "/data/prefix-overview/data.json?max_related=50&resource="
	// RIPEASNURL holds RIPE ASN path
	RIPEASNURL = "/data/as-overview/data.json?resource=AS"
	// RIPEGeoURL holds Geo path
	RIPEGeoURL = "/data/geoloc/data.json?resource=AS"
)

// ASN represents ASN information
type ASN struct {
	Number  string
	Data    map[string]interface{}
	GeoData map[string]interface{}
}

// Prefix represents prefix information
type Prefix struct {
	Resource string
	Data     map[string]interface{}
}

// kv represents key/value(float64) in sort func
type kv struct {
	key   string
	value float64
}

// location represents location information
type location struct {
	City    string `json:"city"`
	Country string `json:"country"`
}

// Set sets the resource value
func (p *Prefix) Set(r string) {
	p.Resource = r
}

// GetData gets prefix information from RIPE NCC
func (p *Prefix) GetData() bool {
	if len(p.Resource) < 6 {
		println("error: prefix invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEPrefixURL + p.Resource)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		println("error: check your prefix")
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &p.Data)
	return true
}

// PrettyPrint print ASN information (holder)
func (p *Prefix) PrettyPrint() {
	data, ok := p.Data["data"].(map[string]interface{})
	if ok {
		println("prefix:", data["resource"].(string))
		asns := data["asns"].([]interface{})
		for _, h := range asns {
			println("holder:", h.(map[string]interface{})["holder"].(string))
		}
	}
}

// Set ASN
func (a *ASN) Set(r string) {
	a.Number = r
}

// GetData gets ASN information from RIPE NCC
func (a *ASN) GetData() bool {
	var (
		wg        sync.WaitGroup
		rOV, rGeo bool
	)

	wg.Add(1)
	go func() {
		defer wg.Done()
		rOV = a.GetOVData()
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		rGeo = a.GetGeoData()
	}()
	wg.Wait()
	return rOV || rGeo
}

// GetOVData gets ASN overview information from RIPE NCC
func (a *ASN) GetOVData() bool {
	if len(a.Number) < 2 {
		println("error: AS number invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEASNURL + a.Number)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.Data)
	return true
}

// GetGeoData gets Geo information from RIPE NCC
func (a *ASN) GetGeoData() bool {
	if len(a.Number) < 2 {
		println("error: AS number invalid")
		return false
	}
	resp, err := http.Get(RIPEAPI + RIPEGeoURL + a.Number)
	if err != nil {
		println(err.Error())
		return false
	}
	if resp.StatusCode != 200 {
		println("error: check your AS number")
		return false
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.GeoData)
	return true
}

// PrettyPrint print ASN information (holder)
func (a *ASN) PrettyPrint() {
	var cols = make(map[string]float64)
	overviewData, ok := a.Data["data"].(map[string]interface{})
	if ok {
		println(string(overviewData["holder"].(string)))
	}
	geoLocData, ok := a.GeoData["data"].(map[string]interface{})
	if !ok {
		return
	}
	locs := geoLocData["locations"].([]interface{})
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Location", "Covered %"})
	for _, loc := range locs {
		geoInfo := loc.(map[string]interface{})
		cols[geoInfo["country"].(string)] = geoInfo["covered_percentage"].(float64)
	}
	for _, v := range sortMapFloat(cols) {
		name := v.key
		percent := v.value
		uc := strings.Split(name, "-")
		if country, ok := data.Country[uc[0]]; ok {
			name = country
		}
		if len(uc) == 2 {
			name = fmt.Sprintf("%s - %s", name, uc[1])
		}
		table.Append([]string{name, fmt.Sprintf("%.4f", percent)})
	}
	table.Render()
}

// IsASN checks if the key is a number
func IsASN(key string) bool {
	m, err := regexp.MatchString(`^\d+$`, key)
	if err != nil {
		return false
	}
	return m
}

// IsIP
func IsIP(key string) bool {
	var regex = map[string]string{
		"IPv4": `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`,
		"IPv6": `^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*`,
	}

	for _, rgx := range regex {
		m, _ := regexp.MatchString(rgx, key)
		if m {
			return m
		}
	}
	return false
}

// IsPrefix evaluates IPv(4/6) CIDR
func IsPrefix(key string) bool {
	var regex = map[string]string{
		"IPv4CIDR": `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$`,
		"IPv6CIDR": `^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(d|dd|1[0-1]d|12[0-8]))$`,
	}

	for _, rgx := range regex {
		m, _ := regexp.MatchString(rgx, key)
		if m {
			return m
		}
	}
	return false
}

// sortMapFloat sorts map[string]float64 w/ value
func sortMapFloat(m map[string]float64) []kv {
	n := map[float64][]string{}
	var (
		a []float64
		r []kv
	)
	for k, v := range m {
		n[v] = append(n[v], k)
	}
	for k := range n {
		a = append(a, k)
	}
	sort.Sort(sort.Reverse(sort.Float64Slice(a)))
	for _, k := range a {
		for _, s := range n[k] {
			r = append(r, kv{s, k})
		}
	}
	return r
}
<|endoftext|>


<commit_before>// csvsplit: Split a .csv file into multiple files.

package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
)

var records = flag.Int("r", 0, "The number of records per file")
var input = flag.String("i", "", "Filename of the input file to split")
var output = flag.String("o", "", "filename / path of the file output (optional)")

func main() {
	flag.Parse()
	if *input == "" || *records < 1 {
		flag.Usage()
		os.Exit(1)
	}

	csvFile, err := os.Open(*input)
	if err != nil {
		log.Fatal(err)
	}
	defer csvFile.Close()

	reader := csv.NewReader(csvFile)
	recordsToWrite := make([][]string, 0)
	fileCount := 1
	for {
		record, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		recordsToWrite = append(recordsToWrite, record)
		if len(recordsToWrite) == *records {
			saveCSVFile(recordsToWrite, fileCount)
			recordsToWrite = make([][]string, 0)
			fileCount += 1
		}
	}
	if len(recordsToWrite) > 0 {
		saveCSVFile(recordsToWrite, fileCount)
	}
}

func saveCSVFile(r [][]string, fileCount int) {
	fileName := fmt.Sprintf("%v%03d%v", *output, fileCount, ".csv")
	if _, err := os.Stat(fileName); os.IsNotExist(err) {
		f, err := os.Create(fileName)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		writer := csv.NewWriter(f)
		writer.WriteAll(r)
	} else {
		log.Fatal("File exists: ", fileName)
	}
}
<commit_msg>Remove new line<commit_after>// csvsplit: Split a .csv file into multiple files.
package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
)

var records = flag.Int("r", 0, "The number of records per file")
var input = flag.String("i", "", "Filename of the input file to split")
var output = flag.String("o", "", "filename / path of the file output (optional)")

func main() {
	flag.Parse()
	if *input == "" || *records < 1 {
		flag.Usage()
		os.Exit(1)
	}

	csvFile, err := os.Open(*input)
	if err != nil {
		log.Fatal(err)
	}
	defer csvFile.Close()

	reader := csv.NewReader(csvFile)
	recordsToWrite := make([][]string, 0)
	fileCount := 1
	for {
		record, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		recordsToWrite = append(recordsToWrite, record)
		if len(recordsToWrite) == *records {
			saveCSVFile(recordsToWrite, fileCount)
			recordsToWrite = make([][]string, 0)
			fileCount += 1
		}
	}
	if len(recordsToWrite) > 0 {
		saveCSVFile(recordsToWrite, fileCount)
	}
}

func saveCSVFile(r [][]string, fileCount int) {
	fileName := fmt.Sprintf("%v%03d%v", *output, fileCount, ".csv")
	if _, err := os.Stat(fileName); os.IsNotExist(err) {
		f, err := os.Create(fileName)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		writer := csv.NewWriter(f)
		writer.WriteAll(r)
	} else {
		log.Fatal("File exists: ", fileName)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package gce

import (
	"fmt"
	"strconv"
	"strings"

	"k8s.io/contrib/cluster-autoscaler/cloudprovider"
	kube_api "k8s.io/kubernetes/pkg/api"
)

// GceCloudProvider implements CloudProvider interface.
type GceCloudProvider struct {
	gceManager *GceManager
	migs       []*Mig
}

// BuildGceCloudProvider builds CloudProvider implementation for GCE.
func BuildGceCloudProvider(gceManager *GceManager, specs []string) (*GceCloudProvider, error) {
	gce := &GceCloudProvider{
		gceManager: gceManager,
		migs:       make([]*Mig, 0),
	}
	for _, spec := range specs {
		if err := gce.addNodeGroup(spec); err != nil {
			return nil, err
		}
	}
	return gce, nil
}

// addNodeGroup adds node group defined in string spec. Format:
// minNodes:maxNodes:migUrl
func (gce *GceCloudProvider) addNodeGroup(spec string) error {
	mig, err := buildMig(spec, gce.gceManager)
	if err != nil {
		return err
	}
	gce.migs = append(gce.migs, mig)
	gce.gceManager.RegisterMig(mig)
	return nil
}

// Name returns name of the cloud provider.
func (gce *GceCloudProvider) Name() string {
	return "gce"
}

// NodeGroups returns all node groups configured for this cloud provider.
func (gce *GceCloudProvider) NodeGroups() []cloudprovider.NodeGroup {
	result := make([]cloudprovider.NodeGroup, 0, len(gce.migs))
	for _, mig := range gce.migs {
		result = append(result, mig)
	}
	return result
}

// NodeGroupForNode returns the node group for the given node.
func (gce *GceCloudProvider) NodeGroupForNode(node *kube_api.Node) (cloudprovider.NodeGroup, error) {
	ref, err := GceRefFromProviderId(node.Spec.ProviderID)
	if err != nil {
		return nil, err
	}
	mig, err := gce.gceManager.GetMigForInstance(ref)
	return mig, err
}

// GceRef contains s reference to some entity in GCE/GKE world.
type GceRef struct {
	Project string
	Zone    string
	Name    string
}

// GceRefFromProviderId creates InstanceConfig object
// from provider id which must be in format:
// gce://<project-id>/<zone>/<name>
// TODO(piosz): add better check whether the id is correct
func GceRefFromProviderId(id string) (*GceRef, error) {
	splitted := strings.Split(id[6:], "/")
	if len(splitted) != 3 {
		return nil, fmt.Errorf("Wrong id: expected format gce://<project-id>/<zone>/<name>, got %v", id)
	}
	return &GceRef{
		Project: splitted[0],
		Zone:    splitted[1],
		Name:    splitted[2],
	}, nil
}

// Mig implements NodeGroup interfrace.
type Mig struct {
	GceRef

	gceManager *GceManager

	minSize int
	maxSize int
}

// MaxSize returns maximum size of the node group.
func (mig *Mig) MaxSize() int {
	return mig.maxSize
}

// MinSize returns minimum size of the node group.
func (mig *Mig) MinSize() int {
	return mig.minSize
}

// TargetSize returns the current TARGET size of the node group. It is possible that the
// number is different from the number of nodes registered in Kuberentes.
func (mig *Mig) TargetSize() (int, error) {
	size, err := mig.gceManager.GetMigSize(mig)
	return int(size), err
}

// IncreaseSize increases Mig size
func (mig *Mig) IncreaseSize(delta int) error {
	if delta <= 0 {
		return fmt.Errorf("size increase must be positive")
	}
	size, err := mig.gceManager.GetMigSize(mig)
	if err != nil {
		return err
	}
	if int(size)+delta > mig.MaxSize() {
		return fmt.Errorf("size increase too large - desired:%d max:%d", int(size)+delta, mig.MaxSize())
	}
	return mig.gceManager.SetMigSize(mig, size+int64(delta))
}

// Belongs returns true if the given node belongs to the NodeGroup.
func (mig *Mig) Belongs(node *kube_api.Node) (bool, error) {
	ref, err := GceRefFromProviderId(node.Spec.ProviderID)
	if err != nil {
		return false, err
	}
	targetMig, err := mig.gceManager.GetMigForInstance(ref)
	if err != nil {
		return false, err
	}
	if targetMig == nil {
		return false, fmt.Errorf("%s doesn't belong to a known mig", node.Name)
	}
	if targetMig.Id() != mig.Id() {
		return false, nil
	}
	return true, nil
}

// DeleteNodes deletes the nodes from the group.
func (mig *Mig) DeleteNodes(nodes []*kube_api.Node) error {
	size, err := mig.gceManager.GetMigSize(mig)
	if err != nil {
		return err
	}
	if int(size) <= mig.MinSize() {
		return fmt.Errorf("min size reached, nodes will not be deleted")
	}
	refs := make([]*GceRef, 0, len(nodes))
	for _, node := range nodes {

		belongs, err := mig.Belongs(node)
		if err != nil {
			return err
		}
		if belongs {
			return fmt.Errorf("%s belong to a different mig than %s", node.Name, mig.Id())
		}
		gceref, err := GceRefFromProviderId(node.Spec.ProviderID)
		if err != nil {
			return err
		}
		refs = append(refs, gceref)
	}
	return mig.gceManager.DeleteInstances(refs)
}

// Id returns mig url.
func (mig *Mig) Id() string {
	return GenerateMigUrl(mig.Project, mig.Zone, mig.Name)
}

// Debug returns a debug string for the Mig.
func (mig *Mig) Debug() string {
	return fmt.Sprintf("%s (%d:%d)", mig.Id(), mig.MinSize(), mig.MaxSize())
}

func buildMig(value string, gceManager *GceManager) (*Mig, error) {
	tokens := strings.SplitN(value, ":", 3)
	if len(tokens) != 3 {
		return nil, fmt.Errorf("wrong nodes configuration: %s", value)
	}

	mig := Mig{
		gceManager: gceManager,
	}
	if size, err := strconv.Atoi(tokens[0]); err == nil {
		if size <= 0 {
			return nil, fmt.Errorf("min size must be >= 1")
		}
		mig.minSize = size
	} else {
		return nil, fmt.Errorf("failed to set min size: %s, expected integer", tokens[0])
	}

	if size, err := strconv.Atoi(tokens[1]); err == nil {
		if size < mig.minSize {
			return nil, fmt.Errorf("max size must be greater or equal to min size")
		}
		mig.maxSize = size
	} else {
		return nil, fmt.Errorf("failed to set max size: %s, expected integer", tokens[1])
	}

	var err error
	if mig.Project, mig.Zone, mig.Name, err = ParseMigUrl(tokens[2]); err != nil {
		return nil, fmt.Errorf("failed to parse mig url: %s got error: %v", tokens[2], err)
	}
	return &mig, nil
}
<commit_msg>Cluster-autoscaler: fix belongs check in gce cloud provider<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package gce

import (
	"fmt"
	"strconv"
	"strings"

	"k8s.io/contrib/cluster-autoscaler/cloudprovider"
	kube_api "k8s.io/kubernetes/pkg/api"
)

// GceCloudProvider implements CloudProvider interface.
type GceCloudProvider struct {
	gceManager *GceManager
	migs       []*Mig
}

// BuildGceCloudProvider builds CloudProvider implementation for GCE.
func BuildGceCloudProvider(gceManager *GceManager, specs []string) (*GceCloudProvider, error) {
	gce := &GceCloudProvider{
		gceManager: gceManager,
		migs:       make([]*Mig, 0),
	}
	for _, spec := range specs {
		if err := gce.addNodeGroup(spec); err != nil {
			return nil, err
		}
	}
	return gce, nil
}

// addNodeGroup adds node group defined in string spec. Format:
// minNodes:maxNodes:migUrl
func (gce *GceCloudProvider) addNodeGroup(spec string) error {
	mig, err := buildMig(spec, gce.gceManager)
	if err != nil {
		return err
	}
	gce.migs = append(gce.migs, mig)
	gce.gceManager.RegisterMig(mig)
	return nil
}

// Name returns name of the cloud provider.
func (gce *GceCloudProvider) Name() string {
	return "gce"
}

// NodeGroups returns all node groups configured for this cloud provider.
func (gce *GceCloudProvider) NodeGroups() []cloudprovider.NodeGroup {
	result := make([]cloudprovider.NodeGroup, 0, len(gce.migs))
	for _, mig := range gce.migs {
		result = append(result, mig)
	}
	return result
}

// NodeGroupForNode returns the node group for the given node.
func (gce *GceCloudProvider) NodeGroupForNode(node *kube_api.Node) (cloudprovider.NodeGroup, error) {
	ref, err := GceRefFromProviderId(node.Spec.ProviderID)
	if err != nil {
		return nil, err
	}
	mig, err := gce.gceManager.GetMigForInstance(ref)
	return mig, err
}

// GceRef contains s reference to some entity in GCE/GKE world.
type GceRef struct {
	Project string
	Zone    string
	Name    string
}

// GceRefFromProviderId creates InstanceConfig object
// from provider id which must be in format:
// gce://<project-id>/<zone>/<name>
// TODO(piosz): add better check whether the id is correct
func GceRefFromProviderId(id string) (*GceRef, error) {
	splitted := strings.Split(id[6:], "/")
	if len(splitted) != 3 {
		return nil, fmt.Errorf("Wrong id: expected format gce://<project-id>/<zone>/<name>, got %v", id)
	}
	return &GceRef{
		Project: splitted[0],
		Zone:    splitted[1],
		Name:    splitted[2],
	}, nil
}

// Mig implements NodeGroup interfrace.
type Mig struct {
	GceRef

	gceManager *GceManager

	minSize int
	maxSize int
}

// MaxSize returns maximum size of the node group.
func (mig *Mig) MaxSize() int {
	return mig.maxSize
}

// MinSize returns minimum size of the node group.
func (mig *Mig) MinSize() int {
	return mig.minSize
}

// TargetSize returns the current TARGET size of the node group. It is possible that the
// number is different from the number of nodes registered in Kuberentes.
func (mig *Mig) TargetSize() (int, error) {
	size, err := mig.gceManager.GetMigSize(mig)
	return int(size), err
}

// IncreaseSize increases Mig size
func (mig *Mig) IncreaseSize(delta int) error {
	if delta <= 0 {
		return fmt.Errorf("size increase must be positive")
	}
	size, err := mig.gceManager.GetMigSize(mig)
	if err != nil {
		return err
	}
	if int(size)+delta > mig.MaxSize() {
		return fmt.Errorf("size increase too large - desired:%d max:%d", int(size)+delta, mig.MaxSize())
	}
	return mig.gceManager.SetMigSize(mig, size+int64(delta))
}

// Belongs returns true if the given node belongs to the NodeGroup.
func (mig *Mig) Belongs(node *kube_api.Node) (bool, error) {
	ref, err := GceRefFromProviderId(node.Spec.ProviderID)
	if err != nil {
		return false, err
	}
	targetMig, err := mig.gceManager.GetMigForInstance(ref)
	if err != nil {
		return false, err
	}
	if targetMig == nil {
		return false, fmt.Errorf("%s doesn't belong to a known mig", node.Name)
	}
	if targetMig.Id() != mig.Id() {
		return false, nil
	}
	return true, nil
}

// DeleteNodes deletes the nodes from the group.
func (mig *Mig) DeleteNodes(nodes []*kube_api.Node) error {
	size, err := mig.gceManager.GetMigSize(mig)
	if err != nil {
		return err
	}
	if int(size) <= mig.MinSize() {
		return fmt.Errorf("min size reached, nodes will not be deleted")
	}
	refs := make([]*GceRef, 0, len(nodes))
	for _, node := range nodes {

		belongs, err := mig.Belongs(node)
		if err != nil {
			return err
		}
		if !belongs {
			return fmt.Errorf("%s belong to a different mig than %s", node.Name, mig.Id())
		}
		gceref, err := GceRefFromProviderId(node.Spec.ProviderID)
		if err != nil {
			return err
		}
		refs = append(refs, gceref)
	}
	return mig.gceManager.DeleteInstances(refs)
}

// Id returns mig url.
func (mig *Mig) Id() string {
	return GenerateMigUrl(mig.Project, mig.Zone, mig.Name)
}

// Debug returns a debug string for the Mig.
func (mig *Mig) Debug() string {
	return fmt.Sprintf("%s (%d:%d)", mig.Id(), mig.MinSize(), mig.MaxSize())
}

func buildMig(value string, gceManager *GceManager) (*Mig, error) {
	tokens := strings.SplitN(value, ":", 3)
	if len(tokens) != 3 {
		return nil, fmt.Errorf("wrong nodes configuration: %s", value)
	}

	mig := Mig{
		gceManager: gceManager,
	}
	if size, err := strconv.Atoi(tokens[0]); err == nil {
		if size <= 0 {
			return nil, fmt.Errorf("min size must be >= 1")
		}
		mig.minSize = size
	} else {
		return nil, fmt.Errorf("failed to set min size: %s, expected integer", tokens[0])
	}

	if size, err := strconv.Atoi(tokens[1]); err == nil {
		if size < mig.minSize {
			return nil, fmt.Errorf("max size must be greater or equal to min size")
		}
		mig.maxSize = size
	} else {
		return nil, fmt.Errorf("failed to set max size: %s, expected integer", tokens[1])
	}

	var err error
	if mig.Project, mig.Zone, mig.Name, err = ParseMigUrl(tokens[2]); err != nil {
		return nil, fmt.Errorf("failed to parse mig url: %s got error: %v", tokens[2], err)
	}
	return &mig, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/dougEfresh/gtoggl"
	"os"
	"strconv"
	"github.com/dougEfresh/gtoggl/gworkspace"
	"github.com/dougEfresh/gtoggl/gclient"
)

type debugger struct {
	debug bool
}

func (l *debugger) Printf(format string, v ...interface{}) {
	if l.debug {
		fmt.Printf(format, v)
	}
}

func main() {
	var debug = flag.Bool("d", false, "Debug")
	var token = flag.String("t", "", "Toggl API token: https://www.toggl.com/app/profile")
	var command = flag.String("c", "workspace", "Sub command: workspace,client,project...etc ")
	flag.Parse()
	tc, err := gtoggl.NewClient(*token, gtoggl.SetTraceLogger(&debugger{debug: *debug}))
	if err != nil {
		fmt.Fprint(os.Stderr, "A token is required\n")
		flag.Usage()
		os.Exit(-1)
	}
	if *command == "workspace" {
		workspace(tc, flag.Args())
	}
	if *command == "client" {
		client(tc, flag.Args())
	}
}

func handleError(error error) {
	if error != nil {
		fmt.Fprintln(os.Stderr, error)
		os.Exit(-1)
	}
}

func client(tc *gtoggl.TogglHttpClient, args []string) {
<<<<<<< HEAD
	c, err := gclient.NewClient(tc)
	var client gclient.Client
=======
	c, err := gtoggl.NewTogglClient(tc)
	var client gtoggl.Client
>>>>>>> 19cdf27c36611089fd53d2e6a4ce82c1bcc3f613
	handleError(err)
	if len(args) == 0 || args[0] == "list" {
		clients, err := c.List()
		handleError(err)
		fmt.Printf("%+v\n", clients)
	}

	if args[0] == "create" && len(args) > 1 {
		err = json.Unmarshal([]byte(args[1]), &client)
		handleError(err)
		client, err = c.Create(&client)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "update" && len(args) > 1 {
		err = json.Unmarshal([]byte(args[1]), &client)
		handleError(err)
		_, err = c.Get(client.Id)
		handleError(err)
		client, err = c.Update(&client)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "get" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		client, err = c.Get(i)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "delete" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		err = c.Delete(i)
		handleError(err)
		fmt.Printf("%+v  deleted\n", i)
	}

}

func workspace(tc *gtoggl.TogglHttpClient, args []string) {
<<<<<<< HEAD
	wsc, err := gworkspace.NewClient(tc)
=======
	wsc, err := gworkspace.NewWorkspaceClient(tc)
>>>>>>> 19cdf27c36611089fd53d2e6a4ce82c1bcc3f613
	handleError(err)
	if len(args) == 0 || args[0] == "list" {
		w, err := wsc.List()
		handleError(err)
		fmt.Printf("%+v\n", w)
		return
	}

	if args[0] == "get" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		w, err := wsc.Get(i)
		fmt.Printf("%+v\n", w)
		return
	}

	if args[0] == "update" && len(args) > 1 {
		var uWs gworkspace.Workspace
		handleError(err)
		err = json.Unmarshal([]byte(args[1]), &uWs)
		handleError(err)
		_, err := wsc.Get(uWs.Id)
		handleError(err)
		uWs, err = wsc.Update(uWs)
		handleError(err)
		fmt.Printf("%+v\n", uWs)
		return
	}
}
<commit_msg>Fixing merge conflict<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/dougEfresh/gtoggl"
	"os"
	"strconv"
	"github.com/dougEfresh/gtoggl/gworkspace"
	"github.com/dougEfresh/gtoggl/gclient"
)

type debugger struct {
	debug bool
}

func (l *debugger) Printf(format string, v ...interface{}) {
	if l.debug {
		fmt.Printf(format, v)
	}
}

func main() {
	var debug = flag.Bool("d", false, "Debug")
	var token = flag.String("t", "", "Toggl API token: https://www.toggl.com/app/profile")
	var command = flag.String("c", "workspace", "Sub command: workspace,client,project...etc ")
	flag.Parse()
	tc, err := gtoggl.NewClient(*token, gtoggl.SetTraceLogger(&debugger{debug: *debug}))
	if err != nil {
		fmt.Fprint(os.Stderr, "A token is required\n")
		flag.Usage()
		os.Exit(-1)
	}
	if *command == "workspace" {
		workspace(tc, flag.Args())
	}
	if *command == "client" {
		client(tc, flag.Args())
	}
}

func handleError(error error) {
	if error != nil {
		fmt.Fprintln(os.Stderr, error)
		os.Exit(-1)
	}
}

func client(tc *gtoggl.TogglHttpClient, args []string) {
	c, err := gclient.NewClient(tc)
	var client gclient.Client
	handleError(err)
	if len(args) == 0 || args[0] == "list" {
		clients, err := c.List()
		handleError(err)
		fmt.Printf("%+v\n", clients)
	}

	if args[0] == "create" && len(args) > 1 {
		err = json.Unmarshal([]byte(args[1]), &client)
		handleError(err)
		client, err = c.Create(&client)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "update" && len(args) > 1 {
		err = json.Unmarshal([]byte(args[1]), &client)
		handleError(err)
		_, err = c.Get(client.Id)
		handleError(err)
		client, err = c.Update(&client)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "get" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		client, err = c.Get(i)
		handleError(err)
		fmt.Printf("%+v\n", client)
	}

	if args[0] == "delete" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		err = c.Delete(i)
		handleError(err)
		fmt.Printf("%+v  deleted\n", i)
	}

}

func workspace(tc *gtoggl.TogglHttpClient, args []string) {
	wsc, err := gworkspace.NewClient(tc)
	handleError(err)
	if len(args) == 0 || args[0] == "list" {
		w, err := wsc.List()
		handleError(err)
		fmt.Printf("%+v\n", w)
		return
	}

	if args[0] == "get" && len(args) > 1 {
		i, err := strconv.ParseUint(args[1], 0, 64)
		handleError(err)
		w, err := wsc.Get(i)
		fmt.Printf("%+v\n", w)
		return
	}

	if args[0] == "update" && len(args) > 1 {
		var uWs gworkspace.Workspace
		handleError(err)
		err = json.Unmarshal([]byte(args[1]), &uWs)
		handleError(err)
		_, err := wsc.Get(uWs.Id)
		handleError(err)
		uWs, err = wsc.Update(uWs)
		handleError(err)
		fmt.Printf("%+v\n", uWs)
		return
	}
}
<|endoftext|>


<commit_before>// Roll is an example CLI die app that rolls a die n times where n is a number
// passed to the application as an arg.  By default roll uses a 6 sided die.
// This can be changed using the -sides flag.
package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/mohae/dice"
)

var (
	sides = flag.Int("sides", 6, "number of sides for the die")
)

// Usage is a replacement usage function for the flags package.
func Usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "  rolldice [-sides] n\n")
	fmt.Fprintf(os.Stderr, "\twhere n is the number of times you want to roll the die\n")
	fmt.Fprintf(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = Usage
	flag.Parse()
	args := flag.Args()
	var rolls int
	var err error
	if len(args) > 0 {
		rolls, err = strconv.Atoi(args[0])
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not convert %s to an int: %s", args[0], err)
			os.Exit(1)
		}
	}
	// rolls must be > 0
	if rolls == 0 {
		rolls = 1
	}
	d := dice.New(*sides)
	for i := 0; i < rolls; i++ {
		v, err := d.Roll()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		fmt.Println(v)
	}
	os.Exit(0)
}
<commit_msg>update roll package doc<commit_after>// Package roll is an example CLI die app that rolls a die n times where n is a number
// passed to the application as an arg.  By default roll uses a 6 sided die.
// This can be changed using the -sides flag.
package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/mohae/dice"
)

var (
	sides = flag.Int("sides", 6, "number of sides for the die")
)

// Usage is a replacement usage function for the flags package.
func Usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "  rolldice [-sides] n\n")
	fmt.Fprintf(os.Stderr, "\twhere n is the number of times you want to roll the die\n")
	fmt.Fprintf(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = Usage
	flag.Parse()
	args := flag.Args()
	var rolls int
	var err error
	if len(args) > 0 {
		rolls, err = strconv.Atoi(args[0])
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not convert %s to an int: %s", args[0], err)
			os.Exit(1)
		}
	}
	// rolls must be > 0
	if rolls == 0 {
		rolls = 1
	}
	d := dice.New(*sides)
	for i := 0; i < rolls; i++ {
		v, err := d.Roll()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		fmt.Println(v)
	}
	os.Exit(0)
}
<|endoftext|>


<commit_before>package mapper

import (
	"reflect"
	"testing"

	"github.com/ottogiron/ironman/template/generator/metadata/field"
)

func TestNew(t *testing.T) {
	type args struct {
		fieldType field.Type
	}
	tests := []struct {
		name    string
		args    args
		want    Mapper
		wantErr bool
	}{
		{"New Text Mapper", args{field.TypeText}, TextMapper, false},
		{"New Array Mapper", args{field.TypeArray}, ArrayMapper, false},
		{"New Fixed List Mapper", args{field.TypeFixedList}, FixedListMapper, false},
		{"New Mapper error", args{field.Type("")}, nil, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := New(tt.args.fieldType)

			if (err != nil) != tt.wantErr {
				t.Errorf("%q. New() error = %v, wantErr %v", tt.name, err, tt.wantErr)
				return
			}
			if got == nil && !tt.wantErr {
				t.Errorf("%q. New() = %v, want %v", tt.name, got, tt.want)
			}
		})

	}
}

func TestMapUnstructuredToField(t *testing.T) {
	type args struct {
		unstructuredField interface{}
	}
	tests := []struct {
		name    string
		args    args
		want    interface{}
		wantErr bool
	}{
		{
			"Invalid unstructured field",
			args{
				nil,
			},
			nil,
			true,
		},
		{
			"Mising mandatory fields",
			args{
				map[string]interface{}{
					"type":  string(field.TypeText),
					"label": "My text field",
				},
			},
			nil,
			true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := MapUnstructuredToField(tt.args.unstructuredField)
			if (err != nil) != tt.wantErr {
				t.Errorf("%q. MapUnstructuredToField() error = %v, wantErr %v", tt.name, err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("%q. MapUnstructuredToField() = \n%v, \nwant \n%v", tt.name, got, tt.want)
			}
		})

	}
}
<commit_msg>#3 complete coverage for map unstructured field function<commit_after>package mapper

import (
	"reflect"
	"testing"

	"github.com/ottogiron/ironman/template/generator/metadata/field"
)

func TestNew(t *testing.T) {
	type args struct {
		fieldType field.Type
	}
	tests := []struct {
		name    string
		args    args
		want    Mapper
		wantErr bool
	}{
		{"New Text Mapper", args{field.TypeText}, TextMapper, false},
		{"New Array Mapper", args{field.TypeArray}, ArrayMapper, false},
		{"New Fixed List Mapper", args{field.TypeFixedList}, FixedListMapper, false},
		{"New Mapper error", args{field.Type("")}, nil, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := New(tt.args.fieldType)

			if (err != nil) != tt.wantErr {
				t.Errorf("%q. New() error = %v, wantErr %v", tt.name, err, tt.wantErr)
				return
			}
			if got == nil && !tt.wantErr {
				t.Errorf("%q. New() = %v, want %v", tt.name, got, tt.want)
			}
		})

	}
}

func TestMapUnstructuredToField(t *testing.T) {
	type args struct {
		unstructuredField interface{}
	}
	tests := []struct {
		name    string
		args    args
		want    interface{}
		wantErr bool
	}{
		{
			"Text field",
			args{
				map[string]interface{}{
					"id":    "myTextField",
					"type":  string("wutype"),
					"label": "My text field",
				},
			},
			nil,
			true,
		},
		{
			"Invalid unstructured field",
			args{
				nil,
			},
			nil,
			true,
		},
		{
			"Mising mandatory fields",
			args{
				map[string]interface{}{
					"type":  string(field.TypeText),
					"label": "My text field",
				},
			},
			nil,
			true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := MapUnstructuredToField(tt.args.unstructuredField)
			if (err != nil) != tt.wantErr {
				t.Errorf("%q. MapUnstructuredToField() error = %v, wantErr %v", tt.name, err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("%q. MapUnstructuredToField() = \n%v, \nwant \n%v", tt.name, got, tt.want)
			}
		})

	}
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"github.com/gorilla/mux"
	"github.com/loopfz/gadgeto/iffy"

	"github.com/ovh/cds/engine/api/application"
	"github.com/ovh/cds/engine/api/auth"
	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/api/pipeline"
	"github.com/ovh/cds/engine/api/scheduler"
	"github.com/ovh/cds/engine/api/test"
	"github.com/ovh/cds/sdk"
)

func Test_getSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_getSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}
	t.Logf("Insert Pipeline %s for Project %s", pip.Name, proj.Name)
	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}
	t.Logf("Insert Application %s for Project %s", app.Name, proj.Name)
	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	t.Logf("Attach Pipeline %s on Application %s", pip.Name, app.Name)
	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		ApplicationID: app.ID,
		EnvironmentID: sdk.DefaultEnv.ID,
		PipelineID:    pip.ID,
		Crontab:       "@hourly",
		Disabled:      false,
		Args: []sdk.Parameter{
			{
				Name:  "p1",
				Type:  sdk.StringParameter,
				Value: "v1",
			},
			{
				Name:  "p2",
				Type:  sdk.StringParameter,
				Value: "v2",
			},
		},
	}
	if err := scheduler.Insert(database.DBMap(db), s); err != nil {
		t.Fatal(err)
	}

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_getSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_addSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_addSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_addSchedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t))
	tester.Run()
	tester.Reset()

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_getSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_updateSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_updatechedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t), iffy.UnmarshalResponse(&s))
	route = router.getRoute("PUT", updateSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "PUT", route, s).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.DumpResponse(t))
	tester.Run()
	tester.Reset()

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_deleteSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)
	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_deleteSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t), iffy.UnmarshalResponse(&s))
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "DELETE", route, s).Headers(headers).Checkers(iffy.ExpectStatus(200))

	tester.Run()
	tester.Reset()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(0), iffy.DumpResponse(t))
	tester.Run()
}
<commit_msg>fix scheduler TU (#169)<commit_after>package main

import (
	"strconv"
	"testing"

	"github.com/gorilla/mux"
	"github.com/loopfz/gadgeto/iffy"

	"github.com/ovh/cds/engine/api/application"
	"github.com/ovh/cds/engine/api/auth"
	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/api/pipeline"
	"github.com/ovh/cds/engine/api/scheduler"
	"github.com/ovh/cds/engine/api/test"
	"github.com/ovh/cds/sdk"
)

func Test_getSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_getSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}
	t.Logf("Insert Pipeline %s for Project %s", pip.Name, proj.Name)
	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}
	t.Logf("Insert Application %s for Project %s", app.Name, proj.Name)
	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	t.Logf("Attach Pipeline %s on Application %s", pip.Name, app.Name)
	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		ApplicationID: app.ID,
		EnvironmentID: sdk.DefaultEnv.ID,
		PipelineID:    pip.ID,
		Crontab:       "@hourly",
		Disabled:      false,
		Args: []sdk.Parameter{
			{
				Name:  "p1",
				Type:  sdk.StringParameter,
				Value: "v1",
			},
			{
				Name:  "p2",
				Type:  sdk.StringParameter,
				Value: "v2",
			},
		},
	}
	if err := scheduler.Insert(database.DBMap(db), s); err != nil {
		t.Fatal(err)
	}

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_getSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_addSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_addSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_addSchedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t))
	tester.Run()
	tester.Reset()

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_getSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_updateSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)

	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_updatechedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t), iffy.UnmarshalResponse(&s))
	route = router.getRoute("PUT", updateSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "PUT", route, s).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.DumpResponse(t))
	tester.Run()
	tester.Reset()

	scheduler.SchedulerRun()
	scheduler.ExecuterRun()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_updatechedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(1), iffy.DumpResponse(t))
	tester.Run()
}

func Test_deleteSchedulerApplicationPipelineHandler(t *testing.T) {
	db := test.SetupPG(t)
	router = &Router{auth.TestLocalAuth(t), mux.NewRouter(), "/Test_deleteSchedulerApplicationPipelineHandler"}
	router.init()

	//Create admin user
	u, pass := test.InsertAdminUser(t, db)

	//Create a fancy httptester
	tester := iffy.NewTester(t, router.mux)

	//Insert Project
	pkey := test.RandomString(t, 10)
	proj := test.InsertTestProject(t, db, pkey, pkey)

	//Insert Pipeline
	pip := &sdk.Pipeline{
		Name:       pkey + "_PIP",
		Type:       sdk.BuildPipeline,
		ProjectKey: proj.Key,
		ProjectID:  proj.ID,
	}

	if err := pipeline.InsertPipeline(db, pip); err != nil {
		t.Fatal(err)
	}

	//Insert Application
	app := &sdk.Application{
		Name: "TEST_APP",
	}

	if err := application.InsertApplication(db, proj, app); err != nil {
		t.Fatal(err)
	}

	if err := application.AttachPipeline(db, app.ID, pip.ID); err != nil {
		t.Fatal(err)
	}

	s := &sdk.PipelineScheduler{
		Crontab: "@hourly",
	}

	vars := map[string]string{
		"key": proj.Key,
		"permApplicationName": app.Name,
		"permPipelineKey":     pip.Name,
	}
	route := router.getRoute("POST", addSchedulerApplicationPipelineHandler, vars)
	headers := test.AuthHeaders(t, u, pass)
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "POST", route, s).Headers(headers).Checkers(iffy.ExpectStatus(201), iffy.DumpResponse(t), iffy.UnmarshalResponse(&s))

	tester.Run()
	tester.Reset()

	vars["id"] = strconv.FormatInt(s.ID, 10)
	route = router.getRoute("DELETE", deleteSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "DELETE", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200))

	tester.Run()
	tester.Reset()

	route = router.getRoute("GET", getSchedulerApplicationPipelineHandler, vars)
	tester.AddCall("Test_deleteSchedulerApplicationPipelineHandler", "GET", route, nil).Headers(headers).Checkers(iffy.ExpectStatus(200), iffy.ExpectListLength(0), iffy.DumpResponse(t))
	tester.Run()
}
<|endoftext|>


<commit_before>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// Copysign returns a value with the magnitude
// of x and the sign of y.
func Copysign(x, y float64) float64 {
	const sign = 1 << 63
	return Float64frombits(Float64bits(x)&^sign | Float64bits(y)&sign)
}
<commit_msg>math: improve documentation of Copysign<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// Copysign returns a value with the magnitude of f
// and the sign of sign.
func Copysign(f, sign float64) float64 {
	const signBit = 1 << 63
	return Float64frombits(Float64bits(f)&^signBit | Float64bits(sign)&signBit)
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
	"math"
)

// RoundFloat rounds float val to the nearest integer value with float64 format, like GNU rint function.
// RoundFloat uses default rounding mode, see http://www.gnu.org/software/libc/manual/html_node/Rounding.html
// so we will choose the even number if the result is midway between two representable value.
// e.g, 1.5 -> 2, 2.5 -> 2.
func RoundFloat(val float64) float64 {
	v, frac := math.Modf(val)
	if val >= 0.0 {
		if frac > 0.5 || (frac == 0.5 && uint64(v)%2 != 0) {
			v += 1.0
		}
	} else {
		if frac < -0.5 || (frac == -0.5 && uint64(v)%2 != 0) {
			v -= 1.0
		}
	}

	return v
}

func getMaxFloat(flen int, decimal int) float64 {
	intPartLen := flen - decimal
	f := math.Pow10(intPartLen)
	f -= math.Pow10(-decimal)
	return f
}

func truncateFloat(f float64, decimal int) float64 {
	pow := math.Pow10(decimal)
	t := (f - math.Floor(f)) * pow

	round := RoundFloat(t)

	f = math.Floor(f) + round/pow
	return f
}

// TruncateFloat tries to truncate f.
// If the result exceeds the max/min float that flen/decimal allowed, returns the max/min float allowed.
func TruncateFloat(f float64, flen int, decimal int) (float64, error) {
	if math.IsNaN(f) {
		// nan returns 0
		return 0, nil
	}

	maxF := getMaxFloat(flen, decimal)

	if !math.IsInf(f, 0) {
		f = truncateFloat(f, decimal)
	}

	if f > maxF {
		f = maxF
	} else if f < -maxF {
		f = -maxF
	}

	return f, nil
}
<commit_msg>util: fix float64 round function.<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
	"math"
)

// RoundFloat rounds float val to the nearest integer value with float64 format, like GNU rint function.
// RoundFloat uses default rounding mode, see http://www.gnu.org/software/libc/manual/html_node/Rounding.html
// so we will choose the even number if the result is midway between two representable value.
// e.g, 1.5 -> 2, 2.5 -> 2.
func RoundFloat(val float64) float64 {
	v, frac := math.Modf(val)
	if val >= 0.0 {
		if frac > 0.5 || (frac == 0.5 && uint64(v)%2 != 0) {
			v += 1.0
		}
	} else {
		if frac < -0.5 || (frac == -0.5 && uint64(math.Abs(v))%2 != 0) {
			v -= 1.0
		}
	}

	return v
}

func getMaxFloat(flen int, decimal int) float64 {
	intPartLen := flen - decimal
	f := math.Pow10(intPartLen)
	f -= math.Pow10(-decimal)
	return f
}

func truncateFloat(f float64, decimal int) float64 {
	pow := math.Pow10(decimal)
	t := (f - math.Floor(f)) * pow

	round := RoundFloat(t)

	f = math.Floor(f) + round/pow
	return f
}

// TruncateFloat tries to truncate f.
// If the result exceeds the max/min float that flen/decimal allowed, returns the max/min float allowed.
func TruncateFloat(f float64, flen int, decimal int) (float64, error) {
	if math.IsNaN(f) {
		// nan returns 0
		return 0, nil
	}

	maxF := getMaxFloat(flen, decimal)

	if !math.IsInf(f, 0) {
		f = truncateFloat(f, decimal)
	}

	if f > maxF {
		f = maxF
	} else if f < -maxF {
		f = -maxF
	}

	return f, nil
}
<|endoftext|>


<commit_before>/*
Package epub generates valid EPUB 3.0 files with additional EPUB 2.0 table of
contents (as seen here: https://github.com/bmaupin/epub-samples) for maximum
compatibility.

Basic usage:

	// Create a new EPUB
	e := epub.NewEpub("My title")

	// Set the author
	e.SetAuthor("Hingle McCringleberry")

	// Add a section
	section1Content := `
Section 1

This is a paragraph.
`
	e.AddSection("Section 1", section1Content)

	section2Content := `
Section 2

This is a paragraph.
`
	e.AddSection("Section 2", section2Content)

	// Write the EPUB
	err = e.Write("My EPUB.epub")
	if err != nil {
		// handle error
	}

*/
package epub

import (
	"fmt"
	"path/filepath"

	"github.com/satori/go.uuid"
)

const (
	urnUUID = "urn:uuid:"
)

// Epub implements an EPUB file.
type Epub struct {
	author string
	images map[string]string // Images added to the EPUB
	lang   string            // Language
	pkg    *pkg              // The package file (package.opf)
	//	sections []section
	sections []xhtml // Sections (chapters)
	title    string
	toc      *toc // Table of contents
	uuid     string
}

// NewEpub returns a new Epub.
func NewEpub(title string) *Epub {
	e := &Epub{}
	e.images = make(map[string]string)
	e.pkg = newPackage()
	e.toc = newToc()
	// Set minimal required attributes
	e.SetLang("en")
	e.SetTitle(title)
	e.SetUUID(uuid.NewV4().String())

	return e
}

// AddImage adds an image to the EPUB and returns a relative path that can be
// used in the content of a section. The image source should either be a URL or
// a path to a local file; in either case, the image will be retrieved and
// stored in the EPUB. The image filename will be used when storing the image in
// the EPUB and must be unique.
func (e *Epub) AddImage(imageSource string, imageFilename string) (string, error) {
	if _, ok := e.images[imageFilename]; ok {
		return "", fmt.Errorf("Image filename %s already used", imageFilename)
	}

	e.images[imageFilename] = imageSource

	return filepath.Join(
		"..",
		imageFolderName,
		imageFilename,
	), nil
}

// AddSection adds a new section (chapter, etc) to the EPUB. The title will be
// used for the table of contents. The content must be valid XHTML that will go
// between the  tags. The content will not be validated.
func (e *Epub) AddSection(title string, content string) {
	x := newXhtml(content)
	x.setTitle(title)

	e.sections = append(e.sections, *x)
}

// Author returns the author of the EPUB.
func (e *Epub) Author() string {
	return e.author
}

// Lang returns the language of the EPUB.
func (e *Epub) Lang() string {
	return e.lang
}

// SetAuthor sets the author of the EPUB.
func (e *Epub) SetAuthor(author string) {
	e.author = author
	e.pkg.setAuthor(author)
}

// SetLang sets the language of the EPUB.
func (e *Epub) SetLang(lang string) {
	e.lang = lang
	e.pkg.setLang(lang)
}

// SetTitle sets the title of the EPUB.
func (e *Epub) SetTitle(title string) {
	e.title = title
	e.pkg.setTitle(title)
	e.toc.setTitle(title)
}

// SetUUID sets the UUID of the EPUB. A UUID will be automatically be generated
// for you when the NewEpub method is run.
func (e *Epub) SetUUID(uuid string) {
	e.uuid = uuid
	e.pkg.setUUID(urnUUID + uuid)
	e.toc.setUUID(urnUUID + uuid)
}

// Title returns the title of the EPUB.
func (e *Epub) Title() string {
	return e.title
}

// UUID returns the UUID of the EPUB.
func (e *Epub) UUID() string {
	return e.uuid
}
<commit_msg>Improve constants<commit_after>/*
Package epub generates valid EPUB 3.0 files with additional EPUB 2.0 table of
contents (as seen here: https://github.com/bmaupin/epub-samples) for maximum
compatibility.

Basic usage:

	// Create a new EPUB
	e := epub.NewEpub("My title")

	// Set the author
	e.SetAuthor("Hingle McCringleberry")

	// Add a section
	section1Content := `
Section 1

This is a paragraph.
`
	e.AddSection("Section 1", section1Content)

	section2Content := `
Section 2

This is a paragraph.
`
	e.AddSection("Section 2", section2Content)

	// Write the EPUB
	err = e.Write("My EPUB.epub")
	if err != nil {
		// handle error
	}

*/
package epub

import (
	"fmt"
	"path/filepath"

	"github.com/satori/go.uuid"
)

const (
	defaultEpubLang = "en"
	urnUUIDPrefix   = "urn:uuid:"
)

// Epub implements an EPUB file.
type Epub struct {
	author string
	images map[string]string // Images added to the EPUB
	lang   string            // Language
	pkg    *pkg              // The package file (package.opf)
	//	sections []section
	sections []xhtml // Sections (chapters)
	title    string
	toc      *toc // Table of contents
	uuid     string
}

// NewEpub returns a new Epub.
func NewEpub(title string) *Epub {
	e := &Epub{}
	e.images = make(map[string]string)
	e.pkg = newPackage()
	e.toc = newToc()
	// Set minimal required attributes
	e.SetLang(defaultEpubLang)
	e.SetTitle(title)
	e.SetUUID(uuid.NewV4().String())

	return e
}

// AddImage adds an image to the EPUB and returns a relative path that can be
// used in the content of a section. The image source should either be a URL or
// a path to a local file; in either case, the image will be retrieved and
// stored in the EPUB. The image filename will be used when storing the image in
// the EPUB and must be unique.
func (e *Epub) AddImage(imageSource string, imageFilename string) (string, error) {
	if _, ok := e.images[imageFilename]; ok {
		return "", fmt.Errorf("Image filename %s already used", imageFilename)
	}

	e.images[imageFilename] = imageSource

	return filepath.Join(
		"..",
		imageFolderName,
		imageFilename,
	), nil
}

// AddSection adds a new section (chapter, etc) to the EPUB. The title will be
// used for the table of contents. The content must be valid XHTML that will go
// between the  tags. The content will not be validated.
func (e *Epub) AddSection(title string, content string) {
	x := newXhtml(content)
	x.setTitle(title)

	e.sections = append(e.sections, *x)
}

// Author returns the author of the EPUB.
func (e *Epub) Author() string {
	return e.author
}

// Lang returns the language of the EPUB.
func (e *Epub) Lang() string {
	return e.lang
}

// SetAuthor sets the author of the EPUB.
func (e *Epub) SetAuthor(author string) {
	e.author = author
	e.pkg.setAuthor(author)
}

// SetLang sets the language of the EPUB.
func (e *Epub) SetLang(lang string) {
	e.lang = lang
	e.pkg.setLang(lang)
}

// SetTitle sets the title of the EPUB.
func (e *Epub) SetTitle(title string) {
	e.title = title
	e.pkg.setTitle(title)
	e.toc.setTitle(title)
}

// SetUUID sets the UUID of the EPUB. A UUID will be automatically be generated
// for you when the NewEpub method is run.
func (e *Epub) SetUUID(uuid string) {
	e.uuid = uuid
	e.pkg.setUUID(urnUUIDPrefix + uuid)
	e.toc.setUUID(urnUUIDPrefix + uuid)
}

// Title returns the title of the EPUB.
func (e *Epub) Title() string {
	return e.title
}

// UUID returns the UUID of the EPUB.
func (e *Epub) UUID() string {
	return e.uuid
}
<|endoftext|>


<commit_before>package rendering

import "github.com/go-gl/gl/v3.2-core/gl"

// Should provide universal calls for all graphics systems we support, like OGL, SDL, etc..
// Generally focusing on OGL is a good idea. Using stuff from https://github.com/go-gl is probably the best idea.

func Init() {
	if err := gl.Init(); err != nil {
		panic(err)
	}
}
<commit_msg>Added threadlock<commit_after>package rendering

import (
	"github.com/go-gl/gl/v3.2-core/gl"
	"runtime"
)

// Should provide universal calls for all graphics systems we support, like OGL, SDL, etc..
// Generally focusing on OGL is a good idea. Using stuff from https://github.com/go-gl is probably the best idea.

func Init() {
	runtime.LockOSThread() // Lock current Gorutine to the thread so we don't run into issues with OGL
	if err := gl.Init(); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Evaluation helpers for Mandira

package mandira

import (
	"errors"
	"fmt"
	"reflect"
)

/*
type lookupExpr struct {
	name string
}

type funcExpr struct {
	name string
	// these are either literal values or lookup expressions
	arguments []interface{}
}

type cond struct {
	not  bool
	expr interface{}
}

type bincond struct {
	oper string
	lhs  *cond
	rhs  *cond
}

type condExpr struct {
	oper string
	lhs  interface{}
	rhs  interface{}
}

type varExpr struct {
	exprs []interface{}
}
*/

// Apply a filter to a value
func (f *funcExpr) Apply(contexts []interface{}, input interface{}) (interface{}, error) {
	// FIXME: for now all filters are no-ops
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("Panic while applying filter %q: %v, %v", f.name, input, f.arguments)
		}
	}()

	filter := GetFilter(f.name)
	if filter == nil {
		return nil, fmt.Errorf("Could not find filter: %s", f.name)
	}

	filterVal := reflect.ValueOf(filter)
	//filterType := filterVal.Type()

	argvals := []reflect.Value{reflect.ValueOf(input)}
	for _, arg := range f.arguments {
		argvals = append(argvals, reflect.ValueOf(arg))
	}

	retval := filterVal.Call(argvals)[0]
	return retval.Interface(), nil
}

// Evaluate a varExpr given the contexts.  Return a string and possible error
func (v *varExpr) Eval(contexts []interface{}) (string, error) {
	var err error
	expr := v.exprs[0].(*lookupExpr)
	val := lookup(contexts, expr.name)

	if !val.IsValid() {
		return "", errors.New("Invalid value in lookup.")
	}

	inter := val.Interface()

	for _, exp := range v.exprs[1:] {
		filter := exp.(*funcExpr)
		inter, err = filter.Apply(contexts, inter)
		if err != nil {
			return "", err
		}
	}

	return fmt.Sprint(inter), nil
}
<commit_msg>fix using context vars in filters<commit_after>// Evaluation helpers for Mandira

package mandira

import (
	"errors"
	"fmt"
	"reflect"
)

/*
type lookupExpr struct {
	name string
}

type funcExpr struct {
	name string
	// these are either literal values or lookup expressions
	arguments []interface{}
}

type cond struct {
	not  bool
	expr interface{}
}

type bincond struct {
	oper string
	lhs  *cond
	rhs  *cond
}

type condExpr struct {
	oper string
	lhs  interface{}
	rhs  interface{}
}

type varExpr struct {
	exprs []interface{}
}
*/

// Apply a filter to a value
func (f *funcExpr) Apply(contexts []interface{}, input interface{}) (interface{}, error) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("Panic while applying filter %q: %v, %v", f.name, input, f.arguments)
		}
	}()

	filter := GetFilter(f.name)
	if filter == nil {
		return nil, fmt.Errorf("Could not find filter: %s", f.name)
	}

	filterVal := reflect.ValueOf(filter)
	filterType := filterVal.Type()

	argvals := []reflect.Value{reflect.ValueOf(input)}
	for i, arg := range f.arguments {
		switch arg.(type) {
		case string, int64, int, float64:
			argvals = append(argvals, reflect.ValueOf(arg))
		case *lookupExpr:
			lu := arg.(*lookupExpr)
			val := lookup(contexts, lu.name)
			if !val.IsValid() {
				return "", fmt.Errorf("Invalid lookup for filter argument: %s", lu.name)
			}
			argtype := filterType.In(i + 1)
			switch argtype.Kind() {
			case reflect.String:
				argvals = append(argvals, reflect.ValueOf(fmt.Sprint(val.Interface())))
			/* FIXME: check non-string types for context args in filters */
			case reflect.Int, reflect.Int64:
				argvals = append(argvals, reflect.ValueOf(val.Int()))
			}
		default:
			fmt.Println("Unknown arg type")
		}
	}

	retval := filterVal.Call(argvals)[0]
	return retval.Interface(), nil
}

// Evaluate a varExpr given the contexts.  Return a string and possible error
func (v *varExpr) Eval(contexts []interface{}) (string, error) {
	var err error
	expr := v.exprs[0].(*lookupExpr)
	val := lookup(contexts, expr.name)

	if !val.IsValid() {
		return "", errors.New("Invalid value in lookup.")
	}

	inter := val.Interface()

	for _, exp := range v.exprs[1:] {
		filter := exp.(*funcExpr)
		inter, err = filter.Apply(contexts, inter)
		if err != nil {
			return "", err
		}
	}
	if inter == nil {
		return "", nil
	}
	return fmt.Sprint(inter), nil
}
<|endoftext|>