<commit_before>// Copyright 2016 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 dep

import (
	"bytes"
	"fmt"
	"io"
	"reflect"
	"sort"

	"github.com/golang/dep/gps"
	"github.com/golang/dep/internal"
	"github.com/pelletier/go-toml"
	"github.com/pkg/errors"
)

const ManifestName = "Gopkg.toml"

type Manifest struct {
	Dependencies gps.ProjectConstraints
	Ovr          gps.ProjectConstraints
	Ignored      []string
	Required     []string
}

type rawManifest struct {
	Dependencies []rawProject `toml:"dependencies,omitempty"`
	Overrides    []rawProject `toml:"overrides,omitempty"`
	Ignored      []string     `toml:"ignored,omitempty"`
	Required     []string     `toml:"required,omitempty"`
}

type rawProject struct {
	Name     string `toml:"name"`
	Branch   string `toml:"branch,omitempty"`
	Revision string `toml:"revision,omitempty"`
	Version  string `toml:"version,omitempty"`
	Source   string `toml:"source,omitempty"`
}

func validateManifest(s string) ([]error, error) {
	var errs []error
	// Load the TomlTree from string
	tree, err := toml.Load(s)
	if err != nil {
		return errs, errors.Wrap(err, "Unable to load TomlTree from string")
	}
	// Convert tree to a map
	manifest := tree.ToMap()

	// Look for unknown fields and collect errors
	for prop, val := range manifest {
		switch prop {
		case "metadata":
			// Check if metadata is of Map type
			if reflect.TypeOf(val).Kind() != reflect.Map {
				errs = append(errs, errors.New("metadata should be a TOML table"))
			}
		case "dependencies", "overrides":
			// Invalid if type assertion fails. Not a TOML array of tables.
			if rawProj, ok := val.([]interface{}); ok {
				// Iterate through each array of tables
				for _, v := range rawProj {
					// Check the individual field's key to be valid
					for key, value := range v.(map[string]interface{}) {
						// Check if the key is valid
						switch key {
						case "name", "branch", "revision", "version", "source":
							// valid key
						case "metadata":
							// Check if metadata is of Map type
							if reflect.TypeOf(value).Kind() != reflect.Map {
								errs = append(errs, fmt.Errorf("metadata in %q should be a TOML table", prop))
							}
						default:
							// unknown/invalid key
							errs = append(errs, fmt.Errorf("Invalid key %q in %q", key, prop))
						}
					}
				}
			} else {
				errs = append(errs, fmt.Errorf("%v should be a TOML array of tables", prop))
			}
		case "ignored", "required":
		default:
			errs = append(errs, fmt.Errorf("Unknown field in manifest: %v", prop))
		}
	}

	return errs, nil
}

func readManifest(r io.Reader) (*Manifest, error) {
	buf := &bytes.Buffer{}
	_, err := buf.ReadFrom(r)
	if err != nil {
		return nil, errors.Wrap(err, "Unable to read byte stream")
	}

	// Validate manifest and log warnings
	errs, err := validateManifest(buf.String())
	if err != nil {
		return nil, errors.Wrap(err, "Manifest validation failed")
	}
	for _, e := range errs {
		internal.Logf("WARNING: %v", e)
	}

	raw := rawManifest{}
	err = toml.Unmarshal(buf.Bytes(), &raw)
	if err != nil {
		return nil, errors.Wrap(err, "Unable to parse the manifest as TOML")
	}

	return fromRawManifest(raw)
}

func fromRawManifest(raw rawManifest) (*Manifest, error) {
	m := &Manifest{
		Dependencies: make(gps.ProjectConstraints, len(raw.Dependencies)),
		Ovr:          make(gps.ProjectConstraints, len(raw.Overrides)),
		Ignored:      raw.Ignored,
		Required:     raw.Required,
	}

	for i := 0; i < len(raw.Dependencies); i++ {
		name, prj, err := toProject(raw.Dependencies[i])
		if err != nil {
			return nil, err
		}
		if _, exists := m.Dependencies[name]; exists {
			return nil, errors.Errorf("multiple dependencies specified for %s, can only specify one", name)
		}
		m.Dependencies[name] = prj
	}

	for i := 0; i < len(raw.Overrides); i++ {
		name, prj, err := toProject(raw.Overrides[i])
		if err != nil {
			return nil, err
		}
		m.Ovr[name] = prj
	}

	return m, nil
}

// toProject interprets the string representations of project information held in
// a rawProject, converting them into a proper gps.ProjectProperties. An
// error is returned if the rawProject contains some invalid combination -
// for example, if both a branch and version constraint are specified.
func toProject(raw rawProject) (n gps.ProjectRoot, pp gps.ProjectProperties, err error) {
	n = gps.ProjectRoot(raw.Name)
	if raw.Branch != "" {
		if raw.Version != "" || raw.Revision != "" {
			return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n)
		}
		pp.Constraint = gps.NewBranch(raw.Branch)
	} else if raw.Version != "" {
		if raw.Revision != "" {
			return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n)
		}

		// always semver if we can
		pp.Constraint, err = gps.NewSemverConstraint(raw.Version)
		if err != nil {
			// but if not, fall back on plain versions
			pp.Constraint = gps.NewVersion(raw.Version)
		}
	} else if raw.Revision != "" {
		pp.Constraint = gps.Revision(raw.Revision)
	} else {
		// If the user specifies nothing, it means an open constraint (accept
		// anything).
		pp.Constraint = gps.Any()
	}

	pp.Source = raw.Source
	return n, pp, nil
}

// toRaw converts the manifest into a representation suitable to write to the manifest file
func (m *Manifest) toRaw() rawManifest {
	raw := rawManifest{
		Dependencies: make([]rawProject, 0, len(m.Dependencies)),
		Overrides:    make([]rawProject, 0, len(m.Ovr)),
		Ignored:      m.Ignored,
		Required:     m.Required,
	}
	for n, prj := range m.Dependencies {
		raw.Dependencies = append(raw.Dependencies, toRawProject(n, prj))
	}
	sort.Sort(sortedRawProjects(raw.Dependencies))

	for n, prj := range m.Ovr {
		raw.Overrides = append(raw.Overrides, toRawProject(n, prj))
	}
	sort.Sort(sortedRawProjects(raw.Overrides))

	return raw
}

type sortedRawProjects []rawProject

func (s sortedRawProjects) Len() int      { return len(s) }
func (s sortedRawProjects) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sortedRawProjects) Less(i, j int) bool {
	l, r := s[i], s[j]

	if l.Name < r.Name {
		return true
	}
	if r.Name < l.Name {
		return false
	}

	return l.Source < r.Source
}

func (m *Manifest) MarshalTOML() ([]byte, error) {
	raw := m.toRaw()
	result, err := toml.Marshal(raw)
	return result, errors.Wrap(err, "Unable to marshal the lock to a TOML string")
}

func toRawProject(name gps.ProjectRoot, project gps.ProjectProperties) rawProject {
	raw := rawProject{
		Name:   string(name),
		Source: project.Source,
	}

	if v, ok := project.Constraint.(gps.Version); ok {
		switch v.Type() {
		case gps.IsRevision:
			raw.Revision = v.String()
		case gps.IsBranch:
			raw.Branch = v.String()
		case gps.IsSemver, gps.IsVersion:
			raw.Version = v.String()
		}
		return raw
	}

	// We simply don't allow for a case where the user could directly
	// express a 'none' constraint, so we can ignore it here. We also ignore
	// the 'any' case, because that's the other possibility, and it's what
	// we interpret not having any constraint expressions at all to mean.
	// if !gps.IsAny(pp.Constraint) && !gps.IsNone(pp.Constraint) {
	if !gps.IsAny(project.Constraint) && project.Constraint != nil {
		// Has to be a semver range.
		raw.Version = project.Constraint.String()
	}
	return raw
}

func (m *Manifest) DependencyConstraints() gps.ProjectConstraints {
	return m.Dependencies
}

func (m *Manifest) TestDependencyConstraints() gps.ProjectConstraints {
	// TODO decide whether we're going to incorporate this or not
	return nil
}

func (m *Manifest) Overrides() gps.ProjectConstraints {
	return m.Ovr
}

func (m *Manifest) IgnoredPackages() map[string]bool {
	if len(m.Ignored) == 0 {
		return nil
	}

	mp := make(map[string]bool, len(m.Ignored))
	for _, i := range m.Ignored {
		mp[i] = true
	}

	return mp
}

func (m *Manifest) RequiredPackages() map[string]bool {
	if len(m.Required) == 0 {
		return nil
	}

	mp := make(map[string]bool, len(m.Required))
	for _, i := range m.Required {
		mp[i] = true
	}

	return mp
}
<commit_msg>Comment out call to global internal logger<commit_after>// Copyright 2016 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 dep

import (
	"bytes"
	"fmt"
	"io"
	"reflect"
	"sort"

	"github.com/golang/dep/gps"
	"github.com/pelletier/go-toml"
	"github.com/pkg/errors"
)

const ManifestName = "Gopkg.toml"

type Manifest struct {
	Dependencies gps.ProjectConstraints
	Ovr          gps.ProjectConstraints
	Ignored      []string
	Required     []string
}

type rawManifest struct {
	Dependencies []rawProject `toml:"dependencies,omitempty"`
	Overrides    []rawProject `toml:"overrides,omitempty"`
	Ignored      []string     `toml:"ignored,omitempty"`
	Required     []string     `toml:"required,omitempty"`
}

type rawProject struct {
	Name     string `toml:"name"`
	Branch   string `toml:"branch,omitempty"`
	Revision string `toml:"revision,omitempty"`
	Version  string `toml:"version,omitempty"`
	Source   string `toml:"source,omitempty"`
}

func validateManifest(s string) ([]error, error) {
	var errs []error
	// Load the TomlTree from string
	tree, err := toml.Load(s)
	if err != nil {
		return errs, errors.Wrap(err, "Unable to load TomlTree from string")
	}
	// Convert tree to a map
	manifest := tree.ToMap()

	// Look for unknown fields and collect errors
	for prop, val := range manifest {
		switch prop {
		case "metadata":
			// Check if metadata is of Map type
			if reflect.TypeOf(val).Kind() != reflect.Map {
				errs = append(errs, errors.New("metadata should be a TOML table"))
			}
		case "dependencies", "overrides":
			// Invalid if type assertion fails. Not a TOML array of tables.
			if rawProj, ok := val.([]interface{}); ok {
				// Iterate through each array of tables
				for _, v := range rawProj {
					// Check the individual field's key to be valid
					for key, value := range v.(map[string]interface{}) {
						// Check if the key is valid
						switch key {
						case "name", "branch", "revision", "version", "source":
							// valid key
						case "metadata":
							// Check if metadata is of Map type
							if reflect.TypeOf(value).Kind() != reflect.Map {
								errs = append(errs, fmt.Errorf("metadata in %q should be a TOML table", prop))
							}
						default:
							// unknown/invalid key
							errs = append(errs, fmt.Errorf("Invalid key %q in %q", key, prop))
						}
					}
				}
			} else {
				errs = append(errs, fmt.Errorf("%v should be a TOML array of tables", prop))
			}
		case "ignored", "required":
		default:
			errs = append(errs, fmt.Errorf("Unknown field in manifest: %v", prop))
		}
	}

	return errs, nil
}

func readManifest(r io.Reader) (*Manifest, error) {
	buf := &bytes.Buffer{}
	_, err := buf.ReadFrom(r)
	if err != nil {
		return nil, errors.Wrap(err, "Unable to read byte stream")
	}

	// Validate manifest and log warnings
	errs, err := validateManifest(buf.String())
	if err != nil {
		return nil, errors.Wrap(err, "Manifest validation failed")
	}
	//for _, e := range errs {
	// FIXME(sdboyer) need to adapt this to use an injected *Loggers
	//internal.Logf("WARNING: %v", e)
	//}

	raw := rawManifest{}
	err = toml.Unmarshal(buf.Bytes(), &raw)
	if err != nil {
		return nil, errors.Wrap(err, "Unable to parse the manifest as TOML")
	}

	return fromRawManifest(raw)
}

func fromRawManifest(raw rawManifest) (*Manifest, error) {
	m := &Manifest{
		Dependencies: make(gps.ProjectConstraints, len(raw.Dependencies)),
		Ovr:          make(gps.ProjectConstraints, len(raw.Overrides)),
		Ignored:      raw.Ignored,
		Required:     raw.Required,
	}

	for i := 0; i < len(raw.Dependencies); i++ {
		name, prj, err := toProject(raw.Dependencies[i])
		if err != nil {
			return nil, err
		}
		if _, exists := m.Dependencies[name]; exists {
			return nil, errors.Errorf("multiple dependencies specified for %s, can only specify one", name)
		}
		m.Dependencies[name] = prj
	}

	for i := 0; i < len(raw.Overrides); i++ {
		name, prj, err := toProject(raw.Overrides[i])
		if err != nil {
			return nil, err
		}
		m.Ovr[name] = prj
	}

	return m, nil
}

