<commit_before>package router

import (
	"net/url"

	"github.com/sqs/mux"
	"sourcegraph.com/sourcegraph/srclib/graph"
)

const (
	Build            = "build"
	BuildDequeueNext = "build.dequeue-next"
	BuildUpdate      = "build.update"
	BuildLog         = "build.log"
	Builds           = "builds"
	BuildTasks       = "build.tasks"
	BuildTaskUpdate  = "build.task"
	BuildTasksCreate = "build.tasks.create"
	BuildTaskLog     = "build.task.log"

	Org               = "org"
	OrgMembers        = "org.members"
	OrgSettings       = "org.settings"
	OrgSettingsUpdate = "org.settings.update"

	Users                 = "users"
	User                  = "user"
	UserOrgs              = "user.orgs"
	UserAuthors           = "user.authors"
	UserClients           = "user.clients"
	UserEmails            = "user.emails"
	UserFromGitHub        = "user.from-github"
	UserRepoContributions = "user.repo-contributions"
	UserRepoDependencies  = "user.repo-dependencies"
	UserRepoDependents    = "user.repo-dependents"
	UserRefreshProfile    = "user.refresh-profile"
	UserSettings          = "user.settings"
	UserSettingsUpdate    = "user.settings.update"
	UserComputeStats      = "user.compute-stats"

	Person = "person"

	RepoPullRequests              = "repo.pull-requests"
	RepoPullRequest               = "repo.pull-request"
	RepoPullRequestMerge          = "repo.pull-request.merge"
	RepoPullRequestComments       = "repo.pull-request.comments"
	RepoPullRequestCommentsCreate = "repo.pull-request.comments.create"
	RepoPullRequestCommentsEdit   = "repo.pull-request.comments.edit"
	RepoPullRequestCommentsDelete = "repo.pull-request.comments.delete"

	RepoIssues        = "repo.issues"
	RepoIssue         = "repo.issue"
	RepoIssueComments = "repo.issue.comments"

	Repos              = "repos"
	ReposCreate        = "repos.create"
	ReposGetOrCreate   = "repos.get-or-create"
	Repo               = "repo"
	RepoAuthors        = "repo.authors"
	RepoClients        = "repo.clients"
	RepoDependents     = "repo.dependents"
	RepoDependencies   = "repo.dependencies"
	RepoBadge          = "repo.badge"
	RepoBadges         = "repo.badges"
	RepoCounter        = "repo.counter"
	RepoCounters       = "repo.counters"
	RepoReadme         = "repo.readme"
	RepoBuilds         = "repo.builds"
	RepoBuildsCreate   = "repo.builds.create"
	RepoBuildDataEntry = "repo.build-data.entry"
	RepoTreeEntry      = "repo.tree.entry"
	RepoRefreshProfile = "repo.refresh-profile"
	RepoRefreshVCSData = "repo.refresh-vcs-data"
	RepoComputeStats   = "repo.compute-stats"

	RepoSettings       = "repo.settings"
	RepoSettingsUpdate = "repo.settings.update"

	RepoStats = "repo.stats"

	RepoBuild = "repo.build"

	RepoCommits        = "repo.commits"
	RepoCommit         = "repo.commit"
	RepoCompareCommits = "repo.compare-commits"
	RepoTags           = "repo.tags"
	RepoBranches       = "repo.branches"

	Search = "search"

	Snippet = "snippet"

	Defs          = "defs"
	Def           = "def"
	DefRefs       = "def.refs"
	DefExamples   = "def.examples"
	DefAuthors    = "def.authors"
	DefClients    = "def.clients"
	DefDependents = "def.dependents"
	DefVersions   = "def.versions"

	Delta                   = "delta"
	DeltaDefs               = "delta.defs"
	DeltaDependencies       = "delta.dependencies"
	DeltaFiles              = "delta.files"
	DeltaAffectedAuthors    = "delta.affected-authors"
	DeltaAffectedClients    = "delta.affected-clients"
	DeltaAffectedDependents = "delta.affected-dependents"
	DeltaReviewers          = "delta.reviewers"
	DeltasIncoming          = "deltas.incoming"

	Unit  = "unit"
	Units = "units"

	ExtGitHubReceiveWebhook = "ext.github.receive-webhook"

	// Redirects for old routes.
	RedirectOldRepoBadgesAndCounters = "repo.redirect-old-badges-and-counters"
)

var APIRouter = NewAPIRouter(mux.NewRouter().PathPrefix("/api").Subrouter())

// NewAPIRouter creates a new API router with route URL pattern definitions but
// no handlers attached to the routes.
//
// It is in a separate package from app so that other packages may use it to
// generate URLs without resulting in Go import cycles (and so we can release
// the router as open-source to support our client library).
func NewAPIRouter(base *mux.Router) *mux.Router {
	if base == nil {
		base = mux.NewRouter()
	}

	base.StrictSlash(true)

	base.Path("/builds").Methods("GET").Name(Builds)
	builds := base.PathPrefix("/builds").Subrouter()
	builds.Path("/next").Methods("POST").Name(BuildDequeueNext)
	buildPath := "/{BID}"
	builds.Path(buildPath).Methods("GET").Name(Build)
	builds.Path(buildPath).Methods("PUT").Name(BuildUpdate)
	build := builds.PathPrefix(buildPath).Subrouter()
	build.Path("/log").Methods("GET").Name(BuildLog)
	build.Path("/tasks").Methods("GET").Name(BuildTasks)
	build.Path("/tasks").Methods("POST").Name(BuildTasksCreate)
	build.Path("/tasks/{TaskID}").Methods("PUT").Name(BuildTaskUpdate)
	build.Path("/tasks/{TaskID}/log").Methods("GET").Name(BuildTaskLog)

	base.Path("/repos").Methods("GET").Name(Repos)
	base.Path("/repos").Methods("POST").Name(ReposCreate)

	base.Path("/repos/github.com/{owner:[^/]+}/{repo:[^/]+}/{what:(?:badges|counters)}/{which}.png").Methods("GET").Name(RedirectOldRepoBadgesAndCounters)

	repoRev := base.PathPrefix(`/repos/` + RepoRevSpecPattern).PostMatchFunc(FixRepoRevSpecVars).BuildVarsFunc(PrepareRepoRevSpecRouteVars).Subrouter()
	repoRev.Path("/.stats").Methods("PUT").Name(RepoComputeStats)
	repoRev.Path("/.stats").Methods("GET").Name(RepoStats)
	repoRev.Path("/.authors").Methods("GET").Name(RepoAuthors)
	repoRev.Path("/.readme").Methods("GET").Name(RepoReadme)
	repoRev.Path("/.build").Methods("GET").Name(RepoBuild)
	repoRev.Path("/.dependencies").Methods("GET").Name(RepoDependencies)
	repoRev.PathPrefix("/.build-data"+TreeEntryPathPattern).PostMatchFunc(FixTreeEntryVars).BuildVarsFunc(PrepareTreeEntryRouteVars).Methods("GET", "HEAD", "PUT", "DELETE").Name(RepoBuildDataEntry)
	repoRev.Path("/.badges/{Badge}.png").Methods("GET").Name(RepoBadge)

	// repo contains routes that are NOT specific to a revision. In these routes, the URL may not contain a revspec after the repo (that is, no "github.com/foo/bar@myrevspec").
	repoPath := `/repos/` + RepoSpecPathPattern
	base.Path(repoPath).Methods("GET").Name(Repo)
	base.Path(repoPath).Methods("PUT").Name(ReposGetOrCreate)
	repo := base.PathPrefix(repoPath).Subrouter()
	repo.Path("/.clients").Methods("GET").Name(RepoClients)
	repo.Path("/.dependents").Methods("GET").Name(RepoDependents)
	repo.Path("/.external-profile").Methods("PUT").Name(RepoRefreshProfile)
	repo.Path("/.vcs-data").Methods("PUT").Name(RepoRefreshVCSData)
	repo.Path("/.settings").Methods("GET").Name(RepoSettings)
	repo.Path("/.settings").Methods("PUT").Name(RepoSettingsUpdate)
	repo.Path("/.commits").Methods("GET").Name(RepoCommits)
	repo.Path("/.commits/{Rev:" + PathComponentNoLeadingDot + "}/.compare").Methods("GET").Name(RepoCompareCommits)
	repo.Path("/.commits/{Rev:" + PathComponentNoLeadingDot + "}").Methods("GET").Name(RepoCommit)
	repo.Path("/.branches").Methods("GET").Name(RepoBranches)
	repo.Path("/.tags").Methods("GET").Name(RepoTags)
	repo.Path("/.badges").Methods("GET").Name(RepoBadges)
	repo.Path("/.counters").Methods("GET").Name(RepoCounters)
	repo.Path("/.counters/{Counter}.png").Methods("GET").Name(RepoCounter)
	repo.Path("/.builds").Methods("GET").Name(RepoBuilds)
	repo.Path("/.builds").Methods("POST").Name(RepoBuildsCreate)

	repo.Path("/.pulls").Methods("GET").Name(RepoPullRequests)
	pullPath := "/.pulls/{Pull}"
	repo.Path(pullPath).Methods("GET").Name(RepoPullRequest)
	pull := repo.PathPrefix(pullPath).Subrouter()
	pull.Path("/merge").Methods("PUT").Name(RepoPullRequestMerge)
	pull.Path("/comments").Methods("GET").Name(RepoPullRequestComments)
	pull.Path("/comments").Methods("POST").Name(RepoPullRequestCommentsCreate)
	pull.Path("/comments/{CommentID}").Methods("PATCH", "PUT").Name(RepoPullRequestCommentsEdit)
	pull.Path("/comments/{CommentID}").Methods("DELETE").Name(RepoPullRequestCommentsDelete)

	repo.Path("/.issues").Methods("GET").Name(RepoIssues)
	issuePath := "/.issues/{Issue}"
	repo.Path(issuePath).Methods("GET").Name(RepoIssue)
	issue := repo.PathPrefix(issuePath).Subrouter()
	issue.Path("/comments").Methods("GET").Name(RepoIssueComments)

	deltaPath := "/.deltas/{Rev:.+}..{DeltaHeadRev:" + PathComponentNoLeadingDot + "}"
	repo.Path(deltaPath).Methods("GET").Name(Delta)
	deltas := repo.PathPrefix(deltaPath).Subrouter()
	deltas.Path("/.defs").Methods("GET").Name(DeltaDefs)
	deltas.Path("/.dependencies").Methods("GET").Name(DeltaDependencies)
	deltas.Path("/.files").Methods("GET").Name(DeltaFiles)
	deltas.Path("/.affected-authors").Methods("GET").Name(DeltaAffectedAuthors)
	deltas.Path("/.affected-clients").Methods("GET").Name(DeltaAffectedClients)
	deltas.Path("/.affected-dependents").Methods("GET").Name(DeltaAffectedDependents)
	deltas.Path("/.reviewers").Methods("GET").Name(DeltaReviewers)

	repo.Path("/.deltas-incoming").Methods("GET").Name(DeltasIncoming)

	// See router_util/tree_route.go for an explanation of how we match tree
	// entry routes.
	repoRev.Path("/.tree" + TreeEntryPathPattern).PostMatchFunc(FixTreeEntryVars).BuildVarsFunc(PrepareTreeEntryRouteVars).Methods("GET").Name(RepoTreeEntry)

	base.Path(`/people/` + PersonSpecPattern).Methods("GET").Name(Person)

	base.Path("/users").Methods("GET").Name(Users)
	userPath := `/users/` + UserSpecPattern
	base.Path(userPath).Methods("GET").Name(User)
	user := base.PathPrefix(userPath).Subrouter()
	user.Path("/orgs").Methods("GET").Name(UserOrgs)
	user.Path("/clients").Methods("GET").Name(UserClients)
	user.Path("/authors").Methods("GET").Name(UserAuthors)
	user.Path("/emails").Methods("GET").Name(UserEmails)
	user.Path("/repo-contributions").Methods("GET").Name(UserRepoContributions)
	user.Path("/repo-dependencies").Methods("GET").Name(UserRepoDependencies)
	user.Path("/repo-dependents").Methods("GET").Name(UserRepoDependents)
	user.Path("/external-profile").Methods("PUT").Name(UserRefreshProfile)
	user.Path("/stats").Methods("PUT").Name(UserComputeStats)
	user.Path("/settings").Methods("GET").Name(UserSettings)
	user.Path("/settings").Methods("PUT").Name(UserSettingsUpdate)
	base.Path("/external-users/github/{GitHubUserSpec}").Methods("GET").Name(UserFromGitHub)

	orgPath := "/orgs/{OrgSpec}"
	base.Path(orgPath).Methods("GET").Name(Org)
	org := base.PathPrefix(orgPath).Subrouter()
	org.Path("/settings").Methods("GET").Name(OrgSettings)
	org.Path("/settings").Methods("PUT").Name(OrgSettingsUpdate)
	org.Path("/members").Methods("GET").Name(OrgMembers)

	base.Path("/search").Methods("GET").Name(Search)

	base.Path("/snippet").Methods("GET", "POST", "ORIGIN").Name(Snippet)

	base.Path("/.defs").Methods("GET").Name(Defs)

	// See router_util/def_route.go for an explanation of how we match def
	// routes.
	defPath := `/.defs/` + DefPathPattern
	repoRev.Path(defPath).Methods("GET").PostMatchFunc(FixDefUnitVars).BuildVarsFunc(PrepareDefRouteVars).Name(Def)
	def := repoRev.PathPrefix(defPath).PostMatchFunc(FixDefUnitVars).BuildVarsFunc(PrepareDefRouteVars).Subrouter()
	def.Path("/.refs").Methods("GET").Name(DefRefs)
	def.Path("/.examples").Methods("GET").Name(DefExamples)
	def.Path("/.authors").Methods("GET").Name(DefAuthors)
	def.Path("/.clients").Methods("GET").Name(DefClients)
	def.Path("/.dependents").Methods("GET").Name(DefDependents)
	def.Path("/.versions").Methods("GET").Name(DefVersions)

	base.Path("/.units").Methods("GET").Name(Units)
	unitPath := `/.units/{UnitType}/{Unit:.*}`
	repoRev.Path(unitPath).Methods("GET").Name(Unit)

	base.Path("/ext/github/webhook").Methods("POST").Name(ExtGitHubReceiveWebhook)

	if ExtraConfig != nil {
		ExtraConfig(base, user)
	}

	return base
}

