<commit_before>// Copyright 2013 The go-github 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 github

import (
	"fmt"
	"time"
)

// IssuesService handles communication with the issue related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/issues/
type IssuesService struct {
	client *Client
}

// Issue represents a GitHub issue on a repository.
type Issue struct {
	Number           *int              `json:"number,omitempty"`
	State            *string           `json:"state,omitempty"`
	Title            *string           `json:"title,omitempty"`
	Body             *string           `json:"body,omitempty"`
	User             *User             `json:"user,omitempty"`
	Labels           []Label           `json:"labels,omitempty"`
	Assignee         *User             `json:"assignee,omitempty"`
	Comments         *int              `json:"comments,omitempty"`
	ClosedAt         *time.Time        `json:"closed_at,omitempty"`
	CreatedAt        *time.Time        `json:"created_at,omitempty"`
	UpdatedAt        *time.Time        `json:"updated_at,omitempty"`
	URL              *string           `json:"url,omitempty"`
	HTMLURL          *string           `json:"html_url,omitempty"`
	Milestone        *Milestone        `json:"milestone,omitempty"`
	PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"`

	// TextMatches is only populated from search results that request text matches
	// See: search.go and https://developer.github.com/v3/search/#text-match-metadata
	TextMatches []TextMatch `json:"text_matches,omitempty"`
}

func (i Issue) String() string {
	return Stringify(i)
}

// IssueRequest represents a request to create/edit an issue.
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
	Title     *string   `json:"title,omitempty"`
	Body      *string   `json:"body,omitempty"`
	Labels    *[]string `json:"labels,omitempty"`
	Assignee  *string   `json:"assignee,omitempty"`
	State     *string   `json:"state,omitempty"`
	Milestone *int      `json:"milestone,omitempty"`
}

// IssueListOptions specifies the optional parameters to the IssuesService.List
// and IssuesService.ListByOrg methods.
type IssueListOptions struct {
	// Filter specifies which issues to list.  Possible values are: assigned,
	// created, mentioned, subscribed, all.  Default is "assigned".
	Filter string `url:"filter,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed, all.  Default is "open".
	State string `url:"state,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,comma,omitempty"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "created".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "desc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// PullRequestLinks object is added to the Issue object when it's an issue included
// in the IssueCommentEvent webhook payload, if the webhooks is fired by a comment on a PR
type PullRequestLinks struct {
	URL      *string `json:"url,omitempty"`
	HTMLURL  *string `json:"html_url,omitempty"`
	DiffURL  *string `json:"diff_url,omitempty"`
	PatchURL *string `json:"patch_url,omitempty"`
}

// List the issues for the authenticated user.  If all is true, list issues
// across all the user's visible repositories including owned, member, and
// organization repositories; if false, list only owned and member
// repositories.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) List(all bool, opt *IssueListOptions) ([]Issue, *Response, error) {
	var u string
	if all {
		u = "issues"
	} else {
		u = "user/issues"
	}
	return s.listIssues(u, opt)
}

// ListByOrg fetches the issues in the specified organization for the
// authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) ListByOrg(org string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("orgs/%v/issues", org)
	return s.listIssues(u, opt)
}