// toProject interprets the string representations of project information held in
// a rawProject, converting them into a proper gps.ProjectProperties. An
// error is returned if the rawProject contains some invalid combination -
// for example, if both a branch and version constraint are specified.
func toProject(raw rawProject) (n gps.ProjectRoot, pp gps.ProjectProperties, err error) {
	n = gps.ProjectRoot(raw.Name)
	if raw.Branch != "" {
		if raw.Version != "" || raw.Revision != "" {
			return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n)
		}
		pp.Constraint = gps.NewBranch(raw.Branch)
	} else if raw.Version != "" {
		if raw.Revision != "" {
			return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n)
		}

		// always semver if we can
		pp.Constraint, err = gps.NewSemverConstraint(raw.Version)
		if err != nil {
			// but if not, fall back on plain versions
			pp.Constraint = gps.NewVersion(raw.Version)
		}
	} else if raw.Revision != "" {
		pp.Constraint = gps.Revision(raw.Revision)
	} else {
		// If the user specifies nothing, it means an open constraint (accept
		// anything).
		pp.Constraint = gps.Any()
	}

	pp.Source = raw.Source
	return n, pp, nil
}

// toRaw converts the manifest into a representation suitable to write to the manifest file
func (m *Manifest) toRaw() rawManifest {
	raw := rawManifest{
		Dependencies: make([]rawProject, 0, len(m.Dependencies)),
		Overrides:    make([]rawProject, 0, len(m.Ovr)),
		Ignored:      m.Ignored,
		Required:     m.Required,
	}
	for n, prj := range m.Dependencies {
		raw.Dependencies = append(raw.Dependencies, toRawProject(n, prj))
	}
	sort.Sort(sortedRawProjects(raw.Dependencies))

	for n, prj := range m.Ovr {
		raw.Overrides = append(raw.Overrides, toRawProject(n, prj))
	}
	sort.Sort(sortedRawProjects(raw.Overrides))

	return raw
}

type sortedRawProjects []rawProject

func (s sortedRawProjects) Len() int      { return len(s) }
func (s sortedRawProjects) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sortedRawProjects) Less(i, j int) bool {
	l, r := s[i], s[j]

	if l.Name < r.Name {
		return true
	}
	if r.Name < l.Name {
		return false
	}

	return l.Source < r.Source
}

func (m *Manifest) MarshalTOML() ([]byte, error) {
	raw := m.toRaw()
	result, err := toml.Marshal(raw)
	return result, errors.Wrap(err, "Unable to marshal the lock to a TOML string")
}

func toRawProject(name gps.ProjectRoot, project gps.ProjectProperties) rawProject {
	raw := rawProject{
		Name:   string(name),
		Source: project.Source,
	}

	if v, ok := project.Constraint.(gps.Version); ok {
		switch v.Type() {
		case gps.IsRevision:
			raw.Revision = v.String()
		case gps.IsBranch:
			raw.Branch = v.String()
		case gps.IsSemver, gps.IsVersion:
			raw.Version = v.String()
		}
		return raw
	}

	// We simply don't allow for a case where the user could directly
	// express a 'none' constraint, so we can ignore it here. We also ignore
	// the 'any' case, because that's the other possibility, and it's what
	// we interpret not having any constraint expressions at all to mean.
	// if !gps.IsAny(pp.Constraint) && !gps.IsNone(pp.Constraint) {
	if !gps.IsAny(project.Constraint) && project.Constraint != nil {
		// Has to be a semver range.
		raw.Version = project.Constraint.String()
	}
	return raw
}

func (m *Manifest) DependencyConstraints() gps.ProjectConstraints {
	return m.Dependencies
}

func (m *Manifest) TestDependencyConstraints() gps.ProjectConstraints {
	// TODO decide whether we're going to incorporate this or not
	return nil
}

func (m *Manifest) Overrides() gps.ProjectConstraints {
	return m.Ovr
}

func (m *Manifest) IgnoredPackages() map[string]bool {
	if len(m.Ignored) == 0 {
		return nil
	}

	mp := make(map[string]bool, len(m.Ignored))
	for _, i := range m.Ignored {
		mp[i] = true
	}

	return mp
}

func (m *Manifest) RequiredPackages() map[string]bool {
	if len(m.Required) == 0 {
		return nil
	}

	mp := make(map[string]bool, len(m.Required))
	for _, i := range m.Required {
		mp[i] = true
	}

	return mp
}
<|endoftext|>


<commit_before>package main

import (
	. "./quadedge"
	"fmt"
	"github.com/ajstarks/svgo/float"
	"math"
	//	"log"
	//	"net/http"
	"os"
)

var fileno int = 0

func nextfile() string {
	fileno++
	return fmt.Sprintf("hello%02d.svg", fileno)
}

func debugDraw(e0 *Edge, e1 *Edge) {
	file, err := os.Create(nextfile())
	if err != nil {
		panic("can't create file")
	}
	s := svg.New(file)
	s.Start(1000, 1000)
	ox, oy := 100.0, 100.0 // put origin at (100,100)
	//	small, _ := BoundingBox(e0)
	//	dx, dy := ox-small.X, oy-small.Y
	dx, dy := ox, oy
	s.Circle(ox, oy, 5, "fill:black;stroke:black")
	for i, e := range e0.Edges() {
		if i == 0 {
			s.Circle(e.Org().X+dx, e.Org().Y+dy, 3, "fill:green;stroke:none")
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#f00;stroke-width:1")
		} else {
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#00f;stroke-width:1")
		}
	}
	if e1 != nil {
		for i, e := range e1.Edges() {
			if i == 0 {
				s.Circle(e.Org().X+dx, e.Org().Y+dy, 3, "fill:blue;stroke:none")
				s.Line(e.Org().X+dx, e.Org().Y+dy,
					e.Dest().X+dx, e.Dest().Y+dy,
					"stroke:#f00;stroke-width:1")
			} else {
				s.Line(e.Org().X+dx, e.Org().Y+dy,
					e.Dest().X+dx, e.Dest().Y+dy,
					"stroke:#00f;stroke-width:1")
			}
		}
	}
	s.End()
}

func main() {
	p := Ngon(3, 30)
	attach(p, Ngon(5, 20))
	p = p.Lnext()
	attach(p, Ngon(7, 10))
	p = p.Lnext()
	attach(p, Ngon(3, 10))
	p = p.Rnext()
	attach(p, Ngon(6, 50))
}

func edgeLength(e *Edge) float64 {
	if e == nil {
		return 0.0
	}
	dx := e.Dest().X - e.Org().X
	dy := e.Dest().Y - e.Org().Y
	return math.Sqrt(dx*dx + dy*dy)
}

func edgeRadians(e *Edge) float64 {
	dx := e.Dest().X - e.Org().X
	dy := e.Dest().Y - e.Org().Y
	return math.Atan2(dy, dx)
}

func scale(e0 *Edge, sf float64) {
	for _, e := range e0.Edges() {
		e.SetOrg(&Point2D{sf * e.Org().X, sf * e.Org().Y})
		e = e.Sym()
		e.SetOrg(&Point2D{sf * e.Org().X, sf * e.Org().Y})
	}
}

func rotate(e0 *Edge, rad float64) {
	rotatePoint := func(p *Point2D) *Point2D {
		angle := math.Atan2(p.Y, p.X)
		distance := math.Sqrt(p.X*p.X + p.Y*p.Y)
		angle2 := angle + rad
		y, x := math.Sincos(angle2)
		x, y = distance*x, distance*y
		return &Point2D{x, y}
	}
	for _, e := range e0.Edges() {
		e.SetOrg(rotatePoint(e.Org()))
		e = e.Sym()
		e.SetOrg(rotatePoint(e.Org()))
	}
}

func translate(e0 *Edge, dx, dy float64) {
	for _, e := range e0.Edges() {
		e.SetOrg(&Point2D{dx + e.Org().X, dy + e.Org().Y})
		e = e.Sym()
		e.SetOrg(&Point2D{dx + e.Org().X, dy + e.Org().Y})
	}
}

func attach(e1, e2 *Edge) {
	debugDraw(e1, e2)
	l1 := edgeLength(e1)
	l2 := edgeLength(e2)
	if l1 == 0.0 || l2 == 0.0 {
		return
	}
	sf := l1 / l2
	translate(e2, -e2.Org().X, -e2.Org().Y) // bring origin of e2 to absolute origin (0,0)
	debugDraw(e1, e2)
	scale(e2, sf)
	debugDraw(e1, e2)
	rotate(e2, edgeRadians(e1)-edgeRadians(e2)+math.Pi)
	debugDraw(e1, e2)
	translate(e2, e1.Dest().X, e1.Dest().Y)
	debugDraw(e1, e2)
	Splice(e1.Oprev(), e2.Sym())
	Splice(e1.Sym(), e2.Oprev())
	DeleteEdge(e2)
	debugDraw(e1, nil)
}
<commit_msg>Web interface<commit_after>package main

import (
	. "./quadedge"
	"fmt"
	"github.com/ajstarks/svgo/float"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"os"
//	"text/template"
	"bytes"
)

var fileno int = 0

func nextfile() string {
	fileno++
	return fmt.Sprintf("hello%02d.svg", fileno)
}

var debug bool = false

func debugDraw(e0 *Edge, e1 *Edge) {
	if !debug {
		return
	}
	file, err := os.Create(nextfile())
	if err != nil {
		panic("can't create file")
	}
	s := svg.New(file)
	s.Start(1000, 1000)
	ox, oy := 100.0, 100.0 // put origin at (100,100)
	//	small, _ := BoundingBox(e0)
	//	dx, dy := ox-small.X, oy-small.Y
	dx, dy := ox, oy
	s.Circle(ox, oy, 5, "fill:black;stroke:black")
	for i, e := range e0.Edges() {
		if i == 0 {
			s.Circle(e.Org().X+dx, e.Org().Y+dy, 3, "fill:green;stroke:none")
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#f00;stroke-width:1")
		} else {
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#00f;stroke-width:1")
		}
	}
	if e1 != nil {
		for i, e := range e1.Edges() {
			if i == 0 {
				s.Circle(e.Org().X+dx, e.Org().Y+dy, 3, "fill:blue;stroke:none")
				s.Line(e.Org().X+dx, e.Org().Y+dy,
					e.Dest().X+dx, e.Dest().Y+dy,
					"stroke:#f00;stroke-width:1")
			} else {
				s.Line(e.Org().X+dx, e.Org().Y+dy,
					e.Dest().X+dx, e.Dest().Y+dy,
					"stroke:#00f;stroke-width:1")
			}
		}
	}
	s.End()
}

func edgeLength(e *Edge) float64 {
	if e == nil {
		return 0.0
	}
	dx := e.Dest().X - e.Org().X
	dy := e.Dest().Y - e.Org().Y
	return math.Sqrt(dx*dx + dy*dy)
}

func edgeRadians(e *Edge) float64 {
	dx := e.Dest().X - e.Org().X
	dy := e.Dest().Y - e.Org().Y
	return math.Atan2(dy, dx)
}

func scale(e0 *Edge, sf float64) {
	for _, e := range e0.Edges() {
		e.SetOrg(&Point2D{sf * e.Org().X, sf * e.Org().Y})
		e = e.Sym()
		e.SetOrg(&Point2D{sf * e.Org().X, sf * e.Org().Y})
	}
}

func rotate(e0 *Edge, rad float64) {
	rotatePoint := func(p *Point2D) *Point2D {
		angle := math.Atan2(p.Y, p.X)
		distance := math.Sqrt(p.X*p.X + p.Y*p.Y)
		angle2 := angle + rad
		y, x := math.Sincos(angle2)
		x, y = distance*x, distance*y
		return &Point2D{x, y}
	}
	for _, e := range e0.Edges() {
		e.SetOrg(rotatePoint(e.Org()))
		e = e.Sym()
		e.SetOrg(rotatePoint(e.Org()))
	}
}

func translate(e0 *Edge, dx, dy float64) {
	for _, e := range e0.Edges() {
		e.SetOrg(&Point2D{dx + e.Org().X, dy + e.Org().Y})
		e = e.Sym()
		e.SetOrg(&Point2D{dx + e.Org().X, dy + e.Org().Y})
	}
}

func attach(e1, e2 *Edge) {
	debugDraw(e1, e2)
	l1 := edgeLength(e1)
	l2 := edgeLength(e2)
	if l1 == 0.0 || l2 == 0.0 {
		return
	}
	sf := l1 / l2
	translate(e2, -e2.Org().X, -e2.Org().Y) // bring origin of e2 to absolute origin (0,0)
	debugDraw(e1, e2)
	scale(e2, sf)
	debugDraw(e1, e2)
	rotate(e2, edgeRadians(e1)-edgeRadians(e2)+math.Pi)
	debugDraw(e1, e2)
	translate(e2, e1.Dest().X, e1.Dest().Y)
	debugDraw(e1, e2)
	Splice(e1.Oprev(), e2.Sym())
	Splice(e1.Sym(), e2.Oprev())
	DeleteEdge(e2)
	debugDraw(e1, nil)
}