// ExtraConfig, if non-nil, is called by NewAPIRouter with the
// *mux.Router after setting up routes in this package and before
// returning it. It can be used by external packages that use this API
// router and want to add additional routes to it.
var ExtraConfig func(base, user *mux.Router)

func URIToDef(key graph.DefKey) *url.URL {
	return URITo(Def, "RepoSpec", key.Repo, "UnitType", key.UnitType, "Unit", key.Unit, "Path", string(key.Path))
}

func URITo(routeName string, params ...string) *url.URL {
	return URLTo(APIRouter, routeName, params...)
}
<commit_msg>remove unused router package defs<commit_after>package router

import "github.com/sqs/mux"

const (
	Build            = "build"
	BuildDequeueNext = "build.dequeue-next"
	BuildUpdate      = "build.update"
	BuildLog         = "build.log"
	Builds           = "builds"
	BuildTasks       = "build.tasks"
	BuildTaskUpdate  = "build.task"
	BuildTasksCreate = "build.tasks.create"
	BuildTaskLog     = "build.task.log"

	Org               = "org"
	OrgMembers        = "org.members"
	OrgSettings       = "org.settings"
	OrgSettingsUpdate = "org.settings.update"

	Users                 = "users"
	User                  = "user"
	UserOrgs              = "user.orgs"
	UserAuthors           = "user.authors"
	UserClients           = "user.clients"
	UserEmails            = "user.emails"
	UserFromGitHub        = "user.from-github"
	UserRepoContributions = "user.repo-contributions"
	UserRepoDependencies  = "user.repo-dependencies"
	UserRepoDependents    = "user.repo-dependents"
	UserRefreshProfile    = "user.refresh-profile"
	UserSettings          = "user.settings"
	UserSettingsUpdate    = "user.settings.update"
	UserComputeStats      = "user.compute-stats"

	Person = "person"

	RepoPullRequests              = "repo.pull-requests"
	RepoPullRequest               = "repo.pull-request"
	RepoPullRequestMerge          = "repo.pull-request.merge"
	RepoPullRequestComments       = "repo.pull-request.comments"
	RepoPullRequestCommentsCreate = "repo.pull-request.comments.create"
	RepoPullRequestCommentsEdit   = "repo.pull-request.comments.edit"
	RepoPullRequestCommentsDelete = "repo.pull-request.comments.delete"

	RepoIssues        = "repo.issues"
	RepoIssue         = "repo.issue"
	RepoIssueComments = "repo.issue.comments"

	Repos              = "repos"
	ReposCreate        = "repos.create"
	ReposGetOrCreate   = "repos.get-or-create"
	Repo               = "repo"
	RepoAuthors        = "repo.authors"
	RepoClients        = "repo.clients"
	RepoDependents     = "repo.dependents"
	RepoDependencies   = "repo.dependencies"
	RepoBadge          = "repo.badge"
	RepoBadges         = "repo.badges"
	RepoCounter        = "repo.counter"
	RepoCounters       = "repo.counters"
	RepoReadme         = "repo.readme"
	RepoBuilds         = "repo.builds"
	RepoBuildsCreate   = "repo.builds.create"
	RepoBuildDataEntry = "repo.build-data.entry"
	RepoTreeEntry      = "repo.tree.entry"
	RepoRefreshProfile = "repo.refresh-profile"
	RepoRefreshVCSData = "repo.refresh-vcs-data"
	RepoComputeStats   = "repo.compute-stats"

	RepoSettings       = "repo.settings"
	RepoSettingsUpdate = "repo.settings.update"

	RepoStats = "repo.stats"

	RepoBuild = "repo.build"

	RepoCommits        = "repo.commits"
	RepoCommit         = "repo.commit"
	RepoCompareCommits = "repo.compare-commits"
	RepoTags           = "repo.tags"
	RepoBranches       = "repo.branches"

	Search = "search"

	Snippet = "snippet"

	Defs          = "defs"
	Def           = "def"
	DefRefs       = "def.refs"
	DefExamples   = "def.examples"
	DefAuthors    = "def.authors"
	DefClients    = "def.clients"
	DefDependents = "def.dependents"
	DefVersions   = "def.versions"

	Delta                   = "delta"
	DeltaDefs               = "delta.defs"
	DeltaDependencies       = "delta.dependencies"
	DeltaFiles              = "delta.files"
	DeltaAffectedAuthors    = "delta.affected-authors"
	DeltaAffectedClients    = "delta.affected-clients"
	DeltaAffectedDependents = "delta.affected-dependents"
	DeltaReviewers          = "delta.reviewers"
	DeltasIncoming          = "deltas.incoming"

	Unit  = "unit"
	Units = "units"

	ExtGitHubReceiveWebhook = "ext.github.receive-webhook"

	// Redirects for old routes.
	RedirectOldRepoBadgesAndCounters = "repo.redirect-old-badges-and-counters"
)

// NewAPIRouter creates a new API router with route URL pattern definitions but
// no handlers attached to the routes.
//
// It is in a separate package from app so that other packages may use it to
// generate URLs without resulting in Go import cycles (and so we can release
// the router as open-source to support our client library).
func NewAPIRouter(base *mux.Router) *mux.Router {
	if base == nil {
		base = mux.NewRouter()
	}

	base.StrictSlash(true)

	base.Path("/builds").Methods("GET").Name(Builds)
	builds := base.PathPrefix("/builds").Subrouter()
	builds.Path("/next").Methods("POST").Name(BuildDequeueNext)
	buildPath := "/{BID}"
	builds.Path(buildPath).Methods("GET").Name(Build)
	builds.Path(buildPath).Methods("PUT").Name(BuildUpdate)
	build := builds.PathPrefix(buildPath).Subrouter()
	build.Path("/log").Methods("GET").Name(BuildLog)
	build.Path("/tasks").Methods("GET").Name(BuildTasks)
	build.Path("/tasks").Methods("POST").Name(BuildTasksCreate)
	build.Path("/tasks/{TaskID}").Methods("PUT").Name(BuildTaskUpdate)
	build.Path("/tasks/{TaskID}/log").Methods("GET").Name(BuildTaskLog)

	base.Path("/repos").Methods("GET").Name(Repos)
	base.Path("/repos").Methods("POST").Name(ReposCreate)

	base.Path("/repos/github.com/{owner:[^/]+}/{repo:[^/]+}/{what:(?:badges|counters)}/{which}.png").Methods("GET").Name(RedirectOldRepoBadgesAndCounters)

	repoRev := base.PathPrefix(`/repos/` + RepoRevSpecPattern).PostMatchFunc(FixRepoRevSpecVars).BuildVarsFunc(PrepareRepoRevSpecRouteVars).Subrouter()
	repoRev.Path("/.stats").Methods("PUT").Name(RepoComputeStats)
	repoRev.Path("/.stats").Methods("GET").Name(RepoStats)
	repoRev.Path("/.authors").Methods("GET").Name(RepoAuthors)
	repoRev.Path("/.readme").Methods("GET").Name(RepoReadme)
	repoRev.Path("/.build").Methods("GET").Name(RepoBuild)
	repoRev.Path("/.dependencies").Methods("GET").Name(RepoDependencies)
	repoRev.PathPrefix("/.build-data"+TreeEntryPathPattern).PostMatchFunc(FixTreeEntryVars).BuildVarsFunc(PrepareTreeEntryRouteVars).Methods("GET", "HEAD", "PUT", "DELETE").Name(RepoBuildDataEntry)
	repoRev.Path("/.badges/{Badge}.png").Methods("GET").Name(RepoBadge)

	// repo contains routes that are NOT specific to a revision. In these routes, the URL may not contain a revspec after the repo (that is, no "github.com/foo/bar@myrevspec").
	repoPath := `/repos/` + RepoSpecPathPattern
	base.Path(repoPath).Methods("GET").Name(Repo)
	base.Path(repoPath).Methods("PUT").Name(ReposGetOrCreate)
	repo := base.PathPrefix(repoPath).Subrouter()
	repo.Path("/.clients").Methods("GET").Name(RepoClients)
	repo.Path("/.dependents").Methods("GET").Name(RepoDependents)
	repo.Path("/.external-profile").Methods("PUT").Name(RepoRefreshProfile)
	repo.Path("/.vcs-data").Methods("PUT").Name(RepoRefreshVCSData)
	repo.Path("/.settings").Methods("GET").Name(RepoSettings)
	repo.Path("/.settings").Methods("PUT").Name(RepoSettingsUpdate)
	repo.Path("/.commits").Methods("GET").Name(RepoCommits)
	repo.Path("/.commits/{Rev:" + PathComponentNoLeadingDot + "}/.compare").Methods("GET").Name(RepoCompareCommits)
	repo.Path("/.commits/{Rev:" + PathComponentNoLeadingDot + "}").Methods("GET").Name(RepoCommit)
	repo.Path("/.branches").Methods("GET").Name(RepoBranches)
	repo.Path("/.tags").Methods("GET").Name(RepoTags)
	repo.Path("/.badges").Methods("GET").Name(RepoBadges)
	repo.Path("/.counters").Methods("GET").Name(RepoCounters)
	repo.Path("/.counters/{Counter}.png").Methods("GET").Name(RepoCounter)
	repo.Path("/.builds").Methods("GET").Name(RepoBuilds)
	repo.Path("/.builds").Methods("POST").Name(RepoBuildsCreate)

	repo.Path("/.pulls").Methods("GET").Name(RepoPullRequests)
	pullPath := "/.pulls/{Pull}"
	repo.Path(pullPath).Methods("GET").Name(RepoPullRequest)
	pull := repo.PathPrefix(pullPath).Subrouter()
	pull.Path("/merge").Methods("PUT").Name(RepoPullRequestMerge)
	pull.Path("/comments").Methods("GET").Name(RepoPullRequestComments)
	pull.Path("/comments").Methods("POST").Name(RepoPullRequestCommentsCreate)
	pull.Path("/comments/{CommentID}").Methods("PATCH", "PUT").Name(RepoPullRequestCommentsEdit)
	pull.Path("/comments/{CommentID}").Methods("DELETE").Name(RepoPullRequestCommentsDelete)

	repo.Path("/.issues").Methods("GET").Name(RepoIssues)
	issuePath := "/.issues/{Issue}"
	repo.Path(issuePath).Methods("GET").Name(RepoIssue)
	issue := repo.PathPrefix(issuePath).Subrouter()
	issue.Path("/comments").Methods("GET").Name(RepoIssueComments)

	deltaPath := "/.deltas/{Rev:.+}..{DeltaHeadRev:" + PathComponentNoLeadingDot + "}"
	repo.Path(deltaPath).Methods("GET").Name(Delta)
	deltas := repo.PathPrefix(deltaPath).Subrouter()
	deltas.Path("/.defs").Methods("GET").Name(DeltaDefs)
	deltas.Path("/.dependencies").Methods("GET").Name(DeltaDependencies)
	deltas.Path("/.files").Methods("GET").Name(DeltaFiles)
	deltas.Path("/.affected-authors").Methods("GET").Name(DeltaAffectedAuthors)
	deltas.Path("/.affected-clients").Methods("GET").Name(DeltaAffectedClients)
	deltas.Path("/.affected-dependents").Methods("GET").Name(DeltaAffectedDependents)
	deltas.Path("/.reviewers").Methods("GET").Name(DeltaReviewers)

	repo.Path("/.deltas-incoming").Methods("GET").Name(DeltasIncoming)

	// See router_util/tree_route.go for an explanation of how we match tree
	// entry routes.
	repoRev.Path("/.tree" + TreeEntryPathPattern).PostMatchFunc(FixTreeEntryVars).BuildVarsFunc(PrepareTreeEntryRouteVars).Methods("GET").Name(RepoTreeEntry)

	base.Path(`/people/` + PersonSpecPattern).Methods("GET").Name(Person)

	base.Path("/users").Methods("GET").Name(Users)
	userPath := `/users/` + UserSpecPattern
	base.Path(userPath).Methods("GET").Name(User)
	user := base.PathPrefix(userPath).Subrouter()
	user.Path("/orgs").Methods("GET").Name(UserOrgs)
	user.Path("/clients").Methods("GET").Name(UserClients)
	user.Path("/authors").Methods("GET").Name(UserAuthors)
	user.Path("/emails").Methods("GET").Name(UserEmails)
	user.Path("/repo-contributions").Methods("GET").Name(UserRepoContributions)
	user.Path("/repo-dependencies").Methods("GET").Name(UserRepoDependencies)
	user.Path("/repo-dependents").Methods("GET").Name(UserRepoDependents)
	user.Path("/external-profile").Methods("PUT").Name(UserRefreshProfile)
	user.Path("/stats").Methods("PUT").Name(UserComputeStats)
	user.Path("/settings").Methods("GET").Name(UserSettings)
	user.Path("/settings").Methods("PUT").Name(UserSettingsUpdate)
	base.Path("/external-users/github/{GitHubUserSpec}").Methods("GET").Name(UserFromGitHub)

	orgPath := "/orgs/{OrgSpec}"
	base.Path(orgPath).Methods("GET").Name(Org)
	org := base.PathPrefix(orgPath).Subrouter()
	org.Path("/settings").Methods("GET").Name(OrgSettings)
	org.Path("/settings").Methods("PUT").Name(OrgSettingsUpdate)
	org.Path("/members").Methods("GET").Name(OrgMembers)

	base.Path("/search").Methods("GET").Name(Search)

	base.Path("/snippet").Methods("GET", "POST", "ORIGIN").Name(Snippet)

	base.Path("/.defs").Methods("GET").Name(Defs)

	// See router_util/def_route.go for an explanation of how we match def
	// routes.
	defPath := `/.defs/` + DefPathPattern
	repoRev.Path(defPath).Methods("GET").PostMatchFunc(FixDefUnitVars).BuildVarsFunc(PrepareDefRouteVars).Name(Def)
	def := repoRev.PathPrefix(defPath).PostMatchFunc(FixDefUnitVars).BuildVarsFunc(PrepareDefRouteVars).Subrouter()
	def.Path("/.refs").Methods("GET").Name(DefRefs)
	def.Path("/.examples").Methods("GET").Name(DefExamples)
	def.Path("/.authors").Methods("GET").Name(DefAuthors)
	def.Path("/.clients").Methods("GET").Name(DefClients)
	def.Path("/.dependents").Methods("GET").Name(DefDependents)
	def.Path("/.versions").Methods("GET").Name(DefVersions)

	base.Path("/.units").Methods("GET").Name(Units)
	unitPath := `/.units/{UnitType}/{Unit:.*}`
	repoRev.Path(unitPath).Methods("GET").Name(Unit)

	base.Path("/ext/github/webhook").Methods("POST").Name(ExtGitHubReceiveWebhook)

	if ExtraConfig != nil {
		ExtraConfig(base, user)
	}

	return base
}