func (s *IssuesService) listIssues(u string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// IssueListByRepoOptions specifies the optional parameters to the
// IssuesService.ListByRepo method.
type IssueListByRepoOptions struct {
	// Milestone limits issues for the specified milestone.  Possible values are
	// a milestone number, "none" for issues with no milestone, "*" for issues
	// with any milestone.
	Milestone string `url:"milestone,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed, all.  Default is "open".
	State string `url:"state,omitempty"`

	// Assignee filters issues based on their assignee.  Possible values are a
	// user name, "none" for issues that are not assigned, "*" for issues with
	// any assigned user.
	Assignee string `url:"assignee,omitempty"`

	// Creator filters issues based on their creator.
	Creator string `url:"creator,omitempty"`

	// Mentioned filters issues to those mentioned a specific user.
	Mentioned string `url:"mentioned,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,omitempty,comma"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "created".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "desc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// ListByRepo lists the issues for the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues-for-a-repository
func (s *IssuesService) ListByRepo(owner string, repo string, opt *IssueListByRepoOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// Get a single issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#get-a-single-issue
func (s *IssuesService) Get(owner string, repo string, number int) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issue := new(Issue)
	resp, err := s.client.Do(req, issue)
	if err != nil {
		return nil, resp, err
	}

	return issue, resp, err
}

// Create a new issue on the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#create-an-issue
func (s *IssuesService) Create(owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	req, err := s.client.NewRequest("POST", u, issue)
	if err != nil {
		return nil, nil, err
	}

	i := new(Issue)
	resp, err := s.client.Do(req, i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}

// Edit an issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#edit-an-issue
func (s *IssuesService) Edit(owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("PATCH", u, issue)
	if err != nil {
		return nil, nil, err
	}

	i := new(Issue)
	resp, err := s.client.Do(req, i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<commit_msg>issues: add Repository<commit_after>// Copyright 2013 The go-github 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 github

import (
	"fmt"
	"time"
)

// IssuesService handles communication with the issue related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/issues/
type IssuesService struct {
	client *Client
}

// Issue represents a GitHub issue on a repository.
type Issue struct {
	Number           *int              `json:"number,omitempty"`
	State            *string           `json:"state,omitempty"`
	Title            *string           `json:"title,omitempty"`
	Body             *string           `json:"body,omitempty"`
	User             *User             `json:"user,omitempty"`
	Labels           []Label           `json:"labels,omitempty"`
	Assignee         *User             `json:"assignee,omitempty"`
	Comments         *int              `json:"comments,omitempty"`
	ClosedAt         *time.Time        `json:"closed_at,omitempty"`
	CreatedAt        *time.Time        `json:"created_at,omitempty"`
	UpdatedAt        *time.Time        `json:"updated_at,omitempty"`
	URL              *string           `json:"url,omitempty"`
	HTMLURL          *string           `json:"html_url,omitempty"`
	Milestone        *Milestone        `json:"milestone,omitempty"`
	PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"`
	Repository       *Repository       `json:"repository,omitempty"`

	// TextMatches is only populated from search results that request text matches
	// See: search.go and https://developer.github.com/v3/search/#text-match-metadata
	TextMatches []TextMatch `json:"text_matches,omitempty"`
}

func (i Issue) String() string {
	return Stringify(i)
}

// IssueRequest represents a request to create/edit an issue.
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
	Title     *string   `json:"title,omitempty"`
	Body      *string   `json:"body,omitempty"`
	Labels    *[]string `json:"labels,omitempty"`
	Assignee  *string   `json:"assignee,omitempty"`
	State     *string   `json:"state,omitempty"`
	Milestone *int      `json:"milestone,omitempty"`
}

// IssueListOptions specifies the optional parameters to the IssuesService.List
// and IssuesService.ListByOrg methods.
type IssueListOptions struct {
	// Filter specifies which issues to list.  Possible values are: assigned,
	// created, mentioned, subscribed, all.  Default is "assigned".
	Filter string `url:"filter,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed, all.  Default is "open".
	State string `url:"state,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,comma,omitempty"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "created".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "desc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// PullRequestLinks object is added to the Issue object when it's an issue included
// in the IssueCommentEvent webhook payload, if the webhooks is fired by a comment on a PR
type PullRequestLinks struct {
	URL      *string `json:"url,omitempty"`
	HTMLURL  *string `json:"html_url,omitempty"`
	DiffURL  *string `json:"diff_url,omitempty"`
	PatchURL *string `json:"patch_url,omitempty"`
}

// List the issues for the authenticated user.  If all is true, list issues
// across all the user's visible repositories including owned, member, and
// organization repositories; if false, list only owned and member
// repositories.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) List(all bool, opt *IssueListOptions) ([]Issue, *Response, error) {
	var u string
	if all {
		u = "issues"
	} else {
		u = "user/issues"
	}
	return s.listIssues(u, opt)
}

// ListByOrg fetches the issues in the specified organization for the
// authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) ListByOrg(org string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("orgs/%v/issues", org)
	return s.listIssues(u, opt)
}

func (s *IssuesService) listIssues(u string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// IssueListByRepoOptions specifies the optional parameters to the
// IssuesService.ListByRepo method.
type IssueListByRepoOptions struct {
	// Milestone limits issues for the specified milestone.  Possible values are
	// a milestone number, "none" for issues with no milestone, "*" for issues
	// with any milestone.
	Milestone string `url:"milestone,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed, all.  Default is "open".
	State string `url:"state,omitempty"`

	// Assignee filters issues based on their assignee.  Possible values are a
	// user name, "none" for issues that are not assigned, "*" for issues with
	// any assigned user.
	Assignee string `url:"assignee,omitempty"`

	// Creator filters issues based on their creator.
	Creator string `url:"creator,omitempty"`

	// Mentioned filters issues to those mentioned a specific user.
	Mentioned string `url:"mentioned,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,omitempty,comma"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "created".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "desc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// ListByRepo lists the issues for the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues-for-a-repository
func (s *IssuesService) ListByRepo(owner string, repo string, opt *IssueListByRepoOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// Get a single issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#get-a-single-issue
func (s *IssuesService) Get(owner string, repo string, number int) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	issue := new(Issue)
	resp, err := s.client.Do(req, issue)
	if err != nil {
		return nil, resp, err
	}

	return issue, resp, err
}

// Create a new issue on the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#create-an-issue
func (s *IssuesService) Create(owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	req, err := s.client.NewRequest("POST", u, issue)
	if err != nil {
		return nil, nil, err
	}

	i := new(Issue)
	resp, err := s.client.Do(req, i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}

// Edit an issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#edit-an-issue
func (s *IssuesService) Edit(owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("PATCH", u, issue)
	if err != nil {
		return nil, nil, err
	}

	i := new(Issue)
	resp, err := s.client.Do(req, i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<|endoftext|>


<commit_before>package main

import (
	"cookoo"
	//"fmt"
	"os"
  "flag"
)

func main() {
  flag.Parse()
  project := flag.Arg(0)
  homedir := os.ExpandEnv("${HOME}/.skunk")
  projectdir := os.ExpandEnv("${PWD}/" + project)
	registry, router, cxt := cookoo.Cookoo()

  cxt.Add("homedir", homedir)
  cxt.Add("basedir", projectdir)
  cxt.Add("project", project)
  cxt.Add("YEAR", "2013")

	registry.
  Route("scaffold", "Scaffold a new app.").
		Does(Notice, "Testing").
		Does(LoadSettings, "settings").
			Using("file").WithDefault(homedir + "/settings.json").From("cxt:SettingsFile").
		Does(MakeDirectories, "dirs").
      Using("basedir").From("cxt:basedir").
			Using("directories").From("cxt:directories").
    Does(RenderTemplates, "template").
      Using("tpldir").From("cxt:homedir").
      Using("basedir").From("cxt:basedir").
      Using("templates").From("cxt:templates").
  Route("help", "Print help").
    Does(Usage, "Testing").
	Done()

	//router.HandleRequest("help", cxt, false)
	router.HandleRequest("scaffold", cxt, false)
}

<commit_msg>Minor change to registry.<commit_after>package main

import (
	"cookoo"
	//"fmt"
	"os"
  "flag"
)

func main() {
  flag.Parse()
  project := flag.Arg(0)
  homedir := os.ExpandEnv("${HOME}/.skunk")
  projectdir := os.ExpandEnv("${PWD}/" + project)
	registry, router, cxt := cookoo.Cookoo()

  cxt.Add("homedir", homedir)
  cxt.Add("basedir", projectdir)
  cxt.Add("project", project)
  cxt.Add("YEAR", "2013")

	registry.
  Route("scaffold", "Scaffold a new app.").
		Does(Notice, "Testing").
		Does(LoadSettings, "settings").
			Using("file").WithDefault(homedir + "/settings.json").From("cxt:SettingsFile").
		Does(MakeDirectories, "dirs").
      Using("basedir").From("cxt:basedir").
			Using("directories").From("cxt:directories").
    Does(RenderTemplates, "template").
      Using("tpldir").From("cxt:homedir").
      Using("basedir").From("cxt:basedir").
      Using("templates").From("cxt:templates").
  Route("help", "Print help").
    Does(Usage, "HelpText").
	Done()

	//router.HandleRequest("help", cxt, false)
	router.HandleRequest("scaffold", cxt, false)
}

<|endoftext|>


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

// Package smart is a pure Go SMART library.
//
package smart

import (
	"encoding/binary"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"unsafe"

	"github.com/BurntSushi/toml"
)

// SMART attribute conversion rule
type attrConv struct {
	Conv string
	Name string
}

type driveModel struct {
	Family         string
	ModelRegex     string
	FirmwareRegex  string
	WarningMsg     string
	Presets        map[string]attrConv
	CompiledRegexp *regexp.Regexp
}

type driveDb struct {
	Drives []driveModel
}

// Individual SMART attribute (12 bytes)
type smartAttr struct {
	Id          uint8
	Flags       uint16
	Value       uint8   // normalised value
	Worst       uint8   // worst value
	VendorBytes [6]byte // vendor-specific (and sometimes device-specific) data
	Reserved    uint8
}

// Page of 30 SMART attributes as per ATA spec
type smartPage struct {
	Version uint16
	Attrs   [30]smartAttr
}

var nativeEndian binary.ByteOrder

// Determine native endianness of system
func init() {
	i := uint32(1)
	b := (*[4]byte)(unsafe.Pointer(&i))
	if b[0] == 1 {
		nativeEndian = binary.LittleEndian
	} else {
		nativeEndian = binary.BigEndian
	}
}

// lookupDrive returns the most appropriate driveModel for a given ATA IDENTIFY value
func (db *driveDb) lookupDrive(ident []byte) driveModel {
	var model driveModel

	for _, d := range db.Drives {
		// Skip placeholder entry
		if strings.HasPrefix(d.Family, "$Id") {
			continue
		}

		if d.Family == "DEFAULT" {
			model = d
			continue
		}

		if d.CompiledRegexp.Match(ident) {
			model.Family = d.Family
			model.ModelRegex = d.ModelRegex
			model.FirmwareRegex = d.FirmwareRegex
			model.WarningMsg = d.WarningMsg
			model.CompiledRegexp = d.CompiledRegexp

			for id, p := range d.Presets {
				if _, exists := model.Presets[id]; exists {
					// Some drives override the conv but don't specify a name, so copy it from default
					if p.Name == "" {
						p.Name = model.Presets[id].Name
					}
				}
				model.Presets[id] = attrConv{Name: p.Name, Conv: p.Conv}
			}

			break
		}
	}

	return model
}

// openDriveDb opens a .toml formatted drive database, unmarshalls it, and returns a driveDb
func openDriveDb(dbfile string) (driveDb, error) {
	var db driveDb

	if _, err := toml.DecodeFile(dbfile, &db); err != nil {
		return db, fmt.Errorf("Cannot open / parse drive DB: %s", err)
	}

	for i, d := range db.Drives {
		db.Drives[i].CompiledRegexp, _ = regexp.Compile(d.ModelRegex)
	}

	return db, nil
}

// decodeVendorBytes decodes the six-byte vendor byte array based on the conversion rule passed as
// conv. The conversion may also include the reserved byte, normalised value or worst value byte.
func (sa *smartAttr) decodeVendorBytes(conv string) uint64 {
	var (
		byteOrder string
		r         uint64
	)

	// Default byte orders if not otherwise specified in drivedb
	// TODO: Handle temperature formats (device-specific)
	switch conv {
	case "raw64", "hex64":
		byteOrder = "543210wv"
	case "raw56", "hex56", "raw24/raw32", "msec24hour32":
		byteOrder = "r543210"
	default:
		byteOrder = "543210"
	}

	// Pick bytes from smartAttr in order specified by byteOrder
	for _, i := range byteOrder {
		var b byte

		switch i {
		case '0', '1', '2', '3', '4', '5':
			b = sa.VendorBytes[i-48]
		case 'r':
			b = sa.Reserved
		case 'v':
			b = sa.Value
		case 'w':
			b = sa.Worst
		default:
			b = 0
		}

		r <<= 8
		r |= uint64(b)
	}

	return r
}

func formatRawValue(v uint64, conv string) (s string) {
	var (
		raw  [6]uint8
		word [3]uint16
	)

	// Split into bytes
	for i := 0; i < 6; i++ {
		raw[i] = uint8(v >> uint(i*8))
	}

	// Split into words
	for i := 0; i < 3; i++ {
		word[i] = uint16(v >> uint(i*16))
	}

	switch conv {
	case "raw8":
		s = fmt.Sprintf("%d %d %d %d %d %d",
			raw[5], raw[4], raw[3], raw[2], raw[1], raw[0])
	case "raw16":
		s = fmt.Sprintf("%d %d %d", word[2], word[1], word[0])
	case "raw48", "raw56", "raw64":
		s = fmt.Sprintf("%d", v)
	case "hex48":
		s = fmt.Sprintf("%#012x", v)
	case "hex56":
		s = fmt.Sprintf("%#014x", v)
	case "hex64":
		s = fmt.Sprintf("%#016x", v)
	case "raw16(raw16)":
		s = fmt.Sprintf("%d", word[0])
		if (word[1] != 0) || (word[2] != 0) {
			s += fmt.Sprintf(" (%d %d)", word[2], word[1])
		}
	case "raw16(avg16)":
		s = fmt.Sprintf("%d", word[0])
		if word[1] != 0 {
			s += fmt.Sprintf(" (Average %d)", word[1])
		}
	case "raw24(raw8)":
		s = fmt.Sprintf("%d", v&0x00ffffff)
		if (raw[3] != 0) || (raw[4] != 0) || (raw[5] != 0) {
			s += fmt.Sprintf(" (%d %d %d)", raw[5], raw[4], raw[3])
		}
	case "raw24/raw24":
		s = fmt.Sprintf("%d/%d", v>>24, v&0x00ffffff)
	case "raw24/raw32":
		s = fmt.Sprintf("%d/%d", v>>32, v&0xffffffff)
	case "min2hour":
		// minutes
		minutes := int64(word[0]) + int64(word[1])<<16
		s = fmt.Sprintf("%dh+%02dm", minutes/60, minutes%60)
		if word[2] != 0 {
			s += fmt.Sprintf(" (%d)", word[2])
		}
	case "sec2hour":
		// seconds
		hours := v / 3600
		minutes := (v % 3600) / 60
		seconds := v % 60
		s = fmt.Sprintf("%dh+%02dm+%02ds", hours, minutes, seconds)
	case "halfmin2hour":
		// 30-second counter
		hours := v / 120
		minutes := (v % 120) / 2
		s = fmt.Sprintf("%dh+%02dm", hours, minutes)
	case "msec24hour32":
		// hours + milliseconds
		hours := v & 0xffffffff
		milliseconds := v >> 32
		seconds := milliseconds / 1000
		s = fmt.Sprintf("%dh+%02dm+%02d.%03ds",
			hours, seconds/60, seconds%60, milliseconds)
	case "tempminmax":
		s = "not implemented"
	case "temp10x":
		// ten times temperature in Celsius
		s = fmt.Sprintf("%d.%d", word[0]/10, word[0]%10)
	default:
		s = "?"
	}

	return s
}

func printSMART(smart smartPage, drive driveModel) {
	fmt.Printf("\nSMART structure version: %d\n", smart.Version)
	fmt.Printf("ID# ATTRIBUTE_NAME           FLAG     VALUE WORST RESERVED TYPE     UPDATED RAW_VALUE           VENDOR_BYTES\n")

	for _, attr := range smart.Attrs {
		var (
			rawValue              uint64
			conv                  attrConv
			attrType, attrUpdated string
		)

		if attr.Id == 0 {
			break
		}

		conv, ok := drive.Presets[strconv.Itoa(int(attr.Id))]
		if ok {
			rawValue = attr.decodeVendorBytes(conv.Conv)
		}

		// Pre-fail / advisory bit
		if attr.Flags&0x0001 != 0 {
			attrType = "Pre-fail"
		} else {
			attrType = "Old_age"
		}

		// Online data collection bit
		if attr.Flags&0x0002 != 0 {
			attrUpdated = "Always"
		} else {
			attrUpdated = "Offline"
		}

		fmt.Printf("%3d %-24s %#04x   %03d   %03d   %03d      %-8s %-7s %-18s  %v (%s)\n",
			attr.Id, conv.Name, attr.Flags, attr.Value, attr.Worst, attr.Reserved, attrType,
			attrUpdated, formatRawValue(rawValue, conv.Conv), attr.VendorBytes, conv.Conv)
	}
}
<commit_msg>Add temperature formatting<commit_after>// Copyright 2017 Daniel Swarbrick. All rights reserved.
// Use of this source code is governed by a GPL license that can be found in the LICENSE file.

// Package smart is a pure Go SMART library.
//
package smart

import (
	"encoding/binary"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"unsafe"

	"github.com/BurntSushi/toml"
)

// SMART attribute conversion rule
type attrConv struct {
	Conv string
	Name string
}

type driveModel struct {
	Family         string
	ModelRegex     string
	FirmwareRegex  string
	WarningMsg     string
	Presets        map[string]attrConv
	CompiledRegexp *regexp.Regexp
}

type driveDb struct {
	Drives []driveModel
}

// Individual SMART attribute (12 bytes)
type smartAttr struct {
	Id          uint8
	Flags       uint16
	Value       uint8   // normalised value
	Worst       uint8   // worst value
	VendorBytes [6]byte // vendor-specific (and sometimes device-specific) data
	Reserved    uint8
}

// Page of 30 SMART attributes as per ATA spec
type smartPage struct {
	Version uint16
	Attrs   [30]smartAttr
}

var nativeEndian binary.ByteOrder

// Determine native endianness of system
func init() {
	i := uint32(1)
	b := (*[4]byte)(unsafe.Pointer(&i))
	if b[0] == 1 {
		nativeEndian = binary.LittleEndian
	} else {
		nativeEndian = binary.BigEndian
	}
}

// lookupDrive returns the most appropriate driveModel for a given ATA IDENTIFY value
func (db *driveDb) lookupDrive(ident []byte) driveModel {
	var model driveModel

	for _, d := range db.Drives {
		// Skip placeholder entry
		if strings.HasPrefix(d.Family, "$Id") {
			continue
		}

		if d.Family == "DEFAULT" {
			model = d
			continue
		}

		if d.CompiledRegexp.Match(ident) {
			model.Family = d.Family
			model.ModelRegex = d.ModelRegex
			model.FirmwareRegex = d.FirmwareRegex
			model.WarningMsg = d.WarningMsg
			model.CompiledRegexp = d.CompiledRegexp

			for id, p := range d.Presets {
				if _, exists := model.Presets[id]; exists {
					// Some drives override the conv but don't specify a name, so copy it from default
					if p.Name == "" {
						p.Name = model.Presets[id].Name
					}
				}
				model.Presets[id] = attrConv{Name: p.Name, Conv: p.Conv}
			}

			break
		}
	}

	return model
}

// openDriveDb opens a .toml formatted drive database, unmarshalls it, and returns a driveDb
func openDriveDb(dbfile string) (driveDb, error) {
	var db driveDb

	if _, err := toml.DecodeFile(dbfile, &db); err != nil {
		return db, fmt.Errorf("Cannot open / parse drive DB: %s", err)
	}

	for i, d := range db.Drives {
		db.Drives[i].CompiledRegexp, _ = regexp.Compile(d.ModelRegex)
	}

	return db, nil
}

// decodeVendorBytes decodes the six-byte vendor byte array based on the conversion rule passed as
// conv. The conversion may also include the reserved byte, normalised value or worst value byte.
func (sa *smartAttr) decodeVendorBytes(conv string) uint64 {
	var (
		byteOrder string
		r         uint64
	)

	// Default byte orders if not otherwise specified in drivedb
	// TODO: Handle temperature formats (device-specific)
	switch conv {
	case "raw64", "hex64":
		byteOrder = "543210wv"
	case "raw56", "hex56", "raw24/raw32", "msec24hour32":
		byteOrder = "r543210"
	default:
		byteOrder = "543210"
	}

	// Pick bytes from smartAttr in order specified by byteOrder
	for _, i := range byteOrder {
		var b byte

		switch i {
		case '0', '1', '2', '3', '4', '5':
			b = sa.VendorBytes[i-48]
		case 'r':
			b = sa.Reserved
		case 'v':
			b = sa.Value
		case 'w':
			b = sa.Worst
		default:
			b = 0
		}

		r <<= 8
		r |= uint64(b)
	}

	return r
}

func checkTempWord(word uint16) int {
	switch {
	case word <= 0x7f:
		return 0x11 // >= 0, signed byte or word
	case word <= 0xff:
		return 0x01 // < 0, signed byte
	case word > 0xff80:
		return 0x10 // < 0, signed word
	default:
		return 0x00
	}
}

func checkTempRange(t int8, ut1, ut2 uint8, lo, hi *int) bool {
	t1, t2 := int8(ut1), int8(ut2)

	if t1 > t2 {
		t1, t2 = t2, t1
	}

	if (-60 <= t1) && (t1 <= t) && (t <= t2) && (t2 <= 120) && !(t1 == -1 && t2 <= 0) {
		*lo, *hi = int(t1), int(t2)
		return true
	}

	return false
}

func formatRawValue(v uint64, conv string) (s string) {
	var (
		raw  [6]uint8
		word [3]uint16
	)

	// Split into bytes
	for i := 0; i < 6; i++ {
		raw[i] = uint8(v >> uint(i*8))
	}

	// Split into words
	for i := 0; i < 3; i++ {
		word[i] = uint16(v >> uint(i*16))
	}

	switch conv {
	case "raw8":
		s = fmt.Sprintf("%d %d %d %d %d %d",
			raw[5], raw[4], raw[3], raw[2], raw[1], raw[0])
	case "raw16":
		s = fmt.Sprintf("%d %d %d", word[2], word[1], word[0])
	case "raw48", "raw56", "raw64":
		s = fmt.Sprintf("%d", v)
	case "hex48":
		s = fmt.Sprintf("%#012x", v)
	case "hex56":
		s = fmt.Sprintf("%#014x", v)
	case "hex64":
		s = fmt.Sprintf("%#016x", v)
	case "raw16(raw16)":
		s = fmt.Sprintf("%d", word[0])
		if (word[1] != 0) || (word[2] != 0) {
			s += fmt.Sprintf(" (%d %d)", word[2], word[1])
		}
	case "raw16(avg16)":
		s = fmt.Sprintf("%d", word[0])
		if word[1] != 0 {
			s += fmt.Sprintf(" (Average %d)", word[1])
		}
	case "raw24(raw8)":
		s = fmt.Sprintf("%d", v&0x00ffffff)
		if (raw[3] != 0) || (raw[4] != 0) || (raw[5] != 0) {
			s += fmt.Sprintf(" (%d %d %d)", raw[5], raw[4], raw[3])
		}
	case "raw24/raw24":
		s = fmt.Sprintf("%d/%d", v>>24, v&0x00ffffff)
	case "raw24/raw32":
		s = fmt.Sprintf("%d/%d", v>>32, v&0xffffffff)
	case "min2hour":
		// minutes
		minutes := uint64(word[0]) + uint64(word[1])<<16
		s = fmt.Sprintf("%dh+%02dm", minutes/60, minutes%60)
		if word[2] != 0 {
			s += fmt.Sprintf(" (%d)", word[2])
		}
	case "sec2hour":
		// seconds
		hours := v / 3600
		minutes := (v % 3600) / 60
		seconds := v % 60
		s = fmt.Sprintf("%dh+%02dm+%02ds", hours, minutes, seconds)
	case "halfmin2hour":
		// 30-second counter
		hours := v / 120
		minutes := (v % 120) / 2
		s = fmt.Sprintf("%dh+%02dm", hours, minutes)
	case "msec24hour32":
		// hours + milliseconds
		hours := v & 0xffffffff
		milliseconds := v >> 32
		seconds := milliseconds / 1000
		s = fmt.Sprintf("%dh+%02dm+%02d.%03ds",
			hours, seconds/60, seconds%60, milliseconds)
	case "tempminmax":
		var tFormat, lo, hi int

		t := int8(raw[0])
		ctw0 := checkTempWord(word[0])

		if word[2] == 0 {
			if (word[1] == 0) && (ctw0 != 0) {
				// 00 00 00 00 xx TT
				tFormat = 0
			} else if (ctw0 != 0) && checkTempRange(t, raw[2], raw[3], &lo, &hi) {
				// 00 00 HL LH xx TT
				tFormat = 1
			} else if (raw[3] == 0) && checkTempRange(t, raw[1], raw[2], &lo, &hi) {
				// 00 00 00 HL LH TT
				tFormat = 2
			} else {
				tFormat = -1
			}
		} else if ctw0 != 0 {
			if (ctw0&checkTempWord(word[1])&checkTempWord(word[2]) != 0x00) && checkTempRange(t, raw[2], raw[4], &lo, &hi) {
				// xx HL xx LH xx TT
				tFormat = 3
			} else if (word[2] < 0x7fff) && checkTempRange(t, raw[2], raw[3], &lo, &hi) && (hi >= 40) {
				// CC CC HL LH xx TT
				tFormat = 4
			} else {
				tFormat = -2
			}
		} else {
			tFormat = -3
		}

		switch tFormat {
		case 0:
			s = fmt.Sprintf("%d", t)
		case 1, 2, 3:
			s = fmt.Sprintf("%d (Min/Max %d/%d)", t, lo, hi)
		case 4:
			s = fmt.Sprintf("%d (Min/Max %d/%d #%d)", t, lo, hi, word[2])
		default:
			s = fmt.Sprintf("%d (%d %d %d %d %d)",
				raw[0], raw[5], raw[4], raw[3], raw[2], raw[1])
		}
	case "temp10x":
		// ten times temperature in Celsius
		s = fmt.Sprintf("%d.%d", word[0]/10, word[0]%10)
	default:
		s = "?"
	}

	return s
}

func printSMART(smart smartPage, drive driveModel) {
	fmt.Printf("\nSMART structure version: %d\n", smart.Version)
	fmt.Printf("ID# ATTRIBUTE_NAME           FLAG     VALUE WORST RESERVED TYPE     UPDATED RAW_VALUE\n")

	for _, attr := range smart.Attrs {
		var (
			rawValue              uint64
			conv                  attrConv
			attrType, attrUpdated string
		)

		if attr.Id == 0 {
			break
		}

		conv, ok := drive.Presets[strconv.Itoa(int(attr.Id))]
		if ok {
			rawValue = attr.decodeVendorBytes(conv.Conv)
		}

		// Pre-fail / advisory bit
		if attr.Flags&0x0001 != 0 {
			attrType = "Pre-fail"
		} else {
			attrType = "Old_age"
		}

		// Online data collection bit
		if attr.Flags&0x0002 != 0 {
			attrUpdated = "Always"
		} else {
			attrUpdated = "Offline"
		}

		fmt.Printf("%3d %-24s %#04x   %03d   %03d   %03d      %-8s %-7s %s\n",
			attr.Id, conv.Name, attr.Flags, attr.Value, attr.Worst, attr.Reserved, attrType,
			attrUpdated, formatRawValue(rawValue, conv.Conv))
	}
}
<|endoftext|>


<commit_before>package goahocorasick

type AhoCorasick struct {
	root *node
}

type node struct {
	children map[rune]*node
	depth    int
	fail     *node
	hit      bool
}

func New(keywords []string) *AhoCorasick {
	a := AhoCorasick{root: newNode(0)}
	a.createTrie(keywords)
	a.createFail()
	return &a
}

func newNode(depth int) *node {
	return &node{
		children: map[rune]*node{},
		depth:    depth}
}

func (a *AhoCorasick) createTrie(keywords []string) {
	for _, keyword := range keywords {
		n := a.root
		for _, r := range keyword {
			v, ok := n.children[r]
			if !ok {
				v = newNode(n.depth + 1)
				n.children[r] = v
			}
			n = v
		}
		n.hit = true
	}
}

func (a *AhoCorasick) createFail() {
	for k, v := range a.root.children {
		a.walkCreateFail(v, []rune{k})
	}
}

func (a *AhoCorasick) walkCreateFail(n *node, text []rune) {
	n.fail = a.backwardMatchNode(text)
	for k, v := range n.children {
		a.walkCreateFail(v, append(text, k))
	}
}

func (a *AhoCorasick) backwardMatchNode(text []rune) *node {
	for t := text[1:]; len(t) > 0; t = t[1:] {
		n, ok := a.matchNode(t)
		if ok {
			return n
		}
	}
	return a.root
}

func (a *AhoCorasick) matchNode(text []rune) (*node, bool) {
	n := a.root
	for _, r := range text {
		v, ok := n.children[r]
		if ok {
			n = v
		} else {
			return nil, false
		}
	}
	return n, true
}

func (a *AhoCorasick) Match(text string) [][]int {
	result := make([][]int, 0)
	n := a.root
	i := 0

	for _, r := range text {
	L:
		if n.hit {
			result = append(result, []int{i - n.depth, n.depth})
		}
		child, ok := n.children[r]
		if ok {
			for n != a.root {
				n = n.fail
				if n.hit {
					result = append(result, []int{i - n.depth, n.depth})
				}
			}
			n = child
			i++
		} else if n == a.root {
			i++
		} else {
			n = n.fail
			goto L
		}
	}

	return result
}
<commit_msg>Add comment<commit_after>package goahocorasick

// AhoCorasick is executor.
type AhoCorasick struct {
	root *node
}

type node struct {
	children map[rune]*node
	depth    int
	fail     *node
	hit      bool
}

// New executor with keywords.
func New(keywords []string) *AhoCorasick {
	a := AhoCorasick{root: newNode(0)}
	a.createTrie(keywords)
	a.createFail()
	return &a
}

func newNode(depth int) *node {
	return &node{
		children: map[rune]*node{},
		depth:    depth}
}

func (a *AhoCorasick) createTrie(keywords []string) {
	for _, keyword := range keywords {
		n := a.root
		for _, r := range keyword {
			v, ok := n.children[r]
			if !ok {
				v = newNode(n.depth + 1)
				n.children[r] = v
			}
			n = v
		}
		n.hit = true
	}
}

func (a *AhoCorasick) createFail() {
	for k, v := range a.root.children {
		a.walkCreateFail(v, []rune{k})
	}
}

func (a *AhoCorasick) walkCreateFail(n *node, text []rune) {
	n.fail = a.backwardMatchNode(text)
	for k, v := range n.children {
		a.walkCreateFail(v, append(text, k))
	}
}

func (a *AhoCorasick) backwardMatchNode(text []rune) *node {
	for t := text[1:]; len(t) > 0; t = t[1:] {
		n, ok := a.matchNode(t)
		if ok {
			return n
		}
	}
	return a.root
}

func (a *AhoCorasick) matchNode(text []rune) (*node, bool) {
	n := a.root
	for _, r := range text {
		v, ok := n.children[r]
		if ok {
			n = v
		} else {
			return nil, false
		}
	}
	return n, true
}

// Match keywords and returns index and length.
func (a *AhoCorasick) Match(text string) [][]int {
	result := make([][]int, 0)
	n := a.root
	i := 0

	for _, r := range text {
	L:
		if n.hit {
			result = append(result, []int{i - n.depth, n.depth})
		}
		child, ok := n.children[r]
		if ok {
			for n != a.root {
				n = n.fail
				if n.hit {
					result = append(result, []int{i - n.depth, n.depth})
				}
			}
			n = child
			i++
		} else if n == a.root {
			i++
		} else {
			n = n.fail
			goto L
		}
	}

	return result
}
<|endoftext|>


<commit_before>package io

import (
	"github.com/RenatoGeh/gospn/spn"
	"io/ioutil"
	"os"
)

// SaveSPN serializes an SPN and writes it to a file. Suggested extension: ".spn".
func SaveSPN(filename string, S spn.SPN) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	bytes := spn.Marshal(S)
	_, err = f.Write(bytes)
	return err
}

// LoadSPN reads a binary file that contains a serialized SPN.
func LoadSPN(filename string) (spn.SPN, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	S := spn.Unmarshal(data)
	return S, nil
}
<commit_msg>io: close file descriptor after saving<commit_after>package io

import (
	"github.com/RenatoGeh/gospn/spn"
	"io/ioutil"
	"os"
)

// SaveSPN serializes an SPN and writes it to a file. Suggested extension: ".spn".
func SaveSPN(filename string, S spn.SPN) error {
	f, err := os.Create(filename)
	defer f.Close()
	if err != nil {
		return err
	}
	bytes := spn.Marshal(S)
	_, err = f.Write(bytes)
	return err
}

// LoadSPN reads a binary file that contains a serialized SPN.
func LoadSPN(filename string) (spn.SPN, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	S := spn.Unmarshal(data)
	return S, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"reflect"
	"testing"
)

func TestIsDir(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	// test
	if !IsDir("tmp") {
		t.Error("IsDir() returned false for directory tmp")
	}

	// cleanUp
	err := os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

func TestIsGoFile(t *testing.T) {
	filename := "test.go"
	if !IsGoFile(filename) {
		t.Error("IsGoFile() returned false for filename test.go")
	}
}

func TestParseFilenames(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	os.Create("tmp/test.txt")
	os.Create("tmp/test2.md")

	test_data := []string{"test.txt", "test2.md"}

	currentDirectory, err := os.Getwd()
	if err != nil {
		t.Error("An error occured trying to get current working directory,", err)
	}

	// test
	filenames := ParseFilenames(currentDirectory + "/tmp")
	if !reflect.DeepEqual(filenames, test_data) {
		t.Error("ParseFilenames() did not return expected value.")
	}

	// cleanUp
	err = os.Remove("tmp/test.txt")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test.txt,", err)
	}

	err = os.Remove("tmp/test2.md")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test2.md,", err)
	}

	err = os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

func TestCheckDirForGo(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	os.Create("tmp/test.go")

	currentDirectory, err := os.Getwd()
	if err != nil {
		t.Error("An error occured trying to get current working directory,", err)
	}

	// test
	if !CheckDirForGo(currentDirectory + "/tmp") {
		t.Error("CheckDirForGo() did not properly identify a directory with a .go file in it.")
	}

	// cleanUp
	err = os.Remove("tmp/test.go")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test.go,", err)
	}

	err = os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

// func TestUpdatePackage(t *testing.T) {

// }
<commit_msg>Added TestUpdatePackage<commit_after>package main

import (
	"os"
	"reflect"
	"testing"
)

func TestIsDir(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	// test
	if !IsDir("tmp") {
		t.Error("IsDir() returned false for directory tmp")
	}

	// cleanUp
	err := os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

func TestIsGoFile(t *testing.T) {
	filename := "test.go"
	if !IsGoFile(filename) {
		t.Error("IsGoFile() returned false for filename test.go")
	}
}

func TestParseFilenames(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	os.Create("tmp/test.txt")
	os.Create("tmp/test2.md")

	test_data := []string{"test.txt", "test2.md"}

	currentDirectory, err := os.Getwd()
	if err != nil {
		t.Error("An error occured trying to get current working directory,", err)
	}

	// test
	filenames := ParseFilenames(currentDirectory + "/tmp")
	if !reflect.DeepEqual(filenames, test_data) {
		t.Error("ParseFilenames() did not return expected value.")
	}

	// cleanUp
	err = os.Remove("tmp/test.txt")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test.txt,", err)
	}

	err = os.Remove("tmp/test2.md")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test2.md,", err)
	}

	err = os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

func TestCheckDirForGo(t *testing.T) {
	// setUp
	os.Mkdir("tmp", 0777)

	os.Create("tmp/test.go")

	currentDirectory, err := os.Getwd()
	if err != nil {
		t.Error("An error occured trying to get current working directory,", err)
	}

	// test
	if !CheckDirForGo(currentDirectory + "/tmp") {
		t.Error("CheckDirForGo() did not properly identify a directory with a .go file in it.")
	}

	// cleanUp
	err = os.Remove("tmp/test.go")
	if err != nil {
		t.Error("An error occured trying to remove tmp/test.go,", err)
	}

	err = os.Remove("tmp")
	if err != nil {
		t.Error("An error occured trying to remove tmp/,", err)
	}
}

func TestUpdatePackage(t *testing.T) {

	currentDirectory, err := os.Getwd()
	if err != nil {
		t.Error("An error occured trying to get current working directory,", err)
	}

	updated := UpdatePackage(currentDirectory)
	if !updated {
		t.Error("An error occured trying to update this Go package,", err)
	}
}
<|endoftext|>


<commit_before>// Package ircudf implements parts of the Internet Realy Chat (IRC) protocol
// as defined in rfc1459 (http://tools.ietf.org/html/rfc1459.html)
// and provides basic IRC functions
package ircudf

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

type Server struct { 		// IRC Server
	Server    string        // Server address
	sendqueue chan string   // Message queue
	conn      net.Conn      // Server connection
	throttle  time.Duration // Throttle for message queue

	Nickname string // User Nickname
	username string // User username
	realname string // User realname

	kill chan bool // kills all routines when closed
}

var Debug = false	// Debug enables logging to stdout

var ( // Events can be changed to custom functions
	eventOnJoin    = func(*Server, string, string) {}         // server, channel, user
	eventOnPart    = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnQuit    = func(*Server, string, string) {}         // server, user, message
	eventOnPrivmsg = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnNotice  = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnReply   = func(*Server, string, string, string) {} // server, number, name, reply
)

// Create sets the Server address and user information.
//	// Example: (Nickname!Username@Hostname): Real Name
// 	freenode := ircudf.Create("irc.freenode.org:6667", "Nickname", "Username, "Real Name")
func Create(addr, Nickname, username, realname string) *Server {
	ref := &Server{Server: addr, sendqueue: make(chan string),
		Nickname: Nickname, username: username, realname: realname,
		throttle: 0, kill: make(chan bool)}

	debug("Created: ", addr, "\n")
	return ref
}

// close closes the server related routines.
func (sock *Server) close() {
	close(sock.kill)
}

// Connect establishes a connection to the Server.
// If no parameter is given the default timeout (5 sec) will be used.
func (sock *Server) Connect(timeout ...int) error {
	wait := 5 * time.Second
	if len(timeout) >= 1 {
		wait = time.Duration(timeout[0]) * time.Second
	}

	conn, err := net.DialTimeout("tcp", sock.Server, wait)
	if err != nil {
		sock.close()
		return err
	}
	defer conn.Close()
	sock.conn = conn

	debug("Connected: ", sock.Server, "\n")
	err = sock.receive()
	if err != nil {
		sock.close()
	}
	return err
}

// Receive receives new messages from the Server and forwards them to parse().
func (sock *Server) receive() error {
	go func() {
		time.Sleep(time.Second)
		sock.Nick(sock.Nickname)
		sock.user(sock.username, "0", "0", sock.realname)
	}()

	debug("Receiving: ", sock.Server, "\n")
	reader := bufio.NewReader(sock.conn)
	sock.sendroutine() //Non-Blocking

	for {
		select {
		case <-sock.kill:
			return nil
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				return err
			}
			debug("-> ", line)
			sock.parse(strings.Trim(line, "\r\n")) //Remove \r\n for easier parsing
		}
	}
}

// parse parses incoming messages from the Server and triggers predefined events.
func (sock *Server) parse(line string) {
	split := strings.SplitN(line, " ", 4)
	split = append(split, make([]string, 4-len(split), 4-len(split))...)

	switch true {
	case split[0] == "PING":
		sock.pong(split[1]) //Ping e.g.: PING :B97B6379
	case split[1] == "JOIN":
		eventOnJoin(sock, split[2][1:], getNick(split[0]))
	case split[1] == "PART":
		eventOnPart(sock, split[2], getNick(split[0]), split[3][1:])
	case split[1] == "QUIT":
		if split[3] != "" {
			split[2] += " " + split[3]
		}
		eventOnQuit(sock, getNick(split[0]), split[2][1:])
	case split[1] == "PRIVMSG":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnPrivmsg(sock, channel, nick, split[3][1:])
	case split[1] == "NOTICE":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnNotice(sock, channel, nick, split[3][1:])
	case isNum(split[1]):
		eventOnReply(sock, split[1], split[2], split[3])
	}
}

// Throttle sets the delay between sending messages in milliseconds.
func (sock *Server) Throttle(delay int) {
	sock.throttle = time.Duration(delay) * time.Millisecond
}

// Nick sets or changes the Nickname. The IRC Server might reply an errorcode,
// if the requsted Nickname is not valid or in use.
func (sock *Server) Nick(Nickname string) {
	sock.Nickname = Nickname
	sock.Send("NICK " + Nickname)
}

// user specifies the userdata at the beginning of a new connection.
// Servername and hostname are likely to be ignored by the IRC Server.
// Scheme: (Nickname!Username@Hostname): Real Name
func (sock *Server) user(username, hostname, Servername, realname string) {
	sock.Send("USER " + username + " " + hostname + " " + Servername + " :" + realname)
}

// Join joins the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Join(channel string) {
	sock.Send("JOIN " + channel)
}

// Part leaves the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Part(channel string) {
	sock.Send("PART " + channel)
}

// Quit closes the connection to the server with a quit message.
func (sock *Server) Quit(message string) {
	sock.SendWait("QUIT " + message)
	sock.close()
}

// pong answers a ping request with a previously received reply string.
func (sock *Server) pong(reply string) {
	sock.Send("PONG " + reply)
}

// Privmsg sends a private message to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Privmsg(user string, message string) {
	sock.Send("PRIVMSG " + user + " :" + message)
}

// Notice sends a notice to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Notice(user string, message string) {
	sock.Send("NOTICE " + user + " :" + message)
}

// Send adds the message to the RAW Message queue
func (sock *Server) Send(message string) {
	go func() {
		select {
		case <-sock.kill:
		case sock.sendqueue <- message + "\n":
		}
	}()
}

// SendWait adds the message to the RAW Message queue and waits until
// the message got sent.
func (sock *Server) SendWait(message string) {
	sock.sendqueue <- message + "\n"
	sock.sendqueue <- "" //ensures that the previous message got sent
}

// sendroutine sends the messages of the queue to the Server.
func (sock *Server) sendroutine() {
	go func() {
		for {
			select {
			case <-sock.kill:
				return
			case smsg := <-sock.sendqueue:
				if smsg != "" {
					io.WriteString(sock.conn, smsg)
					debug("<- ", smsg)
					time.Sleep(sock.throttle)
				}
			}
		}
	}()
}

// getNick extracts the nickame out of an hostmask. This function is
// being used for parsing incoming messages.
func getNick(hostmask string) string {
	return strings.Split(hostmask, "!")[0][1:]
}

// isNum checks wether a string could be represented as integer.
// This function is being used for parsing incoming messages.
func isNum(str string) bool {
	_, err := strconv.Atoi(str)
	return err == nil
}

//HANDLE FUNCTIONS

// HandleJoin registers the handle function for join.
// Handle function parameters: server, channel, user
func HandleJoin(h func(*Server, string, string)) {
	eventOnJoin = h
}

// HandlePart registers the handle function for part.
// Handle function parameters: server, channel, user, message
func HandlePart(h func(*Server, string, string, string)) {
	eventOnPart = h
}

// HandleQuit registers the handle function for quit.
// Handle function parameters: server, user, message
func HandleQuit(h func(*Server, string, string)) {
	eventOnQuit = h
}

// HandlePrivmsg registers the handle function for privmsg.
// Handle function parameters: server, channel, user, message
func HandlePrivmsg(h func(*Server, string, string, string)) {
	eventOnPrivmsg = h
}

// HandleNotice registers the handle function for notice.
// Handle function parameters: server, channel, user, message
func HandleNotice(h func(*Server, string, string, string)) {
	eventOnNotice = h
}

// HandleReply registers the handle function for reply.
// Handle function parameters: server, number, name, reply
func HandleReply(h func(*Server, string, string, string)) {
	eventOnReply = h
}

// DEBUG FUNCTIONS

func debug(s ...interface{}) {
	if Debug {
		fmt.Print(s...)
	}
}
<commit_msg>go fmt<commit_after>// Package ircudf implements parts of the Internet Realy Chat (IRC) protocol
// as defined in rfc1459 (http://tools.ietf.org/html/rfc1459.html)
// and provides basic IRC functions
package ircudf

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

type Server struct { // IRC Server
	Server    string        // Server address
	sendqueue chan string   // Message queue
	conn      net.Conn      // Server connection
	throttle  time.Duration // Throttle for message queue

	Nickname string // User Nickname
	username string // User username
	realname string // User realname

	kill chan bool // kills all routines when closed
}

var Debug = false // Debug enables logging to stdout

var ( // Events can be changed to custom functions
	eventOnJoin    = func(*Server, string, string) {}         // server, channel, user
	eventOnPart    = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnQuit    = func(*Server, string, string) {}         // server, user, message
	eventOnPrivmsg = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnNotice  = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnReply   = func(*Server, string, string, string) {} // server, number, name, reply
)

// Create sets the Server address and user information.
//	// Example: (Nickname!Username@Hostname): Real Name
// 	freenode := ircudf.Create("irc.freenode.org:6667", "Nickname", "Username, "Real Name")
func Create(addr, Nickname, username, realname string) *Server {
	ref := &Server{Server: addr, sendqueue: make(chan string),
		Nickname: Nickname, username: username, realname: realname,
		throttle: 0, kill: make(chan bool)}

	debug("Created: ", addr, "\n")
	return ref
}

// close closes the server related routines.
func (sock *Server) close() {
	close(sock.kill)
}

// Connect establishes a connection to the Server.
// If no parameter is given the default timeout (5 sec) will be used.
func (sock *Server) Connect(timeout ...int) error {
	wait := 5 * time.Second
	if len(timeout) >= 1 {
		wait = time.Duration(timeout[0]) * time.Second
	}

	conn, err := net.DialTimeout("tcp", sock.Server, wait)
	if err != nil {
		sock.close()
		return err
	}
	defer conn.Close()
	sock.conn = conn

	debug("Connected: ", sock.Server, "\n")
	err = sock.receive()
	if err != nil {
		sock.close()
	}
	return err
}

// Receive receives new messages from the Server and forwards them to parse().
func (sock *Server) receive() error {
	go func() {
		time.Sleep(time.Second)
		sock.Nick(sock.Nickname)
		sock.user(sock.username, "0", "0", sock.realname)
	}()

	debug("Receiving: ", sock.Server, "\n")
	reader := bufio.NewReader(sock.conn)
	sock.sendroutine() //Non-Blocking

	for {
		select {
		case <-sock.kill:
			return nil
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				return err
			}
			debug("-> ", line)
			sock.parse(strings.Trim(line, "\r\n")) //Remove \r\n for easier parsing
		}
	}
}

// parse parses incoming messages from the Server and triggers predefined events.
func (sock *Server) parse(line string) {
	split := strings.SplitN(line, " ", 4)
	split = append(split, make([]string, 4-len(split), 4-len(split))...)

	switch true {
	case split[0] == "PING":
		sock.pong(split[1]) //Ping e.g.: PING :B97B6379
	case split[1] == "JOIN":
		eventOnJoin(sock, split[2][1:], getNick(split[0]))
	case split[1] == "PART":
		eventOnPart(sock, split[2], getNick(split[0]), split[3][1:])
	case split[1] == "QUIT":
		if split[3] != "" {
			split[2] += " " + split[3]
		}
		eventOnQuit(sock, getNick(split[0]), split[2][1:])
	case split[1] == "PRIVMSG":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnPrivmsg(sock, channel, nick, split[3][1:])
	case split[1] == "NOTICE":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnNotice(sock, channel, nick, split[3][1:])
	case isNum(split[1]):
		eventOnReply(sock, split[1], split[2], split[3])
	}
}

// Throttle sets the delay between sending messages in milliseconds.
func (sock *Server) Throttle(delay int) {
	sock.throttle = time.Duration(delay) * time.Millisecond
}

// Nick sets or changes the Nickname. The IRC Server might reply an errorcode,
// if the requsted Nickname is not valid or in use.
func (sock *Server) Nick(Nickname string) {
	sock.Nickname = Nickname
	sock.Send("NICK " + Nickname)
}

// user specifies the userdata at the beginning of a new connection.
// Servername and hostname are likely to be ignored by the IRC Server.
// Scheme: (Nickname!Username@Hostname): Real Name
func (sock *Server) user(username, hostname, Servername, realname string) {
	sock.Send("USER " + username + " " + hostname + " " + Servername + " :" + realname)
}

// Join joins the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Join(channel string) {
	sock.Send("JOIN " + channel)
}