func main() {
	http.HandleFunc("/", FrontPage)
	http.HandleFunc("/compile", Compile)
	log.Printf("Listening on localhost:1999")
	log.Fatal(http.ListenAndServe("127.0.0.1:1999", nil))
}

func FrontPage(w http.ResponseWriter, req *http.Request) {
	w.Write(frontPageText)
//	frontPage.Execute(w)
}

//var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var frontPageText =  []byte(`<!doctype html>

<title>Man, I Fold</title>

<input autofocus="true" id="edit" onkeydown="keyHandler(event);"></input>

`)

var e0 *Edge

func Compile(w http.ResponseWriter, req *http.Request) {
	log.Printf("Compile\n")
	cmd, err := ioutil.ReadAll(req.Body)
	if err != nil {
		w.WriteHeader(404)
		return
	}
	log.Printf("Your command: %s\n", cmd)
	switch string(cmd) {
	case "tri":
		e1 := Ngon(3, 40)
		if e0 == nil {
			e0 = e1
		} else {
			attach(e0, e1)
		}
	case "hex":
		e1 := Ngon(6, 40)
		if e0 == nil {
			e0 = e1
		} else {
			attach(e0, e1)
		}
	case "l":
		e0 = e0.Lnext()
	case "r":
		e0 = e0.Rprev()
	case "tl":
		e0 = e0.Onext()
	case "tr":
		e0 = e0.Oprev()
	case "ta":
		e0 = e0.Sym()
	case "box":
		fallthrough
	default:
		e1 := Ngon(4, 40)
		if e0 == nil {
			e0 = e1
		} else {
			attach(e0, e1)
		}
	}
	out := draw()
	w.Write(out) // ignore err
}

func draw() []byte {
	log.Println("draw()")
	buf := new(bytes.Buffer)
	s := svg.New(buf)
	s.Start(1000, 1000)
	ox, oy := 100.0, 100.0 // put origin at (100,100)
	//	small, _ := BoundingBox(e0)
	//	dx, dy := ox-small.X, oy-small.Y
	dx, dy := ox, oy
	s.Circle(ox, oy, 5, "fill:black;stroke:black")
	for i, e := range e0.Edges() {
		if i == 0 {
			s.Circle(e.Org().X+dx, e.Org().Y+dy, 3, "fill:green;stroke:none")
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#f00;stroke-width:1")
		} else {
			s.Line(e.Org().X+dx, e.Org().Y+dy,
				e.Dest().X+dx, e.Dest().Y+dy,
				"stroke:#00f;stroke-width:1")
		}
	}
	s.End()
	log.Println("draw() done")
	return buf.Bytes()
}
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gtw_rtr_udp

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"net"
)

type Adapter struct {
	Logger log.Logger
	conn   *net.UDPConn
}

// New constructs a new Gateway-Router-UDP adapter
func New(router core.Router, port uint) (*Adapter, error) {
	adapter := Adapter{
		Logger: log.VoidLogger{},
	}

	// Connect to the router and start listening on the given port of the current machine
	if err := adapter.Connect(router, port); err != nil {
		return nil, err
	}

	// Return the adapter for further use
	return &adapter, nil
}

// log is nothing more than a shortcut / helper to access the logger
func (a Adapter) log(format string, i ...interface{}) {
	if a.Logger == nil {
		return
	}
	a.Logger.Log(format, i...)
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Ack(router core.Router, packet semtech.Packet, gateway core.GatewayAddress) {
	if a.conn == nil {
		a.log("Connection not established. Connect the adaptor first.")
		router.HandleError(core.ErrAck(fmt.Errorf("Connection not established. Connect the adaptor first.")))
		return
	}

	a.log("Acks packet %+v", packet)

	addr, err := net.ResolveUDPAddr("udp", string(gateway))

	if err != nil {
		a.log("Unable to retrieve gateway address")
		router.HandleError(core.ErrAck(err))
		return
	}

	raw, err := semtech.Marshal(packet)

	if err != nil {
		a.log("Unable to marshal given packet")
		router.HandleError(core.ErrAck(err))
		return
	}

	_, err = a.conn.WriteToUDP(raw, addr)

	if err != nil {
		a.log("Unable to send udp message")
		router.HandleError(core.ErrAck(err))
		return
	}
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Connect(router core.Router, port uint) error {
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		return err
	}
	a.conn, err = net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}
	go a.listen(router) // NOTE: There is no way to stop properly the adapter and thus this goroutine for now.
	return nil
}

// listen Handle incominng packets and forward them to the router
func (a *Adapter) listen(router core.Router) {
	for {
		buf := make([]byte, 1024)
		n, addr, err := a.conn.ReadFromUDP(buf)
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}
		a.log("Incoming datagram %x", buf[:n])

		pkt, err := semtech.Unmarshal(buf[:n])
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}

		// When a packet is received pass it to the router for processing
		router.HandleUplink(a, *pkt, core.GatewayAddress(addr.String()))
	}
}
<commit_msg>[router] Move method for consistency between files<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gtw_rtr_udp

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"net"
)

type Adapter struct {
	Logger log.Logger
	conn   *net.UDPConn
}

// New constructs a new Gateway-Router-UDP adapter
func New(router core.Router, port uint) (*Adapter, error) {
	adapter := Adapter{
		Logger: log.VoidLogger{},
	}

	// Connect to the router and start listening on the given port of the current machine
	if err := adapter.Connect(router, port); err != nil {
		return nil, err
	}

	// Return the adapter for further use
	return &adapter, nil
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Connect(router core.Router, port uint) error {
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		return err
	}
	a.conn, err = net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}
	go a.listen(router) // NOTE: There is no way to stop properly the adapter and thus this goroutine for now.
	return nil
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Ack(router core.Router, packet semtech.Packet, gateway core.GatewayAddress) {
	if a.conn == nil {
		a.log("Connection not established. Connect the adaptor first.")
		router.HandleError(core.ErrAck(fmt.Errorf("Connection not established. Connect the adaptor first.")))
		return
	}

	a.log("Acks packet %+v", packet)

	addr, err := net.ResolveUDPAddr("udp", string(gateway))

	if err != nil {
		a.log("Unable to retrieve gateway address")
		router.HandleError(core.ErrAck(err))
		return
	}

	raw, err := semtech.Marshal(packet)

	if err != nil {
		a.log("Unable to marshal given packet")
		router.HandleError(core.ErrAck(err))
		return
	}

	_, err = a.conn.WriteToUDP(raw, addr)

	if err != nil {
		a.log("Unable to send udp message")
		router.HandleError(core.ErrAck(err))
		return
	}
}

// listen Handle incominng packets and forward them to the router
func (a *Adapter) listen(router core.Router) {
	for {
		buf := make([]byte, 1024)
		n, addr, err := a.conn.ReadFromUDP(buf)
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}
		a.log("Incoming datagram %x", buf[:n])

		pkt, err := semtech.Unmarshal(buf[:n])
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}

		// When a packet is received pass it to the router for processing
		router.HandleUplink(a, *pkt, core.GatewayAddress(addr.String()))
	}
}

// log is nothing more than a shortcut / helper to access the logger
func (a Adapter) log(format string, i ...interface{}) {
	if a.Logger == nil {
		return
	}
	a.Logger.Log(format, i...)
}
<|endoftext|>


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

package markdown

import (
	"bytes"
	"fmt"
	"strings"

	"code.gitea.io/gitea/modules/markup"
	"code.gitea.io/gitea/modules/markup/common"
	giteautil "code.gitea.io/gitea/modules/util"

	"github.com/yuin/goldmark/ast"
	east "github.com/yuin/goldmark/extension/ast"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/renderer"
	"github.com/yuin/goldmark/renderer/html"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
)

var byteMailto = []byte("mailto:")

// GiteaASTTransformer is a default transformer of the goldmark tree.
type GiteaASTTransformer struct{}

// Transform transforms the given AST tree.
func (g *GiteaASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
	_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}

		switch v := n.(type) {
		case *ast.Image:
			// Images need two things:
			//
			// 1. Their src needs to munged to be a real value
			// 2. If they're not wrapped with a link they need a link wrapper

			// Check if the destination is a real link
			link := v.Destination
			if len(link) > 0 && !markup.IsLink(link) {
				prefix := pc.Get(urlPrefixKey).(string)
				if pc.Get(isWikiKey).(bool) {
					prefix = giteautil.URLJoin(prefix, "wiki", "raw")
				}
				prefix = strings.Replace(prefix, "/src/", "/media/", 1)

				lnk := string(link)
				lnk = giteautil.URLJoin(prefix, lnk)
				link = []byte(lnk)
			}
			v.Destination = link

			parent := n.Parent()
			// Create a link around image only if parent is not already a link
			if _, ok := parent.(*ast.Link); !ok && parent != nil {
				wrap := ast.NewLink()
				wrap.Destination = link
				wrap.Title = v.Title
				parent.ReplaceChild(parent, n, wrap)
				wrap.AppendChild(wrap, n)
			}
		case *ast.Link:
			// Links need their href to munged to be a real value
			link := v.Destination
			if len(link) > 0 && !markup.IsLink(link) &&
				link[0] != '#' && !bytes.HasPrefix(link, byteMailto) {
				// special case: this is not a link, a hash link or a mailto:, so it's a
				// relative URL
				lnk := string(link)
				if pc.Get(isWikiKey).(bool) {
					lnk = giteautil.URLJoin("wiki", lnk)
				}
				link = []byte(giteautil.URLJoin(pc.Get(urlPrefixKey).(string), lnk))
			}
			if len(link) > 0 && link[0] == '#' {
				link = []byte("#user-content-" + string(link)[1:])
			}
			v.Destination = link
		case *ast.List:
			if v.HasChildren() && v.FirstChild().HasChildren() && v.FirstChild().FirstChild().HasChildren() {
				if _, ok := v.FirstChild().FirstChild().FirstChild().(*east.TaskCheckBox); ok {
					v.SetAttributeString("class", "task-list")
				}
			}
		}
		return ast.WalkContinue, nil
	})
}

type prefixedIDs struct {
	values map[string]bool
}

// Generate generates a new element id.
func (p *prefixedIDs) Generate(value []byte, kind ast.NodeKind) []byte {
	dft := []byte("id")
	if kind == ast.KindHeading {
		dft = []byte("heading")
	}
	return p.GenerateWithDefault(value, dft)
}

// Generate generates a new element id.
func (p *prefixedIDs) GenerateWithDefault(value []byte, dft []byte) []byte {
	result := common.CleanValue(value)
	if len(result) == 0 {
		result = dft
	}
	if !bytes.HasPrefix(result, []byte("user-content-")) {
		result = append([]byte("user-content-"), result...)
	}
	if _, ok := p.values[util.BytesToReadOnlyString(result)]; !ok {
		p.values[util.BytesToReadOnlyString(result)] = true
		return result
	}
	for i := 1; ; i++ {
		newResult := fmt.Sprintf("%s-%d", result, i)
		if _, ok := p.values[newResult]; !ok {
			p.values[newResult] = true
			return []byte(newResult)
		}
	}
}

// Put puts a given element id to the used ids table.
func (p *prefixedIDs) Put(value []byte) {
	p.values[util.BytesToReadOnlyString(value)] = true
}

func newPrefixedIDs() *prefixedIDs {
	return &prefixedIDs{
		values: map[string]bool{},
	}
}

// NewTaskCheckBoxHTMLRenderer creates a TaskCheckBoxHTMLRenderer to render tasklists
// in the gitea form.
func NewTaskCheckBoxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
	r := &TaskCheckBoxHTMLRenderer{
		Config: html.NewConfig(),
	}
	for _, opt := range opts {
		opt.SetHTMLOption(&r.Config)
	}
	return r
}

// TaskCheckBoxHTMLRenderer is a renderer.NodeRenderer implementation that
// renders checkboxes in list items.
// Overrides the default goldmark one to present the gitea format
type TaskCheckBoxHTMLRenderer struct {
	html.Config
}

// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
func (r *TaskCheckBoxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
	reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox)
}

func (r *TaskCheckBoxHTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
	if !entering {
		return ast.WalkContinue, nil
	}
	n := node.(*east.TaskCheckBox)

	end := ">"
	if r.XHTML {
		end = " />"
	}
	var err error
	if n.IsChecked {
		_, err = w.WriteString(`<span class="ui fitted disabled checkbox"><input type="checkbox" disabled="disabled"` + end + `<label` + end + `</span>`)
	} else {
		_, err = w.WriteString(`<span class="ui checked fitted disabled checkbox"><input type="checkbox" checked="" disabled="disabled"` + end + `<label` + end + `</span>`)
	}
	if err != nil {
		return ast.WalkStop, err
	}
	return ast.WalkContinue, nil
}
<commit_msg>Fix internal server error on checkboxes (#10845)<commit_after>// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package markdown

import (
	"bytes"
	"fmt"
	"strings"

	"code.gitea.io/gitea/modules/markup"
	"code.gitea.io/gitea/modules/markup/common"
	giteautil "code.gitea.io/gitea/modules/util"

	"github.com/yuin/goldmark/ast"
	east "github.com/yuin/goldmark/extension/ast"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/renderer"
	"github.com/yuin/goldmark/renderer/html"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
)

var byteMailto = []byte("mailto:")

// GiteaASTTransformer is a default transformer of the goldmark tree.
type GiteaASTTransformer struct{}

// Transform transforms the given AST tree.
func (g *GiteaASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
	_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}

		switch v := n.(type) {
		case *ast.Image:
			// Images need two things:
			//
			// 1. Their src needs to munged to be a real value
			// 2. If they're not wrapped with a link they need a link wrapper

			// Check if the destination is a real link
			link := v.Destination
			if len(link) > 0 && !markup.IsLink(link) {
				prefix := pc.Get(urlPrefixKey).(string)
				if pc.Get(isWikiKey).(bool) {
					prefix = giteautil.URLJoin(prefix, "wiki", "raw")
				}
				prefix = strings.Replace(prefix, "/src/", "/media/", 1)

				lnk := string(link)
				lnk = giteautil.URLJoin(prefix, lnk)
				link = []byte(lnk)
			}
			v.Destination = link

			parent := n.Parent()
			// Create a link around image only if parent is not already a link
			if _, ok := parent.(*ast.Link); !ok && parent != nil {
				wrap := ast.NewLink()
				wrap.Destination = link
				wrap.Title = v.Title
				parent.ReplaceChild(parent, n, wrap)
				wrap.AppendChild(wrap, n)
			}
		case *ast.Link:
			// Links need their href to munged to be a real value
			link := v.Destination
			if len(link) > 0 && !markup.IsLink(link) &&
				link[0] != '#' && !bytes.HasPrefix(link, byteMailto) {
				// special case: this is not a link, a hash link or a mailto:, so it's a
				// relative URL
				lnk := string(link)
				if pc.Get(isWikiKey).(bool) {
					lnk = giteautil.URLJoin("wiki", lnk)
				}
				link = []byte(giteautil.URLJoin(pc.Get(urlPrefixKey).(string), lnk))
			}
			if len(link) > 0 && link[0] == '#' {
				link = []byte("#user-content-" + string(link)[1:])
			}
			v.Destination = link
		case *ast.List:
			if v.HasChildren() && v.FirstChild().HasChildren() && v.FirstChild().FirstChild().HasChildren() {
				if _, ok := v.FirstChild().FirstChild().FirstChild().(*east.TaskCheckBox); ok {
					v.SetAttributeString("class", []byte("task-list"))
				}
			}
		}
		return ast.WalkContinue, nil
	})
}

type prefixedIDs struct {
	values map[string]bool
}

// Generate generates a new element id.
func (p *prefixedIDs) Generate(value []byte, kind ast.NodeKind) []byte {
	dft := []byte("id")
	if kind == ast.KindHeading {
		dft = []byte("heading")
	}
	return p.GenerateWithDefault(value, dft)
}

// Generate generates a new element id.
func (p *prefixedIDs) GenerateWithDefault(value []byte, dft []byte) []byte {
	result := common.CleanValue(value)
	if len(result) == 0 {
		result = dft
	}
	if !bytes.HasPrefix(result, []byte("user-content-")) {
		result = append([]byte("user-content-"), result...)
	}
	if _, ok := p.values[util.BytesToReadOnlyString(result)]; !ok {
		p.values[util.BytesToReadOnlyString(result)] = true
		return result
	}
	for i := 1; ; i++ {
		newResult := fmt.Sprintf("%s-%d", result, i)
		if _, ok := p.values[newResult]; !ok {
			p.values[newResult] = true
			return []byte(newResult)
		}
	}
}

// Put puts a given element id to the used ids table.
func (p *prefixedIDs) Put(value []byte) {
	p.values[util.BytesToReadOnlyString(value)] = true
}

func newPrefixedIDs() *prefixedIDs {
	return &prefixedIDs{
		values: map[string]bool{},
	}
}

// NewTaskCheckBoxHTMLRenderer creates a TaskCheckBoxHTMLRenderer to render tasklists
// in the gitea form.
func NewTaskCheckBoxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
	r := &TaskCheckBoxHTMLRenderer{
		Config: html.NewConfig(),
	}
	for _, opt := range opts {
		opt.SetHTMLOption(&r.Config)
	}
	return r
}

// TaskCheckBoxHTMLRenderer is a renderer.NodeRenderer implementation that
// renders checkboxes in list items.
// Overrides the default goldmark one to present the gitea format
type TaskCheckBoxHTMLRenderer struct {
	html.Config
}

// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
func (r *TaskCheckBoxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
	reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox)
}

func (r *TaskCheckBoxHTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
	if !entering {
		return ast.WalkContinue, nil
	}
	n := node.(*east.TaskCheckBox)

	end := ">"
	if r.XHTML {
		end = " />"
	}
	var err error
	if n.IsChecked {
		_, err = w.WriteString(`<span class="ui fitted disabled checkbox"><input type="checkbox" disabled="disabled"` + end + `<label` + end + `</span>`)
	} else {
		_, err = w.WriteString(`<span class="ui checked fitted disabled checkbox"><input type="checkbox" checked="" disabled="disabled"` + end + `<label` + end + `</span>`)
	}
	if err != nil {
		return ast.WalkStop, err
	}
	return ast.WalkContinue, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. 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 ctfe

import (
	"crypto/sha256"
	"encoding/pem"
	"fmt"
	"io/ioutil"

	"github.com/golang/glog"
	"github.com/google/certificate-transparency-go/x509"
)

// String for certificate blocks in BEGIN / END PEM headers
const pemCertificateBlockType string = "CERTIFICATE"

// PEMCertPool is a wrapper / extension to x509.CertPool. It allows us to access the
// raw certs, which we need to serve get-roots request and has stricter handling on loading
// certs into the pool. CertPool ignores errors if at least one cert loads correctly but
// PEMCertPool requires all certs to load.
type PEMCertPool struct {
	// maps from sha-256 to certificate, used for dup detection
	fingerprintToCertMap map[[sha256.Size]byte]x509.Certificate
	rawCerts             []*x509.Certificate
	certPool             *x509.CertPool
}

// NewPEMCertPool creates a new, empty,  instance of PEMCertPool.
func NewPEMCertPool() *PEMCertPool {
	return &PEMCertPool{fingerprintToCertMap: make(map[[sha256.Size]byte]x509.Certificate), certPool: x509.NewCertPool()}
}

// AddCert adds a certificate to a pool. Uses fingerprint to weed out duplicates.
// cert must not be nil.
func (p *PEMCertPool) AddCert(cert *x509.Certificate) {
	fingerprint := sha256.Sum256(cert.Raw)
	_, ok := p.fingerprintToCertMap[fingerprint]

	if !ok {
		p.fingerprintToCertMap[fingerprint] = *cert
		p.certPool.AddCert(cert)
		p.rawCerts = append(p.rawCerts, cert)
	}
}

// AppendCertsFromPEM adds certs to the pool from a byte slice assumed to contain PEM encoded data.
// Skips over non certificate blocks in the data. Returns true if all certificates in the
// data were parsed and added to the pool successfully and at least one certificate was found.
func (p *PEMCertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
	for len(pemCerts) > 0 {
		var block *pem.Block
		block, pemCerts = pem.Decode(pemCerts)
		if block == nil {
			break
		}
		if block.Type != pemCertificateBlockType || len(block.Headers) != 0 {
			continue
		}

		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			glog.Warningf("error parsing PEM certificate: %v", err)
			return false
		}

		p.AddCert(cert)
		ok = true
	}

	return
}

// AppendCertsFromPEMFile adds certs from a file that contains concatenated PEM data.
func (p *PEMCertPool) AppendCertsFromPEMFile(pemFile string) error {
	pemData, err := ioutil.ReadFile(pemFile)
	if err != nil {
		return fmt.Errorf("failed to load PEM certs file: %v", err)
	}

	if !p.AppendCertsFromPEM(pemData) {
		return fmt.Errorf("failed to parse PEM certs file: %v", err)
	}
	return nil
}

// Subjects returns a list of the DER-encoded subjects of all of the certificates in the pool.
func (p *PEMCertPool) Subjects() (res [][]byte) {
	return p.certPool.Subjects()
}

// CertPool returns the underlying CertPool.
func (p *PEMCertPool) CertPool() *x509.CertPool {
	return p.certPool
}

// RawCertificates returns a list of the raw bytes of certificates that are in this pool
func (p *PEMCertPool) RawCertificates() []*x509.Certificate {
	return p.rawCerts
}
<commit_msg>Don't output <nil> error (#60)<commit_after>// Copyright 2016 Google Inc. 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 ctfe

import (
	"crypto/sha256"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"

	"github.com/golang/glog"
	"github.com/google/certificate-transparency-go/x509"
)

// String for certificate blocks in BEGIN / END PEM headers
const pemCertificateBlockType string = "CERTIFICATE"

// PEMCertPool is a wrapper / extension to x509.CertPool. It allows us to access the
// raw certs, which we need to serve get-roots request and has stricter handling on loading
// certs into the pool. CertPool ignores errors if at least one cert loads correctly but
// PEMCertPool requires all certs to load.
type PEMCertPool struct {
	// maps from sha-256 to certificate, used for dup detection
	fingerprintToCertMap map[[sha256.Size]byte]x509.Certificate
	rawCerts             []*x509.Certificate
	certPool             *x509.CertPool
}

// NewPEMCertPool creates a new, empty,  instance of PEMCertPool.
func NewPEMCertPool() *PEMCertPool {
	return &PEMCertPool{fingerprintToCertMap: make(map[[sha256.Size]byte]x509.Certificate), certPool: x509.NewCertPool()}
}

// AddCert adds a certificate to a pool. Uses fingerprint to weed out duplicates.
// cert must not be nil.
func (p *PEMCertPool) AddCert(cert *x509.Certificate) {
	fingerprint := sha256.Sum256(cert.Raw)
	_, ok := p.fingerprintToCertMap[fingerprint]

	if !ok {
		p.fingerprintToCertMap[fingerprint] = *cert
		p.certPool.AddCert(cert)
		p.rawCerts = append(p.rawCerts, cert)
	}
}

// AppendCertsFromPEM adds certs to the pool from a byte slice assumed to contain PEM encoded data.
// Skips over non certificate blocks in the data. Returns true if all certificates in the
// data were parsed and added to the pool successfully and at least one certificate was found.
func (p *PEMCertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
	for len(pemCerts) > 0 {
		var block *pem.Block
		block, pemCerts = pem.Decode(pemCerts)
		if block == nil {
			break
		}
		if block.Type != pemCertificateBlockType || len(block.Headers) != 0 {
			continue
		}

		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			glog.Warningf("error parsing PEM certificate: %v", err)
			return false
		}

		p.AddCert(cert)
		ok = true
	}

	return
}

// AppendCertsFromPEMFile adds certs from a file that contains concatenated PEM data.
func (p *PEMCertPool) AppendCertsFromPEMFile(pemFile string) error {
	pemData, err := ioutil.ReadFile(pemFile)
	if err != nil {
		return fmt.Errorf("failed to load PEM certs file: %v", err)
	}

	if !p.AppendCertsFromPEM(pemData) {
		return errors.New("failed to parse PEM certs file")
	}
	return nil
}

// Subjects returns a list of the DER-encoded subjects of all of the certificates in the pool.
func (p *PEMCertPool) Subjects() (res [][]byte) {
	return p.certPool.Subjects()
}

// CertPool returns the underlying CertPool.
func (p *PEMCertPool) CertPool() *x509.CertPool {
	return p.certPool
}

// RawCertificates returns a list of the raw bytes of certificates that are in this pool
func (p *PEMCertPool) RawCertificates() []*x509.Certificate {
	return p.rawCerts
}
<|endoftext|>


<commit_before>package nativebase

import (
    "github.com/johnny-morrice/godelbrot/base"
)

type MockRenderApplication struct {
    base.MockRenderApplication
    MockNativeCoordProvider
}

type MockNativeCoordProvider struct {
    TNativeUserCoords bool

    PlaneMin complex128
    PlaneMax complex128
    FixAspect bool
}

func (mock *MockNativeCoordProvider) NativeUserCoords() (complex128, complex128) {
    mock.TNativeUserCoords = true
    return mock.PlaneMin, mock.PlaneMax
}<commit_msg>Remove misplaced field<commit_after>package nativebase

import (
    "github.com/johnny-morrice/godelbrot/base"
)

type MockRenderApplication struct {
    base.MockRenderApplication
    MockNativeCoordProvider
}

type MockNativeCoordProvider struct {
    TNativeUserCoords bool

    PlaneMin complex128
    PlaneMax complex128
}

func (mock *MockNativeCoordProvider) NativeUserCoords() (complex128, complex128) {
    mock.TNativeUserCoords = true
    return mock.PlaneMin, mock.PlaneMax
}<|endoftext|>


<commit_before>package morningStar

import (
	"../jsonHttp"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"sync"
	"time"
)

const IDS_URL = `https://elasticsearch.vibioh.fr/funds/morningStarId/_search?size=8000`
const PERFORMANCE_URL = `http://www.morningstar.fr/fr/funds/snapshot/snapshot.aspx?tab=1&id=`
const VOLATILITE_URL = `http://www.morningstar.fr/fr/funds/snapshot/snapshot.aspx?tab=2&id=`
const REFRESH_DELAY_HOURS = 12
const CONCURRENT_FETCHER = 32