// ExtraConfig, if non-nil, is called by NewAPIRouter with the
// *mux.Router after setting up routes in this package and before
// returning it. It can be used by external packages that use this API
// router and want to add additional routes to it.
var ExtraConfig func(base, user *mux.Router)
<|endoftext|>


<commit_before>package render

import (
	"html"
	"html/template"
	"io"
	"path/filepath"
	"strings"

<<<<<<< HEAD
=======
	// this blank import is here because dep doesn't
	// handle transitive dependencies correctly
>>>>>>> 0691441... fixed an issue with blank imports and golint
	_ "github.com/russross/blackfriday"
	"github.com/shurcooL/github_flavored_markdown"
)

type templateRenderer struct {
	*Engine
	contentType string
	names       []string
}

func (s templateRenderer) ContentType() string {
	return s.contentType
}

func (s templateRenderer) Render(w io.Writer, data Data) error {
	var body template.HTML
	var err error
	for _, name := range s.names {
		body, err = s.exec(name, data)
		if err != nil {
			return err
		}
		data["yield"] = body
	}
	w.Write([]byte(body))
	return nil
}

func (s templateRenderer) partial(name string, dd Data) (template.HTML, error) {
	d, f := filepath.Split(name)
	name = filepath.Join(d, "_"+f)
	return s.exec(name, dd)
}

func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
	source, err := s.TemplatesBox.MustBytes(name)
	if err != nil {
		return "", err
	}

	helpers := map[string]interface{}{
		"partial": s.partial,
	}

	for k, v := range s.Helpers {
		helpers[k] = v
	}

	if strings.ToLower(filepath.Ext(name)) == ".md" && strings.ToLower(s.contentType) != "text/plain" {
		source = github_flavored_markdown.Markdown(source)
		source = []byte(html.UnescapeString(string(source)))
	}

	body, err := s.TemplateEngine(string(source), data, helpers)
	if err != nil {
		return "", err
	}

	return template.HTML(body), nil
}

// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func Template(c string, names ...string) Renderer {
	e := New(Options{})
	return e.Template(c, names...)
}

// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func (e *Engine) Template(c string, names ...string) Renderer {
	return templateRenderer{
		Engine:      e,
		contentType: c,
		names:       names,
	}
}
<commit_msg>commented the blank blackfriday import<commit_after>package render

import (
	"html"
	"html/template"
	"io"
	"path/filepath"
	"strings"

	// this blank import is here because dep doesn't
	// handle transitive dependencies correctly
	_ "github.com/russross/blackfriday"
	"github.com/shurcooL/github_flavored_markdown"
)

type templateRenderer struct {
	*Engine
	contentType string
	names       []string
}

func (s templateRenderer) ContentType() string {
	return s.contentType
}

func (s templateRenderer) Render(w io.Writer, data Data) error {
	var body template.HTML
	var err error
	for _, name := range s.names {
		body, err = s.exec(name, data)
		if err != nil {
			return err
		}
		data["yield"] = body
	}
	w.Write([]byte(body))
	return nil
}

func (s templateRenderer) partial(name string, dd Data) (template.HTML, error) {
	d, f := filepath.Split(name)
	name = filepath.Join(d, "_"+f)
	return s.exec(name, dd)
}

func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
	source, err := s.TemplatesBox.MustBytes(name)
	if err != nil {
		return "", err
	}

	helpers := map[string]interface{}{
		"partial": s.partial,
	}

	for k, v := range s.Helpers {
		helpers[k] = v
	}

	if strings.ToLower(filepath.Ext(name)) == ".md" && strings.ToLower(s.contentType) != "text/plain" {
		source = github_flavored_markdown.Markdown(source)
		source = []byte(html.UnescapeString(string(source)))
	}

	body, err := s.TemplateEngine(string(source), data, helpers)
	if err != nil {
		return "", err
	}

	return template.HTML(body), nil
}

// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func Template(c string, names ...string) Renderer {
	e := New(Options{})
	return e.Template(c, names...)
}

// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func (e *Engine) Template(c string, names ...string) Renderer {
	return templateRenderer{
		Engine:      e,
		contentType: c,
		names:       names,
	}
}
<|endoftext|>


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

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

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

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

package pulls

import (
	"fmt"

	"k8s.io/contrib/mungegithub/opts"

	"github.com/golang/glog"
	"github.com/google/go-github/github"
)

type PRSizeMunger struct{}

func init() {
	RegisterMungerOrDie(PRSizeMunger{})
}

func (PRSizeMunger) Name() string { return "size" }

const labelSizePrefix = "size/"

func (PRSizeMunger) MungePullRequest(client *github.Client, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent, opts opts.MungeOptions) {
	if pr.Number == nil {
		glog.Warningf("PR has no Number: %+v", *pr)
		return
	}
	if pr.Additions == nil {
		glog.Warningf("PR %d has nil Additions", *pr.Number)
		return
	}
	if pr.Deletions == nil {
		glog.Warningf("PR %d has nil Deletions", *pr.Number)
		return
	}

	adds := *pr.Additions
	dels := *pr.Deletions

	newSize := calculateSize(adds, dels)
	newLabel := labelSizePrefix + newSize

	existing := GetLabelsWithPrefix(issue.Labels, labelSizePrefix)
	needsUpdate := true
	for _, l := range existing {
		if l == newLabel {
			needsUpdate = false
			continue
		}
		if opts.Dryrun {
			glog.Infof("PR #%d: would have removed label %s", *pr.Number, l)
		} else {
			if _, err := client.Issues.RemoveLabelForIssue(opts.Org, opts.Project, *pr.Number, l); err != nil {
				glog.Errorf("PR #%d: error removing label %q: %v", *pr.Number, l, err)
			}
		}
	}
	if needsUpdate {
		if opts.Dryrun {
			glog.Infof("PR #%d: would have added label %s", *pr.Number, newLabel)
		} else {
			if _, _, err := client.Issues.AddLabelsToIssue(opts.Org, opts.Project, *pr.Number, []string{newLabel}); err != nil {
				glog.Errorf("PR #%d: error adding label %q: %v", *pr.Number, newLabel, err)
			}
			body := fmt.Sprintf("Labelling this PR as %s", newLabel)
			if _, _, err := client.Issues.CreateComment(opts.Org, opts.Project, *pr.Number, &github.IssueComment{Body: &body}); err != nil {
				glog.Errorf("PR #%d: error adding comment: %v", *pr.Number, err)
			}
		}
	}
}

const (
	sizeXS  = "XS"
	sizeS   = "S"
	sizeM   = "M"
	sizeL   = "L"
	sizeXL  = "XL"
	sizeXXL = "XXL"
)

func calculateSize(adds, dels int) string {
	lines := adds + dels

	// This is a totally arbitrary heuristic and is open for tweaking.
	if lines < 10 {
		return sizeXS
	}
	if lines < 30 {
		return sizeS
	}
	if lines < 100 {
		return sizeM
	}
	if lines < 500 {
		return sizeL
	}
	if lines < 1000 {
		return sizeXL
	}
	return sizeXXL
}
<commit_msg>mungegithub: Do not count Godeps in PR size<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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

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

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

package pulls

import (
	"fmt"
	"strings"

	"k8s.io/contrib/mungegithub/opts"

	"github.com/golang/glog"
	"github.com/google/go-github/github"
)

type PRSizeMunger struct{}

func init() {
	RegisterMungerOrDie(PRSizeMunger{})
}

func (PRSizeMunger) Name() string { return "size" }

const labelSizePrefix = "size/"

func (PRSizeMunger) MungePullRequest(client *github.Client, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent, opts opts.MungeOptions) {
	if pr.Number == nil {
		glog.Warningf("PR has no Number: %+v", *pr)
		return
	}
	if pr.Additions == nil {
		glog.Warningf("PR %d has nil Additions", *pr.Number)
		return
	}
	if pr.Deletions == nil {
		glog.Warningf("PR %d has nil Deletions", *pr.Number)
		return
	}

	adds := *pr.Additions
	dels := *pr.Deletions

	for _, c := range commits {
		for _, f := range c.Files {
			if strings.HasPrefix(*f.Filename, "Godeps/") {
				adds = adds - *f.Additions
				dels = dels - *f.Deletions
				continue
			}
		}
	}

	newSize := calculateSize(adds, dels)
	newLabel := labelSizePrefix + newSize

	existing := GetLabelsWithPrefix(issue.Labels, labelSizePrefix)
	needsUpdate := true
	for _, l := range existing {
		if l == newLabel {
			needsUpdate = false
			continue
		}
		if opts.Dryrun {
			glog.Infof("PR #%d: would have removed label %s", *pr.Number, l)
		} else {
			if _, err := client.Issues.RemoveLabelForIssue(opts.Org, opts.Project, *pr.Number, l); err != nil {
				glog.Errorf("PR #%d: error removing label %q: %v", *pr.Number, l, err)
			}
		}
	}
	if needsUpdate {
		if opts.Dryrun {
			glog.Infof("PR #%d: would have added label %s", *pr.Number, newLabel)
		} else {
			if _, _, err := client.Issues.AddLabelsToIssue(opts.Org, opts.Project, *pr.Number, []string{newLabel}); err != nil {
				glog.Errorf("PR #%d: error adding label %q: %v", *pr.Number, newLabel, err)
			}
			body := fmt.Sprintf("Labelling this PR as %s", newLabel)
			if _, _, err := client.Issues.CreateComment(opts.Org, opts.Project, *pr.Number, &github.IssueComment{Body: &body}); err != nil {
				glog.Errorf("PR #%d: error adding comment: %v", *pr.Number, err)
			}
		}
	}
}

const (
	sizeXS  = "XS"
	sizeS   = "S"
	sizeM   = "M"
	sizeL   = "L"
	sizeXL  = "XL"
	sizeXXL = "XXL"
)

func calculateSize(adds, dels int) string {
	lines := adds + dels

	// This is a totally arbitrary heuristic and is open for tweaking.
	if lines < 10 {
		return sizeXS
	}
	if lines < 30 {
		return sizeS
	}
	if lines < 100 {
		return sizeM
	}
	if lines < 500 {
		return sizeL
	}
	if lines < 1000 {
		return sizeXL
	}
	return sizeXXL
}
<|endoftext|>


<commit_before>/*
Package idxsort provides types and functions for sorting sequences via separate indexes.
*/
package idxsort

import (
	"sort"
)

/*
IndexedSorter wraps a sequence implementing the sort.Interface interface, supports ascending and descending sort, and duplicates index swaps to other sequences via provided swap functions.

IndexedSorter implements the sort.Interface interface.
*/
type IndexedSorter struct {
	index     sort.Interface
	swapFunc  func(i, j int)
	ascending bool
}

/*
NewIndexedSorter instantiates a new IndexedSorter with the provided index and swap functions.
*/
func NewIndexedSorter(index sort.Interface, swapFunc func(i, j int)) (s *IndexedSorter) {
	s = &IndexedSorter{
		index:     index,
		swapFunc:  swapFunc,
		ascending: true,
	}
	return
}