// Part leaves the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Part(channel string) {
	sock.Send("PART " + channel)
}

// Quit closes the connection to the server with a quit message.
func (sock *Server) Quit(message string) {
	sock.SendWait("QUIT " + message)
	sock.close()
}

// pong answers a ping request with a previously received reply string.
func (sock *Server) pong(reply string) {
	sock.Send("PONG " + reply)
}

// Privmsg sends a private message to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Privmsg(user string, message string) {
	sock.Send("PRIVMSG " + user + " :" + message)
}

// Notice sends a notice to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Notice(user string, message string) {
	sock.Send("NOTICE " + user + " :" + message)
}

// Send adds the message to the RAW Message queue
func (sock *Server) Send(message string) {
	go func() {
		select {
		case <-sock.kill:
		case sock.sendqueue <- message + "\n":
		}
	}()
}

// SendWait adds the message to the RAW Message queue and waits until
// the message got sent.
func (sock *Server) SendWait(message string) {
	sock.sendqueue <- message + "\n"
	sock.sendqueue <- "" //ensures that the previous message got sent
}

// sendroutine sends the messages of the queue to the Server.
func (sock *Server) sendroutine() {
	go func() {
		for {
			select {
			case <-sock.kill:
				return
			case smsg := <-sock.sendqueue:
				if smsg != "" {
					io.WriteString(sock.conn, smsg)
					debug("<- ", smsg)
					time.Sleep(sock.throttle)
				}
			}
		}
	}()
}