var EMPTY_BYTE = []byte(``)
var ZERO_BYTE = []byte(`0`)
var PERIOD_BYTE = []byte(`.`)
var COMMA_BYTE = []byte(`,`)
var PERCENT_BYTE = []byte(`%`)
var AMP_BYTE = []byte(`&`)
var HTML_AMP_BYTE = []byte(`&`)

var LIST_REQUEST = regexp.MustCompile(`^/list$`)
var PERF_REQUEST = regexp.MustCompile(`^/(.+?)$`)

var ID = regexp.MustCompile(`"_id":"(.*?)"`)
var ISIN = regexp.MustCompile(`ISIN.:(\S+)`)
var LABEL = regexp.MustCompile(`<h1[^>]*?>((?:.|\n)*?)</h1>`)
var RATING = regexp.MustCompile(`<span\sclass=".*?stars([0-9]).*?">`)
var CATEGORY = regexp.MustCompile(`<span[^>]*?>Catégorie</span>.*?<span[^>]*?>(.*?)</span>`)
var PERF_ONE_MONTH = regexp.MustCompile(`<td[^>]*?>1 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_THREE_MONTH = regexp.MustCompile(`<td[^>]*?>3 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_SIX_MONTH = regexp.MustCompile(`<td[^>]*?>6 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_ONE_YEAR = regexp.MustCompile(`<td[^>]*?>1 an</td><td[^>]*?>(.*?)</td>`)
var VOL_3_YEAR = regexp.MustCompile(`<td[^>]*?>Ecart-type 3 ans.?</td><td[^>]*?>(.*?)</td>`)

type SyncedMap struct {
	sync.RWMutex
	performances map[string]Performance
}

func (m *SyncedMap) get(key string) (Performance, bool) {
	m.RLock()
	defer m.RUnlock()

	performance, ok := m.performances[key]
	return performance, ok
}

func (m *SyncedMap) push(key string, performance Performance) {
	m.Lock()
	defer m.Unlock()

	m.performances[key] = performance
}

var PERFORMANCE_CACHE = SyncedMap{performances: make(map[string]Performance)}

type Performance struct {
	Id            string    `json:"id"`
	Isin          string    `json:"isin"`
	Label         string    `json:"label"`
	Category      string    `json:"category"`
	Rating        string    `json:"rating"`
	OneMonth      float64   `json:"1m"`
	ThreeMonth    float64   `json:"3m"`
	SixMonth      float64   `json:"6m"`
	OneYear       float64   `json:"1y"`
	VolThreeYears float64   `json:"v3y"`
	Score         float64   `json:"score"`
	Update        time.Time `json:"ts"`
}

type Results struct {
	Results interface{} `json:"results"`
}

func init() {
	go func() {
		ids := fetchIds()
		refreshCache(ids)

		c := time.Tick(REFRESH_DELAY_HOURS * time.Hour)
		for range c {
			refreshCache(ids)
		}
	}()
}

func refreshCache(ids [][]byte) {
	log.Print(`Cache refresh - start`)
	defer log.Print(`Cache refresh - end`)
	for _, performance := range retrievePerformances(ids, fetchPerformance) {
		PERFORMANCE_CACHE.push(performance.Id, *performance)
	}
}

func readBody(body io.ReadCloser) ([]byte, error) {
	defer body.Close()
	return ioutil.ReadAll(body)
}

func getBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf(`Error while retrieving data from %s: %v`, url, err)
	}

	if response.StatusCode >= 400 {
		return nil, fmt.Errorf(`Got error %d while getting %s`, response.StatusCode, url)
	}

	body, err := readBody(response.Body)
	if err != nil {
		return nil, fmt.Errorf(`Error while reading body of %s: %v`, url, err)
	}

	return body, nil
}

func extractLabel(extract *regexp.Regexp, body []byte, defaultValue []byte) []byte {
	match := extract.FindSubmatch(body)
	if match == nil {
		return defaultValue
	}

	return bytes.Replace(match[1], HTML_AMP_BYTE, AMP_BYTE, -1)
}

func extractPerformance(extract *regexp.Regexp, body []byte) float64 {
	dotResult := bytes.Replace(extractLabel(extract, body, EMPTY_BYTE), COMMA_BYTE, PERIOD_BYTE, -1)
	percentageResult := bytes.Replace(dotResult, PERCENT_BYTE, EMPTY_BYTE, -1)
	trimResult := bytes.TrimSpace(percentageResult)

	result, err := strconv.ParseFloat(string(trimResult), 64)
	if err != nil {
		return 0.0
	}
	return result
}

func cleanId(morningStarId []byte) string {
	return string(bytes.ToLower(morningStarId))
}

func fetchPerformance(morningStarId []byte) (*Performance, error) {
	cleanId := cleanId(morningStarId)
	performanceBody, err := getBody(PERFORMANCE_URL + cleanId)
	if err != nil {
		return nil, err
	}

	volatiliteBody, err := getBody(VOLATILITE_URL + cleanId)
	if err != nil {
		return nil, err
	}

	isin := string(extractLabel(ISIN, performanceBody, EMPTY_BYTE))
	label := string(extractLabel(LABEL, performanceBody, EMPTY_BYTE))
	rating := string(extractLabel(RATING, performanceBody, ZERO_BYTE))
	category := string(extractLabel(CATEGORY, performanceBody, EMPTY_BYTE))
	oneMonth := extractPerformance(PERF_ONE_MONTH, performanceBody)
	threeMonths := extractPerformance(PERF_THREE_MONTH, performanceBody)
	sixMonths := extractPerformance(PERF_SIX_MONTH, performanceBody)
	oneYear := extractPerformance(PERF_ONE_YEAR, performanceBody)
	volThreeYears := extractPerformance(VOL_3_YEAR, volatiliteBody)

	score := (0.25 * oneMonth) + (0.3 * threeMonths) + (0.25 * sixMonths) + (0.2 * oneYear) - (0.1 * volThreeYears)
	scoreTruncated := float64(int(score*100)) / 100

	return &Performance{cleanId, isin, label, category, rating, oneMonth, threeMonths, sixMonths, oneYear, volThreeYears, scoreTruncated, time.Now()}, nil
}

func fetchIds() [][]byte {
	if idsBody, err := getBody(IDS_URL); err != nil {
		log.Print(err)
		return nil
	} else {
		idsMatch := ID.FindAllSubmatch(idsBody, -1)

		ids := make([][]byte, 0, len(idsMatch))
		for _, match := range idsMatch {
			ids = append(ids, match[1])
		}

		return ids
	}
}

func retrievePerformance(morningStarId []byte) (*Performance, error) {
	cleanId := cleanId(morningStarId)

	performance, ok := PERFORMANCE_CACHE.get(cleanId)
	if ok && time.Now().Add(time.Hour*-(REFRESH_DELAY_HOURS+1)).Before(performance.Update) {
		return &performance, nil
	}

	if performance, err := fetchPerformance(morningStarId); err != nil {
		return nil, err
	} else {
		PERFORMANCE_CACHE.push(cleanId, *performance)
		return performance, nil
	}
}

func concurrentRetrievePerformances(ids [][]byte, wg *sync.WaitGroup, performances chan<- *Performance, method func([]byte) (*Performance, error)) {
	tokens := make(chan int, CONCURRENT_FETCHER)

	clearSemaphores := func() {
		wg.Done()
		<-tokens
	}

	for _, id := range ids {
		tokens <- 1

		go func(morningStarId []byte) {
			defer clearSemaphores()
			if performance, err := method(morningStarId); err == nil {
				performances <- performance
			}
		}(id)
	}
}

func retrievePerformances(ids [][]byte, method func([]byte) (*Performance, error)) []*Performance {
	var wg sync.WaitGroup
	wg.Add(len(ids))

	performances := make(chan *Performance, CONCURRENT_FETCHER)
	go concurrentRetrievePerformances(ids, &wg, performances, method)

	go func() {
		wg.Wait()
		close(performances)
	}()

	results := make([]*Performance, 0, len(ids))
	for performance := range performances {
		results = append(results, performance)
	}

	return results
}

func performanceHandler(w http.ResponseWriter, morningStarId []byte) {
	performance, err := retrievePerformance(morningStarId)

	if err != nil {
		http.Error(w, err.Error(), 500)
	} else {
		jsonHttp.ResponseJson(w, *performance)
	}
}

func listHandler(w http.ResponseWriter, r *http.Request) {
	listBody, err := readBody(r.Body)
	if err != nil {
		http.Error(w, `Error while reading body for list: `+err.Error(), 500)
		return
	}

	if len(bytes.TrimSpace(listBody)) == 0 {
		jsonHttp.ResponseJson(w, Results{[0]Performance{}})
		return
	}

	jsonHttp.ResponseJson(w, Results{retrievePerformances(bytes.Split(listBody, COMMA_BYTE), retrievePerformance)})
}

type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	urlPath := []byte(r.URL.Path)

	if LIST_REQUEST.Match(urlPath) {
		listHandler(w, r)
	} else if PERF_REQUEST.Match(urlPath) {
		performanceHandler(w, PERF_REQUEST.FindSubmatch(urlPath)[1])
	}
}
<commit_msg>Changing refreshing cache<commit_after>package morningStar

import (
	"../jsonHttp"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"sync"
	"time"
)

const IDS_URL = `https://elasticsearch.vibioh.fr/funds/morningStarId/_search?size=8000`
const PERFORMANCE_URL = `http://www.morningstar.fr/fr/funds/snapshot/snapshot.aspx?tab=1&id=`
const VOLATILITE_URL = `http://www.morningstar.fr/fr/funds/snapshot/snapshot.aspx?tab=2&id=`
const REFRESH_DELAY_HOURS = 12
const CONCURRENT_FETCHER = 32

var EMPTY_BYTE = []byte(``)
var ZERO_BYTE = []byte(`0`)
var PERIOD_BYTE = []byte(`.`)
var COMMA_BYTE = []byte(`,`)
var PERCENT_BYTE = []byte(`%`)
var AMP_BYTE = []byte(`&`)
var HTML_AMP_BYTE = []byte(`&`)

var LIST_REQUEST = regexp.MustCompile(`^/list$`)
var PERF_REQUEST = regexp.MustCompile(`^/(.+?)$`)

var ID = regexp.MustCompile(`"_id":"(.*?)"`)
var ISIN = regexp.MustCompile(`ISIN.:(\S+)`)
var LABEL = regexp.MustCompile(`<h1[^>]*?>((?:.|\n)*?)</h1>`)
var RATING = regexp.MustCompile(`<span\sclass=".*?stars([0-9]).*?">`)
var CATEGORY = regexp.MustCompile(`<span[^>]*?>Catégorie</span>.*?<span[^>]*?>(.*?)</span>`)
var PERF_ONE_MONTH = regexp.MustCompile(`<td[^>]*?>1 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_THREE_MONTH = regexp.MustCompile(`<td[^>]*?>3 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_SIX_MONTH = regexp.MustCompile(`<td[^>]*?>6 mois</td><td[^>]*?>(.*?)</td>`)
var PERF_ONE_YEAR = regexp.MustCompile(`<td[^>]*?>1 an</td><td[^>]*?>(.*?)</td>`)
var VOL_3_YEAR = regexp.MustCompile(`<td[^>]*?>Ecart-type 3 ans.?</td><td[^>]*?>(.*?)</td>`)

type Performance struct {
	Id            string    `json:"id"`
	Isin          string    `json:"isin"`
	Label         string    `json:"label"`
	Category      string    `json:"category"`
	Rating        string    `json:"rating"`
	OneMonth      float64   `json:"1m"`
	ThreeMonth    float64   `json:"3m"`
	SixMonth      float64   `json:"6m"`
	OneYear       float64   `json:"1y"`
	VolThreeYears float64   `json:"v3y"`
	Score         float64   `json:"score"`
	Update        time.Time `json:"ts"`
}

type SyncedMap struct {
	sync.RWMutex
	performances map[string]*Performance
}

func (m *SyncedMap) get(key string) (*Performance, bool) {
	m.RLock()
	defer m.RUnlock()

	performance, ok := m.performances[key]
	return performance, ok
}

func (m *SyncedMap) push(key string, performance *Performance) {
	m.Lock()
	defer m.Unlock()

	m.performances[key] = performance
}

var PERFORMANCE_CACHE = SyncedMap{performances: make(map[string]*Performance)}

type Results struct {
	Results interface{} `json:"results"`
}

func init() {
	go func() {
		refreshCache()
		c := time.Tick(REFRESH_DELAY_HOURS * time.Hour)
		for range c {
			refreshCache()
		}
	}()
}

func refreshCache() {
	log.Print(`Cache refresh - start`)
	defer log.Print(`Cache refresh - end`)
	for _, performance := range retrievePerformances(fetchIds(), fetchPerformance) {
		PERFORMANCE_CACHE.push(performance.Id, performance)
	}
}

func readBody(body io.ReadCloser) ([]byte, error) {
	defer body.Close()
	return ioutil.ReadAll(body)
}

func getBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf(`Error while retrieving data from %s: %v`, url, err)
	}

	if response.StatusCode >= 400 {
		return nil, fmt.Errorf(`Got error %d while getting %s`, response.StatusCode, url)
	}

	body, err := readBody(response.Body)
	if err != nil {
		return nil, fmt.Errorf(`Error while reading body of %s: %v`, url, err)
	}

	return body, nil
}

func extractLabel(extract *regexp.Regexp, body []byte, defaultValue []byte) []byte {
	match := extract.FindSubmatch(body)
	if match == nil {
		return defaultValue
	}

	return bytes.Replace(match[1], HTML_AMP_BYTE, AMP_BYTE, -1)
}

func extractPerformance(extract *regexp.Regexp, body []byte) float64 {
	dotResult := bytes.Replace(extractLabel(extract, body, EMPTY_BYTE), COMMA_BYTE, PERIOD_BYTE, -1)
	percentageResult := bytes.Replace(dotResult, PERCENT_BYTE, EMPTY_BYTE, -1)
	trimResult := bytes.TrimSpace(percentageResult)

	result, err := strconv.ParseFloat(string(trimResult), 64)
	if err != nil {
		return 0.0
	}
	return result
}

func cleanId(morningStarId []byte) string {
	return string(bytes.ToLower(morningStarId))
}

func fetchPerformance(morningStarId []byte) (*Performance, error) {
	cleanId := cleanId(morningStarId)
	performanceBody, err := getBody(PERFORMANCE_URL + cleanId)
	if err != nil {
		return nil, err
	}

	volatiliteBody, err := getBody(VOLATILITE_URL + cleanId)
	if err != nil {
		return nil, err
	}

	isin := string(extractLabel(ISIN, performanceBody, EMPTY_BYTE))
	label := string(extractLabel(LABEL, performanceBody, EMPTY_BYTE))
	rating := string(extractLabel(RATING, performanceBody, ZERO_BYTE))
	category := string(extractLabel(CATEGORY, performanceBody, EMPTY_BYTE))
	oneMonth := extractPerformance(PERF_ONE_MONTH, performanceBody)
	threeMonths := extractPerformance(PERF_THREE_MONTH, performanceBody)
	sixMonths := extractPerformance(PERF_SIX_MONTH, performanceBody)
	oneYear := extractPerformance(PERF_ONE_YEAR, performanceBody)
	volThreeYears := extractPerformance(VOL_3_YEAR, volatiliteBody)

	score := (0.25 * oneMonth) + (0.3 * threeMonths) + (0.25 * sixMonths) + (0.2 * oneYear) - (0.1 * volThreeYears)
	scoreTruncated := float64(int(score*100)) / 100

	return &Performance{cleanId, isin, label, category, rating, oneMonth, threeMonths, sixMonths, oneYear, volThreeYears, scoreTruncated, time.Now()}, nil
}

func fetchIds() [][]byte {
	if idsBody, err := getBody(IDS_URL); err != nil {
		log.Print(err)
		return nil
	} else {
		idsMatch := ID.FindAllSubmatch(idsBody, -1)

		ids := make([][]byte, 0, len(idsMatch))
		for _, match := range idsMatch {
			ids = append(ids, match[1])
		}

		return ids
	}
}

func retrievePerformance(morningStarId []byte) (*Performance, error) {
	cleanId := cleanId(morningStarId)

	performance, ok := PERFORMANCE_CACHE.get(cleanId)
	if ok && time.Now().Add(time.Hour*-(REFRESH_DELAY_HOURS+1)).Before(performance.Update) {
		return performance, nil
	}

	if performance, err := fetchPerformance(morningStarId); err != nil {
		return nil, err
	} else {
		PERFORMANCE_CACHE.push(cleanId, performance)
		return performance, nil
	}
}

func concurrentRetrievePerformances(ids [][]byte, wg *sync.WaitGroup, performances chan<- *Performance, method func([]byte) (*Performance, error)) {
	tokens := make(chan int, CONCURRENT_FETCHER)

	clearSemaphores := func() {
		wg.Done()
		<-tokens
	}

	for _, id := range ids {
		tokens <- 1

		go func(morningStarId []byte) {
			defer clearSemaphores()
			if performance, err := method(morningStarId); err == nil {
				performances <- performance
			}
		}(id)
	}
}

func retrievePerformances(ids [][]byte, method func([]byte) (*Performance, error)) []*Performance {
	var wg sync.WaitGroup
	wg.Add(len(ids))

	performances := make(chan *Performance, CONCURRENT_FETCHER)
	go concurrentRetrievePerformances(ids, &wg, performances, method)

	go func() {
		wg.Wait()
		close(performances)
	}()

	results := make([]*Performance, 0, len(ids))
	for performance := range performances {
		results = append(results, performance)
	}

	return results
}

func performanceHandler(w http.ResponseWriter, morningStarId []byte) {
	performance, err := retrievePerformance(morningStarId)

	if err != nil {
		http.Error(w, err.Error(), 500)
	} else {
		jsonHttp.ResponseJson(w, *performance)
	}
}

func listHandler(w http.ResponseWriter, r *http.Request) {
	listBody, err := readBody(r.Body)
	if err != nil {
		http.Error(w, `Error while reading body for list: `+err.Error(), 500)
		return
	}

	if len(bytes.TrimSpace(listBody)) == 0 {
		jsonHttp.ResponseJson(w, Results{[0]Performance{}})
		return
	}

	jsonHttp.ResponseJson(w, Results{retrievePerformances(bytes.Split(listBody, COMMA_BYTE), retrievePerformance)})
}

type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	urlPath := []byte(r.URL.Path)

	if LIST_REQUEST.Match(urlPath) {
		listHandler(w, r)
	} else if PERF_REQUEST.Match(urlPath) {
		performanceHandler(w, PERF_REQUEST.FindSubmatch(urlPath)[1])
	}
}
<|endoftext|>