func (s *IndexedSorter) Sort(ascending bool) {
	s.ascending = ascending
	sort.Sort(s)
}

func (s *IndexedSorter) SortAsc() {
	s.Sort(true)
}

func (s *IndexedSorter) SortDesc() {
	s.Sort(false)
}

func (s *IndexedSorter) Len() int {
	return s.index.Len()
}

func (s *IndexedSorter) Swap(i, j int) {
	s.index.Swap(i, j)
	s.swapFunc(i, j)
}

func (s *IndexedSorter) Less(i, j int) bool {
	if s.ascending {
		return s.index.Less(i, j)
	} else {
		return s.index.Less(j, i)
	}
}

func Sort(index sort.Interface, ascending bool, swapFunc func(i, j int)) {
	sorter := NewIndexedSorter(index, swapFunc)
	sorter.Sort(ascending)
}

func SortAsc(index sort.Interface, swapFunc func(i, j int)) {
	Sort(index, true, swapFunc)
}

func SortDesc(index sort.Interface, swapFunc func(i, j int)) {
	Sort(index, false, swapFunc)
}
<commit_msg>- renamed Sorter - docs<commit_after>/*
Package idxsort provides types and functions for sorting sequences via separate indexes.
*/
package idxsort

import (
	"sort"
)

/*
Sorter wraps a sequence implementing the sort.Interface interface, supports ascending and descending sort, and duplicates index swaps to other sequences via a swap function.

Methods of Sorter are not safe for concurrent use. The provided index and/or swap functions may also require explicit locking to prevent concurrent access.

Sorter implements the sort.Interface interface.
*/
type Sorter struct {
	index     sort.Interface
	swapFunc  func(i, j int)
	ascending bool
}

/*
NewSorter instantiates a new Sorter with the provided index and swap function.
*/
func NewSorter(index sort.Interface, swapFunc func(i, j int)) (s *Sorter) {
	s = &Sorter{
		index:     index,
		swapFunc:  swapFunc,
		ascending: true,
	}
	return
}

/*
Sorts the index in ascending or descending order.
*/
func (s *Sorter) Sort(ascending bool) {
	s.ascending = ascending
	sort.Sort(s)
}

/*
Sorts the index in ascending order.
*/
func (s *Sorter) SortAsc() {
	s.Sort(true)
}

/*
Sorts the index in descending order.
*/
func (s *Sorter) SortDesc() {
	s.Sort(false)
}

func (s *Sorter) Len() int {
	return s.index.Len()
}

func (s *Sorter) Swap(i, j int) {
	s.index.Swap(i, j)
	s.swapFunc(i, j)
}

func (s *Sorter) Less(i, j int) bool {
	if s.ascending {
		return s.index.Less(i, j)
	} else {
		return s.index.Less(j, i)
	}
}

/*
Sorts an index in the provided order, and duplicates index swaps to swapFunc.
*/
func Sort(index sort.Interface, ascending bool, swapFunc func(i, j int)) {
	sorter := NewSorter(index, swapFunc)
	sorter.Sort(ascending)
}

/*
Sorts an index in ascending order, and duplicates index swaps to swapFunc.
*/
func SortAsc(index sort.Interface, swapFunc func(i, j int)) {
	Sort(index, true, swapFunc)
}

/*
Sorts an index in descending order, and duplicates index swaps to swapFunc.
*/
func SortDesc(index sort.Interface, swapFunc func(i, j int)) {
	Sort(index, false, swapFunc)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io"
	"log"
	"os"
	"runtime"
	"sync"
	"time"
)

type Source struct {
	frames          []DataFrame
	frameBytes      uint64
	gone            bool
	input           io.ReadCloser
	nextFrame       uint64 // How many frames have ever been here
	path            string
	sync.RWMutex    // Must be held while changing nextFrame or gone
	*sync.Cond      // Control access to frames other than nextFrame
	statBytesIn     uint64
	statBytesOut    uint64
	statLogInterval time.Duration
}

var sourceMap = make(map[string]*Source)
var sourceMapMutex = sync.RWMutex{}

func NewSource(path string, c Config) (s *Source) {
	s = &Source{}
	s.Cond = sync.NewCond(s.RLocker())
	s.frames = make([]DataFrame, c.SourceBuffer)
	for i := range s.frames {
		s.frames[i] = make(DataFrame, c.FrameBytes)
	}
	s.frameBytes = c.FrameBytes
	s.path = path
	s.statLogInterval = c.StatLogInterval
	return
}

// Read data from the given source into the buffer. If the source
// reaches EOF and cannot be reopened, remove the source from
// sourceMap and return.
func (s *Source) run() {
	var err error
	lastLog := time.Now()
	defer func() {
		if err != nil {
			log.Printf("Source %s error: %s", s.path, err)
		}
		s.Close()
	}()
	if s.input, err = os.Open(s.path); err != nil {
		log.Printf("Source %s error: %s", s.path, err)
		return
	}
	defer s.input.Close()
	for {
		bufPos := s.nextFrame % uint64(cap(s.frames))
		for framePos := uint64(0); framePos < s.frameBytes; {
			var got int
			if got, err = s.input.Read(s.frames[bufPos][framePos:]); err != nil {
				log.Printf("Source %s error: %s", s.path, err)
				return
			}
			framePos += uint64(got)
		}
		s.Lock()
		s.statBytesIn += s.frameBytes
		s.nextFrame += 1
		if s.statLogInterval > 0 && time.Since(lastLog) >= s.statLogInterval {
			log.Printf("Stats: %d in %d out", s.statBytesIn, s.statBytesOut)
			lastLog = time.Now()
		}
		s.Unlock()
		s.Cond.Broadcast()
		runtime.Gosched()
	}
	log.Printf("Input channel closed for %s", s.path)
	// TODO: Reopen
}

// Copy the next data frame into the given buffer and update the
// nextFrame pointer.
//
// Return the number of frames skipped due to buffer underrun. If the
// data source is exhausted, return with err != nil (with frame
// untouched and other return values undefined).
func (s *Source) Next(nextFrame *uint64, frame DataFrame) (nSkipped uint64, err error) {
	s.Cond.L.Lock()
	for *nextFrame >= s.nextFrame && !s.gone {
		// If we don't Unlock and GoSched here, performance goes awful.
		s.Cond.L.Unlock()
		runtime.Gosched()
		s.Cond.L.Lock()
		// Theoretically, this should be enough:
		s.Cond.Wait()
	}
	if s.gone {
		err = errors.New("Read past end of stream")
		s.Cond.L.Unlock()
		return
	}
	lag := s.nextFrame - *nextFrame
	if lag >= uint64(cap(s.frames)-1) {
		*nextFrame = s.nextFrame - 1
		nSkipped = lag
	}
	bufPos := *nextFrame%uint64(cap(s.frames))
	if cap(frame) < len(s.frames[bufPos]) {
		err = errors.New("Caller's frame buffer is too small.")
		return
	}
	copy(frame, s.frames[bufPos])
	s.Cond.L.Unlock()
	s.Lock()
	s.statBytesOut += s.frameBytes
	s.Unlock()
	*nextFrame += 1
	runtime.Gosched()
	return
}

// Remove the source from sourceMap.
func (s *Source) Close() {
	sourceMapMutex.Lock()
	delete(sourceMap, s.path)
	sourceMapMutex.Unlock()
	s.RWMutex.Lock()
	s.gone = true
	s.RWMutex.Unlock()
	s.Broadcast()
}

// Return a Source for the given path (URI) and config (argv). At any
// given time, there is at most one Source for a given path.
func GetSource(path string, c Config) *Source {
	sourceMapMutex.RLock()
	if src, ok := sourceMap[path]; ok {
		sourceMapMutex.RUnlock()
		return src
	}
	sourceMapMutex.RUnlock()
	sourceMapMutex.Lock()
	defer sourceMapMutex.Unlock()
	if src, ok := sourceMap[path]; ok {
		return src
	}
	src := NewSource(path, c)
	sourceMap[path] = src
	go src.run()
	return src
}
<commit_msg>Tidy up unlocking.<commit_after>package main

import (
	"errors"
	"io"
	"log"
	"os"
	"runtime"
	"sync"
	"time"
)

type Source struct {
	frames          []DataFrame
	frameBytes      uint64
	gone            bool
	input           io.ReadCloser
	nextFrame       uint64 // How many frames have ever been here
	path            string
	sync.RWMutex    // Must be held while changing nextFrame or gone
	*sync.Cond      // Control access to frames other than nextFrame
	statBytesIn     uint64
	statBytesOut    uint64
	statLogInterval time.Duration
}

var sourceMap = make(map[string]*Source)
var sourceMapMutex = sync.RWMutex{}

func NewSource(path string, c Config) (s *Source) {
	s = &Source{}
	s.Cond = sync.NewCond(s.RLocker())
	s.frames = make([]DataFrame, c.SourceBuffer)
	for i := range s.frames {
		s.frames[i] = make(DataFrame, c.FrameBytes)
	}
	s.frameBytes = c.FrameBytes
	s.path = path
	s.statLogInterval = c.StatLogInterval
	return
}

// Read data from the given source into the buffer. If the source
// reaches EOF and cannot be reopened, remove the source from
// sourceMap and return.
func (s *Source) run() {
	var err error
	lastLog := time.Now()
	defer func() {
		if err != nil {
			log.Printf("Source %s error: %s", s.path, err)
		}
		s.Close()
	}()
	if s.input, err = os.Open(s.path); err != nil {
		log.Printf("Source %s error: %s", s.path, err)
		return
	}
	defer s.input.Close()
	for {
		bufPos := s.nextFrame % uint64(cap(s.frames))
		for framePos := uint64(0); framePos < s.frameBytes; {
			var got int
			if got, err = s.input.Read(s.frames[bufPos][framePos:]); err != nil {
				log.Printf("Source %s error: %s", s.path, err)
				return
			}
			framePos += uint64(got)
		}
		s.Lock()
		s.statBytesIn += s.frameBytes
		s.nextFrame += 1
		if s.statLogInterval > 0 && time.Since(lastLog) >= s.statLogInterval {
			log.Printf("Stats: %d in %d out", s.statBytesIn, s.statBytesOut)
			lastLog = time.Now()
		}
		s.Unlock()
		s.Cond.Broadcast()
		runtime.Gosched()
	}
	log.Printf("Input channel closed for %s", s.path)
	// TODO: Reopen
}

// Copy the next data frame into the given buffer and update the
// nextFrame pointer.
//
// Return the number of frames skipped due to buffer underrun. If the
// data source is exhausted, return with err != nil (with frame
// untouched and other return values undefined).
func (s *Source) Next(nextFrame *uint64, frame DataFrame) (nSkipped uint64, err error) {
	s.Cond.L.Lock()
	defer func() {
		s.Cond.L.Unlock()
		if err != nil {
			s.Lock()
			s.statBytesOut += s.frameBytes
			s.Unlock()
			*nextFrame += 1
			runtime.Gosched()
		}
	}()
	for *nextFrame >= s.nextFrame && !s.gone {
		// If we don't Unlock and GoSched here, performance goes awful.
		s.Cond.L.Unlock()
		runtime.Gosched()
		s.Cond.L.Lock()
		// Theoretically, this should be enough:
		s.Cond.Wait()
	}
	if *nextFrame >= s.nextFrame {
		err = errors.New("Read past end of stream")
		return
	}
	lag := s.nextFrame - *nextFrame
	if lag >= uint64(cap(s.frames)-1) {
		*nextFrame = s.nextFrame - 1
		nSkipped = lag
	}
	bufPos := *nextFrame%uint64(cap(s.frames))
	if cap(frame) < len(s.frames[bufPos]) {
		err = errors.New("Caller's frame buffer is too small.")
		return
	}
	copy(frame, s.frames[bufPos])
	return
}

// Remove the source from sourceMap.
func (s *Source) Close() {
	sourceMapMutex.Lock()
	delete(sourceMap, s.path)
	sourceMapMutex.Unlock()
	s.RWMutex.Lock()
	s.gone = true
	s.RWMutex.Unlock()
	s.Broadcast()
}

// Return a Source for the given path (URI) and config (argv). At any
// given time, there is at most one Source for a given path.
func GetSource(path string, c Config) *Source {
	sourceMapMutex.RLock()
	if src, ok := sourceMap[path]; ok {
		sourceMapMutex.RUnlock()
		return src
	}
	sourceMapMutex.RUnlock()
	sourceMapMutex.Lock()
	defer sourceMapMutex.Unlock()
	if src, ok := sourceMap[path]; ok {
		return src
	}
	src := NewSource(path, c)
	sourceMap[path] = src
	go src.run()
	return src
}
<|endoftext|>


<commit_before>package cgp

import (
	"math"
	"math/rand"
)

type Gene struct {
	Function    int
	Constant    float64
	Connections []int
}

func (g *Gene) Mutate(position int, options *CGP) {
	toMutate := rand.Intn(2 + len(g.Connections))

	if toMutate == 0 {
		g.Function = rand.Intn(len(options.FunctionList))
		return
	}

	if toMutate == 1 {
		g.Constant = options.RandConst()
		return
	}

	g.Connections[toMutate-2] = rand.Intn(position)
}

type Individual struct {
	Genes   []Gene
	Outputs []int
	Options *CGP
	Fitness float64
}