// getNick extracts the nickame out of an hostmask. This function is
// being used for parsing incoming messages.
func getNick(hostmask string) string {
	return strings.Split(hostmask, "!")[0][1:]
}

// isNum checks wether a string could be represented as integer.
// This function is being used for parsing incoming messages.
func isNum(str string) bool {
	_, err := strconv.Atoi(str)
	return err == nil
}

//HANDLE FUNCTIONS

// HandleJoin registers the handle function for join.
// Handle function parameters: server, channel, user
func HandleJoin(h func(*Server, string, string)) {
	eventOnJoin = h
}

// HandlePart registers the handle function for part.
// Handle function parameters: server, channel, user, message
func HandlePart(h func(*Server, string, string, string)) {
	eventOnPart = h
}

// HandleQuit registers the handle function for quit.
// Handle function parameters: server, user, message
func HandleQuit(h func(*Server, string, string)) {
	eventOnQuit = h
}

// HandlePrivmsg registers the handle function for privmsg.
// Handle function parameters: server, channel, user, message
func HandlePrivmsg(h func(*Server, string, string, string)) {
	eventOnPrivmsg = h
}

// HandleNotice registers the handle function for notice.
// Handle function parameters: server, channel, user, message
func HandleNotice(h func(*Server, string, string, string)) {
	eventOnNotice = h
}