<commit_before>package index

import (
	"context"
	"database/sql"
	"time"

	"github.com/acoustid/go-acoustid/database/fingerprint_db"
	pb "github.com/acoustid/go-acoustid/proto/index"
	"github.com/acoustid/go-acoustid/common"

	_ "github.com/lib/pq"
	log "github.com/sirupsen/logrus"
)

const UpdateBatchSize = 1000

type UpdaterConfig struct {
	Database *common.DatabaseConfig
	Index    *IndexConfig
	Debug    bool
}

func NewUpdaterConfig() *UpdaterConfig {
	return &UpdaterConfig{
		Database: common.NewDatabaseConfig(),
		Index:    NewIndexConfig(),
	}
}

func RunUpdater(cfg *UpdaterConfig) {
	if cfg.Debug {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}

	db, err := sql.Open("postgres", cfg.Database.URL().String())
	if err != nil {
		log.Fatalf("Failed to connect to database: %v", err)
	}
	defer db.Close()

	err = db.Ping()
	if err != nil {
		log.Fatalf("Can't ping the database: %v", err)
	}

	idx, err := ConnectWithConfig(context.Background(), cfg.Index)
	if err != nil {
		log.Fatalf("Failed to connect to index: %s", err)
	}
	defer idx.Close(context.Background())

	fpDB := fingerprint_db.NewFingerprintDB(db)

	const NoDelay = 0 * time.Millisecond
	const MinDelay = 10 * time.Millisecond
	const MaxDelay = time.Minute

	var delay time.Duration

	for {
		if delay > NoDelay {
			if delay > MaxDelay {
				delay = MaxDelay
			}
			log.Debugf("Sleeping for %v", delay)
			time.Sleep(delay)
		}

		ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
		defer cancel()

		lastID, err := GetLastFingerprintID(ctx, idx)
		if err != nil {
			log.Errorf("Failed to get the last fingerprint ID in index: %s", err)
			delay = MaxDelay
			continue
		}

		fingerprints, err := fpDB.GetNextFingerprints(ctx, lastID, true, UpdateBatchSize)
		if err != nil {
			log.Errorf("Failed to get the next fingerprints to import: %s", err)
			delay = MaxDelay
			continue
		}

		_, err = idx.Insert(ctx, &pb.InsertRequest{Fingerprints: fingerprints})
		if err != nil {
			log.Errorf("Failed to import the fingerprints: %s", err)
			delay = MaxDelay
			continue
		}

		fingerprintCount := len(fingerprints)
		if fingerprintCount > 0 {
			lastID = fingerprints[fingerprintCount-1].Id
			log.Infof("Added %d fingerprints up to ID %d", fingerprintCount, lastID)
		} else {
			log.Debugf("Added %d fingerprints up to ID %d", fingerprintCount, lastID)
		}

		if fingerprintCount == 0 {
			if delay > NoDelay {
				delay += (delay * 10) / 100
			} else {
				delay = MinDelay
			}
		} else {
			delay = NoDelay
		}
	}
}
<commit_msg>Reconnect on index connection error<commit_after>package index