func NewIndividual(cgp *CGP) (ind Individual) {
	ind.Options = cgp
	ind.Fitness = math.Inf(1)
	ind.Genes = make([]Gene, cgp.NumGenes)
	ind.Outputs = make([]int, cgp.NumOutputs)

	for i := range ind.Genes {
		ind.Genes[i].Function = rand.Intn(len(cgp.FunctionList))
		ind.Genes[i].Constant = cgp.RandConst()
		ind.Genes[i].Connections = make([]int, cgp.MaxArity)
		for j := range ind.Genes[i].Connections {
			ind.Genes[i].Connections[j] = rand.Intn(cgp.NumInputs + i)
		}
	}

	for i := range ind.Outputs {
		ind.Outputs[i] = rand.Intn(cgp.NumInputs + cgp.NumGenes)
	}

	return
}

func (ind Individual) Mutate() (mutant Individual) {
	// Copy the parent individual
	mutant.Fitness = math.Inf(1)
	mutant.Options = ind.Options
	mutant.Genes = make([]Gene, ind.Options.NumGenes)
	mutant.Outputs = make([]int, ind.Options.NumOutputs)
	copy(mutant.Genes, ind.Genes)
	copy(mutant.Outputs, ind.Outputs)

	numMutations := ind.Options.MutationRate * float64(ind.Options.NumGenes+ind.Options.NumOutputs)
	if numMutations < 1 {
		numMutations = 1
	}

	for numMutations > 0 {
		toMutate := rand.Intn(mutant.Options.NumGenes + mutant.Options.NumOutputs)

		if toMutate < mutant.Options.NumGenes {
			mutant.Genes[toMutate].Mutate(toMutate+mutant.Options.NumInputs, mutant.Options)
		} else {
			mutant.Outputs[toMutate-mutant.Options.NumGenes] =
				rand.Intn(mutant.Options.NumInputs + mutant.Options.NumGenes)
		}

		numMutations--
	}

	return
}

func (ind Individual) Run(input []float64) (output []float64) {
	return []float64{0, 0, 0}
}
<commit_msg>Implement Individual.Run()<commit_after>package cgp

import (
	"math"
	"math/rand"
)

type Gene struct {
	Function    int
	Constant    float64
	Connections []int
}

func (g *Gene) Mutate(position int, options *CGP) {
	toMutate := rand.Intn(2 + len(g.Connections))

	if toMutate == 0 {
		g.Function = rand.Intn(len(options.FunctionList))
		return
	}

	if toMutate == 1 {
		g.Constant = options.RandConst()
		return
	}

	g.Connections[toMutate-2] = rand.Intn(position)
}

type Individual struct {
	Genes   []Gene
	Outputs []int
	Options *CGP
	Fitness float64

	activeGenes []bool
}

func NewIndividual(cgp *CGP) (ind Individual) {
	ind.Options = cgp
	ind.Fitness = math.Inf(1)
	ind.Genes = make([]Gene, cgp.NumGenes)
	ind.Outputs = make([]int, cgp.NumOutputs)

	for i := range ind.Genes {
		ind.Genes[i].Function = rand.Intn(len(cgp.FunctionList))
		ind.Genes[i].Constant = cgp.RandConst()
		ind.Genes[i].Connections = make([]int, cgp.MaxArity)
		for j := range ind.Genes[i].Connections {
			ind.Genes[i].Connections[j] = rand.Intn(cgp.NumInputs + i)
		}
	}

	for i := range ind.Outputs {
		ind.Outputs[i] = rand.Intn(cgp.NumInputs + cgp.NumGenes)
	}

	return
}

func (ind Individual) Mutate() (mutant Individual) {
	// Copy the parent individual
	mutant.Fitness = math.Inf(1)
	mutant.Options = ind.Options
	mutant.Genes = make([]Gene, ind.Options.NumGenes)
	mutant.Outputs = make([]int, ind.Options.NumOutputs)
	copy(mutant.Genes, ind.Genes)
	copy(mutant.Outputs, ind.Outputs)

	numMutations := ind.Options.MutationRate * float64(ind.Options.NumGenes+ind.Options.NumOutputs)
	if numMutations < 1 {
		numMutations = 1
	}

	for numMutations > 0 {
		toMutate := rand.Intn(mutant.Options.NumGenes + mutant.Options.NumOutputs)

		if toMutate < mutant.Options.NumGenes {
			mutant.Genes[toMutate].Mutate(toMutate+mutant.Options.NumInputs, mutant.Options)
		} else {
			mutant.Outputs[toMutate-mutant.Options.NumGenes] =
				rand.Intn(mutant.Options.NumInputs + mutant.Options.NumGenes)
		}

		numMutations--
	}

	return
}

func (ind *Individual) markActive(gene int) {
	if ind.activeGenes[gene] {
		return
	}

	ind.activeGenes[gene] = true

	for _, conn := range ind.Genes[gene-ind.Options.NumInputs].Connections {
		ind.markActive(conn)
	}
}

func (ind *Individual) determineActiveGenes() {
	// Check if we already did this
	if len(ind.activeGenes) != 0 {
		return
	}

	ind.activeGenes = make([]bool,
		ind.Options.NumInputs+ind.Options.NumGenes+ind.Options.NumOutputs)

	// Mark inputs as Active
	for i := 0; i < ind.Options.NumInputs; i++ {
		ind.activeGenes[i] = true
	}

	// Recursively mark active genes beginning from the outputs
	for _, conn := range ind.Outputs {
		ind.markActive(conn)
	}
}

func (ind Individual) Run(input []float64) []float64 {
	if len(input) != ind.Options.NumInputs {
		panic("Individual.Run() was called with the wrong number of inputs")
	}

	ind.determineActiveGenes()

	nodeOutput := make([]float64, ind.Options.NumInputs+ind.Options.NumGenes)
	for i := 0; i < ind.Options.NumInputs; i++ {
		nodeOutput[i] = input[i]
	}

	for i := 0; i < ind.Options.NumGenes; i++ {
		if !ind.activeGenes[i+ind.Options.NumInputs] {
			continue
		}

		functionInput := make([]float64, 1+ind.Options.MaxArity)
		functionInput[0] = ind.Genes[i].Constant
		for j, c := range ind.Genes[i].Connections {
			functionInput[j+1] = nodeOutput[c]
		}

		functionOutput := ind.Options.FunctionList[ind.Genes[i].Function](functionInput)
		nodeOutput[i+ind.Options.NumInputs] = functionOutput
	}

	output := make([]float64, 0, ind.Options.NumOutputs)
	for _, o := range ind.Outputs {
		output = append(output, nodeOutput[o])
	}

	return output
}
<|endoftext|>


<commit_before>package cgp

import (
	"math"
	"math/rand"
)

type Gene struct {
	Function    int
	Constant    float64
	Connections []int
}

func (g *Gene) Mutate(options *CGP) {
}

type Individual struct {
	Genes   []Gene
	Outputs []int
	Options *CGP
	Fitness float64
}

func NewIndividual(cgp *CGP) (ind Individual) {
	ind.Options = cgp
	ind.Fitness = math.Inf(1)
	ind.Genes = make([]Gene, cgp.NumGenes)
	ind.Outputs = make([]int, cgp.NumOutputs)

	for i := range ind.Genes {
		ind.Genes[i].Function = rand.Intn(len(cgp.FunctionList))
		ind.Genes[i].Constant = cgp.RandConst()
		ind.Genes[i].Connections = make([]int, cgp.MaxArity)
		for j := range ind.Genes[i].Connections {
			ind.Genes[i].Connections[j] = rand.Intn(cgp.NumInputs + i)
		}
	}

	for i := range ind.Outputs {
		ind.Outputs[i] = rand.Intn(cgp.NumInputs + cgp.NumGenes)
	}

	return
}

func (ind Individual) Mutate() (mutant Individual) {
	// Copy the parent individual
	mutant.Fitness = math.Inf(1)
	mutant.Options = ind.Options
	mutant.Genes = make([]Gene, ind.Options.NumGenes)
	mutant.Outputs = make([]int, ind.Options.NumOutputs)
	copy(mutant.Genes, ind.Genes)
	copy(mutant.Outputs, ind.Outputs)

	numMutations := ind.Options.MutationRate * float64(ind.Options.NumGenes+ind.Options.NumOutputs)
	if numMutations < 1 {
		numMutations = 1
	}

	for numMutations > 0 {
		toMutate := rand.Intn(mutant.Options.NumGenes + mutant.Options.NumOutputs)

		if toMutate < mutant.Options.NumGenes {
			mutant.Genes[toMutate].Mutate(mutant.Options)
		} else {
			mutant.Outputs[toMutate-mutant.Options.NumGenes] =
				rand.Intn(mutant.Options.NumInputs + mutant.Options.NumGenes)
		}

		numMutations--
	}

	return
}

func (ind Individual) Run(input []float64) (output []float64) {
	return []float64{0, 0, 0}
}
<commit_msg>Write Gene.Mutate()<commit_after>package cgp

import (
	"math"
	"math/rand"
)

type Gene struct {
	Function    int
	Constant    float64
	Connections []int
}

func (g *Gene) Mutate(position int, options *CGP) {
	toMutate := rand.Intn(2 + len(g.Connections))

	if toMutate == 0 {
		g.Function = rand.Intn(len(options.FunctionList))
		return
	}

	if toMutate == 1 {
		g.Constant = options.RandConst()
		return
	}

	g.Connections[toMutate-2] = rand.Intn(position)
}

type Individual struct {
	Genes   []Gene
	Outputs []int
	Options *CGP
	Fitness float64
}

func NewIndividual(cgp *CGP) (ind Individual) {
	ind.Options = cgp
	ind.Fitness = math.Inf(1)
	ind.Genes = make([]Gene, cgp.NumGenes)
	ind.Outputs = make([]int, cgp.NumOutputs)

	for i := range ind.Genes {
		ind.Genes[i].Function = rand.Intn(len(cgp.FunctionList))
		ind.Genes[i].Constant = cgp.RandConst()
		ind.Genes[i].Connections = make([]int, cgp.MaxArity)
		for j := range ind.Genes[i].Connections {
			ind.Genes[i].Connections[j] = rand.Intn(cgp.NumInputs + i)
		}
	}

	for i := range ind.Outputs {
		ind.Outputs[i] = rand.Intn(cgp.NumInputs + cgp.NumGenes)
	}

	return
}

func (ind Individual) Mutate() (mutant Individual) {
	// Copy the parent individual
	mutant.Fitness = math.Inf(1)
	mutant.Options = ind.Options
	mutant.Genes = make([]Gene, ind.Options.NumGenes)
	mutant.Outputs = make([]int, ind.Options.NumOutputs)
	copy(mutant.Genes, ind.Genes)
	copy(mutant.Outputs, ind.Outputs)

	numMutations := ind.Options.MutationRate * float64(ind.Options.NumGenes+ind.Options.NumOutputs)
	if numMutations < 1 {
		numMutations = 1
	}

	for numMutations > 0 {
		toMutate := rand.Intn(mutant.Options.NumGenes + mutant.Options.NumOutputs)

		if toMutate < mutant.Options.NumGenes {
			mutant.Genes[toMutate].Mutate(toMutate+mutant.Options.NumInputs, mutant.Options)
		} else {
			mutant.Outputs[toMutate-mutant.Options.NumGenes] =
				rand.Intn(mutant.Options.NumInputs + mutant.Options.NumGenes)
		}

		numMutations--
	}

	return
}

func (ind Individual) Run(input []float64) (output []float64) {
	return []float64{0, 0, 0}
}
<|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 (
	"math"

	"github.com/cpmech/gosl/rnd"
	"github.com/cpmech/gosl/utl"
)

// Individual implements one individual in a population
type Individual struct {

	// essential data
	Ovas   []float64 // objective values
	Oors   []float64 // out-of-range values: sum of positive distances from constraints
	Floats []float64 // [optional] floats
	Ints   []int     // [optional] integers

	// auxiliary
	Id int // identifier; e.g. for debugging

	// comparison, diversity and non-dominance sorting data
	WinOver   []*Individual // [ninds] individuals dominated by this individual
	Nwins     int           // number of wins => current len(WinOver)
	Nlosses   int           // number of individuals dominating this individual
	FrontId   int           // Pareto front id
	DistCrowd float64       // crowd distance
	DistNeigh float64       // minimum distance to any neighbouring individual
}

// NewIndividual allocates a new individual
func NewIndividual(nova, noor int, floats []float64, ints []int) (o *Individual) {
	o = new(Individual)
	o.Ovas = make([]float64, nova)
	o.Oors = make([]float64, noor)
	if len(floats) > 0 {
		o.Floats = make([]float64, len(floats))
		copy(o.Floats, floats)
	}
	if len(ints) > 0 {
		o.Ints = make([]int, len(ints))
		copy(o.Ints, ints)
	}
	return
}

// GetCopy returns a copy of this individual
func (o Individual) GetCopy() (x *Individual) {
	x = new(Individual)
	x.Ovas = make([]float64, len(o.Ovas))
	x.Oors = make([]float64, len(o.Oors))
	copy(x.Ovas, o.Ovas)
	copy(x.Oors, o.Oors)
	if len(o.Floats) > 0 {
		x.Floats = make([]float64, len(o.Floats))
		copy(x.Floats, o.Floats)
	}
	if len(o.Ints) > 0 {
		x.Ints = make([]int, len(o.Ints))
		copy(x.Ints, o.Ints)
	}
	x.Id = o.Id
	return
}