// HandleReply registers the handle function for reply.
// Handle function parameters: server, number, name, reply
func HandleReply(h func(*Server, string, string, string)) {
	eventOnReply = h
}

// DEBUG FUNCTIONS

func debug(s ...interface{}) {
	if Debug {
		fmt.Print(s...)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goga

import (
	"bytes"
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/plt"
	"github.com/cpmech/gosl/rnd"
	"github.com/cpmech/gosl/utl"
)

// ObjFunc_t defines the template for the objective function
type ObjFunc_t func(ind *Individual, idIsland, time int, report *bytes.Buffer) (ova, oor float64)

// Island holds one population and performs the reproduction operation
type Island struct {

	// input
	Id        int         // index of this island
	C         *ConfParams // configuration parameters
	Pop       Population  // pointer to current population
	BkpPop    Population  // backup population
	OvOorFunc ObjFunc_t   // function to compute objective and out-of-range values
	BingoGrid *Bingo      // bingo for regeneration with initial values from grid
	BingoBest *Bingo      // bingo for regeneration with values recomputed based on best individual

	// results
	Report bytes.Buffer // buffer to report results
	OVS    []float64    // best objective values collected from multiple calls to SelectAndReprod
	OOR    []float64    // best out-of-range values
	SCO    []float64    // best scores

	// auxiliary internal data
	ovas    []float64 // all ova values
	oors    []float64 // all oor values
	sovas   []float64 // scaled ova values
	soors   []float64 // scaled oor values
	fitness []float64 // all fitness values
	prob    []float64 // probabilities
	cumprob []float64 // cumulated probabilities
	selinds []int     // indices of selected individuals
	A, B    []int     // indices of selected parents

	// for statistics
	maxabsgene []float64   // [ngenes] max absolute values of genes
	fltbases   [][]float64 // [ngenes*nbases][ninds] all bases
	devbases   []float64   // [ngenes*nbases] deviations of bases
}

// NewIsland allocates a new island but with a give population already allocated
// Input:
//  id     -- index of this island
//  pop    -- the population
//  ovfunc -- objective function
//  bingo  -- structure needed for regeneration of individuals
func NewIsland(id int, C *ConfParams, pop Population, ovfunc ObjFunc_t, bingo *Bingo) (o *Island) {

	// check
	ninds := len(pop)
	chk.IntAssert(C.Ninds, ninds)
	if ninds%2 != 0 {
		chk.Panic("size of population must be even")
	}

	// allocate
	o = new(Island)
	o.Id = id
	o.C = C
	o.Pop = pop
	o.BkpPop = pop.GetCopy()
	o.OvOorFunc = ovfunc
	o.BingoGrid = bingo
	o.BingoBest = bingo.GetCopy()

	// auxiliary data
	o.ovas = make([]float64, ninds)
	o.oors = make([]float64, ninds)
	o.sovas = make([]float64, ninds)
	o.soors = make([]float64, ninds)
	o.fitness = make([]float64, ninds)
	o.prob = make([]float64, ninds)
	o.cumprob = make([]float64, ninds)
	o.selinds = make([]int, ninds)
	o.A = make([]int, ninds/2)
	o.B = make([]int, ninds/2)

	// compute objective values, demerits, and sort population
	o.CalcOvsAndDemerits(o.Pop, 0)
	o.Pop.Sort()

	// results
	o.OVS = []float64{o.Pop[0].Ova}
	o.OOR = []float64{o.Pop[0].Oor}
	o.SCO = []float64{o.Pop[0].Demerit}

	// for statistics
	nfltgenes := o.Pop[0].Nfltgenes
	if nfltgenes > 0 {
		nbases := o.Pop[0].Nbases
		o.maxabsgene = make([]float64, nfltgenes)
		o.fltbases = la.MatAlloc(nfltgenes*nbases, ninds)
		o.devbases = make([]float64, nfltgenes*nbases)
	}
	return
}

// CalcOvsAndDemerits computes objective values, out-of-range values and demerits
func (o *Island) CalcOvsAndDemerits(pop Population, time int) {

	// ovs and oors
	var ova, oor float64
	var iova, ioor int // indices of individuals with ova and with oor, respectively
	for _, ind := range pop {
		ova, oor = o.OvOorFunc(ind, o.Id, time, &o.Report)
		if oor < 0 {
			chk.Panic("out-of-range values must be positive (or zero) indicating the positive distance to constraints. oor=%g is invalid", oor)
		}
		if oor > 0 { // infeasible solutions (out-of-range)
			ind.Ova = 0 // not used for infeasible (oor) individuals
			ind.Oor = oor
			o.oors[ioor] = oor
			ioor++
		} else { // feasible solutions
			ind.Ova = ova
			ind.Oor = 0 // not used for feasible individuals
			o.ovas[iova] = ova
			iova++
		}
	}

	// scaled ovs and oors
	utl.Scaling(o.sovas[:iova], o.ovas[:iova], 0, 1e-16, false, true)
	utl.Scaling(o.soors[:ioor], o.oors[:ioor], 2, 1e-16, false, true)

	// set demerits in individuals (loop with the same comparisons as before)
	ioor, iova = 0, 0
	for _, ind := range pop {
		if ind.Oor > 0 { // infeasible solutions (out-of-range)
			ind.Demerit = o.soors[ioor]
			ioor++
		} else { // feasible solutions
			ind.Demerit = o.sovas[iova]
			iova++
		}
	}
}

// SelectAndReprod performs the selection and reproduction processes
//  Note: this function considers a SORTED population already
func (o *Island) SelectAndReprod(time int) {

	// fitness
	ninds := len(o.Pop)
	var sumfit float64
	if o.C.Rnk { // ranking
		sp := o.C.RnkSp
		for i := 0; i < ninds; i++ {
			o.fitness[i] = 2.0 - sp + 2.0*(sp-1.0)*float64(ninds-i-1)/float64(ninds-1)
			sumfit += o.fitness[i]
		}
	} else {
		mindem := o.Pop[0].Demerit
		maxdem := mindem
		for i := 0; i < ninds; i++ {
			mindem = min(mindem, o.Pop[i].Demerit)
			maxdem = max(maxdem, o.Pop[i].Demerit)
		}
		for i, ind := range o.Pop {
			o.fitness[i] = (maxdem - ind.Demerit) / (maxdem - mindem)
			sumfit += o.fitness[i]
		}
	}

	// probabilities
	for i := 0; i < ninds; i++ {
		o.prob[i] = o.fitness[i] / sumfit
		if i == 0 {
			o.cumprob[i] = o.prob[i]
		} else {
			o.cumprob[i] = o.cumprob[i-1] + o.prob[i]
		}
	}

	// selection
	if o.C.Rws {
		RouletteSelect(o.selinds, o.cumprob, nil)
	} else {
		SUSselect(o.selinds, o.cumprob, -1)
	}
	FilterPairs(o.A, o.B, o.selinds)

	// reproduction
	h := ninds / 2
	for i := 0; i < ninds/2; i++ {
		Crossover(o.BkpPop[i], o.BkpPop[h+i], o.Pop[o.A[i]], o.Pop[o.B[i]], o.C.CxNcuts, o.C.CxCuts, o.C.CxProbs, o.C.CxIntFunc, o.C.CxFltFunc, o.C.CxStrFunc, o.C.CxKeyFunc, o.C.CxBytFunc, o.C.CxFunFunc)
		Mutation(o.BkpPop[i], o.C.MtNchanges, o.C.MtProbs, o.C.MtExtra, o.C.MtIntFunc, o.C.MtFltFunc, o.C.MtStrFunc, o.C.MtKeyFunc, o.C.MtBytFunc, o.C.MtFunFunc)
		Mutation(o.BkpPop[h+i], o.C.MtNchanges, o.C.MtProbs, o.C.MtExtra, o.C.MtIntFunc, o.C.MtFltFunc, o.C.MtStrFunc, o.C.MtKeyFunc, o.C.MtBytFunc, o.C.MtFunFunc)
	}

	// compute objective values, demerits, and sort population
	o.CalcOvsAndDemerits(o.BkpPop, time+1) // +1 => this is an updated generation
	o.BkpPop.Sort()

	// elitism
	if o.C.Elite {
		if o.Pop[0].Demerit > o.BkpPop[0].Demerit {
			o.Pop[0].CopyInto(o.BkpPop[ninds-1])
			o.BkpPop.Sort()
		}
	}

	// swap populations (Pop will always point to current one)
	o.Pop, o.BkpPop = o.BkpPop, o.Pop

	// results
	o.OVS = append(o.OVS, o.Pop[0].Ova)
	o.OOR = append(o.OVS, o.Pop[0].Oor)
	o.SCO = append(o.OVS, o.Pop[0].Demerit)
}

// Regenerate regenerates population with basis on best individual(s)
//  Output:
//   regtype -- 1=best, 2=lims
func (o *Island) Regenerate(time int, basedOnBest bool) (regtype int) {
	bingo := o.BingoGrid
	regtype = 2
	if basedOnBest || o.C.RegBest {
		regtype = 1
		o.BingoBest.ResetBasedOnRef(time, o.Pop[0], o.C.RegMmin, o.C.RegMmax)
		bingo = o.BingoBest
	}
	ninds := len(o.Pop)
	start := ninds - int(o.C.RegPct*float64(ninds))
	for i := start; i < ninds; i++ {
		for j := 0; j < o.Pop[i].Nfltgenes; j++ {
			o.Pop[i].SetFloat(j, bingo.DrawFloat(i, j, ninds))
		}
	}
	o.CalcOvsAndDemerits(o.Pop, time)
	o.Pop.Sort()
	return
}

// Stat computes some statistic information
//  rho (ρ) is a normalised quantity measuring the deviation of bases of each gene
//  Note: OoR individuals are excluded
func (o *Island) Stat() (minrho, averho, maxrho, devrho float64) {
	ngenes := o.Pop[0].Nfltgenes
	if ngenes < 1 {
		return
	}
	nbases := o.Pop[0].Nbases
	iova := 0
	for _, ind := range o.Pop {
		if ind.Oor > 0 && o.C.StatOorSkip { // skip oor individuals
			continue
		}
		for i := 0; i < ngenes; i++ {
			x := math.Abs(ind.GetFloat(i))
			if iova == 0 {
				o.maxabsgene[i] = x
			} else {
				o.maxabsgene[i] = max(o.maxabsgene[i], x)
			}
			for j := 0; j < nbases; j++ {
				o.fltbases[i*nbases+j][iova] = ind.Floats[i*nbases+j]
			}
		}
		iova++
	}
	if iova < 2 {
		return
	}
	for i := 0; i < ngenes; i++ {
		x := 1.0 + o.maxabsgene[i]
		for j := 0; j < nbases; j++ {
			o.devbases[i*nbases+j] = rnd.StatDev(o.fltbases[i*nbases+j][:iova], o.C.UseStdDev) / x
		}
	}
	minrho, averho, maxrho, devrho = rnd.StatBasic(o.devbases, o.C.UseStdDev)
	return
}

// Write writes results to buffer
func (o Island) Write(buf *bytes.Buffer, t int, json bool) {
	if json {
		return
	}
	buf.Write(o.Pop.Output(nil, o.C.ShowBases).Bytes())
}

// PlotOvs plots objective values versus time
func (o Island) PlotOvs(ext, args string, t0, tf int, withtxt bool, numfmt string, first, last bool) {
	if o.C.DoPlot == false || o.C.FnKey == "" {
		return
	}
	if first {
		plt.SetForEps(0.75, 250)
	}
	n := len(o.OVS) - t0
	T := utl.LinSpace(float64(t0), float64(tf), n)
	plt.Plot(T, o.OVS[:n], args)
	if withtxt {
		plt.Text(T[0], o.OVS[0], io.Sf(numfmt, o.OVS[0]), "ha='left'")
		plt.Text(T[n-1], o.OVS[n-1], io.Sf(numfmt, o.OVS[n-1]), "ha='right'")
	}
	if last {
		plt.Gll("time", "objective value", "")
		plt.SaveD(o.C.DirOut, o.C.FnKey+ext)
	}
}

// SaveReport saves report to file
func (o Island) SaveReport(dirout, fnkey string, verbose bool) {
	if dirout == "" {
		dirout = "/tmp/goga"
	}
	if verbose {
		io.WriteFileVD(dirout, fnkey+".rpt", &o.Report)
		return
	}
	io.WriteFileD(dirout, fnkey+".rpt", &o.Report)
}
<commit_msg>elitism fixed: must use ova<commit_after>// Copyright 2015 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goga

import (
	"bytes"
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/plt"
	"github.com/cpmech/gosl/rnd"
	"github.com/cpmech/gosl/utl"
)

// ObjFunc_t defines the template for the objective function
type ObjFunc_t func(ind *Individual, idIsland, time int, report *bytes.Buffer) (ova, oor float64)

// Island holds one population and performs the reproduction operation
type Island struct {

	// input
	Id        int         // index of this island
	C         *ConfParams // configuration parameters
	Pop       Population  // pointer to current population
	BkpPop    Population  // backup population
	OvOorFunc ObjFunc_t   // function to compute objective and out-of-range values
	BingoGrid *Bingo      // bingo for regeneration with initial values from grid
	BingoBest *Bingo      // bingo for regeneration with values recomputed based on best individual

	// results
	Report bytes.Buffer // buffer to report results
	OVS    []float64    // best objective values collected from multiple calls to SelectAndReprod
	OOR    []float64    // best out-of-range values
	SCO    []float64    // best scores

	// auxiliary internal data
	ovas    []float64 // all ova values
	oors    []float64 // all oor values
	sovas   []float64 // scaled ova values
	soors   []float64 // scaled oor values
	fitness []float64 // all fitness values
	prob    []float64 // probabilities
	cumprob []float64 // cumulated probabilities
	selinds []int     // indices of selected individuals
	A, B    []int     // indices of selected parents

	// for statistics
	maxabsgene []float64   // [ngenes] max absolute values of genes
	fltbases   [][]float64 // [ngenes*nbases][ninds] all bases
	devbases   []float64   // [ngenes*nbases] deviations of bases
}

// NewIsland allocates a new island but with a give population already allocated
// Input:
//  id     -- index of this island
//  pop    -- the population
//  ovfunc -- objective function
//  bingo  -- structure needed for regeneration of individuals
func NewIsland(id int, C *ConfParams, pop Population, ovfunc ObjFunc_t, bingo *Bingo) (o *Island) {

	// check
	ninds := len(pop)
	chk.IntAssert(C.Ninds, ninds)
	if ninds%2 != 0 {
		chk.Panic("size of population must be even")
	}

	// allocate
	o = new(Island)
	o.Id = id
	o.C = C
	o.Pop = pop
	o.BkpPop = pop.GetCopy()
	o.OvOorFunc = ovfunc
	o.BingoGrid = bingo
	o.BingoBest = bingo.GetCopy()

	// auxiliary data
	o.ovas = make([]float64, ninds)
	o.oors = make([]float64, ninds)
	o.sovas = make([]float64, ninds)
	o.soors = make([]float64, ninds)
	o.fitness = make([]float64, ninds)
	o.prob = make([]float64, ninds)
	o.cumprob = make([]float64, ninds)
	o.selinds = make([]int, ninds)
	o.A = make([]int, ninds/2)
	o.B = make([]int, ninds/2)

	// compute objective values, demerits, and sort population
	o.CalcOvsAndDemerits(o.Pop, 0)
	o.Pop.Sort()

	// results
	o.OVS = []float64{o.Pop[0].Ova}
	o.OOR = []float64{o.Pop[0].Oor}
	o.SCO = []float64{o.Pop[0].Demerit}

	// for statistics
	nfltgenes := o.Pop[0].Nfltgenes
	if nfltgenes > 0 {
		nbases := o.Pop[0].Nbases
		o.maxabsgene = make([]float64, nfltgenes)
		o.fltbases = la.MatAlloc(nfltgenes*nbases, ninds)
		o.devbases = make([]float64, nfltgenes*nbases)
	}
	return
}

// CalcOvsAndDemerits computes objective values, out-of-range values and demerits
func (o *Island) CalcOvsAndDemerits(pop Population, time int) {

	// ovs and oors
	var ova, oor float64
	var iova, ioor int // indices of individuals with ova and with oor, respectively
	for _, ind := range pop {
		ova, oor = o.OvOorFunc(ind, o.Id, time, &o.Report)
		if oor < 0 {
			chk.Panic("out-of-range values must be positive (or zero) indicating the positive distance to constraints. oor=%g is invalid", oor)
		}
		if oor > 0 { // infeasible solutions (out-of-range)
			ind.Ova = 0 // not used for infeasible (oor) individuals
			ind.Oor = oor
			o.oors[ioor] = oor
			ioor++
		} else { // feasible solutions
			ind.Ova = ova
			ind.Oor = 0 // not used for feasible individuals
			o.ovas[iova] = ova
			iova++
		}
	}

	// scaled ovs and oors
	utl.Scaling(o.sovas[:iova], o.ovas[:iova], 0, 1e-16, false, true)
	utl.Scaling(o.soors[:ioor], o.oors[:ioor], 2, 1e-16, false, true)

	// set demerits in individuals (loop with the same comparisons as before)
	ioor, iova = 0, 0
	for _, ind := range pop {
		if ind.Oor > 0 { // infeasible solutions (out-of-range)
			ind.Demerit = o.soors[ioor]
			ioor++
		} else { // feasible solutions
			ind.Demerit = o.sovas[iova]
			iova++
		}
	}
}

// SelectAndReprod performs the selection and reproduction processes
//  Note: this function considers a SORTED population already
func (o *Island) SelectAndReprod(time int) {

	// fitness
	ninds := len(o.Pop)
	var sumfit float64
	if o.C.Rnk { // ranking
		sp := o.C.RnkSp
		for i := 0; i < ninds; i++ {
			o.fitness[i] = 2.0 - sp + 2.0*(sp-1.0)*float64(ninds-i-1)/float64(ninds-1)
			sumfit += o.fitness[i]
		}
	} else {
		mindem := o.Pop[0].Demerit
		maxdem := mindem
		for i := 0; i < ninds; i++ {
			mindem = min(mindem, o.Pop[i].Demerit)
			maxdem = max(maxdem, o.Pop[i].Demerit)
		}
		for i, ind := range o.Pop {
			o.fitness[i] = (maxdem - ind.Demerit) / (maxdem - mindem)
			sumfit += o.fitness[i]
		}
	}

	// probabilities
	for i := 0; i < ninds; i++ {
		o.prob[i] = o.fitness[i] / sumfit
		if i == 0 {
			o.cumprob[i] = o.prob[i]
		} else {
			o.cumprob[i] = o.cumprob[i-1] + o.prob[i]
		}
	}

	// selection
	if o.C.Rws {
		RouletteSelect(o.selinds, o.cumprob, nil)
	} else {
		SUSselect(o.selinds, o.cumprob, -1)
	}
	FilterPairs(o.A, o.B, o.selinds)

	// reproduction
	h := ninds / 2
	for i := 0; i < ninds/2; i++ {
		Crossover(o.BkpPop[i], o.BkpPop[h+i], o.Pop[o.A[i]], o.Pop[o.B[i]], o.C.CxNcuts, o.C.CxCuts, o.C.CxProbs, o.C.CxIntFunc, o.C.CxFltFunc, o.C.CxStrFunc, o.C.CxKeyFunc, o.C.CxBytFunc, o.C.CxFunFunc)
		Mutation(o.BkpPop[i], o.C.MtNchanges, o.C.MtProbs, o.C.MtExtra, o.C.MtIntFunc, o.C.MtFltFunc, o.C.MtStrFunc, o.C.MtKeyFunc, o.C.MtBytFunc, o.C.MtFunFunc)
		Mutation(o.BkpPop[h+i], o.C.MtNchanges, o.C.MtProbs, o.C.MtExtra, o.C.MtIntFunc, o.C.MtFltFunc, o.C.MtStrFunc, o.C.MtKeyFunc, o.C.MtBytFunc, o.C.MtFunFunc)
	}

	// compute objective values, demerits, and sort population
	o.CalcOvsAndDemerits(o.BkpPop, time+1) // +1 => this is an updated generation
	o.BkpPop.Sort()

	// elitism
	if o.C.Elite {
		if o.Pop[0].Ova < o.BkpPop[0].Ova {
			o.Pop[0].CopyInto(o.BkpPop[ninds-1])
			o.BkpPop.Sort()
		}
	}

	// swap populations (Pop will always point to current one)
	o.Pop, o.BkpPop = o.BkpPop, o.Pop

	// results
	o.OVS = append(o.OVS, o.Pop[0].Ova)
	o.OOR = append(o.OVS, o.Pop[0].Oor)
	o.SCO = append(o.OVS, o.Pop[0].Demerit)
}

// Regenerate regenerates population with basis on best individual(s)
//  Output:
//   regtype -- 1=best, 2=lims
func (o *Island) Regenerate(time int, basedOnBest bool) (regtype int) {
	bingo := o.BingoGrid
	regtype = 2
	if basedOnBest || o.C.RegBest {
		regtype = 1
		o.BingoBest.ResetBasedOnRef(time, o.Pop[0], o.C.RegMmin, o.C.RegMmax)
		bingo = o.BingoBest
	}
	ninds := len(o.Pop)
	start := ninds - int(o.C.RegPct*float64(ninds))
	for i := start; i < ninds; i++ {
		for j := 0; j < o.Pop[i].Nfltgenes; j++ {
			o.Pop[i].SetFloat(j, bingo.DrawFloat(i, j, ninds))
		}
	}
	o.CalcOvsAndDemerits(o.Pop, time)
	o.Pop.Sort()
	return
}

// Stat computes some statistic information
//  rho (ρ) is a normalised quantity measuring the deviation of bases of each gene
//  Note: OoR individuals are excluded
func (o *Island) Stat() (minrho, averho, maxrho, devrho float64) {
	ngenes := o.Pop[0].Nfltgenes
	if ngenes < 1 {
		return
	}
	nbases := o.Pop[0].Nbases
	iova := 0
	for _, ind := range o.Pop {
		if ind.Oor > 0 && o.C.StatOorSkip { // skip oor individuals
			continue
		}
		for i := 0; i < ngenes; i++ {
			x := math.Abs(ind.GetFloat(i))
			if iova == 0 {
				o.maxabsgene[i] = x
			} else {
				o.maxabsgene[i] = max(o.maxabsgene[i], x)
			}
			for j := 0; j < nbases; j++ {
				o.fltbases[i*nbases+j][iova] = ind.Floats[i*nbases+j]
			}
		}
		iova++
	}
	if iova < 2 {
		return
	}
	for i := 0; i < ngenes; i++ {
		x := 1.0 + o.maxabsgene[i]
		for j := 0; j < nbases; j++ {
			o.devbases[i*nbases+j] = rnd.StatDev(o.fltbases[i*nbases+j][:iova], o.C.UseStdDev) / x
		}
	}
	minrho, averho, maxrho, devrho = rnd.StatBasic(o.devbases, o.C.UseStdDev)
	return
}

// Write writes results to buffer
func (o Island) Write(buf *bytes.Buffer, t int, json bool) {
	if json {
		return
	}
	buf.Write(o.Pop.Output(nil, o.C.ShowBases).Bytes())
}

// PlotOvs plots objective values versus time
func (o Island) PlotOvs(ext, args string, t0, tf int, withtxt bool, numfmt string, first, last bool) {
	if o.C.DoPlot == false || o.C.FnKey == "" {
		return
	}
	if first {
		plt.SetForEps(0.75, 250)
	}
	n := len(o.OVS) - t0
	T := utl.LinSpace(float64(t0), float64(tf), n)
	plt.Plot(T, o.OVS[:n], args)
	if withtxt {
		plt.Text(T[0], o.OVS[0], io.Sf(numfmt, o.OVS[0]), "ha='left'")
		plt.Text(T[n-1], o.OVS[n-1], io.Sf(numfmt, o.OVS[n-1]), "ha='right'")
	}
	if last {
		plt.Gll("time", "objective value", "")
		plt.SaveD(o.C.DirOut, o.C.FnKey+ext)
	}
}

// SaveReport saves report to file
func (o Island) SaveReport(dirout, fnkey string, verbose bool) {
	if dirout == "" {
		dirout = "/tmp/goga"
	}
	if verbose {
		io.WriteFileVD(dirout, fnkey+".rpt", &o.Report)
		return
	}
	io.WriteFileD(dirout, fnkey+".rpt", &o.Report)
}
<|endoftext|>


<commit_before>//Package isokey allows you to make and verify API keys without a database connection via HMAC signatures.
//The keys are scalable and persistent. All information is stored in the key, and with the client.
package isokey

import (
	"errors"
	"fmt"
	"time"
)

//Secret is used if GetSecret and SecretMap is nil
var Secret []byte

//SecretMap maps secret versions to secrets
var SecretMap map[uint32][]byte

//GetSecret allows you to dynamically use secrets depending on the provided secret version.
//Returning nil indicates that no secret was found for the version
var GetSecret func(secretVersion uint32) (secret []byte)

//Invalidate allows you to invalidate certain keys based off the Key's parameters (e.g when it was made.)
//This is useful when a client has been compromised
var Invalidate = func(key *Key) (invalid bool) {
	if key.Expires.Before(time.Now()) {
		return true
	}
	return false
}

//Common errors
var (
	ErrNoSecret  = errors.New("No secret was found for the secret version.")
	ErrKeySize   = fmt.Errorf("Key is not %v bytes long.", keySize)
	ErrBadSecret = errors.New("Secret is incorrect")
	ErrInvalid   = errors.New("Key is expired or invalid.")
)

func getSecret(secretVersion uint32) (secret []byte, err error) {
	var ok bool
	if GetSecret != nil {
		secret = GetSecret(secretVersion)
	} else if SecretMap != nil {
		secret, ok = SecretMap[secretVersion]
		if !ok {
			return secret, ErrNoSecret
		}
	} else {
		secret = Secret
	}

	if secret == nil {
		return secret, ErrNoSecret
	}
	return
}
<commit_msg>Make Invalidate more descriptive<commit_after>//Package isokey allows you to make and verify API keys without a database connection via HMAC signatures.
//The keys are scalable and persistent. All information is stored in the key, and with the client.
package isokey

import (
	"errors"
	"fmt"
	"time"
)

//Secret is used if GetSecret and SecretMap is nil
var Secret []byte

//SecretMap maps secret versions to secrets
var SecretMap map[uint32][]byte

//GetSecret allows you to dynamically use secrets depending on the provided secret version.
//Returning nil indicates that no secret was found for the version
var GetSecret func(secretVersion uint32) (secret []byte)

//Invalidate allows you to invalidate certain keys based off the Key's parameters (e.g when it was made.)
//Invalidate is ran after the key's signature has been validated.
//This is useful to deal with cases revolving compromised users.
var Invalidate = func(key *Key) (invalid bool) {
	if key.Expires.Before(time.Now()) {
		return true
	}
	return false
}

//Common errors
var (
	ErrNoSecret  = errors.New("No secret was found for the secret version.")
	ErrKeySize   = fmt.Errorf("Key is not %v bytes long.", keySize)
	ErrBadSecret = errors.New("Secret is incorrect")
	ErrInvalid   = errors.New("Key is expired or invalid.")
)

func getSecret(secretVersion uint32) (secret []byte, err error) {
	var ok bool
	if GetSecret != nil {
		secret = GetSecret(secretVersion)
	} else if SecretMap != nil {
		secret, ok = SecretMap[secretVersion]
		if !ok {
			return secret, ErrNoSecret
		}
	} else {
		secret = Secret
	}

	if secret == nil {
		return secret, ErrNoSecret
	}
	return
}
<|endoftext|>