import (
	"context"
	"database/sql"
	"time"

	"github.com/acoustid/go-acoustid/common"
	"github.com/acoustid/go-acoustid/database/fingerprint_db"
	pb "github.com/acoustid/go-acoustid/proto/index"

	_ "github.com/lib/pq"
	log "github.com/sirupsen/logrus"
)

const UpdateBatchSize = 1000

type UpdaterConfig struct {
	Database *common.DatabaseConfig
	Index    *IndexConfig
	Debug    bool
}

func NewUpdaterConfig() *UpdaterConfig {
	return &UpdaterConfig{
		Database: common.NewDatabaseConfig(),
		Index:    NewIndexConfig(),
	}
}

func RunUpdater(cfg *UpdaterConfig) {
	if cfg.Debug {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}

	db, err := sql.Open("postgres", cfg.Database.URL().String())
	if err != nil {
		log.Fatalf("Failed to connect to database: %v", err)
		return
	}
	defer db.Close()

	err = db.Ping()
	if err != nil {
		log.Fatalf("Can't ping the database: %v", err)
		return
	}

	idx, err := ConnectWithConfig(context.Background(), cfg.Index)
	if err != nil {
		log.Fatalf("Failed to connect to index: %s", err)
		return
	}
	defer idx.Close(context.Background())

	fpDB := fingerprint_db.NewFingerprintDB(db)

	const NoDelay = 0 * time.Millisecond
	const MinDelay = 10 * time.Millisecond
	const MaxDelay = time.Minute

	var delay time.Duration

	for {
		if !idx.IsOK() {
			log.Infof("Index connection failed, reconnecting...")
			idx, err = ConnectWithConfig(context.Background(), cfg.Index)
			if err != nil {
				log.Fatalf("Failed to connect to index: %s", err)
				return
			}
		}

		if delay > NoDelay {
			if delay > MaxDelay {
				delay = MaxDelay
			}
			log.Debugf("Sleeping for %v", delay)
			time.Sleep(delay)
		}

		ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
		defer cancel()

		lastID, err := GetLastFingerprintID(ctx, idx)
		if err != nil {
			log.Errorf("Failed to get the last fingerprint ID in index: %s", err)
			delay = MaxDelay
			continue
		}

		fingerprints, err := fpDB.GetNextFingerprints(ctx, lastID, true, UpdateBatchSize)
		if err != nil {
			log.Errorf("Failed to get the next fingerprints to import: %s", err)
			delay = MaxDelay
			continue
		}

		_, err = idx.Insert(ctx, &pb.InsertRequest{Fingerprints: fingerprints})
		if err != nil {
			log.Errorf("Failed to import the fingerprints: %s", err)
			delay = MaxDelay
			continue
		}

		fingerprintCount := len(fingerprints)
		if fingerprintCount > 0 {
			lastID = fingerprints[fingerprintCount-1].Id
			log.Infof("Added %d fingerprints up to ID %d", fingerprintCount, lastID)
		} else {
			log.Debugf("Added %d fingerprints up to ID %d", fingerprintCount, lastID)
		}

		if fingerprintCount == 0 {
			if delay > NoDelay {
				delay += (delay * 10) / 100
			} else {
				delay = MinDelay
			}
		} else {
			delay = NoDelay
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-present, Alibaba Cloud 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 config

import (
	"github.com/aliyun/aliyun-cli/cli"
	"github.com/aliyun/aliyun-cli/i18n"
)

func NewConfigureDeleteCommand() *cli.Command {
	cmd := &cli.Command{
		Name:  "delete",
		Usage: "delete --profile <profileName>",
		Short: i18n.T("Delete the specified profile", "删除指定配置"),
		Run: func(c *cli.Context, args []string) error {
			profileName, ok := ProfileFlag(c.Flags()).GetValue()
			if !ok {
				cli.Errorf(c.Stderr(), "missing --profile <profileName>\n")
				cli.Noticef(c.Stderr(), "\nusage:\n  aliyun configure delete --profile <profileName>\n")
				return nil
			}
			doConfigureDelete(c, profileName)
			return nil
		},
	}
	return cmd
}

func doConfigureDelete(ctx *cli.Context, profileName string) {
	conf, err := hookLoadConfiguration(LoadConfiguration)(GetConfigPath() + "/" + configFile)
	if err != nil {
		cli.Errorf(ctx.Stderr(), "ERROR: load configure failed: %v\n", err)
	}
	deleted := false
	r := make([]Profile, 0)
	for _, p := range conf.Profiles {
		if p.Name != profileName {
			r = append(r, p)
		} else {
			deleted = true
		}
	}

	if !deleted {
		cli.Errorf(ctx.Stderr(), "Error: configuration profile `%s` not found\n", profileName)
		return
	}

	conf.Profiles = r
	if conf.CurrentProfile == profileName {
		if len(conf.Profiles) > 0 {
			conf.CurrentProfile = conf.Profiles[0].Name
		} else {
			conf.CurrentProfile = DefaultConfigProfileName
		}
	}

	err = hookSaveConfiguration(SaveConfiguration)(conf)
	if err != nil {
		cli.Errorf(ctx.Stderr(), "Error: save configuration failed %s\n", err)
	}
}
<commit_msg>make the help message consisit with others<commit_after>// Copyright (c) 2009-present, Alibaba Cloud 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 config

import (
	"github.com/aliyun/aliyun-cli/cli"
	"github.com/aliyun/aliyun-cli/i18n"
)

func NewConfigureDeleteCommand() *cli.Command {
	cmd := &cli.Command{
		Name:  "delete",
		Usage: "delete --profile <profileName>",
		Short: i18n.T("delete the specified profile", "删除指定配置"),
		Run: func(c *cli.Context, args []string) error {
			profileName, ok := ProfileFlag(c.Flags()).GetValue()
			if !ok {
				cli.Errorf(c.Stderr(), "missing --profile <profileName>\n")
				cli.Noticef(c.Stderr(), "\nusage:\n  aliyun configure delete --profile <profileName>\n")
				return nil
			}
			doConfigureDelete(c, profileName)
			return nil
		},
	}
	return cmd
}

func doConfigureDelete(ctx *cli.Context, profileName string) {
	conf, err := hookLoadConfiguration(LoadConfiguration)(GetConfigPath() + "/" + configFile)
	if err != nil {
		cli.Errorf(ctx.Stderr(), "ERROR: load configure failed: %v\n", err)
	}
	deleted := false
	r := make([]Profile, 0)
	for _, p := range conf.Profiles {
		if p.Name != profileName {
			r = append(r, p)
		} else {
			deleted = true
		}
	}

	if !deleted {
		cli.Errorf(ctx.Stderr(), "Error: configuration profile `%s` not found\n", profileName)
		return
	}

	conf.Profiles = r
	if conf.CurrentProfile == profileName {
		if len(conf.Profiles) > 0 {
			conf.CurrentProfile = conf.Profiles[0].Name
		} else {
			conf.CurrentProfile = DefaultConfigProfileName
		}
	}

	err = hookSaveConfiguration(SaveConfiguration)(conf)
	if err != nil {
		cli.Errorf(ctx.Stderr(), "Error: save configuration failed %s\n", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"flag"
	"os"
	"strings"
	"time"

	"github.com/keybase/kbfs/env"
	"github.com/keybase/kbfs/libgit"
	"github.com/keybase/kbfs/libkbfs"
	"github.com/keybase/kbfs/libpages"
	"github.com/keybase/kbfs/simplefs"
	"github.com/keybase/kbfs/stderrutils"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	fProd          bool
	fDiskCertCache bool
	fKBFSLogFile   string
	fStathatEZKey  string
	fStathatPrefix string
	fBlacklist     string
)

func init() {
	flag.BoolVar(&fProd, "prod", false, "disable development mode")
	flag.BoolVar(&fDiskCertCache, "use-disk-cert-cache", false, "cache cert on disk")
	flag.StringVar(&fKBFSLogFile, "kbfs-logfile", "kbp-kbfs.log",
		"path to KBFS log file; empty means print to stdout")
	flag.StringVar(&fStathatEZKey, "stathat-key", "",
		"stathat EZ key for reporting stats to stathat; empty disables stathat")
	flag.StringVar(&fStathatPrefix, "stathat-prefix", "kbp -",
		"prefix to stathat statnames")
	// TODO: hook up support in kbpagesd.
	// TODO: when we make kbpagesd horizontally scalable, blacklist and
	// whitelist should be dynamically configurable.
	flag.StringVar(&fBlacklist, "blacklist", "",
		"a comma-separated list of domains to block")
}

func newLogger(isCLI bool) (*zap.Logger, error) {
	// In keybase/client/go/logger fd 2 is closed. To make sure our logger can
	// log to stderr, duplicate the fd beforehand. Apparently it's important to
	// call this function before any keybase/client/go/logger logging is set
	// up.
	stderr, err := stderrutils.DupStderr()
	if err != nil {
		panic(err)
	}

	// Zap loggers use os.Stderr by default. We could pass in stderr by making
	// more boilerplate, but there's not much else we need from those. So
	// override os.Stderr temporarily as a hack to inject stderr to the zap
	// logger.
	// TODO: replace this hack when we get logstash forwarding to work.
	originalStderr := os.Stderr
	os.Stderr = stderr
	defer func() { os.Stderr = originalStderr }()

	var loggerConfig zap.Config
	if isCLI {
		// The default development logger is suitable for console. Disable
		// stacktrace here for less verbosity, and colorize loglevel for better
		// readability.
		loggerConfig = zap.NewDevelopmentConfig()
		loggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
		loggerConfig.DisableStacktrace = true
	} else {
		// The default production logger simply logs a json object for each
		// line. We override the time format to ISO8601 here to make it more
		// readable and compatible.
		loggerConfig = zap.NewProductionConfig()
		loggerConfig.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
		loggerConfig.EncoderConfig.TimeKey = "time"
	}

	return loggerConfig.Build()
}

func removeEmpty(strs []string) (ret []string) {
	ret = make([]string, 0, len(strs))
	for _, str := range strs {
		if len(str) > 0 {
			ret = append(ret, str)
		}
	}
	return ret
}

const autoGitNumWorkers = 10
const activityStatsReportInterval = 5 * time.Minute
const activityStatsPath = "./kbp-stats"

func main() {
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())

	// TODO: make logstash forwarding work and use isCLI=false here if logstash
	// forwarding address is set.
	logger, err := newLogger(true)
	if err != nil {
		panic(err)
	}

	// Hack to make libkbfs.Init connect to prod {md,b}server all the time.
	os.Setenv("KEYBASE_RUN_MODE", "prod")

	kbCtx := env.NewContext()
	params := libkbfs.DefaultInitParams(kbCtx)
	params.EnableJournal = true
	params.Debug = true
	params.LogFileConfig.Path = fKBFSLogFile
	params.LogFileConfig.MaxKeepFiles = 32
	// Enable simpleFS in case we need to debug.
	params.CreateSimpleFSInstance = simplefs.NewSimpleFS
	kbfsLog, err := libkbfs.InitLog(params, kbCtx)
	if err != nil {
		logger.Panic("libkbfs.InitLog", zap.Error(err))
	}
	kbConfig, err := libkbfs.Init(
		ctx, kbCtx, params, nil, cancel, kbfsLog)
	if err != nil {
		logger.Panic("libkbfs.Init", zap.Error(err))
	}

	shutdown := libgit.StartAutogit(kbCtx, kbConfig, &params, autoGitNumWorkers)
	defer shutdown()

	var statsReporter libpages.StatsReporter
	if len(fStathatEZKey) != 0 {
		activityStorer, err := libpages.NewFileBasedActivityStatsStorer(
			activityStatsPath, logger)
		if err != nil {
			logger.Panic(
				"libpages.NewFileBasedActivityStatsStorer", zap.Error(err))
		}
		enabler := &libpages.ActivityStatsEnabler{
			Durations: []libpages.NameableDuration{
				libpages.NameableDuration{
					Duration: time.Hour, Name: "hourly"},
				libpages.NameableDuration{
					Duration: time.Hour * 24, Name: "daily"},
				libpages.NameableDuration{
					Duration: time.Hour * 24 * 7, Name: "weekly"},
			},
			Interval: activityStatsReportInterval,
			Storer:   activityStorer,
		}
		statsReporter = libpages.NewStathatReporter(
			logger, fStathatPrefix, fStathatEZKey, enabler)
	}

	serverConfig := &libpages.ServerConfig{
		DomainBlacklist:  removeEmpty(strings.Split(fBlacklist, ",")),
		UseStaging:       !fProd,
		Logger:           logger,
		UseDiskCertCache: fDiskCertCache,
		StatsReporter:    statsReporter,
	}

	libpages.ListenAndServe(ctx, serverConfig, kbConfig)
}
<commit_msg>kbpagesd: use new way to specify protocols in params<commit_after>// Copyright 2017 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"flag"
	"os"
	"strings"
	"time"

	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"github.com/keybase/kbfs/env"
	"github.com/keybase/kbfs/libgit"
	"github.com/keybase/kbfs/libkbfs"
	"github.com/keybase/kbfs/libpages"
	"github.com/keybase/kbfs/simplefs"
	"github.com/keybase/kbfs/stderrutils"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	fProd          bool
	fDiskCertCache bool
	fKBFSLogFile   string
	fStathatEZKey  string
	fStathatPrefix string
	fBlacklist     string
)

func init() {
	flag.BoolVar(&fProd, "prod", false, "disable development mode")
	flag.BoolVar(&fDiskCertCache, "use-disk-cert-cache", false, "cache cert on disk")
	flag.StringVar(&fKBFSLogFile, "kbfs-logfile", "kbp-kbfs.log",
		"path to KBFS log file; empty means print to stdout")
	flag.StringVar(&fStathatEZKey, "stathat-key", "",
		"stathat EZ key for reporting stats to stathat; empty disables stathat")
	flag.StringVar(&fStathatPrefix, "stathat-prefix", "kbp -",
		"prefix to stathat statnames")
	// TODO: hook up support in kbpagesd.
	// TODO: when we make kbpagesd horizontally scalable, blacklist and
	// whitelist should be dynamically configurable.
	flag.StringVar(&fBlacklist, "blacklist", "",
		"a comma-separated list of domains to block")
}

func newLogger(isCLI bool) (*zap.Logger, error) {
	// In keybase/client/go/logger fd 2 is closed. To make sure our logger can
	// log to stderr, duplicate the fd beforehand. Apparently it's important to
	// call this function before any keybase/client/go/logger logging is set
	// up.
	stderr, err := stderrutils.DupStderr()
	if err != nil {
		panic(err)
	}

	// Zap loggers use os.Stderr by default. We could pass in stderr by making
	// more boilerplate, but there's not much else we need from those. So
	// override os.Stderr temporarily as a hack to inject stderr to the zap
	// logger.
	// TODO: replace this hack when we get logstash forwarding to work.
	originalStderr := os.Stderr
	os.Stderr = stderr
	defer func() { os.Stderr = originalStderr }()

	var loggerConfig zap.Config
	if isCLI {
		// The default development logger is suitable for console. Disable
		// stacktrace here for less verbosity, and colorize loglevel for better
		// readability.
		loggerConfig = zap.NewDevelopmentConfig()
		loggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
		loggerConfig.DisableStacktrace = true
	} else {
		// The default production logger simply logs a json object for each
		// line. We override the time format to ISO8601 here to make it more
		// readable and compatible.
		loggerConfig = zap.NewProductionConfig()
		loggerConfig.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
		loggerConfig.EncoderConfig.TimeKey = "time"
	}

	return loggerConfig.Build()
}

func removeEmpty(strs []string) (ret []string) {
	ret = make([]string, 0, len(strs))
	for _, str := range strs {
		if len(str) > 0 {
			ret = append(ret, str)
		}
	}
	return ret
}

const autoGitNumWorkers = 10
const activityStatsReportInterval = 5 * time.Minute
const activityStatsPath = "./kbp-stats"

func main() {
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())

	// TODO: make logstash forwarding work and use isCLI=false here if logstash
	// forwarding address is set.
	logger, err := newLogger(true)
	if err != nil {
		panic(err)
	}

	// Hack to make libkbfs.Init connect to prod {md,b}server all the time.
	os.Setenv("KEYBASE_RUN_MODE", "prod")

	kbCtx := env.NewContext()
	params := libkbfs.DefaultInitParams(kbCtx)
	params.EnableJournal = true
	params.Debug = true
	params.LogFileConfig.Path = fKBFSLogFile
	params.LogFileConfig.MaxKeepFiles = 32
	// Enable simpleFS in case we need to debug.
	createSimpleFS := func(
		libkbfsCtx libkbfs.Context, config libkbfs.Config) (
		rpc.Protocol, error) {
		return keybase1.SimpleFSProtocol(
			simplefs.NewSimpleFS(libkbfsCtx.GetGlobalContext(), config)), nil
	}
	params.AdditionalProtocolCreators = []libkbfs.AdditionalProtocolCreator{
		createSimpleFS,
	}

	kbfsLog, err := libkbfs.InitLog(params, kbCtx)
	if err != nil {
		logger.Panic("libkbfs.InitLog", zap.Error(err))
	}
	kbConfig, err := libkbfs.Init(
		ctx, kbCtx, params, nil, cancel, kbfsLog)
	if err != nil {
		logger.Panic("libkbfs.Init", zap.Error(err))
	}

	shutdown := libgit.StartAutogit(kbCtx, kbConfig, &params, autoGitNumWorkers)
	defer shutdown()

	var statsReporter libpages.StatsReporter
	if len(fStathatEZKey) != 0 {
		activityStorer, err := libpages.NewFileBasedActivityStatsStorer(
			activityStatsPath, logger)
		if err != nil {
			logger.Panic(
				"libpages.NewFileBasedActivityStatsStorer", zap.Error(err))
		}
		enabler := &libpages.ActivityStatsEnabler{
			Durations: []libpages.NameableDuration{
				libpages.NameableDuration{
					Duration: time.Hour, Name: "hourly"},
				libpages.NameableDuration{
					Duration: time.Hour * 24, Name: "daily"},
				libpages.NameableDuration{
					Duration: time.Hour * 24 * 7, Name: "weekly"},
			},
			Interval: activityStatsReportInterval,
			Storer:   activityStorer,
		}
		statsReporter = libpages.NewStathatReporter(
			logger, fStathatPrefix, fStathatEZKey, enabler)
	}

	serverConfig := &libpages.ServerConfig{
		DomainBlacklist:  removeEmpty(strings.Split(fBlacklist, ",")),
		UseStaging:       !fProd,
		Logger:           logger,
		UseDiskCertCache: fDiskCertCache,
		StatsReporter:    statsReporter,
	}

	libpages.ListenAndServe(ctx, serverConfig, kbConfig)
}
<|endoftext|>


<commit_before>package validate

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/dictyBase/apihelpers/aphcollection"
	jsapi "github.com/dictyBase/apihelpers/aphjsonapi"
	"github.com/manyminds/api2go/jsonapi"
)

//HasRelationships matches if the relationships rels are implemented in the
//given JSONAPI implementing data
func HasRelationships(data interface{}, rels []string) error {
	matchedRel := true
	matchedSelf := true
	self, ok := data.(jsapi.MarshalSelfRelations)
	if ok {
		for _, rel := range self.GetSelfLinksInfo() {
			if aphcollection.Contains(rels, rel.Name) {
				matchedSelf = true
				break
			}
		}
	}
	related, ok := data.(jsapi.MarshalRelatedRelations)
	if ok {
		for _, rel := range related.GetRelatedLinksInfo() {
			if !aphcollection.Contains(rels, rel.Name) {
				matchedRel = true
			}
		}
	}
	if !matchedRel && !matchedSelf {
		return fmt.Errorf("given names %s does not matches to any relationship", strings.Join(rels, ","))
	}
	return nil
}

// ResourceType matches name with JSONAPI type in data's fields
func ResourceType(name string, data interface{}) bool {
	if name == getTypeName(data) {
		return true
	}
	return false
}

// RelatedResourceType matches name with all related JSONAPI type in data's fields
func RelatedResourceType(name string, data interface{}) bool {
	if aphcollection.Contains(GetRelatedTypeNames(data), name) {
		return true
	}
	return false
}

// FieldNames matches all elements of s with all JSONAPI field names
// in data's fields
func FieldNames(s []string, data interface{}) bool {
	t := reflect.TypeOf(data)
	for i := 0; i < t.NumField(); i++ {
		v, ok := t.Field(i).Tag.Lookup("json")
		if ok && v != "-" && !aphcollection.Contains(s, v) {
			return false
		}
	}
	return true
}

//GetRelatedTypeNames returns the JSONAPI types of the related resources
func GetRelatedTypeNames(data interface{}) []string {
	var names []string
	mtype := reflect.TypeOf((*jsonapi.MarshalIdentifier)(nil)).Elem()
	t := reflect.TypeOf(data)
	for i := 0; i < t.NumField(); i++ {
		ftype := t.Field(i).Type
		if ftype.Kind() == reflect.Slice {
			if ftype.Elem().Implements(mtype) {
				names = append(
					names,
					jsonapi.Pluralize(
						jsonapi.Jsonify(
							ftype.Elem().Name(),
						),
					),
				)
				continue
			}
		}
		if ftype.Implements(mtype) {
			names = append(
				names,
				jsonapi.Pluralize(
					jsonapi.Jsonify(
						ftype.Name(),
					),
				),
			)
		}
	}
	return names
}

func getTypeName(data interface{}) string {
	entity, ok := data.(jsonapi.EntityNamer)
	if ok {
		return entity.GetName()
	}
	rType := reflect.TypeOf(data)
	if rType.Kind() == reflect.Ptr {
		return jsonapi.Pluralize(jsonapi.Jsonify(rType.Elem().Name()))
	}
	return jsonapi.Pluralize(jsonapi.Jsonify(rType.Name()))
}
<commit_msg>Added bunch of functions i) Gets all relationships from implementing interface ii) maps relationship struct to its name iii) check relationship names iv) check relationship types<commit_after>package validate