// CopyInto copies this individual's data into another individual
func (o Individual) CopyInto(x *Individual) {
	copy(x.Ovas, o.Ovas)
	copy(x.Oors, o.Oors)
	if len(o.Floats) > 0 {
		copy(x.Floats, o.Floats)
	}
	if len(o.Ints) > 0 {
		copy(x.Ints, o.Ints)
	}
	x.Id = o.Id
	return
}

// Feasible returns whether this individual is feasible or not
func (o Individual) Feasible() bool {
	for _, oor := range o.Oors {
		if oor > 0 {
			return false
		}
	}
	return true
}

// Fight implements the competition between A and B
func (A *Individual) Fight(B *Individual) (A_wins bool) {
	A_dom, B_dom := IndCompare(A, B)
	if A_dom {
		return true
	}
	if B_dom {
		return false
	}
	if A.FrontId == B.FrontId {
		if A.DistCrowd > B.DistCrowd {
			return true
		}
		if B.DistCrowd > A.DistCrowd {
			return false
		}
	}
	//if false {
	if true {
		//io.Pforan("A.dist=%v  B.dist=%v\n", A.DistNeigh, B.DistNeigh)
		if A.DistNeigh > B.DistNeigh {
			return true
		}
		if B.DistNeigh > A.DistNeigh {
			return true
		}
	}
	if rnd.FlipCoin(0.5) {
		return true
	}
	return false
}

// global functions ////////////////////////////////////////////////////////////////////////////////

// IndCompare compares individual 'A' with another one 'B'. Deterministic method
func IndCompare(A, B *Individual) (A_dominates, B_dominates bool) {
	var A_nviolations, B_nviolations int
	for i := 0; i < len(A.Oors); i++ {
		if A.Oors[i] > 0 {
			A_nviolations++
		}
		if B.Oors[i] > 0 {
			B_nviolations++
		}
	}
	if A_nviolations > 0 {
		if B_nviolations > 0 {
			if A_nviolations < B_nviolations {
				A_dominates = true
				return
			}
			if B_nviolations < A_nviolations {
				B_dominates = true
				return
			}
			A_dominates, B_dominates = utl.DblsParetoMin(A.Oors, B.Oors)
			if !A_dominates && !B_dominates {
				A_dominates, B_dominates = utl.DblsParetoMin(A.Ovas, B.Ovas)
			}
			return
		}
		B_dominates = true
		return
	}
	if B_nviolations > 0 {
		A_dominates = true
		return
	}
	A_dominates, B_dominates = utl.DblsParetoMin(A.Ovas, B.Ovas)
	return
}

// IndDistance computes a distance measure from individual 'A' to another individual 'B'
func IndDistance(A, B *Individual, omin, omax []float64) (dist float64) {
	for i := 0; i < len(A.Ovas); i++ {
		δ := omax[i] - omin[i] + 1e-15
		dist += math.Pow((A.Ovas[i]-B.Ovas[i])/δ, 2.0)
	}
	return math.Sqrt(dist)
}

// IndCrossover performs the crossover between chromosomes of two individuals A and B
// resulting in the chromosomes of other two individuals a and b
func IndCrossover(a, b, A, B, C, D *Individual, time int, ops *OpsData) {
	if len(A.Floats) > 0 {
		if D == nil {
			ops.CxFlt(a.Floats, b.Floats, A.Floats, B.Floats, nil, nil, time, ops)
		} else {
			ops.CxFlt(a.Floats, b.Floats, A.Floats, B.Floats, C.Floats, D.Floats, time, ops)
		}
	}
	if len(A.Ints) > 0 {
		if D == nil {
			ops.CxInt(a.Ints, b.Ints, A.Ints, B.Ints, nil, nil, time, ops)
		} else {
			ops.CxInt(a.Ints, b.Ints, A.Ints, B.Ints, C.Ints, D.Ints, time, ops)
		}
	}
}

// IndMutation performs the mutation operation in the chromosomes of an individual
func IndMutation(A *Individual, time int, ops *OpsData) {
	if len(A.Floats) > 0 {
		ops.MtFlt(A.Floats, time, ops)
	}
	if len(A.Ints) > 0 {
		ops.MtInt(A.Ints, time, ops)
	}
}
<commit_msg>code clean up<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 (
	"math"

	"github.com/cpmech/gosl/rnd"
	"github.com/cpmech/gosl/utl"
)

// Individual implements one individual in a population
type Individual struct {

	// essential data
	Ovas   []float64 // objective values
	Oors   []float64 // out-of-range values: sum of positive distances from constraints
	Floats []float64 // [optional] floats
	Ints   []int     // [optional] integers

	// auxiliary
	Id int // identifier; e.g. for debugging

	// comparison, diversity and non-dominance sorting data
	WinOver   []*Individual // [ninds] individuals dominated by this individual
	Nwins     int           // number of wins => current len(WinOver)
	Nlosses   int           // number of individuals dominating this individual
	FrontId   int           // Pareto front id
	DistCrowd float64       // crowd distance
	DistNeigh float64       // minimum distance to any neighbouring individual
}

// NewIndividual allocates a new individual
func NewIndividual(nova, noor int, floats []float64, ints []int) (o *Individual) {
	o = new(Individual)
	o.Ovas = make([]float64, nova)
	o.Oors = make([]float64, noor)
	if len(floats) > 0 {
		o.Floats = make([]float64, len(floats))
		copy(o.Floats, floats)
	}
	if len(ints) > 0 {
		o.Ints = make([]int, len(ints))
		copy(o.Ints, ints)
	}
	return
}

// GetCopy returns a copy of this individual
func (o Individual) GetCopy() (x *Individual) {
	x = new(Individual)
	x.Ovas = make([]float64, len(o.Ovas))
	x.Oors = make([]float64, len(o.Oors))
	copy(x.Ovas, o.Ovas)
	copy(x.Oors, o.Oors)
	if len(o.Floats) > 0 {
		x.Floats = make([]float64, len(o.Floats))
		copy(x.Floats, o.Floats)
	}
	if len(o.Ints) > 0 {
		x.Ints = make([]int, len(o.Ints))
		copy(x.Ints, o.Ints)
	}
	x.Id = o.Id
	return
}

// CopyInto copies this individual's data into another individual
func (o Individual) CopyInto(x *Individual) {
	copy(x.Ovas, o.Ovas)
	copy(x.Oors, o.Oors)
	if len(o.Floats) > 0 {
		copy(x.Floats, o.Floats)
	}
	if len(o.Ints) > 0 {
		copy(x.Ints, o.Ints)
	}
	x.Id = o.Id
	return
}

// Feasible returns whether this individual is feasible or not
func (o Individual) Feasible() bool {
	for _, oor := range o.Oors {
		if oor > 0 {
			return false
		}
	}
	return true
}

// Fight implements the competition between A and B
func (A *Individual) Fight(B *Individual) (A_wins bool) {
	A_dom, B_dom := IndCompare(A, B)
	if A_dom {
		return true
	}
	if B_dom {
		return false
	}
	if A.FrontId == B.FrontId {
		if A.DistCrowd > B.DistCrowd {
			return true
		}
		if B.DistCrowd > A.DistCrowd {
			return false
		}
	}
	if A.DistNeigh > B.DistNeigh {
		return true
	}
	if B.DistNeigh > A.DistNeigh {
		return true
	}
	if rnd.FlipCoin(0.5) {
		return true
	}
	return false
}

// global functions ////////////////////////////////////////////////////////////////////////////////

// IndCompare compares individual 'A' with another one 'B'. Deterministic method
func IndCompare(A, B *Individual) (A_dominates, B_dominates bool) {
	var A_nviolations, B_nviolations int
	for i := 0; i < len(A.Oors); i++ {
		if A.Oors[i] > 0 {
			A_nviolations++
		}
		if B.Oors[i] > 0 {
			B_nviolations++
		}
	}
	if A_nviolations > 0 {
		if B_nviolations > 0 {
			if A_nviolations < B_nviolations {
				A_dominates = true
				return
			}
			if B_nviolations < A_nviolations {
				B_dominates = true
				return
			}
			A_dominates, B_dominates = utl.DblsParetoMin(A.Oors, B.Oors)
			if !A_dominates && !B_dominates {
				A_dominates, B_dominates = utl.DblsParetoMin(A.Ovas, B.Ovas)
			}
			return
		}
		B_dominates = true
		return
	}
	if B_nviolations > 0 {
		A_dominates = true
		return
	}
	A_dominates, B_dominates = utl.DblsParetoMin(A.Ovas, B.Ovas)
	return
}

// IndDistance computes a distance measure from individual 'A' to another individual 'B'
func IndDistance(A, B *Individual, omin, omax []float64) (dist float64) {
	for i := 0; i < len(A.Ovas); i++ {
		δ := omax[i] - omin[i] + 1e-15
		dist += math.Pow((A.Ovas[i]-B.Ovas[i])/δ, 2.0)
	}
	return math.Sqrt(dist)
}

// IndCrossover performs the crossover between chromosomes of two individuals A and B
// resulting in the chromosomes of other two individuals a and b
func IndCrossover(a, b, A, B, C, D *Individual, time int, ops *OpsData) {
	if len(A.Floats) > 0 {
		if D == nil {
			ops.CxFlt(a.Floats, b.Floats, A.Floats, B.Floats, nil, nil, time, ops)
		} else {
			ops.CxFlt(a.Floats, b.Floats, A.Floats, B.Floats, C.Floats, D.Floats, time, ops)
		}
	}
	if len(A.Ints) > 0 {
		if D == nil {
			ops.CxInt(a.Ints, b.Ints, A.Ints, B.Ints, nil, nil, time, ops)
		} else {
			ops.CxInt(a.Ints, b.Ints, A.Ints, B.Ints, C.Ints, D.Ints, time, ops)
		}
	}
}

