<commit_before>package controller

import (
	"github.com/pkg/errors"
	"github.com/satori/go.uuid"
	"gitlab.com/remp/remp/Beam/go/cmd/segments/app"
	"gitlab.com/remp/remp/Beam/go/model"
)

// Segment represents segment information stored in storage.
type Segment model.Segment

// SegmentCollection is the collection of Segments.
type SegmentCollection model.SegmentCollection

// Event represent tracked generic events data.
type Event model.Event

// EventRowCollection is the collection of Events bucketed by tags.
type EventRowCollection model.EventRowCollection

// Commerce represent tracked commerce events data.
type Commerce model.Commerce

// CommerceRowCollection is the collection of Commerce events bucketed by tags.
type CommerceRowCollection model.CommerceRowCollection

// Pageview represent tracked Pageview events data.
type Pageview model.Pageview

// PageviewRow represent tracked pageview data with tags.
type PageviewRow model.PageviewRow

// PageviewRowCollection is the collection of PageviewRow events.
type PageviewRowCollection model.PageviewRowCollection

// SegmentCache represent cache object for count of events of SegmentRules.
type SegmentCache model.SegmentCache

// HistogramItem represent row with date time histogram data.
type HistogramItem model.HistogramItem

// CountRow represent row with count result.
type CountRow model.CountRow

// CountRowCollection is the collection of count rows.
type CountRowCollection model.CountRowCollection

// SumRow represent row with sum result.
type SumRow model.SumRow

// SumRowCollection is the collection of sum rows.
type SumRowCollection model.SumRowCollection

// AvgRow represent row with sum result.
type AvgRow model.AvgRow

// AvgRowCollection is the collection of sum rows.
type AvgRowCollection model.AvgRowCollection

// ToMediaType converts internal Segment representation to application one.
func (s *Segment) ToMediaType() *app.Segment {
	return &app.Segment{
		Code: s.Code,
		Name: s.Name,
		Group: &app.SegmentGroup{
			Name:    s.Group.Name,
			Sorting: s.Group.Sorting,
		},
	}
}

// ToMediaType converts internal SegmentCollection representation to application one.
func (sc SegmentCollection) ToMediaType() app.SegmentCollection {
	mt := app.SegmentCollection{}
	for _, s := range sc {
		mt = append(mt, (*Segment)(s).ToMediaType())
	}
	return mt
}

// ToMediaType converts internal Event representation to application one.
func (e *Event) ToMediaType() (*app.Event, error) {
	token, err := uuid.FromString(e.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}
	event := &app.Event{
		Category: e.Category,
		Action:   e.Action,
		System: &app.System{
			Time:          e.Time,
			PropertyToken: token,
		},
		User: &app.User{},
	}
	if e.IP != "" {
		event.User.IPAddress = &e.IP
	}
	if e.UserID != "" {
		event.User.ID = &e.UserID
	}
	if e.URL != "" {
		event.User.URL = &e.URL
	}
	if e.UserAgent != "" {
		event.User.UserAgent = &e.UserAgent
	}
	if e.UtmSource != "" {
		event.UtmSource = &e.UtmSource
	}
	if e.UtmCampaign != "" {
		event.UtmCampaign = &e.UtmCampaign
	}
	if e.UtmMedium != "" {
		event.UtmMedium = &e.UtmMedium
	}
	if e.UtmContent != "" {
		event.UtmContent = &e.UtmContent
	}
	return event, nil
}

// ToMediaType converts internal EventCollection representation to application one.
func (erc EventRowCollection) ToMediaType() (app.EventsCollection, error) {
	mt := app.EventsCollection{}
	for _, er := range erc {
		events := &app.Events{
			Tags: er.Tags,
		}
		for _, p := range er.Events {
			event, err := (*Event)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			events.Events = append(events.Events, event)
		}
		mt = append(mt, events)
	}
	return mt, nil
}

// ToMediaType converts internal Commerce representation to application one.
func (c *Commerce) ToMediaType() (*app.Commerce, error) {
	token, err := uuid.FromString(c.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}
	event := &app.Commerce{
		Step: c.Step,
		System: &app.System{
			Time:          c.Time,
			PropertyToken: token,
		},
		User: &app.User{},
	}
	if c.IP != "" {
		event.User.IPAddress = &c.IP
	}
	if c.UserID != "" {
		event.User.ID = &c.UserID
	}
	if c.URL != "" {
		event.User.URL = &c.URL
	}
	if c.UserAgent != "" {
		event.User.UserAgent = &c.UserAgent
	}
	return event, nil
}

// ToMediaType converts internal CommerceCollection representation to application one.
func (crc CommerceRowCollection) ToMediaType() (app.CommercesCollection, error) {
	mt := app.CommercesCollection{}
	for _, cr := range crc {
		commerces := &app.Commerces{
			Tags: cr.Tags,
		}
		for _, p := range cr.Commerces {
			commerce, err := (*Commerce)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			commerces.Commerces = append(commerces.Commerces, commerce)
		}
		mt = append(mt, commerces)
	}
	return mt, nil
}

// ToMediaType converts internal PageviewRow representation to application one.
func (p *Pageview) ToMediaType() (*app.Pageview, error) {
	token, err := uuid.FromString(p.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}

	// PageviewRow, generic user and system data
	pageview := &app.Pageview{
		System: &app.System{
			Time:          p.Time,
			PropertyToken: token,
		},
		User: &app.User{
			Source:         &app.Source{},
			RempPageviewID: p.PageviewID,
		},
	}

	// article data
	if p.ArticleID != "" {
		pageview.Article = &app.Article{
			ID:     p.ArticleID,
			Locked: &p.ArticleLocked,
		}
		if p.AuthorID != "" {
			pageview.Article.AuthorID = &p.AuthorID
		}
	}

	// user data
	if p.UserID != "" {
		pageview.User.ID = &p.UserID
	}

	// optional tracked params
	if p.UTMSource != "" {
		pageview.User.Source.UtmSource = &p.UTMSource
	}
	if p.UTMMedium != "" {
		pageview.User.Source.UtmMedium = &p.UTMMedium
	}
	if p.UTMCampaign != "" {
		pageview.User.Source.UtmCampaign = &p.UTMCampaign
	}
	if p.UTMContent != "" {
		pageview.User.Source.UtmContent = &p.UTMContent
	}
	if p.SocialSource != "" {
		pageview.User.Source.Social = &p.SocialSource
	}
	if p.IP != "" {
		pageview.User.IPAddress = &p.IP
	}
	if p.URL != "" {
		pageview.User.URL = &p.URL
	}
	if p.Referer != "" {
		pageview.User.Referer = &p.Referer
	}
	if p.BrowserID != "" {
		pageview.User.BrowserID = &p.BrowserID
	}
	if p.SessionID != "" {
		pageview.User.RempSessionID = &p.SessionID
	}
	if p.UserAgent != "" {
		pageview.User.UserAgent = &p.UserAgent
	}

	return pageview, nil
}

// ToMediaType converts internal PageviewRowCollection representation to application one.
func (prc PageviewRowCollection) ToMediaType() (app.PageviewsCollection, error) {
	mt := app.PageviewsCollection{}
	for _, rc := range prc {
		pr := &app.Pageviews{
			Tags: rc.Tags,
		}
		for _, p := range rc.Pageviews {
			pageview, err := (*Pageview)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			pr.Pageviews = append(pr.Pageviews, pageview)
		}
		mt = append(mt, pr)
	}
	return mt, nil
}

// ToMediaType converts internal PageviewRowCollection representation to application one.
func (sc SegmentCache) ToMediaType() map[int]*app.SegmentRuleCache {
	mt := make(map[int]*app.SegmentRuleCache)
	for key, c := range sc {
		mt[key] = &app.SegmentRuleCache{
			S: c.SyncedAt,
			C: c.Count,
		}
	}
	return mt
}

// ToMediaType converts internal HistogramItem representation to application one.
func (hi HistogramItem) ToMediaType() *app.TimeHistogram {
	c := float64(hi.Value)

	th := &app.TimeHistogram{
		Time:  hi.Time,
		Value: c,
	}

	return th
}

// ToMediaType converts internal CountRow representation to application one.
func (cr CountRow) ToMediaType() *app.Count {
	coll := app.TimeHistogramCollection{}

	for _, c := range cr.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		coll = append(coll, hi)
	}

	if len(cr.Tags) == 0 {
		cr.Tags = nil
	}

	mt := &app.Count{
		Count:         cr.Count,
		Tags:          cr.Tags,
		TimeHistogram: coll,
	}

	return mt
}