import (
	"fmt"
	"reflect"

	"github.com/dictyBase/apihelpers/aphcollection"
	jsapi "github.com/dictyBase/apihelpers/aphjsonapi"
	"github.com/manyminds/api2go/jsonapi"
)

func mapRelsToName(js []jsapi.RelationShipLink, fn func(jsapi.RelationShipLink) string) []string {
	s := make([]string, len(js))
	for i, v := range js {
		s[i] = fn(v)
	}
	return s
}

// GetAllRelationships returns all relationships of data interface
func GetAllRelationships(data interface{}) ([]jsapi.RelationShipLink, error) {
	var r []jsapi.RelationShipLink
	self, ok := data.(jsapi.MarshalSelfRelations)
	if ok {
		if err := self.ValidateSelfLinks(); err != nil {
			return r, err
		}
		r = append(r, self.GetSelfLinksInfo()...)
	}
	related, ok := data.(jsapi.MarshalRelatedRelations)
	if ok {
		if err := related.ValidateRelatedLinks(); err != nil {
			return r, err
		}
		r = append(r, related.GetRelatedLinksInfo()...)
	}
	if len(r) == 0 {
		return r, fmt.Errorf("no relationship defined")
	}
	return r, nil
}

//HasRelationships checks if slice a contains any relationship name in rs slice
func HasRelationships(a []string, rs []jsapi.RelationShipLink) error {
	allNames := mapRelsToName(rs, func(r jsapi.RelationShipLink) string {
		return r.Name
	})
	for _, s := range a {
		if !aphcollection.Contains(allNames, s) {
			return fmt.Errorf(
				"given name %s does not matches to any defined relationships",
				s,
			)
		}
	}
	return nil
}