// IndMutation performs the mutation operation in the chromosomes of an individual
func IndMutation(A *Individual, time int, ops *OpsData) {
	if len(A.Floats) > 0 {
		ops.MtFlt(A.Floats, time, ops)
	}
	if len(A.Ints) > 0 {
		ops.MtInt(A.Ints, time, ops)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"strings"

	"torpedobot/multibot"
)

func GetStripEnv(envvar string) (result string) {
	result = os.Getenv(envvar)
	result = strings.TrimLeft(result, "'")
	result = strings.TrimRight(result, "'")
	return
}

func main() {
	var (
		slack                  = flag.String("slack", "", "Comma separated list of Slack legacy tokens")
		telegram               = flag.String("telegram", "", "Comma separated list of Telegram bot keys")
		jabber                 = flag.String("jabber", "", "Comma separated list of jabber creds, user@host.com:password,")
		skype                  = flag.String("skype", "", "Comma separated list of dev.botframework.com creds, app_id:app_password,")
		kik                    = flag.String("kik", "", "Comma separated list of Kik creds, username:api_key,")
		skype_incoming_addr    = flag.String("skype_incoming_addr", "0.0.0.0:3978", "Listen on this address for incoming Skype messages")
		facebook               = flag.String("facebook", "", "Comma separated list of Facebook creds, page_token1:verify_token1,..")
		google_webapp_key      = flag.String("google_webapp_key", "", "Google Data API Web Application Key")
		facebook_incoming_addr = flag.String("facebook_incoming_addr", "0.0.0.0:3979", "Listen on this address for incoming Facebook messages")
		kik_incoming_addr      = flag.String("kik_incoming_addr", "0.0.0.0:3980", "Listen on this address for incoming Kik messages")
		kik_webhook_url        = flag.String("kik_webhook_url", "", "Webhook URL (external) for incoming Kik messages")
		handlers               = make(map[string]func(*multibot.TorpedoBotAPI, interface{}, string))
		lastfm_key             = flag.String("lastfm_key", "", "Last.FM API Key")
		lastfm_secret          = flag.String("lastfm_secret", "", "Last.FM API Secret")
		line_creds             = flag.String("line", "", "Line.Me credentials client_secret:client_token,")
		line_incoming_addr     = flag.String("line_incoming_addr", "0.0.0.0:3981", "Listen on this address for incoming Line.Me messages")
		pinterest_token        = flag.String("pinterest_token", "", "Pinterest Client Token")
		matrix                 = flag.String("matrix", "", "Matrix.org creds: ID:AccessToken,")
	)
	flag.Parse()
	handlers["bashim"] = BashProcessMessage
	handlers["bashorg"] = BashOrgProcessMessage
	handlers["lastfm"] = LastFmProcessMessage
	handlers["qr"] = QREncoderProcessMessage
	handlers["tinyurl"] = TinyURLProcessMessage
	// in progress
	// handlers["pinterest"] = PinterestProcessMessage
	// Help handlers
	handlers["?"] = HelpProcessMessage
	handlers["h"] = HelpProcessMessage
	handlers["help"] = HelpProcessMessage
	// Multimedia
	handlers["wiki"] = WikiProcessMessage
	handlers["youtube"] = YoutubeProcessMessage
	// in progress
	handlers["giphy"] = GiphyProcessMessage
	// Probably useless stuff
	handlers["b64e"] = CryptoProcessMessage
	handlers["b64d"] = CryptoProcessMessage
	handlers["md5"] = CryptoProcessMessage
	handlers["sha1"] = CryptoProcessMessage
	handlers["sha256"] = CryptoProcessMessage
	handlers["sha512"] = CryptoProcessMessage
	// entertainment :)
	handlers["sudo"] = FunProcessMessage
	handlers["rm"] = FunProcessMessage
	handlers["shutdown"] = FunProcessMessage
	handlers["halt"] = FunProcessMessage
	handlers["reboot"] = FunProcessMessage
	handlers["poweroff"] = FunProcessMessage
	handlers["kill"] = FunProcessMessage
	// statistics
	handlers["stats"] = StatsProcessMessage
	// File category (broken!)
	//handlers["getimg"] = GetSetImageProcessMessage
	//handlers["lsimg"] = GetSetImageProcessMessage
	//handlers["listimg"] = GetSetImageProcessMessage
	//handlers["setimg"] = GetSetImageProcessMessage
	//handlers["rmimg"] = GetSetImageProcessMessage
	// Games'n'stuff
	// needs better formatting + Facebook rework
	handlers["steam"] = SteamProcessMessage

	if *slack == "" {
		*slack = GetStripEnv("SLACK")
	}
	if *telegram == "" {
		*telegram = GetStripEnv("TELEGRAM")
	}
	if *jabber == "" {
		*jabber = GetStripEnv("JABBER")
	}
	if *skype == "" {
		*skype = GetStripEnv("SKYPE")
	}
	if *facebook == "" {
		*facebook = GetStripEnv("FACEBOOK")
	}
	if *kik == "" {
		*kik = GetStripEnv("KIK")
	}
	if *kik_webhook_url == "" {
		*kik_webhook_url = GetStripEnv("KIK_WEBHOOK_URL")
	}
	if *lastfm_key == "" {
		*lastfm_key = GetStripEnv("LASTFM_KEY")
	}
	if *lastfm_secret == "" {
		*lastfm_secret = GetStripEnv("LASTFM_SECRET")
	}
	if *line_creds == "" {
		*line_creds = GetStripEnv("LINE")
	}
	if *pinterest_token == "" {
		*pinterest_token = GetStripEnv("PINTEREST")
	}
	if *google_webapp_key == "" {
		*google_webapp_key = GetStripEnv("GOOGLE_WEBAPP_KEY")
	}
	if *matrix == "" {
		*matrix = GetStripEnv("MATRIX")
	}

	bot := multibot.New(*facebook_incoming_addr, *google_webapp_key,
		*skype_incoming_addr, *kik_incoming_addr,
		*kik_webhook_url,
		*lastfm_key, *lastfm_secret, *line_incoming_addr, *pinterest_token)
	bot.RegisterHandlers(handlers)
	//bot.RunBotsCSV(bot.RunSlackBot, *slack, "!")
	//bot.RunBotsCSV(bot.RunTelegramBot, *telegram, "/")
	bot.RunBotsCSV(bot.RunJabberBot, *jabber, "!")
	//bot.RunBotsCSV(bot.RunSkypeBot, *skype, "!")
	//bot.RunBotsCSV(bot.RunFacebookBot, *facebook, "!")
	//bot.RunBotsCSV(bot.RunKikBot, *kik, "!")
	//bot.RunBotsCSV(bot.RunLineBot, *line_creds, "!")
	//bot.RunBotsCSV(bot.RunMatrixBot, *matrix, "!")
	bot.RunLoop()
}
<commit_msg>jabber muc invite + contact list<commit_after>package main

import (
	"flag"
	"os"
	"strings"

	"torpedobot/multibot"
)

func GetStripEnv(envvar string) (result string) {
	result = os.Getenv(envvar)
	result = strings.TrimLeft(result, "'")
	result = strings.TrimRight(result, "'")
	return
}

func main() {
	var (
		slack                  = flag.String("slack", "", "Comma separated list of Slack legacy tokens")
		telegram               = flag.String("telegram", "", "Comma separated list of Telegram bot keys")
		jabber                 = flag.String("jabber", "", "Comma separated list of jabber creds, user@host.com:password,")
		skype                  = flag.String("skype", "", "Comma separated list of dev.botframework.com creds, app_id:app_password,")
		kik                    = flag.String("kik", "", "Comma separated list of Kik creds, username:api_key,")
		skype_incoming_addr    = flag.String("skype_incoming_addr", "0.0.0.0:3978", "Listen on this address for incoming Skype messages")
		facebook               = flag.String("facebook", "", "Comma separated list of Facebook creds, page_token1:verify_token1,..")
		google_webapp_key      = flag.String("google_webapp_key", "", "Google Data API Web Application Key")
		facebook_incoming_addr = flag.String("facebook_incoming_addr", "0.0.0.0:3979", "Listen on this address for incoming Facebook messages")
		kik_incoming_addr      = flag.String("kik_incoming_addr", "0.0.0.0:3980", "Listen on this address for incoming Kik messages")
		kik_webhook_url        = flag.String("kik_webhook_url", "", "Webhook URL (external) for incoming Kik messages")
		handlers               = make(map[string]func(*multibot.TorpedoBotAPI, interface{}, string))
		lastfm_key             = flag.String("lastfm_key", "", "Last.FM API Key")
		lastfm_secret          = flag.String("lastfm_secret", "", "Last.FM API Secret")
		line_creds             = flag.String("line", "", "Line.Me credentials client_secret:client_token,")
		line_incoming_addr     = flag.String("line_incoming_addr", "0.0.0.0:3981", "Listen on this address for incoming Line.Me messages")
		pinterest_token        = flag.String("pinterest_token", "", "Pinterest Client Token")
		matrix                 = flag.String("matrix", "", "Matrix.org creds: ID:AccessToken,")
	)
	flag.Parse()
	handlers["bashim"] = BashProcessMessage
	handlers["bashorg"] = BashOrgProcessMessage
	handlers["lastfm"] = LastFmProcessMessage
	handlers["qr"] = QREncoderProcessMessage
	handlers["tinyurl"] = TinyURLProcessMessage
	// in progress
	// handlers["pinterest"] = PinterestProcessMessage
	// Help handlers
	handlers["?"] = HelpProcessMessage
	handlers["h"] = HelpProcessMessage
	handlers["help"] = HelpProcessMessage
	// Multimedia
	handlers["wiki"] = WikiProcessMessage
	handlers["youtube"] = YoutubeProcessMessage
	// in progress
	handlers["giphy"] = GiphyProcessMessage
	// Probably useless stuff
	handlers["b64e"] = CryptoProcessMessage
	handlers["b64d"] = CryptoProcessMessage
	handlers["md5"] = CryptoProcessMessage
	handlers["sha1"] = CryptoProcessMessage
	handlers["sha256"] = CryptoProcessMessage
	handlers["sha512"] = CryptoProcessMessage
	// entertainment :)
	handlers["sudo"] = FunProcessMessage
	handlers["rm"] = FunProcessMessage
	handlers["shutdown"] = FunProcessMessage
	handlers["halt"] = FunProcessMessage
	handlers["reboot"] = FunProcessMessage
	handlers["poweroff"] = FunProcessMessage
	handlers["kill"] = FunProcessMessage
	// statistics
	handlers["stats"] = StatsProcessMessage
	// File category (broken!)
	//handlers["getimg"] = GetSetImageProcessMessage
	//handlers["lsimg"] = GetSetImageProcessMessage
	//handlers["listimg"] = GetSetImageProcessMessage
	//handlers["setimg"] = GetSetImageProcessMessage
	//handlers["rmimg"] = GetSetImageProcessMessage
	// Games'n'stuff
	// needs better formatting + Facebook rework
	handlers["steam"] = SteamProcessMessage

	if *slack == "" {
		*slack = GetStripEnv("SLACK")
	}
	if *telegram == "" {
		*telegram = GetStripEnv("TELEGRAM")
	}
	if *jabber == "" {
		*jabber = GetStripEnv("JABBER")
	}
	if *skype == "" {
		*skype = GetStripEnv("SKYPE")
	}
	if *facebook == "" {
		*facebook = GetStripEnv("FACEBOOK")
	}
	if *kik == "" {
		*kik = GetStripEnv("KIK")
	}
	if *kik_webhook_url == "" {
		*kik_webhook_url = GetStripEnv("KIK_WEBHOOK_URL")
	}
	if *lastfm_key == "" {
		*lastfm_key = GetStripEnv("LASTFM_KEY")
	}
	if *lastfm_secret == "" {
		*lastfm_secret = GetStripEnv("LASTFM_SECRET")
	}
	if *line_creds == "" {
		*line_creds = GetStripEnv("LINE")
	}
	if *pinterest_token == "" {
		*pinterest_token = GetStripEnv("PINTEREST")
	}
	if *google_webapp_key == "" {
		*google_webapp_key = GetStripEnv("GOOGLE_WEBAPP_KEY")
	}
	if *matrix == "" {
		*matrix = GetStripEnv("MATRIX")
	}

	bot := multibot.New(*facebook_incoming_addr, *google_webapp_key,
		*skype_incoming_addr, *kik_incoming_addr,
		*kik_webhook_url,
		*lastfm_key, *lastfm_secret, *line_incoming_addr, *pinterest_token)
	bot.RegisterHandlers(handlers)
	bot.RunBotsCSV(bot.RunSlackBot, *slack, "!")
	bot.RunBotsCSV(bot.RunTelegramBot, *telegram, "/")
	bot.RunBotsCSV(bot.RunJabberBot, *jabber, "!")
	bot.RunBotsCSV(bot.RunSkypeBot, *skype, "!")
	bot.RunBotsCSV(bot.RunFacebookBot, *facebook, "!")
	bot.RunBotsCSV(bot.RunKikBot, *kik, "!")
	bot.RunBotsCSV(bot.RunLineBot, *line_creds, "!")
	bot.RunBotsCSV(bot.RunMatrixBot, *matrix, "!")
	bot.RunLoop()
}
<|endoftext|>


<commit_before>package trdsql

import (
	"bufio"
	"errors"
	"io"
	"strings"
)

// LTSVReader provides methods of the Reader interface
type LTSVReader struct {
	reader    *bufio.Reader
	preRead   []map[string]string
	delimiter string
	names     []string
	types     []string
}

// NewLTSVReader returns LTSVReader and error.
func NewLTSVReader(reader io.Reader, opts *ReadOpts) (*LTSVReader, error) {
	r := &LTSVReader{}
	r.reader = bufio.NewReader(reader)
	r.delimiter = "\t"

	if opts.InSkip > 0 {
		skipRead(r, opts.InSkip)
	}

	names := map[string]bool{}
	for i := 0; i < opts.InPreRead; i++ {
		row, keys, err := r.read()
		if err != nil {
			if err != io.EOF {
				return r, err
			}
			r.setColumnType()
			return r, nil
		}

		// Add only unique column names.
		for k := 0; k < len(keys); k++ {
			if !names[keys[k]] {
				names[keys[k]] = true
				r.names = append(r.names, keys[k])
			}
		}
		r.preRead = append(r.preRead, row)
	}
	r.setColumnType()
	return r, nil
}

func (r *LTSVReader) setColumnType() {
	if r.names == nil {
		return
	}
	r.types = make([]string, len(r.names))
	for i := 0; i < len(r.names); i++ {
		r.types[i] = DefaultDBType
	}
}

// Names returns column names.
func (r *LTSVReader) Names() ([]string, error) {
	return r.names, nil
}

// Types returns column types.
// All LTSV types return the DefaultDBType.
func (r *LTSVReader) Types() ([]string, error) {
	return r.types, nil
}

// PreReadRow is returns only columns that store preread rows.
func (r *LTSVReader) PreReadRow() [][]interface{} {
	rowNum := len(r.preRead)
	rows := make([][]interface{}, rowNum)
	for n := 0; n < rowNum; n++ {
		rows[n] = make([]interface{}, len(r.names))
		for i := range r.names {
			rows[n][i] = r.preRead[n][r.names[i]]
		}
	}
	return rows
}

// ReadRow is read the rest of the row.
func (r *LTSVReader) ReadRow(row []interface{}) ([]interface{}, error) {
	record, _, err := r.read()
	if err != nil {
		return row, err
	}
	for i, name := range r.names {
		row[i] = record[name]
	}
	return row, nil
}

func (r *LTSVReader) read() (map[string]string, []string, error) {
	line, err := r.readline()
	if err != nil {
		return nil, nil, err
	}
	columns := strings.Split(line, r.delimiter)
	lvs := make(map[string]string)
	keys := make([]string, 0, len(columns))
	for _, column := range columns {
		kv := strings.SplitN(column, ":", 2)
		if len(kv) != 2 {
			return nil, nil, errors.New("invalid column")
		}
		lvs[kv[0]] = kv[1]
		keys = append(keys, kv[0])
	}
	return lvs, keys, nil
}

func (r *LTSVReader) readline() (string, error) {
	for {
		line, _, err := r.reader.ReadLine()
		if err != nil {
			return "", err
		}
		str := strings.TrimSpace(string(line))
		if len(str) != 0 {
			return str, nil
		}
	}
}
<commit_msg>Supported long line of LTSV<commit_after>package trdsql

import (
	"bufio"
	"errors"
	"io"
	"strings"
)

// LTSVReader provides methods of the Reader interface
type LTSVReader struct {
	reader    *bufio.Reader
	preRead   []map[string]string
	delimiter string
	names     []string
	types     []string
}

// NewLTSVReader returns LTSVReader and error.
func NewLTSVReader(reader io.Reader, opts *ReadOpts) (*LTSVReader, error) {
	r := &LTSVReader{}
	r.reader = bufio.NewReader(reader)
	r.delimiter = "\t"

	if opts.InSkip > 0 {
		skipRead(r, opts.InSkip)
	}

	names := map[string]bool{}
	for i := 0; i < opts.InPreRead; i++ {
		row, keys, err := r.read()
		if err != nil {
			if err != io.EOF {
				return r, err
			}
			r.setColumnType()
			return r, nil
		}

		// Add only unique column names.
		for k := 0; k < len(keys); k++ {
			if !names[keys[k]] {
				names[keys[k]] = true
				r.names = append(r.names, keys[k])
			}
		}
		r.preRead = append(r.preRead, row)
	}
	r.setColumnType()
	return r, nil
}

func (r *LTSVReader) setColumnType() {
	if r.names == nil {
		return
	}
	r.types = make([]string, len(r.names))
	for i := 0; i < len(r.names); i++ {
		r.types[i] = DefaultDBType
	}
}

// Names returns column names.
func (r *LTSVReader) Names() ([]string, error) {
	return r.names, nil
}

// Types returns column types.
// All LTSV types return the DefaultDBType.
func (r *LTSVReader) Types() ([]string, error) {
	return r.types, nil
}

// PreReadRow is returns only columns that store preread rows.
func (r *LTSVReader) PreReadRow() [][]interface{} {
	rowNum := len(r.preRead)
	rows := make([][]interface{}, rowNum)
	for n := 0; n < rowNum; n++ {
		rows[n] = make([]interface{}, len(r.names))
		for i := range r.names {
			rows[n][i] = r.preRead[n][r.names[i]]
		}
	}
	return rows
}

// ReadRow is read the rest of the row.
func (r *LTSVReader) ReadRow(row []interface{}) ([]interface{}, error) {
	record, _, err := r.read()
	if err != nil {
		return row, err
	}
	for i, name := range r.names {
		row[i] = record[name]
	}
	return row, nil
}

func (r *LTSVReader) read() (map[string]string, []string, error) {
	line, err := r.readline()
	if err != nil {
		return nil, nil, err
	}
	columns := strings.Split(line, r.delimiter)
	lvs := make(map[string]string)
	keys := make([]string, 0, len(columns))
	for _, column := range columns {
		kv := strings.SplitN(column, ":", 2)
		if len(kv) != 2 {
			return nil, nil, errors.New("invalid column")
		}
		lvs[kv[0]] = kv[1]
		keys = append(keys, kv[0])
	}
	return lvs, keys, nil
}

func (r *LTSVReader) readline() (string, error) {
	var buffer []byte
	for {
		for {
			line, isPrefix, err := r.reader.ReadLine()
			if err != nil {
				return "", err
			}
			buffer = append(buffer, line...)
			if !isPrefix {
				break
			}
		}
		str := strings.TrimSpace(string(buffer))
		if len(str) != 0 {
			return str, nil
		}
	}
}
<|endoftext|>


<commit_before>package user_printer

import (
	"fmt"

	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/cloudfoundry/cli/plugin/models"
)

type UserPrinter interface {
	PrintUsers(guid string, username string)
}

type SpaceUsersPluginPrinter struct {
	UserPrinter
	Roles       []string
	UserLister  func(spaceGuid string, role string) ([]models.UserFields, error)
	PluginModel *[]plugin_models.GetSpaceUsers_Model
	users       users
}

type SpaceUsersUiPrinter struct {
	UserPrinter
	Ui               terminal.UI
	UserLister       func(spaceGuid string, role string) ([]models.UserFields, error)
	Roles            []string
	RoleDisplayNames map[string]string
}

type OrgUsersPluginPrinter struct {
	UserPrinter
	Roles       []string
	UserLister  func(orgGuid string, role string) ([]models.UserFields, error)
	PluginModel *[]plugin_models.GetOrgUsers_Model
	users       users
}

type OrgUsersUiPrinter struct {
	UserPrinter
	Roles            []string
	RoleDisplayNames map[string]string
	UserLister       func(orgGuid string, role string) ([]models.UserFields, error)
	Ui               terminal.UI
}

type userWithRoles struct {
	models.UserFields
	Roles []string
}

type users struct {
	db map[string]userWithRoles
}

func NewOrgUsersPluginPrinter(
	pluginModel *[]plugin_models.GetOrgUsers_Model,
	userLister func(orgGuid string, role string) ([]models.UserFields, error),
	roles []string,
) (printer *OrgUsersPluginPrinter) {
	return &OrgUsersPluginPrinter{
		PluginModel: pluginModel,
		users:       users{db: make(map[string]userWithRoles)},
		UserLister:  userLister,
		Roles:       roles,
	}
}

func NewSpaceUsersPluginPrinter(
	pluginModel *[]plugin_models.GetSpaceUsers_Model,
	userLister func(orgGuid string, role string) ([]models.UserFields, error),
	roles []string,
) (printer *SpaceUsersPluginPrinter) {
	return &SpaceUsersPluginPrinter{
		PluginModel: pluginModel,
		users:       users{db: make(map[string]userWithRoles)},
		UserLister:  userLister,
		Roles:       roles,
	}
}

func (p *OrgUsersPluginPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		users, _ := p.UserLister(guid, role)
		for _, user := range users {
			p.users.StoreAppendingRole(role, user.Username, user.Guid, user.IsAdmin)
		}
	}
	*(p.PluginModel) = p.users.AsOrgUsers()
}