// ToMediaType converts internal CountRowCollection representation to application one.
func (crc CountRowCollection) ToMediaType() app.CountCollection {
	mt := app.CountCollection{}
	for _, c := range crc {
		mtc := (CountRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}

// ToMediaType converts internal SumRow representation to application one.
func (sr SumRow) ToMediaType() *app.Sum {
	thc := app.TimeHistogramCollection{}

	for _, c := range sr.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		thc = append(thc, hi)
	}

	if len(sr.Tags) == 0 {
		sr.Tags = nil
	}

	mt := &app.Sum{
		Sum:           sr.Sum,
		Tags:          sr.Tags,
		TimeHistogram: thc,
	}
	return mt
}

// ToMediaType converts internal SumRowCollection representation to application one.
func (src SumRowCollection) ToMediaType() app.SumCollection {
	mt := app.SumCollection{}
	for _, c := range src {
		mtc := (SumRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}

// ToMediaType converts internal AvgRow representation to application one.
func (sr AvgRow) ToMediaType() *app.Avg {
	thc := app.TimeHistogramCollection{}

	for _, c := range sr.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		thc = append(thc, hi)
	}

	if len(sr.Tags) == 0 {
		sr.Tags = nil
	}

	mt := &app.Avg{
		Avg:           sr.Avg,
		Tags:          sr.Tags,
		TimeHistogram: thc,
	}
	return mt
}

// ToMediaType converts internal AvgRowCollection representation to application one.
func (src AvgRowCollection) ToMediaType() app.AvgCollection {
	mt := app.AvgCollection{}
	for _, c := range src {
		mtc := (AvgRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}
<commit_msg>Naming fixed<commit_after>package controller

import (
	"github.com/pkg/errors"
	"github.com/satori/go.uuid"
	"gitlab.com/remp/remp/Beam/go/cmd/segments/app"
	"gitlab.com/remp/remp/Beam/go/model"
)

// Segment represents segment information stored in storage.
type Segment model.Segment

// SegmentCollection is the collection of Segments.
type SegmentCollection model.SegmentCollection

// Event represent tracked generic events data.
type Event model.Event

// EventRowCollection is the collection of Events bucketed by tags.
type EventRowCollection model.EventRowCollection

// Commerce represent tracked commerce events data.
type Commerce model.Commerce

// CommerceRowCollection is the collection of Commerce events bucketed by tags.
type CommerceRowCollection model.CommerceRowCollection

// Pageview represent tracked Pageview events data.
type Pageview model.Pageview

// PageviewRow represent tracked pageview data with tags.
type PageviewRow model.PageviewRow

// PageviewRowCollection is the collection of PageviewRow events.
type PageviewRowCollection model.PageviewRowCollection

// SegmentCache represent cache object for count of events of SegmentRules.
type SegmentCache model.SegmentCache

// HistogramItem represent row with date time histogram data.
type HistogramItem model.HistogramItem

// CountRow represent row with count result.
type CountRow model.CountRow

// CountRowCollection is the collection of count rows.
type CountRowCollection model.CountRowCollection

// SumRow represent row with sum result.
type SumRow model.SumRow

// SumRowCollection is the collection of sum rows.
type SumRowCollection model.SumRowCollection

// AvgRow represent row with sum result.
type AvgRow model.AvgRow

// AvgRowCollection is the collection of sum rows.
type AvgRowCollection model.AvgRowCollection

// ToMediaType converts internal Segment representation to application one.
func (s *Segment) ToMediaType() *app.Segment {
	return &app.Segment{
		Code: s.Code,
		Name: s.Name,
		Group: &app.SegmentGroup{
			Name:    s.Group.Name,
			Sorting: s.Group.Sorting,
		},
	}
}

// ToMediaType converts internal SegmentCollection representation to application one.
func (sc SegmentCollection) ToMediaType() app.SegmentCollection {
	mt := app.SegmentCollection{}
	for _, s := range sc {
		mt = append(mt, (*Segment)(s).ToMediaType())
	}
	return mt
}

// ToMediaType converts internal Event representation to application one.
func (e *Event) ToMediaType() (*app.Event, error) {
	token, err := uuid.FromString(e.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}
	event := &app.Event{
		Category: e.Category,
		Action:   e.Action,
		System: &app.System{
			Time:          e.Time,
			PropertyToken: token,
		},
		User: &app.User{},
	}
	if e.IP != "" {
		event.User.IPAddress = &e.IP
	}
	if e.UserID != "" {
		event.User.ID = &e.UserID
	}
	if e.URL != "" {
		event.User.URL = &e.URL
	}
	if e.UserAgent != "" {
		event.User.UserAgent = &e.UserAgent
	}
	if e.UtmSource != "" {
		event.UtmSource = &e.UtmSource
	}
	if e.UtmCampaign != "" {
		event.UtmCampaign = &e.UtmCampaign
	}
	if e.UtmMedium != "" {
		event.UtmMedium = &e.UtmMedium
	}
	if e.UtmContent != "" {
		event.UtmContent = &e.UtmContent
	}
	return event, nil
}

// ToMediaType converts internal EventCollection representation to application one.
func (erc EventRowCollection) ToMediaType() (app.EventsCollection, error) {
	mt := app.EventsCollection{}
	for _, er := range erc {
		events := &app.Events{
			Tags: er.Tags,
		}
		for _, p := range er.Events {
			event, err := (*Event)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			events.Events = append(events.Events, event)
		}
		mt = append(mt, events)
	}
	return mt, nil
}

// ToMediaType converts internal Commerce representation to application one.
func (c *Commerce) ToMediaType() (*app.Commerce, error) {
	token, err := uuid.FromString(c.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}
	event := &app.Commerce{
		Step: c.Step,
		System: &app.System{
			Time:          c.Time,
			PropertyToken: token,
		},
		User: &app.User{},
	}
	if c.IP != "" {
		event.User.IPAddress = &c.IP
	}
	if c.UserID != "" {
		event.User.ID = &c.UserID
	}
	if c.URL != "" {
		event.User.URL = &c.URL
	}
	if c.UserAgent != "" {
		event.User.UserAgent = &c.UserAgent
	}
	return event, nil
}

// ToMediaType converts internal CommerceCollection representation to application one.
func (crc CommerceRowCollection) ToMediaType() (app.CommercesCollection, error) {
	mt := app.CommercesCollection{}
	for _, cr := range crc {
		commerces := &app.Commerces{
			Tags: cr.Tags,
		}
		for _, p := range cr.Commerces {
			commerce, err := (*Commerce)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			commerces.Commerces = append(commerces.Commerces, commerce)
		}
		mt = append(mt, commerces)
	}
	return mt, nil
}

// ToMediaType converts internal PageviewRow representation to application one.
func (p *Pageview) ToMediaType() (*app.Pageview, error) {
	token, err := uuid.FromString(p.Token)
	if err != nil {
		return nil, errors.Wrap(err, "unable to parse property token as UUID")
	}

	// PageviewRow, generic user and system data
	pageview := &app.Pageview{
		System: &app.System{
			Time:          p.Time,
			PropertyToken: token,
		},
		User: &app.User{
			Source:         &app.Source{},
			RempPageviewID: p.PageviewID,
		},
	}

	// article data
	if p.ArticleID != "" {
		pageview.Article = &app.Article{
			ID:     p.ArticleID,
			Locked: &p.ArticleLocked,
		}
		if p.AuthorID != "" {
			pageview.Article.AuthorID = &p.AuthorID
		}
	}

	// user data
	if p.UserID != "" {
		pageview.User.ID = &p.UserID
	}

	// optional tracked params
	if p.UTMSource != "" {
		pageview.User.Source.UtmSource = &p.UTMSource
	}
	if p.UTMMedium != "" {
		pageview.User.Source.UtmMedium = &p.UTMMedium
	}
	if p.UTMCampaign != "" {
		pageview.User.Source.UtmCampaign = &p.UTMCampaign
	}
	if p.UTMContent != "" {
		pageview.User.Source.UtmContent = &p.UTMContent
	}
	if p.SocialSource != "" {
		pageview.User.Source.Social = &p.SocialSource
	}
	if p.IP != "" {
		pageview.User.IPAddress = &p.IP
	}
	if p.URL != "" {
		pageview.User.URL = &p.URL
	}
	if p.Referer != "" {
		pageview.User.Referer = &p.Referer
	}
	if p.BrowserID != "" {
		pageview.User.BrowserID = &p.BrowserID
	}
	if p.SessionID != "" {
		pageview.User.RempSessionID = &p.SessionID
	}
	if p.UserAgent != "" {
		pageview.User.UserAgent = &p.UserAgent
	}

	return pageview, nil
}

// ToMediaType converts internal PageviewRowCollection representation to application one.
func (prc PageviewRowCollection) ToMediaType() (app.PageviewsCollection, error) {
	mt := app.PageviewsCollection{}
	for _, rc := range prc {
		pr := &app.Pageviews{
			Tags: rc.Tags,
		}
		for _, p := range rc.Pageviews {
			pageview, err := (*Pageview)(p).ToMediaType()
			if err != nil {
				return nil, err
			}
			pr.Pageviews = append(pr.Pageviews, pageview)
		}
		mt = append(mt, pr)
	}
	return mt, nil
}

// ToMediaType converts internal PageviewRowCollection representation to application one.
func (sc SegmentCache) ToMediaType() map[int]*app.SegmentRuleCache {
	mt := make(map[int]*app.SegmentRuleCache)
	for key, c := range sc {
		mt[key] = &app.SegmentRuleCache{
			S: c.SyncedAt,
			C: c.Count,
		}
	}
	return mt
}

// ToMediaType converts internal HistogramItem representation to application one.
func (hi HistogramItem) ToMediaType() *app.TimeHistogram {
	c := float64(hi.Value)

	th := &app.TimeHistogram{
		Time:  hi.Time,
		Value: c,
	}

	return th
}

// ToMediaType converts internal CountRow representation to application one.
func (cr CountRow) ToMediaType() *app.Count {
	coll := app.TimeHistogramCollection{}

	for _, c := range cr.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		coll = append(coll, hi)
	}

	if len(cr.Tags) == 0 {
		cr.Tags = nil
	}

	mt := &app.Count{
		Count:         cr.Count,
		Tags:          cr.Tags,
		TimeHistogram: coll,
	}

	return mt
}

// ToMediaType converts internal CountRowCollection representation to application one.
func (crc CountRowCollection) ToMediaType() app.CountCollection {
	mt := app.CountCollection{}
	for _, c := range crc {
		mtc := (CountRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}

// ToMediaType converts internal SumRow representation to application one.
func (sr SumRow) ToMediaType() *app.Sum {
	thc := app.TimeHistogramCollection{}

	for _, c := range sr.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		thc = append(thc, hi)
	}

	if len(sr.Tags) == 0 {
		sr.Tags = nil
	}

	mt := &app.Sum{
		Sum:           sr.Sum,
		Tags:          sr.Tags,
		TimeHistogram: thc,
	}
	return mt
}

// ToMediaType converts internal SumRowCollection representation to application one.
func (src SumRowCollection) ToMediaType() app.SumCollection {
	mt := app.SumCollection{}
	for _, c := range src {
		mtc := (SumRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}

// ToMediaType converts internal AvgRow representation to application one.
func (ar AvgRow) ToMediaType() *app.Avg {
	thc := app.TimeHistogramCollection{}

	for _, c := range ar.Histogram {
		hi := (HistogramItem)(c).ToMediaType()
		thc = append(thc, hi)
	}

	if len(ar.Tags) == 0 {
		ar.Tags = nil
	}

	mt := &app.Avg{
		Avg:           ar.Avg,
		Tags:          ar.Tags,
		TimeHistogram: thc,
	}
	return mt
}

// ToMediaType converts internal AvgRowCollection representation to application one.
func (src AvgRowCollection) ToMediaType() app.AvgCollection {
	mt := app.AvgCollection{}
	for _, c := range src {
		mtc := (AvgRow)(c).ToMediaType()
		mt = append(mt, mtc)
	}
	return mt
}
<|endoftext|>


<commit_before>package netlog

import (
	"errors"
	"fmt"
	"io"
	"net/url"
	"os"
)

type Logger interface {
	Info(format string, v ...interface{})
	Warning(format string, v ...interface{})
	Err(format string, v ...interface{})
	Crit(format string, v ...interface{})
}

type Facility int

const (
	LOG_SYSTEM      = facilitySystem
	LOG_APPLICATION = facilityApplication
	LOG_SERVICE     = facilityService
	LOG_SECURITY    = facilitySecurity
)

func parseFacility(s string) (Facility, error) {
	switch s {
	case "sys", "system":
		return LOG_SYSTEM, nil
	case "app", "application":
		return LOG_APPLICATION, nil
	case "service":
		return LOG_SERVICE, nil
	case "security":
		return LOG_SECURITY, nil
	default:
		return LOG_SYSTEM, errors.New("unknown scheme")
	}
}

var (
	DefaultLogger Logger = consoleLogger{w: os.Stderr}
)

type consoleLogger struct {
	w io.Writer
}

func (c consoleLogger) Info(format string, v ...interface{}) {
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Warning(format string, v ...interface{}) {
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Err(format string, v ...interface{}) {
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Crit(format string, v ...interface{}) {
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
	os.Exit(2)
}

// SetOutputURL is to set output for netlog.
func SetOutputURL(s string) error {
	u, err := url.Parse(s)
	if err != nil {
		return err
	}

	q := u.Query()
	facility := LOG_APPLICATION
	t := q.Get("facility")
	if t != "" {
		facility, err = parseFacility(t)
		if err != nil {
			return err
		}
	}
	tag := q.Get("tag")

	switch u.Scheme {
	case "file":
		// file:///var/log/xxx.log
		fout, err := os.OpenFile(u.Path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
		if err != nil {
			return err
		}
		DefaultLogger = consoleLogger{w: fout}
		return nil
	case "net":
		// net:///?facility=x&tag=x
		DefaultLogger = NewLogger(facility, tag)
		return nil
	case "tcp", "tcp4", "tcp6":
		// tcp://localhost/?facility=x&tag=x
		return errors.New("not implemented")
	default:
		// ??
		return errors.New("unsupported scheme")
	}
}

func Info(format string, v ...interface{}) {
	DefaultLogger.Info(format, v...)
}

func Warning(format string, v ...interface{}) {
	DefaultLogger.Warning(format, v...)
}

func Err(format string, v ...interface{}) {
	DefaultLogger.Err(format, v...)
}

func Crit(format string, v ...interface{}) {
	DefaultLogger.Crit(format, v...)
}
<commit_msg>add timestamp to consoleLogger<commit_after>package netlog

import (
	"errors"
	"fmt"
	"io"
	"net/url"
	"os"
	"time"
)

type Logger interface {
	Info(format string, v ...interface{})
	Warning(format string, v ...interface{})
	Err(format string, v ...interface{})
	Crit(format string, v ...interface{})
}

type Facility int

const (
	LOG_SYSTEM      = facilitySystem
	LOG_APPLICATION = facilityApplication
	LOG_SERVICE     = facilityService
	LOG_SECURITY    = facilitySecurity
)

func parseFacility(s string) (Facility, error) {
	switch s {
	case "sys", "system":
		return LOG_SYSTEM, nil
	case "app", "application":
		return LOG_APPLICATION, nil
	case "service":
		return LOG_SERVICE, nil
	case "security":
		return LOG_SECURITY, nil
	default:
		return LOG_SYSTEM, errors.New("unknown scheme")
	}
}

var (
	DefaultLogger Logger = consoleLogger{w: os.Stderr}
)

const stampFormat = "2006/01/02 15:04:05.000000"

type consoleLogger struct {
	w io.Writer
}

func (c consoleLogger) stamp(t time.Time) {
	fmt.Fprintf(c.w, "%s ", t.Format(stampFormat))
}

func (c consoleLogger) Info(format string, v ...interface{}) {
	c.stamp(time.Now())
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Warning(format string, v ...interface{}) {
	c.stamp(time.Now())
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Err(format string, v ...interface{}) {
	c.stamp(time.Now())
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
}

func (c consoleLogger) Crit(format string, v ...interface{}) {
	c.stamp(time.Now())
	fmt.Fprintf(c.w, format, v...)
	if format[len(format)-1] != '\n' {
		fmt.Fprintf(c.w, "\n")
	}
	os.Exit(2)
}

// SetOutputURL is to set output for netlog.
func SetOutputURL(s string) error {
	u, err := url.Parse(s)
	if err != nil {
		return err
	}

	q := u.Query()
	facility := LOG_APPLICATION
	t := q.Get("facility")
	if t != "" {
		facility, err = parseFacility(t)
		if err != nil {
			return err
		}
	}
	tag := q.Get("tag")

	switch u.Scheme {
	case "file":
		// file:///var/log/xxx.log
		fout, err := os.OpenFile(u.Path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
		if err != nil {
			return err
		}
		DefaultLogger = consoleLogger{w: fout}
		return nil
	case "net":
		// net:///?facility=x&tag=x
		DefaultLogger = NewLogger(facility, tag)
		return nil
	case "tcp", "tcp4", "tcp6":
		// tcp://localhost/?facility=x&tag=x
		return errors.New("not implemented")
	default:
		// ??
		return errors.New("unsupported scheme")
	}
}

func Info(format string, v ...interface{}) {
	DefaultLogger.Info(format, v...)
}

func Warning(format string, v ...interface{}) {
	DefaultLogger.Warning(format, v...)
}

func Err(format string, v ...interface{}) {
	DefaultLogger.Err(format, v...)
}

func Crit(format string, v ...interface{}) {
	DefaultLogger.Crit(format, v...)
}
<|endoftext|>


<commit_before>package utils

// transfer2go/utils - Go utilities for transfer2go
//
// Author: Valentin Kuznetsov <vkuznet@gmail.com>

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"os/user"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/vkuznet/x509proxy"
)

// ResponseType structure is what we expect to get for our URL call.
// It contains a request URL, the data chunk and possible error from remote
type ResponseType struct {
	Url        string // response url
	Data       []byte // response data, i.e. what we got with Body of the response
	Error      error  // http error, a non-2xx return code is not an error
	Status     string // http status string
	StatusCode int    // http status code
}

// UrlRequest structure holds details about url request's attributes
type UrlRequest struct {
	rurl string
	args string
	out  chan<- ResponseType
	ts   int64
}

// VERBOSE variable control verbosity level of client's utilities
var VERBOSE int

// global HTTP client
var _client = HttpClient()

// global client's x509 certificates
var _certs []tls.Certificate

// UserDN function parses user Distinguished Name (DN) from client's HTTP request
func UserDN(r *http.Request) string {
	var names []interface{}
	for _, cert := range r.TLS.PeerCertificates {
		for _, name := range cert.Subject.Names {
			switch v := name.Value.(type) {
			case string:
				names = append(names, v)
			}
		}
	}
	parts := names[:7]
	return fmt.Sprintf("/DC=%s/DC=%s/OU=%s/OU=%s/CN=%s/CN=%s/CN=%s", parts...)
}

// client X509 certificates
func tlsCerts() ([]tls.Certificate, error) {
	if len(_certs) != 0 {
		return _certs, nil // use cached certs
	}
	uproxy := os.Getenv("X509_USER_PROXY")
	uckey := os.Getenv("X509_USER_KEY")
	ucert := os.Getenv("X509_USER_CERT")

	// check if /tmp/x509up_u$UID exists, if so setup X509_USER_PROXY env
	u, err := user.Current()
	if err == nil {
		fname := fmt.Sprintf("/tmp/x509up_u%s", u.Uid)
		if _, err := os.Stat(fname); err == nil {
			uproxy = fname
		}
	}
	if VERBOSE > 1 {
		log.WithFields(log.Fields{
			"uproxy": uproxy,
		}).Println("")
		log.WithFields(log.Fields{
			"uckey": uckey,
		}).Println("")
		log.WithFields(log.Fields{
			"ucert": ucert,
		}).Println("")
	}

	if uproxy == "" && uckey == "" { // user doesn't have neither proxy or user certs
		return nil, nil
	}
	if uproxy != "" {
		// use local implementation of LoadX409KeyPair instead of tls one
		x509cert, err := x509proxy.LoadX509Proxy(uproxy)
		if err != nil {
			return nil, fmt.Errorf("failed to parse proxy X509 proxy set by X509_USER_PROXY: %v", err)
		}
		_certs = []tls.Certificate{x509cert}
		return _certs, nil
	}
	x509cert, err := tls.LoadX509KeyPair(ucert, uckey)
	if err != nil {
		return nil, fmt.Errorf("failed to parse user X509 certificate: %v", err)
	}
	_certs = []tls.Certificate{x509cert}
	return _certs, nil
}

// HttpClient provides HTTP client
func HttpClient() *http.Client {
	// get X509 certs
	certs, err := tlsCerts()
	if err != nil {
		panic(err.Error())
	}
	if len(certs) == 0 {
		return &http.Client{}
	}
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{Certificates: certs,
			InsecureSkipVerify: true},
	}
	return &http.Client{Transport: tr}
}

func (r *ResponseType) String() string {
	return fmt.Sprintf("<Response: url=%s data=%s error=%v>", r.Url, string(r.Data), r.Error)
}

// FetchResponse fetches data for provided URL, args is a json dump of arguments
func FetchResponse(rurl string, args []byte) ResponseType {
	startTime := time.Now()
	var response ResponseType
	response.Url = rurl
	if validateUrl(rurl) == false {
		response.Error = errors.New("Invalid URL")
		return response
	}
	var req *http.Request
	var e error
	if len(args) > 0 {
		req, e = http.NewRequest("POST", rurl, bytes.NewBuffer(args))
		req.Header.Set("Content-Type", "application/json")
	} else {
		req, e = http.NewRequest("GET", rurl, nil)
		if e != nil {
			log.WithFields(log.Fields{
				"Error": e,
			}).Error("Unable to make GET request")
		}
		req.Header.Add("Accept", "*/*")
	}
	if VERBOSE > 1 {
		dump1, err1 := httputil.DumpRequestOut(req, true)
		log.WithFields(log.Fields{
			"Request": req,
			"Dump":    string(dump1),
			"Error":   err1,
		}).Println("HTTP request")
	}
	resp, err := _client.Do(req)
	if err != nil {
		log.WithFields(log.Fields{
			"Error": err,
		}).Error("HTTP", err)
		response.Error = err
		return response
	}
	response.Status = resp.Status
	response.StatusCode = resp.StatusCode
	if VERBOSE > 0 {
		if len(args) > 0 {
			log.WithFields(log.Fields{
				"URL":   rurl,
				"Args":  string(args),
				"Error": err,
				"Time":  time.Now().Sub(startTime),
			}).Println("HTTP POST")
		} else {
			log.WithFields(log.Fields{
				"URL":   rurl,
				"Args":  string(args),
				"Error": err,
				"Time":  time.Now().Sub(startTime),
			}).Println("HTTP GET")
		}
	}
	if VERBOSE > 1 {
		dump2, err2 := httputil.DumpResponse(resp, true)
		log.WithFields(log.Fields{
			"Dump":  string(dump2),
			"Error": err2,
		}).Println("HTTP response")
	}
	if err != nil {
		response.Error = err
		return response
	}
	defer resp.Body.Close()
	response.Data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		response.Error = err
	}
	return response
}

// Fetch data for provided URL and redirect results to given channel
func Fetch(rurl string, args []byte, ch chan<- ResponseType) {
	urlRetry := 3
	var resp, r ResponseType
	resp = FetchResponse(rurl, args)
	if resp.Error != nil {
		log.WithFields(log.Fields{
			"URL":   rurl,
			"Error": resp.Error,
		}).Warn("Fail to fetch data")
		for i := 1; i <= urlRetry; i++ {
			sleep := time.Duration(i) * time.Second
			time.Sleep(sleep)
			r = FetchResponse(rurl, args)
			if r.Error == nil {
				break
			}
			log.WithFields(log.Fields{
				"URL":   rurl,
				"retry": i,
				"Error": r.Error,
			}).Warn("TRANSFER2GO")
		}
		resp = r
	}
	if resp.Error != nil {
		log.WithFields(log.Fields{
			"URL":   rurl,
			"Retry": urlRetry,
			"Error": resp.Error,
		}).Error("TRANSFER2GO, fail to fetch data")
	}
	ch <- resp
}

// Helper function which validates given URL
func validateUrl(rurl string) bool {
	if len(rurl) > 0 {
		if PatternUrl.MatchString(rurl) {
			return true
		}
		log.WithFields(log.Fields{
			"URL": rurl,
		}).Error("Invalid URL:", rurl)
	}
	return false
}

// Response represents final response in a form of JSON structure
// we use custorm representation
func Response(rurl string, data []byte) []byte {
	b := []byte(`{"url":`)
	u := []byte(rurl)
	c := []byte(",")
	d := []byte(`"data":`)
	e := []byte(`}`)
	a := [][]byte{b, u, c, d, data, e}
	s := []byte(" ")
	r := bytes.Join(a, s)
	return r

}
<commit_msg>Show warning message if user do not provide X509 environment<commit_after>package utils

// transfer2go/utils - Go utilities for transfer2go
//
// Author: Valentin Kuznetsov <vkuznet@gmail.com>

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"os/user"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/vkuznet/x509proxy"
)

// ResponseType structure is what we expect to get for our URL call.
// It contains a request URL, the data chunk and possible error from remote
type ResponseType struct {
	Url        string // response url
	Data       []byte // response data, i.e. what we got with Body of the response
	Error      error  // http error, a non-2xx return code is not an error
	Status     string // http status string
	StatusCode int    // http status code
}

// UrlRequest structure holds details about url request's attributes
type UrlRequest struct {
	rurl string
	args string
	out  chan<- ResponseType
	ts   int64
}

// VERBOSE variable control verbosity level of client's utilities
var VERBOSE int

// global HTTP client
var _client = HttpClient()

// global client's x509 certificates
var _certs []tls.Certificate

// UserDN function parses user Distinguished Name (DN) from client's HTTP request
func UserDN(r *http.Request) string {
	var names []interface{}
	for _, cert := range r.TLS.PeerCertificates {
		for _, name := range cert.Subject.Names {
			switch v := name.Value.(type) {
			case string:
				names = append(names, v)
			}
		}
	}
	parts := names[:7]
	return fmt.Sprintf("/DC=%s/DC=%s/OU=%s/OU=%s/CN=%s/CN=%s/CN=%s", parts...)
}

// client X509 certificates
func tlsCerts() ([]tls.Certificate, error) {
	if len(_certs) != 0 {
		return _certs, nil // use cached certs
	}
	uproxy := os.Getenv("X509_USER_PROXY")
	uckey := os.Getenv("X509_USER_KEY")
	ucert := os.Getenv("X509_USER_CERT")

	// check if /tmp/x509up_u$UID exists, if so setup X509_USER_PROXY env
	u, err := user.Current()
	if err == nil {
		fname := fmt.Sprintf("/tmp/x509up_u%s", u.Uid)
		if _, err := os.Stat(fname); err == nil {
			uproxy = fname
		}
	}
	if VERBOSE > 1 {
		log.WithFields(log.Fields{
			"uproxy": uproxy,
		}).Println("")
		log.WithFields(log.Fields{
			"uckey": uckey,
		}).Println("")
		log.WithFields(log.Fields{
			"ucert": ucert,
		}).Println("")
	}

	if uproxy == "" && uckey == "" { // user doesn't have neither proxy or user certs
		log.Warn("Neither proxy or user certs are found, to proceed use auth=false option otherwise setup X509 environment")
		return nil, nil
	}
	if uproxy != "" {
		// use local implementation of LoadX409KeyPair instead of tls one
		x509cert, err := x509proxy.LoadX509Proxy(uproxy)
		if err != nil {
			return nil, fmt.Errorf("failed to parse proxy X509 proxy set by X509_USER_PROXY: %v", err)
		}
		_certs = []tls.Certificate{x509cert}
		return _certs, nil
	}
	x509cert, err := tls.LoadX509KeyPair(ucert, uckey)
	if err != nil {
		return nil, fmt.Errorf("failed to parse user X509 certificate: %v", err)
	}
	_certs = []tls.Certificate{x509cert}
	return _certs, nil
}

// HttpClient provides HTTP client
func HttpClient() *http.Client {
	// get X509 certs
	certs, err := tlsCerts()
	if err != nil {
		panic(err.Error())
	}
	if len(certs) == 0 {
		return &http.Client{}
	}
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{Certificates: certs,
			InsecureSkipVerify: true},
	}
	return &http.Client{Transport: tr}
}

func (r *ResponseType) String() string {
	return fmt.Sprintf("<Response: url=%s data=%s error=%v>", r.Url, string(r.Data), r.Error)
}

// FetchResponse fetches data for provided URL, args is a json dump of arguments
func FetchResponse(rurl string, args []byte) ResponseType {
	startTime := time.Now()
	var response ResponseType
	response.Url = rurl
	if validateUrl(rurl) == false {
		response.Error = errors.New("Invalid URL")
		return response
	}
	var req *http.Request
	var e error
	if len(args) > 0 {
		req, e = http.NewRequest("POST", rurl, bytes.NewBuffer(args))
		req.Header.Set("Content-Type", "application/json")
	} else {
		req, e = http.NewRequest("GET", rurl, nil)
		if e != nil {
			log.WithFields(log.Fields{
				"Error": e,
			}).Error("Unable to make GET request")
		}
		req.Header.Add("Accept", "*/*")
	}
	if VERBOSE > 1 {
		dump1, err1 := httputil.DumpRequestOut(req, true)
		log.WithFields(log.Fields{
			"Request": req,
			"Dump":    string(dump1),
			"Error":   err1,
		}).Println("HTTP request")
	}
	resp, err := _client.Do(req)
	if err != nil {
		log.WithFields(log.Fields{
			"Error": err,
		}).Error("HTTP", err)
		response.Error = err
		return response
	}
	response.Status = resp.Status
	response.StatusCode = resp.StatusCode
	if VERBOSE > 0 {
		if len(args) > 0 {
			log.WithFields(log.Fields{
				"URL":   rurl,
				"Args":  string(args),
				"Error": err,
				"Time":  time.Now().Sub(startTime),
			}).Println("HTTP POST")
		} else {
			log.WithFields(log.Fields{
				"URL":   rurl,
				"Args":  string(args),
				"Error": err,
				"Time":  time.Now().Sub(startTime),
			}).Println("HTTP GET")
		}
	}
	if VERBOSE > 1 {
		dump2, err2 := httputil.DumpResponse(resp, true)
		log.WithFields(log.Fields{
			"Dump":  string(dump2),
			"Error": err2,
		}).Println("HTTP response")
	}
	if err != nil {
		response.Error = err
		return response
	}
	defer resp.Body.Close()
	response.Data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		response.Error = err
	}
	return response
}

// Fetch data for provided URL and redirect results to given channel
func Fetch(rurl string, args []byte, ch chan<- ResponseType) {
	urlRetry := 3
	var resp, r ResponseType
	resp = FetchResponse(rurl, args)
	if resp.Error != nil {
		log.WithFields(log.Fields{
			"URL":   rurl,
			"Error": resp.Error,
		}).Warn("Fail to fetch data")
		for i := 1; i <= urlRetry; i++ {
			sleep := time.Duration(i) * time.Second
			time.Sleep(sleep)
			r = FetchResponse(rurl, args)
			if r.Error == nil {
				break
			}
			log.WithFields(log.Fields{
				"URL":   rurl,
				"retry": i,
				"Error": r.Error,
			}).Warn("TRANSFER2GO")
		}
		resp = r
	}
	if resp.Error != nil {
		log.WithFields(log.Fields{
			"URL":   rurl,
			"Retry": urlRetry,
			"Error": resp.Error,
		}).Error("TRANSFER2GO, fail to fetch data")
	}
	ch <- resp
}

// Helper function which validates given URL
func validateUrl(rurl string) bool {
	if len(rurl) > 0 {
		if PatternUrl.MatchString(rurl) {
			return true
		}
		log.WithFields(log.Fields{
			"URL": rurl,
		}).Error("Invalid URL:", rurl)
	}
	return false
}

// Response represents final response in a form of JSON structure
// we use custorm representation
func Response(rurl string, data []byte) []byte {
	b := []byte(`{"url":`)
	u := []byte(rurl)
	c := []byte(",")
	d := []byte(`"data":`)
	e := []byte(`}`)
	a := [][]byte{b, u, c, d, data, e}
	s := []byte(" ")
	r := bytes.Join(a, s)
	return r

}
<|endoftext|>


<commit_before>package main

import (
	"math/rand"
)

type HaveSypapses interface {
	AddOutputSynapse(syn *Synapse)
	AddInputSynapse(syn *Synapse)

	GetOutputSynapses() []*Synapse
	GetInputSynapses() []*Synapse

	Handle(value float64)
	Broadcast(value float64)
}

type Trainable interface {
	Train(delta float64)
}

type Workable interface {
	CollectSignals() []float64
	Activation() float64
	Deactivation() float64
}

type LiveNeuron interface {
	Alive()
}

type Redirectable interface {
	GetOutput() chan float64
}

type Neuron interface {
	Workable
	HaveSypapses
	Trainable
}

type BaseNeuron struct {
	bias        float64
	cache       float64
	inSynapses  []*Synapse
	outSynapses []*Synapse
}

func (n *BaseNeuron) AddOutputSynapse(syn *Synapse) {
	n.outSynapses = append(n.outSynapses, syn)
}

func (n *BaseNeuron) AddInputSynapse(syn *Synapse) {
	n.inSynapses = append(n.inSynapses, syn)
}

func (n *BaseNeuron) GetOutputSynapses() []*Synapse {
	return n.outSynapses
}

func (n *BaseNeuron) GetInputSynapses() []*Synapse {
	return n.inSynapses
}

func (n *BaseNeuron) Handle(value float64) {
	n.Broadcast(value)
}

func (n *BaseNeuron) Broadcast(value float64) {
	for o := range n.outSynapses {
		n.outSynapses[o].in <- value
	}
}

func (n *BaseNeuron) CollectSignals() []float64 {
	inputSignals := make([]float64, len(n.inSynapses))
	for i := range inputSignals {
		inputSignals[i] = <-n.inSynapses[i].out
	}
	return inputSignals
}

func (n *BaseNeuron) Activation() float64 {
	n.cache = sum(n.CollectSignals()) + n.bias
	outputSignal := activation_sigmoid(n.cache)
	return outputSignal
}

func (n *BaseNeuron) Deactivation() float64 {
	return derivative_sigmoid(n.cache)
}

func (n *BaseNeuron) Train(neuronDelta float64) {
	n.bias += neuronDelta
	for _, s := range n.inSynapses {
		s.weight += s.cache * neuronDelta
	}
}

type InputNeuron struct {
	BaseNeuron
}

func CreateInputNeuron() *InputNeuron {
	neuron := InputNeuron{BaseNeuron{bias: rand.Float64()}}
	return &neuron
}

type HiddenNeuron struct {
	BaseNeuron
}

func CreateHiddenNeuron() *HiddenNeuron {
	neuron := HiddenNeuron{BaseNeuron{bias: rand.Float64()}}
	return &neuron
}

func (n *HiddenNeuron) Alive() {
	for {
		value := n.Activation()
		n.Broadcast(value)
	}
}

type OutputNeuron struct {
	BaseNeuron
	output chan float64
}

func CreateOutputNeuron() *OutputNeuron {
	neuron := OutputNeuron{BaseNeuron{bias: rand.Float64()}, make(chan float64)}
	return &neuron
}

func (n *OutputNeuron) GetOutput() chan float64 {
	return n.output
}

func (n *OutputNeuron) Alive() {
	for {
		value := n.Activation()
		n.output <- value
	}
}
<commit_msg>- Change Neuron file structure<commit_after>package main

import (
	"math/rand"
)

type HaveSypapses interface {
	AddOutputSynapse(syn *Synapse)
	AddInputSynapse(syn *Synapse)

	GetOutputSynapses() []*Synapse
	GetInputSynapses() []*Synapse

	Handle(value float64)
	Broadcast(value float64)
}

type Trainable interface {
	Train(delta float64)
}

type Workable interface {
	CollectSignals() []float64
	Activation() float64
	Deactivation() float64
}

type LiveNeuron interface {
	Alive()
}

type Redirectable interface {
	GetOutput() chan float64
}

type Neuron interface {
	Workable
	HaveSypapses
	Trainable
}

type BaseNeuron struct {
	bias        float64
	cache       float64
	inSynapses  []*Synapse
	outSynapses []*Synapse
}

type InputNeuron struct {
	BaseNeuron
}

type HiddenNeuron struct {
	BaseNeuron
}

type OutputNeuron struct {
	BaseNeuron
	output chan float64
}

func CreateInputNeuron() *InputNeuron {
	neuron := InputNeuron{BaseNeuron{bias: rand.Float64()}}
	return &neuron
}

func CreateHiddenNeuron() *HiddenNeuron {
	neuron := HiddenNeuron{BaseNeuron{bias: rand.Float64()}}
	return &neuron
}

func CreateOutputNeuron() *OutputNeuron {
	neuron := OutputNeuron{BaseNeuron{bias: rand.Float64()}, make(chan float64)}
	return &neuron
}

func (n *BaseNeuron) AddOutputSynapse(syn *Synapse) {
	n.outSynapses = append(n.outSynapses, syn)
}

func (n *BaseNeuron) AddInputSynapse(syn *Synapse) {
	n.inSynapses = append(n.inSynapses, syn)
}

func (n *BaseNeuron) GetOutputSynapses() []*Synapse {
	return n.outSynapses
}

func (n *BaseNeuron) GetInputSynapses() []*Synapse {
	return n.inSynapses
}

func (n *BaseNeuron) Handle(value float64) {
	n.Broadcast(value)
}

func (n *BaseNeuron) Broadcast(value float64) {
	for o := range n.outSynapses {
		n.outSynapses[o].in <- value
	}
}

func (n *BaseNeuron) CollectSignals() []float64 {
	inputSignals := make([]float64, len(n.inSynapses))
	for i := range inputSignals {
		inputSignals[i] = <-n.inSynapses[i].out
	}
	return inputSignals
}

func (n *BaseNeuron) Activation() float64 {
	n.cache = sum(n.CollectSignals()) + n.bias
	outputSignal := activation_sigmoid(n.cache)
	return outputSignal
}

func (n *BaseNeuron) Deactivation() float64 {
	return derivative_sigmoid(n.cache)
}

func (n *BaseNeuron) Train(neuronDelta float64) {
	n.bias += neuronDelta
	for _, s := range n.inSynapses {
		s.weight += s.cache * neuronDelta
	}
}

func (n *HiddenNeuron) Alive() {
	for {
		n.Broadcast(n.Activation())
	}
}

func (n *OutputNeuron) GetOutput() chan float64 {
	return n.output
}

func (n *OutputNeuron) Alive() {
	for {
		n.output <- n.Activation()
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 spanstore

import (
	"time"

	"github.com/pkg/errors"
	"github.com/uber/jaeger-lib/metrics"
	"go.uber.org/zap"

	"github.com/jaegertracing/jaeger/pkg/cache"
	"github.com/jaegertracing/jaeger/pkg/cassandra"
	casMetrics "github.com/jaegertracing/jaeger/pkg/cassandra/metrics"
)

const (
	insertOperationName = `INSERT INTO operation_names(service_name, operation_name) VALUES (?, ?)`
	queryOperationNames = `SELECT operation_name FROM operation_names WHERE service_name = ?`
)

// OperationNamesStorage stores known operation names by service.
type OperationNamesStorage struct {
	// CQL statements are public so that Cassandra2 storage can override them
	InsertStmt     string
	QueryStmt      string
	session        cassandra.Session
	writeCacheTTL  time.Duration
	metrics        *casMetrics.Table
	operationNames cache.Cache
	logger         *zap.Logger
}

// NewOperationNamesStorage returns a new OperationNamesStorage
func NewOperationNamesStorage(
	session cassandra.Session,
	writeCacheTTL time.Duration,
	metricsFactory metrics.Factory,
	logger *zap.Logger,
) *OperationNamesStorage {
	return &OperationNamesStorage{
		session:       session,
		InsertStmt:    insertOperationName,
		QueryStmt:     queryOperationNames,
		metrics:       casMetrics.NewTable(metricsFactory, "OperationNames"),
		writeCacheTTL: writeCacheTTL,
		logger:        logger,
		operationNames: cache.NewLRUWithOptions(
			100000,
			&cache.Options{
				TTL:             writeCacheTTL,
				InitialCapacity: 0000,
			}),
	}
}

// Write saves Operation and Service name tuples
func (s *OperationNamesStorage) Write(serviceName string, operationName string) error {
	var err error
	query := s.session.Query(s.InsertStmt)
	if inCache := checkWriteCache(serviceName+"|"+operationName, s.operationNames, s.writeCacheTTL); !inCache {
		q := query.Bind(serviceName, operationName)
		err2 := s.metrics.Exec(q, s.logger)
		if err2 != nil {
			err = err2
		}
	}
	return err
}

// GetOperations returns all operations for a specific service traced by Jaeger
func (s *OperationNamesStorage) GetOperations(service string) ([]string, error) {
	iter := s.session.Query(s.QueryStmt, service).Iter()

	var operation string
	var operations []string
	for iter.Scan(&operation) {
		operations = append(operations, operation)
	}
	if err := iter.Close(); err != nil {
		err = errors.Wrap(err, "Error reading operation_names from storage")
		return nil, err
	}
	return operations, nil
}
<commit_msg>Set operationNames cache initial capacity to 10000 (#621)<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 spanstore

import (
	"time"

	"github.com/pkg/errors"
	"github.com/uber/jaeger-lib/metrics"
	"go.uber.org/zap"

	"github.com/jaegertracing/jaeger/pkg/cache"
	"github.com/jaegertracing/jaeger/pkg/cassandra"
	casMetrics "github.com/jaegertracing/jaeger/pkg/cassandra/metrics"
)

const (
	insertOperationName = `INSERT INTO operation_names(service_name, operation_name) VALUES (?, ?)`
	queryOperationNames = `SELECT operation_name FROM operation_names WHERE service_name = ?`
)

// OperationNamesStorage stores known operation names by service.
type OperationNamesStorage struct {
	// CQL statements are public so that Cassandra2 storage can override them
	InsertStmt     string
	QueryStmt      string
	session        cassandra.Session
	writeCacheTTL  time.Duration
	metrics        *casMetrics.Table
	operationNames cache.Cache
	logger         *zap.Logger
}

// NewOperationNamesStorage returns a new OperationNamesStorage
func NewOperationNamesStorage(
	session cassandra.Session,
	writeCacheTTL time.Duration,
	metricsFactory metrics.Factory,
	logger *zap.Logger,
) *OperationNamesStorage {
	return &OperationNamesStorage{
		session:       session,
		InsertStmt:    insertOperationName,
		QueryStmt:     queryOperationNames,
		metrics:       casMetrics.NewTable(metricsFactory, "OperationNames"),
		writeCacheTTL: writeCacheTTL,
		logger:        logger,
		operationNames: cache.NewLRUWithOptions(
			100000,
			&cache.Options{
				TTL:             writeCacheTTL,
				InitialCapacity: 10000,
			}),
	}
}

// Write saves Operation and Service name tuples
func (s *OperationNamesStorage) Write(serviceName string, operationName string) error {
	var err error
	query := s.session.Query(s.InsertStmt)
	if inCache := checkWriteCache(serviceName+"|"+operationName, s.operationNames, s.writeCacheTTL); !inCache {
		q := query.Bind(serviceName, operationName)
		err2 := s.metrics.Exec(q, s.logger)
		if err2 != nil {
			err = err2
		}
	}
	return err
}

// GetOperations returns all operations for a specific service traced by Jaeger
func (s *OperationNamesStorage) GetOperations(service string) ([]string, error) {
	iter := s.session.Query(s.QueryStmt, service).Iter()

	var operation string
	var operations []string
	for iter.Scan(&operation) {
		operations = append(operations, operation)
	}
	if err := iter.Close(); err != nil {
		err = errors.Wrap(err, "Error reading operation_names from storage")
		return nil, err
	}
	return operations, nil
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	"math"
)

type Duration uint // seconds

func (d Duration) String() string {
	seconds := d % 60
	minutes := int(d/60) % 60
	hours := int(d / 60 / 60)

	if hours < 24 {
		return fmt.Sprintf("%d:%02d:%02d", hours, minutes, seconds)
	}

	days := int(hours / 24)
	hours %= 24
	if days == 1 {
		return fmt.Sprintf("1 day %d:%02d:%02d", hours, minutes, seconds)
	}

	return fmt.Sprintf("%d days %d:%02d:%02d", days, hours, minutes, seconds)
}

type Distance uint // meters

func (d Distance) String() string {
	km := float64(d) / 1000.0
	return fmt.Sprintf("%.02f km", km)
}

type Speed float64 // meters per second

func (s Speed) String() string {
	kmh := s / 1000.0 * 3600.0
	return fmt.Sprintf("%.02f km/h", kmh)
}

func (s Speed) Pace() Pace {
	return Pace(1 / s)
}

type Pace float64 // seconds per meter

func (p Pace) String() string {
	secPerKM := p * 1000
	min := int(secPerKM / 60)
	sec := int(secPerKM) % 60
	return fmt.Sprintf("%d:%02d min/km", min, sec)
}

const earthRadius = 6371000

func Haversine(lat1, lon1, lat2, lon2 float64) float64 {
	dLat := (lat2 - lat1) * (math.Pi / 180.0)
	dLon := (lon2 - lon1) * (math.Pi / 180.0)
	rlat1 := lat1 * (math.Pi / 180.0)
	rlat2 := lat2 * (math.Pi / 180.0)
	a1 := math.Sin(dLat/2) * math.Sin(dLat/2)
	a2 := math.Sin(dLon/2) * math.Sin(dLon/2) * math.Cos(rlat1) * math.Cos(rlat2)
	a := a1 + a2
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
	return earthRadius * c
}
<commit_msg>Remove unused Haversine func<commit_after>package utils

import "fmt"

type Duration uint // seconds

func (d Duration) String() string {
	seconds := d % 60
	minutes := int(d/60) % 60
	hours := int(d / 60 / 60)

	if hours < 24 {
		return fmt.Sprintf("%d:%02d:%02d", hours, minutes, seconds)
	}

	days := int(hours / 24)
	hours %= 24
	if days == 1 {
		return fmt.Sprintf("1 day %d:%02d:%02d", hours, minutes, seconds)
	}

	return fmt.Sprintf("%d days %d:%02d:%02d", days, hours, minutes, seconds)
}

type Distance uint // meters

func (d Distance) String() string {
	km := float64(d) / 1000.0
	return fmt.Sprintf("%.02f km", km)
}

type Speed float64 // meters per second

func (s Speed) String() string {
	kmh := s / 1000.0 * 3600.0
	return fmt.Sprintf("%.02f km/h", kmh)
}

func (s Speed) Pace() Pace {
	return Pace(1 / s)
}

type Pace float64 // seconds per meter

func (p Pace) String() string {
	secPerKM := p * 1000
	min := int(secPerKM / 60)
	sec := int(secPerKM) % 60
	return fmt.Sprintf("%d:%02d min/km", min, sec)
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
)

func TimeString(secs int) string {
	if secs < 0 {
		return "--:--"
	}
	hours := int(secs / 3600)
	secs = secs % 3600
	minutes := int(secs / 60)
	secs = secs % 60
	if hours > 0 {
		return fmt.Sprintf("%d:%02d:%02d", hours, minutes, secs)
	}
	return fmt.Sprintf("%02d:%02d", minutes, secs)
}

func TimeRunes(secs int) []rune {
	return []rune(TimeString(secs))
}

// ReverseRunes returns a new, reversed rune slice.
func ReverseRunes(src []rune) []rune {
	dest := make([]rune, len(src))
	for i, j := 0, len(src)-1; i <= j; i, j = i+1, j-1 {
		dest[i], dest[j] = src[j], src[i]
	}
	return dest
}

func Min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func Max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
<commit_msg>Document utils<commit_after>// package utils provides simple transformation functions which do not fit anywhere else in particular.
package utils

import (
	"fmt"
)

// TimeString formats length in seconds as H:mm:ss.
func TimeString(secs int) string {
	if secs < 0 {
		return `--:--`
	}
	hours := int(secs / 3600)
	secs = secs % 3600
	minutes := int(secs / 60)
	secs = secs % 60
	if hours > 0 {
		return fmt.Sprintf("%d:%02d:%02d", hours, minutes, secs)
	}
	return fmt.Sprintf("%02d:%02d", minutes, secs)
}

// TimeRunes acts as TimeString, but returns a slice of runes.
func TimeRunes(secs int) []rune {
	return []rune(TimeString(secs))
}

// ReverseRunes returns a new, reversed rune slice.
func ReverseRunes(src []rune) []rune {
	dest := make([]rune, len(src))
	for i, j := 0, len(src)-1; i <= j; i, j = i+1, j-1 {
		dest[i], dest[j] = src[j], src[i]
	}
	return dest
}

// Min returns the minimum of a and b.
func Min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Max returns the maximum of a and b.
func Max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
<|endoftext|>


<commit_before>/*
Copyright 2015-2016, RadiantBlue Technologies, Inc.

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

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

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 utils provides various utilities that are used throughout the project.

Provide functions to return canned responses: StatusOK, StatusBadRequest, and StatusInternalServerError.
*/
package utils

import (
	"log"
	"net/http"
	"os"

	"github.com/venicegeo/pzsvc-sdk-go/job"
	"github.com/venicegeo/pzsvc-sdk-go/s3"
)

// FunctionFunc defines the signature of our function creator.
type FunctionFunc func(
	http.ResponseWriter,
	*http.Request,
	*job.OutputMsg,
	job.InputMsg,
)

// MakeFunction wraps the individual PDAL functions.
// Parse the input and output filenames, creating files as needed. Download the
// input data and upload the output data.
func MakeFunction(
	fn func(
		http.ResponseWriter,
		*http.Request,
		*job.OutputMsg,
		job.InputMsg,
		string,
		string,
	),
) FunctionFunc {
	return func(
		w http.ResponseWriter,
		r *http.Request,
		res *job.OutputMsg,
		msg job.InputMsg,
	) {
		var inputName, outputName string
		var fileIn, fileOut *os.File

		// Split the source S3 key string, interpreting the last element as the
		// input filename. Create the input file, throwing 500 on error.
		inputName = s3.ParseFilenameFromKey(msg.Source.Key)
		fileIn, err := os.Create(inputName)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer fileIn.Close()

		// If provided, split the destination S3 key string, interpreting the last
		// element as the output filename. Create the output file, throwing 500 on
		// error.
		if len(msg.Destination.Key) > 0 {
			outputName = s3.ParseFilenameFromKey(msg.Destination.Key)
		}

		// Download the source data from S3, throwing 500 on error.
		err = s3.Download(fileIn, msg.Source.Bucket, msg.Source.Key)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		log.Printf("Stat %s\n", outputName)
		info, _ := os.Stat(outputName)
		log.Println(info)
		// if err != nil {
		// 	http.Error(w, err.Error(), http.StatusInternalServerError)
		// 	return
		// }
		log.Println("Run!")

		// Run the PDAL function.
		fn(w, r, res, msg, inputName, outputName)

		// If an output has been created, upload the destination data to S3,
		// throwing 500 on error.
		if len(msg.Destination.Key) > 0 {
			fileOut, err = os.Open(outputName)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			defer fileOut.Close()
			err = s3.Upload(fileOut, msg.Destination.Bucket, msg.Destination.Key)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		}
	}
}
<commit_msg>debugging<commit_after>/*
Copyright 2015-2016, RadiantBlue Technologies, Inc.

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

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

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 utils provides various utilities that are used throughout the project.

Provide functions to return canned responses: StatusOK, StatusBadRequest, and StatusInternalServerError.
*/
package utils

import (
	"log"
	"net/http"
	"os"

	"github.com/venicegeo/pzsvc-sdk-go/job"
	"github.com/venicegeo/pzsvc-sdk-go/s3"
)

// FunctionFunc defines the signature of our function creator.
type FunctionFunc func(
	http.ResponseWriter,
	*http.Request,
	*job.OutputMsg,
	job.InputMsg,
)

// MakeFunction wraps the individual PDAL functions.
// Parse the input and output filenames, creating files as needed. Download the
// input data and upload the output data.
func MakeFunction(
	fn func(
		http.ResponseWriter,
		*http.Request,
		*job.OutputMsg,
		job.InputMsg,
		string,
		string,
	),
) FunctionFunc {
	return func(
		w http.ResponseWriter,
		r *http.Request,
		res *job.OutputMsg,
		msg job.InputMsg,
	) {
		log.Println("Here we are in MakeFunction")

		var inputName, outputName string
		var fileIn, fileOut *os.File

		// Split the source S3 key string, interpreting the last element as the
		// input filename. Create the input file, throwing 500 on error.
		inputName = s3.ParseFilenameFromKey(msg.Source.Key)
		fileIn, err := os.Create(inputName)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer fileIn.Close()

		// If provided, split the destination S3 key string, interpreting the last
		// element as the output filename. Create the output file, throwing 500 on
		// error.
		if len(msg.Destination.Key) > 0 {
			outputName = s3.ParseFilenameFromKey(msg.Destination.Key)
		}

		// Download the source data from S3, throwing 500 on error.
		err = s3.Download(fileIn, msg.Source.Bucket, msg.Source.Key)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		log.Printf("Stat %s\n", outputName)
		info, _ := os.Stat(outputName)
		log.Println(info)
		// if err != nil {
		// 	http.Error(w, err.Error(), http.StatusInternalServerError)
		// 	return
		// }
		log.Println("Run!")

		// Run the PDAL function.
		fn(w, r, res, msg, inputName, outputName)

		// If an output has been created, upload the destination data to S3,
		// throwing 500 on error.
		if len(msg.Destination.Key) > 0 {
			fileOut, err = os.Open(outputName)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			defer fileOut.Close()
			err = s3.Upload(fileOut, msg.Destination.Bucket, msg.Destination.Key)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package dms

import (
	"encoding/xml"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"bitbucket.org/anacrolix/dms/dlna"
	"bitbucket.org/anacrolix/dms/ffmpeg"
	"bitbucket.org/anacrolix/dms/misc"
	"bitbucket.org/anacrolix/dms/upnp"
	"bitbucket.org/anacrolix/dms/upnpav"
)

type contentDirectoryService struct {
	*Server
	upnp.Eventing
}

// Turns the given entry and DMS host into a UPnP object. A nil object is
// returned if the entry is not of interest.
func (me *contentDirectoryService) cdsObjectToUpnpavObject(cdsObject object, fileInfo os.FileInfo, host, userAgent string) interface{} {
	obj := upnpav.Object{
		ID:         cdsObject.ID(),
		Restricted: 1,
		ParentID:   cdsObject.ParentID(),
	}
	if fileInfo.IsDir() {
		//if !me.objectHasChildren(cdsObject) {
		//		return nil
		//	}
		obj.Class = "object.container.storageFolder"
		obj.Title = fileInfo.Name()
		return upnpav.Container{
			Object: obj,
			//		ChildCount: me.objectChildCount(cdsObject),
		}
	}
	if !fileInfo.Mode().IsRegular() {
		return nil
	}
	entryFilePath := cdsObject.FilePath()
	mimeType := MimeTypeByPath(entryFilePath)
	mimeTypeType := mimeType.Type()
	if !mimeType.IsMedia() {
		return nil
	}
	iconURI := (&url.URL{
		Scheme: "http",
		Host:   host,
		Path:   iconPath,
		RawQuery: url.Values{
			"path": {cdsObject.Path},
		}.Encode(),
	}).String()
	obj.Icon = iconURI
	// TODO(anacrolix): This might not be necessary due to item res image
	// element.
	obj.AlbumArtURI = iconURI
	obj.Class = "object.item." + string(mimeTypeType) + "Item"
	var (
		nativeBitrate uint
		resDuration   string
	)
	ffInfo, probeErr := me.ffmpegProbe(entryFilePath)
	switch probeErr {
	case nil:
		if ffInfo != nil {
			nativeBitrate, _ = ffInfo.Bitrate()
			if d, err := ffInfo.Duration(); err == nil {
				resDuration = misc.FormatDurationSexagesimal(d)
			}
		}
	case ffmpeg.FfprobeUnavailableError:
	default:
		log.Printf("error probing %s: %s", entryFilePath, probeErr)
	}
	if obj.Title == "" {
		obj.Title = fileInfo.Name()
	}
	resolution := func() string {
		if ffInfo != nil {
			for _, strm := range ffInfo.Streams {
				if strm["codec_type"] != "video" {
					continue
				}
				width := strm["width"]
				height := strm["height"]
				return fmt.Sprintf("%.0fx%.0f", width, height)
			}
		}
		return ""
	}()
	item := upnpav.Item{
		Object: obj,
		// Capacity: 1 for raw, 1 for icon, plus transcodes.
		Res: make([]upnpav.Resource, 0, 2+len(transcodes)),
	}
	item.Res = append(item.Res, upnpav.Resource{
		URL: (&url.URL{
			Scheme: "http",
			Host:   host,
			Path:   resPath,
			RawQuery: url.Values{
				"path": {cdsObject.Path},
			}.Encode(),
		}).String(),
		ProtocolInfo: fmt.Sprintf("http-get:*:%s:%s", mimeType, dlna.ContentFeatures{
			SupportRange: true,
		}.String()),
		Bitrate:    nativeBitrate,
		Duration:   resDuration,
		Size:       uint64(fileInfo.Size()),
		Resolution: resolution,
	})
	if mimeTypeType == "video" {
		if !me.NoTranscode {
			item.Res = append(item.Res, transcodeResources(host, cdsObject.Path, resolution, resDuration)...)
		}
	}
	if mimeTypeType.IsMedia() {
		item.Res = append(item.Res, upnpav.Resource{
			URL: (&url.URL{
				Scheme: "http",
				Host:   host,
				Path:   iconPath,
				RawQuery: url.Values{
					"path": {cdsObject.Path},
					"c":    {"jpeg"},
				}.Encode(),
			}).String(),
			ProtocolInfo: "http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN",
		})
	}
	return item
}

// Returns all the upnpav objects in a directory.
func (me *contentDirectoryService) readContainer(o object, host, userAgent string) (ret []interface{}, err error) {
	sfis := sortableFileInfoSlice{
		// TODO(anacrolix): Dig up why this special cast was added.
		FoldersLast: strings.Contains(userAgent, `AwoX/1.1`),
	}
	sfis.fileInfoSlice, err = o.readDir()
	if err != nil {
		return
	}
	sort.Sort(sfis)
	for _, fi := range sfis.fileInfoSlice {
		obj := me.cdsObjectToUpnpavObject(object{path.Join(o.Path, fi.Name()), me.RootObjectPath}, fi, host, userAgent)
		if obj != nil {
			ret = append(ret, obj)
		}
	}
	return
}

type browse struct {
	ObjectID       string
	BrowseFlag     string
	Filter         string
	StartingIndex  int
	RequestedCount int
}

// ContentDirectory object from ObjectID.
func (me *contentDirectoryService) objectFromID(id string) (o object, err error) {
	o.Path, err = url.QueryUnescape(id)
	if err != nil {
		return
	}
	if o.Path == "0" {
		o.Path = "/"
	}
	o.Path = path.Clean(o.Path)
	if !path.IsAbs(o.Path) {
		err = errors.New("bad ObjectID")
		return
	}
	o.RootObjectPath = me.RootObjectPath
	return
}

func (me *contentDirectoryService) Handle(action string, argsXML []byte, r *http.Request) (map[string]string, *upnp.Error) {
	host := r.Host
	userAgent := r.UserAgent()
	switch action {
	case "GetSystemUpdateID":
		return map[string]string{
			"Id": fmt.Sprintf("%d", uint32(os.Getpid())),
		}, nil
	case "GetSortCapabilities":
		return map[string]string{
			"SortCaps": "dc:title",
		}, nil
	case "Browse":
		var browse browse
		if err := xml.Unmarshal([]byte(argsXML), &browse); err != nil {
			panic(err)
		}
		obj, err := me.objectFromID(browse.ObjectID)
		if err != nil {
			return nil, &upnp.Error{
				Code: upnpav.NoSuchObjectErrorCode,
				Desc: err.Error(),
			}
		}
		switch browse.BrowseFlag {
		case "BrowseDirectChildren":
			objs, err := me.readContainer(obj, host, userAgent)
			if err != nil {
				return nil, &upnp.Error{
					// readContainer can only fail due to bad ObjectID afaict
					Code: upnpav.NoSuchObjectErrorCode,
					Desc: err.Error(),
				}
			}
			totalMatches := len(objs)
			objs = objs[func() (low int) {
				low = browse.StartingIndex
				if low > len(objs) {
					low = len(objs)
				}
				return
			}():]
			if browse.RequestedCount != 0 && int(browse.RequestedCount) < len(objs) {
				objs = objs[:browse.RequestedCount]
			}
			result, err := xml.Marshal(objs)
			if err != nil {
				panic(err)
			}
			return map[string]string{
				"TotalMatches":   fmt.Sprint(totalMatches),
				"NumberReturned": fmt.Sprint(len(objs)),
				"Result":         didl_lite(string(result)),
				"UpdateID":       fmt.Sprintf("%d", uint32(time.Now().Unix())),
			}, nil
		case "BrowseMetadata":
			fileInfo, err := os.Stat(obj.FilePath())
			if err != nil {
				return nil, &upnp.Error{
					Code: upnpav.NoSuchObjectErrorCode,
					Desc: err.Error(),
				}
			}
			return map[string]string{
				"TotalMatches":   "1",
				"NumberReturned": "1",
				"Result": didl_lite(func() string {
					buf, err := xml.Marshal(me.cdsObjectToUpnpavObject(obj, fileInfo, host, userAgent))
					if err != nil {
						panic(err) // because aliens
					}
					return string(buf)
				}()),
				"UpdateID": fmt.Sprintf("%d", uint32(time.Now().Unix())),
			}, nil
		default:
			return nil, &upnp.Error{
				Code: upnp.ArgumentValueInvalidErrorCode,
				Desc: fmt.Sprint("unhandled browse flag:", browse.BrowseFlag),
			}
		}
	case "GetSearchCapabilities":
		return map[string]string{
			"SearchCaps": "",
		}, nil
	default:
		log.Println("unhandled CDS action:", action)
		return nil, &upnp.InvalidActionError
	}
}

// Represents a ContentDirectory object.
type object struct {
	Path           string // The cleaned, absolute path for the object relative to the server.
	RootObjectPath string
}

// Returns the number of children this object has, such as for a container.
func (cds *contentDirectoryService) objectChildCount(me object) int {
	objs, err := cds.readContainer(me, "", "")
	if err != nil {
		log.Printf("error reading container: %s", err)
	}
	return len(objs)
}

func (cds *contentDirectoryService) objectHasChildren(obj object) bool {
	return cds.objectChildCount(obj) != 0
}

// Returns the actual local filesystem path for the object.
func (o *object) FilePath() string {
	return filepath.Join(o.RootObjectPath, filepath.FromSlash(o.Path))
}

// Returns the ObjectID for the object. This is used in various ContentDirectory actions.
func (o object) ID() string {
	if !path.IsAbs(o.Path) {
		panic(o.Path)
	}
	if len(o.Path) == 1 {
		return "0"
	}
	return url.QueryEscape(o.Path)
}

func (o *object) IsRoot() bool {
	return o.Path == "/"
}

// Returns the object's parent ObjectID. Fortunately it can be deduced from the
// ObjectID (for now).
func (o object) ParentID() string {
	if o.IsRoot() {
		return "-1"
	}
	o.Path = path.Dir(o.Path)
	return o.ID()
}

// This function exists rather than just calling os.(*File).Readdir because I
// want to stat(), not lstat() each entry.
func (o *object) readDir() (fis []os.FileInfo, err error) {
	dirPath := o.FilePath()
	dirFile, err := os.Open(dirPath)
	if err != nil {
		return
	}
	defer dirFile.Close()
	var dirContent []string
	dirContent, err = dirFile.Readdirnames(-1)
	if err != nil {
		return
	}
	fis = make([]os.FileInfo, 0, len(dirContent))
	for _, file := range dirContent {
		fi, err := os.Stat(filepath.Join(dirPath, file))
		if err != nil {
			continue
		}
		fis = append(fis, fi)
	}
	return
}

type sortableFileInfoSlice struct {
	fileInfoSlice []os.FileInfo
	FoldersLast   bool
}

func (me sortableFileInfoSlice) Len() int {
	return len(me.fileInfoSlice)
}

func (me sortableFileInfoSlice) Less(i, j int) bool {
	if me.fileInfoSlice[i].IsDir() && !me.fileInfoSlice[j].IsDir() {
		return !me.FoldersLast
	}
	if !me.fileInfoSlice[i].IsDir() && me.fileInfoSlice[j].IsDir() {
		return me.FoldersLast
	}
	return strings.ToLower(me.fileInfoSlice[i].Name()) < strings.ToLower(me.fileInfoSlice[j].Name())
}

func (me sortableFileInfoSlice) Swap(i, j int) {
	me.fileInfoSlice[i], me.fileInfoSlice[j] = me.fileInfoSlice[j], me.fileInfoSlice[i]
}
<commit_msg>Create CDS method for UpdateIDs<commit_after>package dms

import (
	"encoding/xml"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"

	"bitbucket.org/anacrolix/dms/dlna"
	"bitbucket.org/anacrolix/dms/ffmpeg"
	"bitbucket.org/anacrolix/dms/misc"
	"bitbucket.org/anacrolix/dms/upnp"
	"bitbucket.org/anacrolix/dms/upnpav"
)

type contentDirectoryService struct {
	*Server
	upnp.Eventing
}

func (cds *contentDirectoryService) updateIDString() string {
	return fmt.Sprintf("%d", uint32(os.Getpid()))
}

// Turns the given entry and DMS host into a UPnP object. A nil object is
// returned if the entry is not of interest.
func (me *contentDirectoryService) cdsObjectToUpnpavObject(cdsObject object, fileInfo os.FileInfo, host, userAgent string) interface{} {
	obj := upnpav.Object{
		ID:         cdsObject.ID(),
		Restricted: 1,
		ParentID:   cdsObject.ParentID(),
	}
	if fileInfo.IsDir() {
		//if !me.objectHasChildren(cdsObject) {
		//		return nil
		//	}
		obj.Class = "object.container.storageFolder"
		obj.Title = fileInfo.Name()
		return upnpav.Container{
			Object: obj,
			//		ChildCount: me.objectChildCount(cdsObject),
		}
	}
	if !fileInfo.Mode().IsRegular() {
		return nil
	}
	entryFilePath := cdsObject.FilePath()
	mimeType := MimeTypeByPath(entryFilePath)
	mimeTypeType := mimeType.Type()
	if !mimeType.IsMedia() {
		return nil
	}
	iconURI := (&url.URL{
		Scheme: "http",
		Host:   host,
		Path:   iconPath,
		RawQuery: url.Values{
			"path": {cdsObject.Path},
		}.Encode(),
	}).String()
	obj.Icon = iconURI
	// TODO(anacrolix): This might not be necessary due to item res image
	// element.
	obj.AlbumArtURI = iconURI
	obj.Class = "object.item." + string(mimeTypeType) + "Item"
	var (
		nativeBitrate uint
		resDuration   string
	)
	ffInfo, probeErr := me.ffmpegProbe(entryFilePath)
	switch probeErr {
	case nil:
		if ffInfo != nil {
			nativeBitrate, _ = ffInfo.Bitrate()
			if d, err := ffInfo.Duration(); err == nil {
				resDuration = misc.FormatDurationSexagesimal(d)
			}
		}
	case ffmpeg.FfprobeUnavailableError:
	default:
		log.Printf("error probing %s: %s", entryFilePath, probeErr)
	}
	if obj.Title == "" {
		obj.Title = fileInfo.Name()
	}
	resolution := func() string {
		if ffInfo != nil {
			for _, strm := range ffInfo.Streams {
				if strm["codec_type"] != "video" {
					continue
				}
				width := strm["width"]
				height := strm["height"]
				return fmt.Sprintf("%.0fx%.0f", width, height)
			}
		}
		return ""
	}()
	item := upnpav.Item{
		Object: obj,
		// Capacity: 1 for raw, 1 for icon, plus transcodes.
		Res: make([]upnpav.Resource, 0, 2+len(transcodes)),
	}
	item.Res = append(item.Res, upnpav.Resource{
		URL: (&url.URL{
			Scheme: "http",
			Host:   host,
			Path:   resPath,
			RawQuery: url.Values{
				"path": {cdsObject.Path},
			}.Encode(),
		}).String(),
		ProtocolInfo: fmt.Sprintf("http-get:*:%s:%s", mimeType, dlna.ContentFeatures{
			SupportRange: true,
		}.String()),
		Bitrate:    nativeBitrate,
		Duration:   resDuration,
		Size:       uint64(fileInfo.Size()),
		Resolution: resolution,
	})
	if mimeTypeType == "video" {
		if !me.NoTranscode {
			item.Res = append(item.Res, transcodeResources(host, cdsObject.Path, resolution, resDuration)...)
		}
	}
	if mimeTypeType.IsMedia() {
		item.Res = append(item.Res, upnpav.Resource{
			URL: (&url.URL{
				Scheme: "http",
				Host:   host,
				Path:   iconPath,
				RawQuery: url.Values{
					"path": {cdsObject.Path},
					"c":    {"jpeg"},
				}.Encode(),
			}).String(),
			ProtocolInfo: "http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN",
		})
	}
	return item
}

// Returns all the upnpav objects in a directory.
func (me *contentDirectoryService) readContainer(o object, host, userAgent string) (ret []interface{}, err error) {
	sfis := sortableFileInfoSlice{
		// TODO(anacrolix): Dig up why this special cast was added.
		FoldersLast: strings.Contains(userAgent, `AwoX/1.1`),
	}
	sfis.fileInfoSlice, err = o.readDir()
	if err != nil {
		return
	}
	sort.Sort(sfis)
	for _, fi := range sfis.fileInfoSlice {
		obj := me.cdsObjectToUpnpavObject(object{path.Join(o.Path, fi.Name()), me.RootObjectPath}, fi, host, userAgent)
		if obj != nil {
			ret = append(ret, obj)
		}
	}
	return
}

type browse struct {
	ObjectID       string
	BrowseFlag     string
	Filter         string
	StartingIndex  int
	RequestedCount int
}

// ContentDirectory object from ObjectID.
func (me *contentDirectoryService) objectFromID(id string) (o object, err error) {
	o.Path, err = url.QueryUnescape(id)
	if err != nil {
		return
	}
	if o.Path == "0" {
		o.Path = "/"
	}
	o.Path = path.Clean(o.Path)
	if !path.IsAbs(o.Path) {
		err = errors.New("bad ObjectID")
		return
	}
	o.RootObjectPath = me.RootObjectPath
	return
}

func (me *contentDirectoryService) Handle(action string, argsXML []byte, r *http.Request) (map[string]string, *upnp.Error) {
	host := r.Host
	userAgent := r.UserAgent()
	switch action {
	case "GetSystemUpdateID":
		return map[string]string{
			"Id": me.updateIDString(),
		}, nil
	case "GetSortCapabilities":
		return map[string]string{
			"SortCaps": "dc:title",
		}, nil
	case "Browse":
		var browse browse
		if err := xml.Unmarshal([]byte(argsXML), &browse); err != nil {
			panic(err)
		}
		obj, err := me.objectFromID(browse.ObjectID)
		if err != nil {
			return nil, &upnp.Error{
				Code: upnpav.NoSuchObjectErrorCode,
				Desc: err.Error(),
			}
		}
		switch browse.BrowseFlag {
		case "BrowseDirectChildren":
			objs, err := me.readContainer(obj, host, userAgent)
			if err != nil {
				return nil, &upnp.Error{
					// readContainer can only fail due to bad ObjectID afaict
					Code: upnpav.NoSuchObjectErrorCode,
					Desc: err.Error(),
				}
			}
			totalMatches := len(objs)
			objs = objs[func() (low int) {
				low = browse.StartingIndex
				if low > len(objs) {
					low = len(objs)
				}
				return
			}():]
			if browse.RequestedCount != 0 && int(browse.RequestedCount) < len(objs) {
				objs = objs[:browse.RequestedCount]
			}
			result, err := xml.Marshal(objs)
			if err != nil {
				panic(err)
			}
			return map[string]string{
				"TotalMatches":   fmt.Sprint(totalMatches),
				"NumberReturned": fmt.Sprint(len(objs)),
				"Result":         didl_lite(string(result)),
				"UpdateID":       me.updateIDString(),
			}, nil
		case "BrowseMetadata":
			fileInfo, err := os.Stat(obj.FilePath())
			if err != nil {
				return nil, &upnp.Error{
					Code: upnpav.NoSuchObjectErrorCode,
					Desc: err.Error(),
				}
			}
			return map[string]string{
				"TotalMatches":   "1",
				"NumberReturned": "1",
				"Result": didl_lite(func() string {
					buf, err := xml.Marshal(me.cdsObjectToUpnpavObject(obj, fileInfo, host, userAgent))
					if err != nil {
						panic(err) // because aliens
					}
					return string(buf)
				}()),
				"UpdateID": me.updateIDString(),
			}, nil
		default:
			return nil, &upnp.Error{
				Code: upnp.ArgumentValueInvalidErrorCode,
				Desc: fmt.Sprint("unhandled browse flag:", browse.BrowseFlag),
			}
		}
	case "GetSearchCapabilities":
		return map[string]string{
			"SearchCaps": "",
		}, nil
	default:
		log.Println("unhandled CDS action:", action)
		return nil, &upnp.InvalidActionError
	}
}

// Represents a ContentDirectory object.
type object struct {
	Path           string // The cleaned, absolute path for the object relative to the server.
	RootObjectPath string
}

// Returns the number of children this object has, such as for a container.
func (cds *contentDirectoryService) objectChildCount(me object) int {
	objs, err := cds.readContainer(me, "", "")
	if err != nil {
		log.Printf("error reading container: %s", err)
	}
	return len(objs)
}

func (cds *contentDirectoryService) objectHasChildren(obj object) bool {
	return cds.objectChildCount(obj) != 0
}

// Returns the actual local filesystem path for the object.
func (o *object) FilePath() string {
	return filepath.Join(o.RootObjectPath, filepath.FromSlash(o.Path))
}

// Returns the ObjectID for the object. This is used in various ContentDirectory actions.
func (o object) ID() string {
	if !path.IsAbs(o.Path) {
		panic(o.Path)
	}
	if len(o.Path) == 1 {
		return "0"
	}
	return url.QueryEscape(o.Path)
}

func (o *object) IsRoot() bool {
	return o.Path == "/"
}

// Returns the object's parent ObjectID. Fortunately it can be deduced from the
// ObjectID (for now).
func (o object) ParentID() string {
	if o.IsRoot() {
		return "-1"
	}
	o.Path = path.Dir(o.Path)
	return o.ID()
}

// This function exists rather than just calling os.(*File).Readdir because I
// want to stat(), not lstat() each entry.
func (o *object) readDir() (fis []os.FileInfo, err error) {
	dirPath := o.FilePath()
	dirFile, err := os.Open(dirPath)
	if err != nil {
		return
	}
	defer dirFile.Close()
	var dirContent []string
	dirContent, err = dirFile.Readdirnames(-1)
	if err != nil {
		return
	}
	fis = make([]os.FileInfo, 0, len(dirContent))
	for _, file := range dirContent {
		fi, err := os.Stat(filepath.Join(dirPath, file))
		if err != nil {
			continue
		}
		fis = append(fis, fi)
	}
	return
}

type sortableFileInfoSlice struct {
	fileInfoSlice []os.FileInfo
	FoldersLast   bool
}

func (me sortableFileInfoSlice) Len() int {
	return len(me.fileInfoSlice)
}

func (me sortableFileInfoSlice) Less(i, j int) bool {
	if me.fileInfoSlice[i].IsDir() && !me.fileInfoSlice[j].IsDir() {
		return !me.FoldersLast
	}
	if !me.fileInfoSlice[i].IsDir() && me.fileInfoSlice[j].IsDir() {
		return me.FoldersLast
	}
	return strings.ToLower(me.fileInfoSlice[i].Name()) < strings.ToLower(me.fileInfoSlice[j].Name())
}

func (me sortableFileInfoSlice) Swap(i, j int) {
	me.fileInfoSlice[i], me.fileInfoSlice[j] = me.fileInfoSlice[j], me.fileInfoSlice[i]
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "os"
import "os/signal"
import "path/filepath"
import "regexp"
import "strings"

import "github.com/shiena/ansicolor"

import "./alias"
import "./commands"
import "./completion"
import "./conio"
import "./dos"
import "./history"
import "./interpreter"
import "./lua"

func signalOff() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	go func() {
		for _ = range ch {

		}
	}()
}

var rxAnsiEscCode = regexp.MustCompile("\x1b[^a-zA-Z]*[a-zA-Z]")

var stamp string
var commit string

func main() {
	signalOff()

	// KeyBind += completion Module
	historyUp := conio.KeyGoFuncT{history.KeyFuncHistoryUp}
	historyDown := conio.KeyGoFuncT{history.KeyFuncHistoryDown}
	completion := conio.KeyGoFuncT{completion.KeyFuncCompletion}

	conio.KeyMap['\t'] = &completion
	conio.ZeroMap[conio.K_UP] = &historyUp
	conio.ZeroMap[conio.K_DOWN] = &historyDown
	conio.KeyMap['P'&0x1F] = &historyUp
	conio.KeyMap['N'&0x1F] = &historyDown

	// ANSI Escape Sequence Support
	ansiOut := ansicolor.NewAnsiColorWriter(os.Stdout)

	commands.Init()
	alias.Init()

	// Lua extension
	L := lua.New()
	L.OpenLibs()
	SetLuaFunctions(L)
	L.GetGlobal("nyagos")
	L.PushString(stamp)
	L.SetField(-2, "stamp")
	L.PushString(commit)
	L.SetField(-2, "commit")
	L.Pop(1)
	defer L.Close()

	// Parameter Parsing
	argc := 0
	OptionParse(func() (string, bool) {
		argc++
		if argc < len(os.Args) {
			return os.Args[argc], true
		} else {
			return "", false
		}
	})

	appData := filepath.Join(os.Getenv("APPDATA"), "NYAOS_ORG")
	os.Mkdir(appData, 0777)
	histPath := filepath.Join(appData, "nyagos.history")
	history.Load(histPath)
	defer history.Save(histPath)

	exeName, exeNameErr := dos.GetModuleFileName()
	if exeNameErr != nil {
		fmt.Fprintln(os.Stderr, exeNameErr)
	}
	exeFolder := filepath.Dir(exeName)
	nyagos_lua := filepath.Join(exeFolder, "nyagos.lua")
	if _, err := os.Stat(nyagos_lua); err == nil {
		err := L.Source(nyagos_lua)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}

	for {
		wd, wdErr := os.Getwd()
		if wdErr == nil {
			conio.SetTitle("NYAOS - " + wd)
		} else {
			conio.SetTitle("NYAOS - " + wdErr.Error())
		}
		line, cont := conio.ReadLine(
			func() int {
				text := Format2Prompt(os.Getenv("PROMPT"))
				fmt.Fprint(ansiOut, text)
				text = rxAnsiEscCode.ReplaceAllString(text, "")
				lfPos := strings.LastIndex(text, "\n")
				if lfPos >= 0 {
					text = text[lfPos+1:]
				}
				return conio.GetStringWidth(text)
			})
		if cont == conio.ABORT {
			break
		}
		stackPos := L.GetTop()
		L.GetGlobal("nyagos")
		L.GetField(-1, "filter")
		if L.IsFunction(-1) {
			L.PushString(line)
			err := L.Call(1, 1)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
			} else {
				if L.IsString(-1) {
					line = L.ToString(-1)
				}
			}
		}
		L.SetTop(stackPos)

		var isReplaced bool
		line, isReplaced = history.Replace(line)
		if isReplaced {
			fmt.Fprintln(os.Stdout, line)
		}
		history.Push(line)
		whatToDo, err := interpreter.Interpret(line, nil)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		if whatToDo == interpreter.SHUTDOWN {
			break
		}
	}
}
<commit_msg>filter(nyagos.eval)の結果が history に乗る不具合を修正<commit_after>package main

import "fmt"
import "os"
import "os/signal"
import "path/filepath"
import "regexp"
import "strings"

import "github.com/shiena/ansicolor"

import "./alias"
import "./commands"
import "./completion"
import "./conio"
import "./dos"
import "./history"
import "./interpreter"
import "./lua"

func signalOff() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	go func() {
		for _ = range ch {

		}
	}()
}

var rxAnsiEscCode = regexp.MustCompile("\x1b[^a-zA-Z]*[a-zA-Z]")

var stamp string
var commit string

func main() {
	signalOff()

	// KeyBind += completion Module
	historyUp := conio.KeyGoFuncT{history.KeyFuncHistoryUp}
	historyDown := conio.KeyGoFuncT{history.KeyFuncHistoryDown}
	completion := conio.KeyGoFuncT{completion.KeyFuncCompletion}

	conio.KeyMap['\t'] = &completion
	conio.ZeroMap[conio.K_UP] = &historyUp
	conio.ZeroMap[conio.K_DOWN] = &historyDown
	conio.KeyMap['P'&0x1F] = &historyUp
	conio.KeyMap['N'&0x1F] = &historyDown

	// ANSI Escape Sequence Support
	ansiOut := ansicolor.NewAnsiColorWriter(os.Stdout)

	commands.Init()
	alias.Init()

	// Lua extension
	L := lua.New()
	L.OpenLibs()
	SetLuaFunctions(L)
	L.GetGlobal("nyagos")
	L.PushString(stamp)
	L.SetField(-2, "stamp")
	L.PushString(commit)
	L.SetField(-2, "commit")
	L.Pop(1)
	defer L.Close()

	// Parameter Parsing
	argc := 0
	OptionParse(func() (string, bool) {
		argc++
		if argc < len(os.Args) {
			return os.Args[argc], true
		} else {
			return "", false
		}
	})

	appData := filepath.Join(os.Getenv("APPDATA"), "NYAOS_ORG")
	os.Mkdir(appData, 0777)
	histPath := filepath.Join(appData, "nyagos.history")
	history.Load(histPath)
	defer history.Save(histPath)

	exeName, exeNameErr := dos.GetModuleFileName()
	if exeNameErr != nil {
		fmt.Fprintln(os.Stderr, exeNameErr)
	}
	exeFolder := filepath.Dir(exeName)
	nyagos_lua := filepath.Join(exeFolder, "nyagos.lua")
	if _, err := os.Stat(nyagos_lua); err == nil {
		err := L.Source(nyagos_lua)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}

	for {
		wd, wdErr := os.Getwd()
		if wdErr == nil {
			conio.SetTitle("NYAOS - " + wd)
		} else {
			conio.SetTitle("NYAOS - " + wdErr.Error())
		}
		line, cont := conio.ReadLine(
			func() int {
				text := Format2Prompt(os.Getenv("PROMPT"))
				fmt.Fprint(ansiOut, text)
				text = rxAnsiEscCode.ReplaceAllString(text, "")
				lfPos := strings.LastIndex(text, "\n")
				if lfPos >= 0 {
					text = text[lfPos+1:]
				}
				return conio.GetStringWidth(text)
			})
		if cont == conio.ABORT {
			break
		}

		var isReplaced bool
		line, isReplaced = history.Replace(line)
		if isReplaced {
			fmt.Fprintln(os.Stdout, line)
		}
		history.Push(line)

		stackPos := L.GetTop()
		L.GetGlobal("nyagos")
		L.GetField(-1, "filter")
		if L.IsFunction(-1) {
			L.PushString(line)
			err := L.Call(1, 1)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
			} else {
				if L.IsString(-1) {
					line = L.ToString(-1)
				}
			}
		}
		L.SetTop(stackPos)

		whatToDo, err := interpreter.Interpret(line, nil)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		if whatToDo == interpreter.SHUTDOWN {
			break
		}
	}
}
<|endoftext|>