// ResourceType matches name with JSONAPI type in data's fields
func ResourceType(name string, data interface{}) bool {
	if name == getTypeName(data) {
		return true
	}
	return false
}

// RelationshipResourceType checks if the given resource name matches any type
// in the rs slice
func RelationshipResourceType(name string, rs []jsapi.RelationShipLink) error {
	for _, r := range rs {
		if name == r.Type {
			return nil
		}
	}
	return fmt.Errorf("%s resource type does not matches any relationship type", name)
}

// FieldNames matches all elements of s with all JSONAPI field names
// in data's fields
func FieldNames(s []string, data interface{}) bool {
	t := reflect.TypeOf(data)
	for i := 0; i < t.NumField(); i++ {
		v, ok := t.Field(i).Tag.Lookup("json")
		if ok && v != "-" && !aphcollection.Contains(s, v) {
			return false
		}
	}
	return true
}

//GetRelatedTypeNames returns the JSONAPI types of the related resources
func GetRelatedTypeNames(data interface{}) []string {
	var names []string
	mtype := reflect.TypeOf((*jsonapi.MarshalIdentifier)(nil)).Elem()
	t := reflect.TypeOf(data)
	for i := 0; i < t.NumField(); i++ {
		ftype := t.Field(i).Type
		if ftype.Kind() == reflect.Slice {
			if ftype.Elem().Implements(mtype) {
				names = append(
					names,
					jsonapi.Pluralize(
						jsonapi.Jsonify(
							ftype.Elem().Name(),
						),
					),
				)
				continue
			}
		}
		if ftype.Implements(mtype) {
			names = append(
				names,
				jsonapi.Pluralize(
					jsonapi.Jsonify(
						ftype.Name(),
					),
				),
			)
		}
	}
	return names
}

func getTypeName(data interface{}) string {
	entity, ok := data.(jsonapi.EntityNamer)
	if ok {
		return entity.GetName()
	}
	rType := reflect.TypeOf(data)
	if rType.Kind() == reflect.Ptr {
		return jsonapi.Pluralize(jsonapi.Jsonify(rType.Elem().Name()))
	}
	return jsonapi.Pluralize(jsonapi.Jsonify(rType.Name()))
}
<|endoftext|>


<commit_before>package lexicon

import (
	"github.com/PreetamJinka/orderedlist"
	"sync"
)

type LexValue struct {
	value interface{}
}

type LexKeyValue struct {
	Key   string
	Value interface{}
}

// Lexicon is an ordered key-value store.
type Lexicon struct {
	list    *orderedlist.OrderedList
	hashmap map[string]*LexValue
	mutex   *sync.Mutex
}

// New returns an initialized lexicon.
func New() *Lexicon {
	return &Lexicon{
		list:    orderedlist.New(),
		hashmap: make(map[string]*LexValue),
		mutex:   &sync.Mutex{},
	}
}

// Set sets a key to a value.
func (lex *Lexicon) Set(key string, value interface{}) {
	lex.mutex.Lock()
	lex.hashmap[key] = &LexValue{value: value}
	lex.list.Insert(key)
	lex.mutex.Unlock()
}

// Get returns a value at the given key.
func (lex *Lexicon) Get(key string) (value interface{}) {
	lexvalue := lex.hashmap[key]
	value = lexvalue.value
	return
}

// Remove deletes a key-value pair from the lexicon.
func (lex *Lexicon) Remove(key string) {
	delete(lex.hashmap, key)
	lex.list.Remove(key)
}

// GetRange returns a slice of LexKeyValue structs.
// The range is from [start, end).
func (lex *Lexicon) GetRange(start string, end string) (kv []LexKeyValue) {
	kv = make([]LexKeyValue, 0)
	keys := lex.list.GetRange(start, end)

	for _, key := range keys {
		kv = append(kv, LexKeyValue{
			Key:   key,
			Value: lex.hashmap[key].value,
		})
	}
	return
}
<commit_msg>Add mutex locking to more functions.<commit_after>package lexicon

import (
	"github.com/PreetamJinka/orderedlist"
	"sync"
)

type LexValue struct {
	value interface{}
}

type LexKeyValue struct {
	Key   string
	Value interface{}
}

// Lexicon is an ordered key-value store.
type Lexicon struct {
	list    *orderedlist.OrderedList
	hashmap map[string]*LexValue
	mutex   *sync.Mutex
}

// New returns an initialized lexicon.
func New() *Lexicon {
	return &Lexicon{
		list:    orderedlist.New(),
		hashmap: make(map[string]*LexValue),
		mutex:   &sync.Mutex{},
	}
}

// Set sets a key to a value.
func (lex *Lexicon) Set(key string, value interface{}) {
	lex.mutex.Lock()
	lex.hashmap[key] = &LexValue{value: value}
	lex.list.Insert(key)
	lex.mutex.Unlock()
}

// Get returns a value at the given key.
func (lex *Lexicon) Get(key string) (value interface{}) {
	lexvalue := lex.hashmap[key]
	value = lexvalue.value
	return
}

// Remove deletes a key-value pair from the lexicon.
func (lex *Lexicon) Remove(key string) {
	lex.mutex.Lock()
	delete(lex.hashmap, key)
	lex.list.Remove(key)
	lex.mutex.Unlock()
}

// GetRange returns a slice of LexKeyValue structs.
// The range is from [start, end).
func (lex *Lexicon) GetRange(start string, end string) (kv []LexKeyValue) {
	kv = make([]LexKeyValue, 0)

	lex.mutex.Lock()
	keys := lex.list.GetRange(start, end)
	lex.mutex.Unlock()

	for _, key := range keys {
		kv = append(kv, LexKeyValue{
			Key:   key,
			Value: lex.hashmap[key].value,
		})
	}
	return
}
<|endoftext|>