func (p *SpaceUsersPluginPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		users, _ := p.UserLister(guid, role)
		for _, user := range users {
			p.users.StoreAppendingRole(role, user.Username, user.Guid, user.IsAdmin)
		}
	}
	*(p.PluginModel) = p.users.AsSpaceUsers()
}

func (p *OrgUsersUiPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		displayName := p.RoleDisplayNames[role]
		users, err := p.UserLister(guid, role)
		if err != nil {
			p.Ui.Failed(T("Failed fetching org-users for role {{.OrgRoleToDisplayName}}.\n{{.Error}}",
				map[string]interface{}{
					"Error":                err.Error(),
					"OrgRoleToDisplayName": displayName,
				}))
			return
		}
		p.Ui.Say("")
		p.Ui.Say("%s", terminal.HeaderColor(displayName))

		if len(users) == 0 {
			p.Ui.Say(fmt.Sprintf("  "+T("No %s found"), displayName))
		} else {
			for _, user := range users {
				p.Ui.Say("  %s", user.Username)
			}
		}
	}
}

func (p *SpaceUsersUiPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		displayName := p.RoleDisplayNames[role]
		users, err := p.UserLister(guid, role)
		if err != nil {
			p.Ui.Failed(T("Failed fetching space-users for role {{.SpaceRoleToDisplayName}}.\n{{.Error}}",
				map[string]interface{}{
					"Error":                  err.Error(),
					"SpaceRoleToDisplayName": displayName,
				}))
			return
		}
		p.Ui.Say("")
		p.Ui.Say("%s", terminal.HeaderColor(displayName))

		if len(users) == 0 {
			p.Ui.Say(fmt.Sprintf("  "+T("No %s found"), displayName))
		} else {
			for _, user := range users {
				p.Ui.Say("  %s", user.Username)
			}
		}
	}
}

func (c *users) StoreAppendingRole(role string, username string, guid string, isAdmin bool) {
	u := c.db[username]
	u.Roles = append(u.Roles, role)
	u.Username = username
	u.Guid = guid
	u.IsAdmin = isAdmin
	c.db[username] = u
}

func (c *users) AsOrgUsers() (coll []plugin_models.GetOrgUsers_Model) {
	for _, u := range c.db {
		coll = append(coll, plugin_models.GetOrgUsers_Model{
			Guid:     u.Guid,
			Username: u.Username,
			IsAdmin:  u.IsAdmin,
			Roles:    u.Roles,
		})
	}
	return coll
}

func (c *users) AsSpaceUsers() (coll []plugin_models.GetSpaceUsers_Model) {
	for _, u := range c.db {
		coll = append(coll, plugin_models.GetSpaceUsers_Model{
			Guid:     u.Guid,
			Username: u.Username,
			IsAdmin:  u.IsAdmin,
			Roles:    u.Roles,
		})
	}
	return coll
}
<commit_msg>Shuffle and correct stuff<commit_after>package user_printer

import (
	"fmt"

	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/cloudfoundry/cli/plugin/models"
)

type UserPrinter interface {
	PrintUsers(guid string, username string)
}

type SpaceUsersPluginPrinter struct {
	UserPrinter
	Roles       []string
	UserLister  func(spaceGuid string, role string) ([]models.UserFields, error)
	PluginModel *[]plugin_models.GetSpaceUsers_Model
	users       users
}

type OrgUsersPluginPrinter struct {
	UserPrinter
	Roles       []string
	UserLister  func(orgGuid string, role string) ([]models.UserFields, error)
	PluginModel *[]plugin_models.GetOrgUsers_Model
	users       users
}

type SpaceUsersUiPrinter struct {
	UserPrinter
	Ui               terminal.UI
	UserLister       func(spaceGuid string, role string) ([]models.UserFields, error)
	Roles            []string
	RoleDisplayNames map[string]string
}

type OrgUsersUiPrinter struct {
	UserPrinter
	Roles            []string
	RoleDisplayNames map[string]string
	UserLister       func(orgGuid string, role string) ([]models.UserFields, error)
	Ui               terminal.UI
}

type userWithRoles struct {
	models.UserFields
	Roles []string
}

type users struct {
	db map[string]userWithRoles
}

func NewOrgUsersPluginPrinter(
	pluginModel *[]plugin_models.GetOrgUsers_Model,
	userLister func(guid string, role string) ([]models.UserFields, error),
	roles []string,
) (printer *OrgUsersPluginPrinter) {
	return &OrgUsersPluginPrinter{
		PluginModel: pluginModel,
		users:       users{db: make(map[string]userWithRoles)},
		UserLister:  userLister,
		Roles:       roles,
	}
}

func NewSpaceUsersPluginPrinter(
	pluginModel *[]plugin_models.GetSpaceUsers_Model,
	userLister func(guid string, role string) ([]models.UserFields, error),
	roles []string,
) (printer *SpaceUsersPluginPrinter) {
	return &SpaceUsersPluginPrinter{
		PluginModel: pluginModel,
		users:       users{db: make(map[string]userWithRoles)},
		UserLister:  userLister,
		Roles:       roles,
	}
}

func (p *OrgUsersPluginPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		users, _ := p.UserLister(guid, role)
		for _, user := range users {
			p.users.StoreAppendingRole(role, user.Username, user.Guid, user.IsAdmin)
		}
	}
	*(p.PluginModel) = p.users.AsOrgUsers()
}

func (p *SpaceUsersPluginPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		users, _ := p.UserLister(guid, role)
		for _, user := range users {
			p.users.StoreAppendingRole(role, user.Username, user.Guid, user.IsAdmin)
		}
	}
	*(p.PluginModel) = p.users.AsSpaceUsers()
}

func (p *OrgUsersUiPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		displayName := p.RoleDisplayNames[role]
		users, err := p.UserLister(guid, role)
		if err != nil {
			p.Ui.Failed(T("Failed fetching org-users for role {{.OrgRoleToDisplayName}}.\n{{.Error}}",
				map[string]interface{}{
					"Error":                err.Error(),
					"OrgRoleToDisplayName": displayName,
				}))
			return
		}
		p.Ui.Say("")
		p.Ui.Say("%s", terminal.HeaderColor(displayName))

		if len(users) == 0 {
			p.Ui.Say(fmt.Sprintf("  "+T("No %s found"), displayName))
		} else {
			for _, user := range users {
				p.Ui.Say("  %s", user.Username)
			}
		}
	}
}

func (p *SpaceUsersUiPrinter) PrintUsers(guid string, username string) {
	for _, role := range p.Roles {
		displayName := p.RoleDisplayNames[role]
		users, err := p.UserLister(guid, role)
		if err != nil {
			p.Ui.Failed(T("Failed fetching space-users for role {{.SpaceRoleToDisplayName}}.\n{{.Error}}",
				map[string]interface{}{
					"Error":                  err.Error(),
					"SpaceRoleToDisplayName": displayName,
				}))
			return
		}
		p.Ui.Say("")
		p.Ui.Say("%s", terminal.HeaderColor(displayName))

		if len(users) == 0 {
			p.Ui.Say(fmt.Sprintf("  "+T("No %s found"), displayName))
		} else {
			for _, user := range users {
				p.Ui.Say("  %s", user.Username)
			}
		}
	}
}

func (c *users) StoreAppendingRole(role string, username string, guid string, isAdmin bool) {
	u := c.db[username]
	u.Roles = append(u.Roles, role)
	u.Username = username
	u.Guid = guid
	u.IsAdmin = isAdmin
	c.db[username] = u
}

func (c *users) AsOrgUsers() (coll []plugin_models.GetOrgUsers_Model) {
	for _, u := range c.db {
		coll = append(coll, plugin_models.GetOrgUsers_Model{
			Guid:     u.Guid,
			Username: u.Username,
			IsAdmin:  u.IsAdmin,
			Roles:    u.Roles,
		})
	}
	return coll
}

func (c *users) AsSpaceUsers() (coll []plugin_models.GetSpaceUsers_Model) {
	for _, u := range c.db {
		coll = append(coll, plugin_models.GetSpaceUsers_Model{
			Guid:     u.Guid,
			Username: u.Username,
			IsAdmin:  u.IsAdmin,
			Roles:    u.Roles,
		})
	}
	return coll
}
<|endoftext|>