<commit_before>package g

import "path/filepath"

var Modules map[string]bool
var BinOf map[string]string
var cfgOf map[string]string
var ModuleApps map[string]string
var logpathOf map[string]string
var PidOf map[string]string
var AllModulesInOrder []string

func init() {
	//	dirs, _ := ioutil.ReadDir("./modules")
	//	for _, dir := range dirs {
	//		Modules[dir.Name()] = true
	//	}
	Modules = map[string]bool{
		"agent":      true,
		"nqm-agent":  true,
		"aggregator": true,
		"alarm":      true,
		"fe":         true,
		"graph":      true,
		"hbs":        true,
		"judge":      true,
		"nodata":     true,
		"query":      true,
		"sender":     true,
		"task":       true,
		"transfer":   true,
	}

	BinOf = map[string]string{
		"agent":      "./agent/bin/falcon-agent",
		"nqm-agent":  "./agent/bin/falcon-nqm-agent",
		"aggregator": "./aggregator/bin/falcon-aggregator",
		"alarm":      "./alarm/bin/falcon-alarm",
		"fe":         "./fe/bin/falcon-fe",
		"graph":      "./graph/bin/falcon-graph",
		"hbs":        "./hbs/bin/falcon-hbs",
		"judge":      "./judge/bin/falcon-judge",
		"nodata":     "./nodata/bin/falcon-nodata",
		"query":      "./query/bin/falcon-query",
		"sender":     "./sender/bin/falcon-sender",
		"task":       "./task/bin/falcon-task",
		"transfer":   "./transfer/bin/falcon-transfer",
	}

	cfgOf = map[string]string{
		"agent":      "./agent/config/cfg.json",
		"nqm-agent":  "./nqm-agent/config/cfg.json",
		"aggregator": "./aggregator/config/cfg.json",
		"alarm":      "./alarm/config/cfg.json",
		"fe":         "./fe/config/cfg.json",
		"graph":      "./graph/config/cfg.json",
		"hbs":        "./hbs/config/cfg.json",
		"judge":      "./judge/config/cfg.json",
		"nodata":     "./nodata/config/cfg.json",
		"query":      "./query/config/cfg.json",
		"sender":     "./sender/config/cfg.json",
		"task":       "./task/config/cfg.json",
		"transfer":   "./transfer/config/cfg.json",
	}

	ModuleApps = map[string]string{
		"agent":      "falcon-agent",
		"nqm-agent":  "falcon-nqm-agent",
		"aggregator": "falcon-aggregator",
		"alarm":      "falcon-alarm",
		"graph":      "falcon-graph",
		"fe":         "falcon-fe",
		"hbs":        "falcon-hbs",
		"judge":      "falcon-judge",
		"nodata":     "falcon-nodata",
		"query":      "falcon-query",
		"sender":     "falcon-sender",
		"task":       "falcon-task",
		"transfer":   "falcon-transfer",
	}

	logpathOf = map[string]string{
		"agent":      "./agent/logs/agent.log",
		"nqm-agent":  "./nqm-agent/logs/nqm-agent.log",
		"aggregator": "./aggregator/logs/aggregator.log",
		"alarm":      "./alarm/logs/alarm.log",
		"fe":         "./fe/logs/fe.log",
		"graph":      "./graph/logs/graph.log",
		"hbs":        "./hbs/logs/hbs.log",
		"judge":      "./judge/logs/judge.log",
		"nodata":     "./nodata/logs/nodata.log",
		"query":      "./query/logs/query.log",
		"sender":     "./sender/logs/sender.log",
		"task":       "./task/logs/task.log",
		"transfer":   "./transfer/logs/transfer.log",
	}

	PidOf = map[string]string{
		"agent":      "<NOT SET>",
		"nqm-agent":  "<NOT SET>",
		"aggregator": "<NOT SET>",
		"alarm":      "<NOT SET>",
		"graph":      "<NOT SET>",
		"fe":         "<NOT SET>",
		"hbs":        "<NOT SET>",
		"judge":      "<NOT SET>",
		"nodata":     "<NOT SET>",
		"query":      "<NOT SET>",
		"sender":     "<NOT SET>",
		"task":       "<NOT SET>",
		"transfer":   "<NOT SET>",
	}

	// Modules are deployed in this order
	AllModulesInOrder = []string{
		"graph",
		"hbs",
		"fe",
		"alarm",
		"sender",
		"query",
		"judge",
		"transfer",
		"nodata",
		"task",
		"aggregator",
		"agent",
	}
}

func Bin(name string) string {
	p, _ := filepath.Abs(BinOf[name])
	return p
}

func Cfg(name string) string {
	p, _ := filepath.Abs(cfgOf[name])
	return p
}

func LogPath(name string) string {
	p, _ := filepath.Abs(logpathOf[name])
	return p
}

func LogDir(name string) string {
	d, _ := filepath.Abs(filepath.Dir(logpathOf[name]))
	return d
}
<commit_msg>[OWL-999][backend] Support nqm-agent in the order<commit_after>package g

import "path/filepath"

var Modules map[string]bool
var BinOf map[string]string
var cfgOf map[string]string
var ModuleApps map[string]string
var logpathOf map[string]string
var PidOf map[string]string
var AllModulesInOrder []string

func init() {
	//	dirs, _ := ioutil.ReadDir("./modules")
	//	for _, dir := range dirs {
	//		Modules[dir.Name()] = true
	//	}
	Modules = map[string]bool{
		"agent":      true,
		"nqm-agent":  true,
		"aggregator": true,
		"alarm":      true,
		"fe":         true,
		"graph":      true,
		"hbs":        true,
		"judge":      true,
		"nodata":     true,
		"query":      true,
		"sender":     true,
		"task":       true,
		"transfer":   true,
	}

	BinOf = map[string]string{
		"agent":      "./agent/bin/falcon-agent",
		"nqm-agent":  "./agent/bin/falcon-nqm-agent",
		"aggregator": "./aggregator/bin/falcon-aggregator",
		"alarm":      "./alarm/bin/falcon-alarm",
		"fe":         "./fe/bin/falcon-fe",
		"graph":      "./graph/bin/falcon-graph",
		"hbs":        "./hbs/bin/falcon-hbs",
		"judge":      "./judge/bin/falcon-judge",
		"nodata":     "./nodata/bin/falcon-nodata",
		"query":      "./query/bin/falcon-query",
		"sender":     "./sender/bin/falcon-sender",
		"task":       "./task/bin/falcon-task",
		"transfer":   "./transfer/bin/falcon-transfer",
	}

	cfgOf = map[string]string{
		"agent":      "./agent/config/cfg.json",
		"nqm-agent":  "./nqm-agent/config/cfg.json",
		"aggregator": "./aggregator/config/cfg.json",
		"alarm":      "./alarm/config/cfg.json",
		"fe":         "./fe/config/cfg.json",
		"graph":      "./graph/config/cfg.json",
		"hbs":        "./hbs/config/cfg.json",
		"judge":      "./judge/config/cfg.json",
		"nodata":     "./nodata/config/cfg.json",
		"query":      "./query/config/cfg.json",
		"sender":     "./sender/config/cfg.json",
		"task":       "./task/config/cfg.json",
		"transfer":   "./transfer/config/cfg.json",
	}

	ModuleApps = map[string]string{
		"agent":      "falcon-agent",
		"nqm-agent":  "falcon-nqm-agent",
		"aggregator": "falcon-aggregator",
		"alarm":      "falcon-alarm",
		"graph":      "falcon-graph",
		"fe":         "falcon-fe",
		"hbs":        "falcon-hbs",
		"judge":      "falcon-judge",
		"nodata":     "falcon-nodata",
		"query":      "falcon-query",
		"sender":     "falcon-sender",
		"task":       "falcon-task",
		"transfer":   "falcon-transfer",
	}

	logpathOf = map[string]string{
		"agent":      "./agent/logs/agent.log",
		"nqm-agent":  "./nqm-agent/logs/nqm-agent.log",
		"aggregator": "./aggregator/logs/aggregator.log",
		"alarm":      "./alarm/logs/alarm.log",
		"fe":         "./fe/logs/fe.log",
		"graph":      "./graph/logs/graph.log",
		"hbs":        "./hbs/logs/hbs.log",
		"judge":      "./judge/logs/judge.log",
		"nodata":     "./nodata/logs/nodata.log",
		"query":      "./query/logs/query.log",
		"sender":     "./sender/logs/sender.log",
		"task":       "./task/logs/task.log",
		"transfer":   "./transfer/logs/transfer.log",
	}

	PidOf = map[string]string{
		"agent":      "<NOT SET>",
		"nqm-agent":  "<NOT SET>",
		"aggregator": "<NOT SET>",
		"alarm":      "<NOT SET>",
		"graph":      "<NOT SET>",
		"fe":         "<NOT SET>",
		"hbs":        "<NOT SET>",
		"judge":      "<NOT SET>",
		"nodata":     "<NOT SET>",
		"query":      "<NOT SET>",
		"sender":     "<NOT SET>",
		"task":       "<NOT SET>",
		"transfer":   "<NOT SET>",
	}

	// Modules are deployed in this order
	AllModulesInOrder = []string{
		"graph",
		"hbs",
		"fe",
		"alarm",
		"sender",
		"query",
		"judge",
		"transfer",
		"nodata",
		"task",
		"aggregator",
		"agent",
		"nqm-agent",
	}
}

func Bin(name string) string {
	p, _ := filepath.Abs(BinOf[name])
	return p
}

func Cfg(name string) string {
	p, _ := filepath.Abs(cfgOf[name])
	return p
}

func LogPath(name string) string {
	p, _ := filepath.Abs(logpathOf[name])
	return p
}

func LogDir(name string) string {
	d, _ := filepath.Abs(filepath.Dir(logpathOf[name]))
	return d
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

var toolPaths = []string{
	"golang.org/x/tools/cmd/goimports",
	"github.com/golang/lint/golint",
}

func getTools(verbose bool) error {
	for _, tool := range toolPaths {
		if err := getTool(tool, verbose); err != nil {
			return err
		}
	}
	return nil
}

func getTool(tool string, verbose bool) error {
	args := []string{"get"}
	if verbose {
		args = append(args, "-v")
	}
	args = append(args, tool)
	if verbose {
		fmt.Println("go", strings.Join(args, " "))
	}
	cmd := exec.Command("go", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<commit_msg>adjust path<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

var toolPaths = []string{
	"golang.org/x/lint/golint",
	"golang.org/x/tools/cmd/goimports",
}

func getTools(verbose bool) error {
	for _, tool := range toolPaths {
		if err := getTool(tool, verbose); err != nil {
			return err
		}
	}
	return nil
}

func getTool(tool string, verbose bool) error {
	args := []string{"get"}
	if verbose {
		args = append(args, "-v")
	}
	args = append(args, tool)
	if verbose {
		fmt.Println("go", strings.Join(args, " "))
	}
	cmd := exec.Command("go", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<|endoftext|>


<commit_before>package web

import (
	"fmt"
	"mime"
	"net/http"
	"path"

	"golang.org/x/net/context"
	"golang.org/x/net/context/ctxhttp"

	"github.com/omeid/gonzo"
)

func get(ctx context.Context, client *http.Client, url string) (gonzo.File, error) {

	resp, err := ctxhttp.Get(ctx, client, url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode < 200 || resp.StatusCode > 399 {
		return nil, fmt.Errorf("%s (%s)", resp.Status, url)
	}

	_, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition"))
	name, ok := params["filename"]
	if !ok || err != nil {
		name = path.Base(url)
	}

	file := gonzo.NewFile(resp.Body, gonzo.NewFileInfo())
	file.FileInfo().SetName(name)
	file.FileInfo().SetSize(resp.ContentLength)

	return file, nil
}
<commit_msg>use context instead of x/net/context<commit_after>package web

import (
	"fmt"
	"mime"
	"net/http"
	"path"

	"context"

	"github.com/omeid/gonzo"
)

func get(ctx context.Context, client *http.Client, url string) (gonzo.File, error) {

	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		return nil, err
	}

	req = req.WithContext(ctx)

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

	if resp.StatusCode < 200 || resp.StatusCode > 399 {
		return nil, fmt.Errorf("%s (%s)", resp.Status, url)
	}

	_, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition"))
	name, ok := params["filename"]
	if !ok || err != nil {
		name = path.Base(url)
	}

	file := gonzo.NewFile(resp.Body, gonzo.NewFileInfo())
	file.FileInfo().SetName(name)
	file.FileInfo().SetSize(resp.ContentLength)

	return file, nil
}
<|endoftext|>


<commit_before>package gin

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/julienschmidt/httprouter"
	"html/template"
	"log"
	"math"
	"net/http"
	"path"
)

const (
	AbortIndex = math.MaxInt8 / 2
)

type (
	HandlerFunc func(*Context)

	H map[string]interface{}

	// Used internally to collect a error ocurred during a http request.
	ErrorMsg struct {
		Err  string      `json:"error"`
		Meta interface{} `json:"meta"`
	}

	ErrorMsgs []ErrorMsg

	// Context is the most important part of gin. It allows us to pass variables between middleware,
	// manage the flow, validate the JSON of a request and render a JSON response for example.
	Context struct {
		Req      *http.Request
		Writer   http.ResponseWriter
		Keys     map[string]interface{}
		Errors   ErrorMsgs
		Params   httprouter.Params
		handlers []HandlerFunc
		engine   *Engine
		index    int8
	}

	// Used internally to configure router, a RouterGroup is associated with a prefix
	// and an array of handlers (middlewares)
	RouterGroup struct {
		Handlers []HandlerFunc
		prefix   string
		parent   *RouterGroup
		engine   *Engine
	}

	// Represents the web framework, it wrappers the blazing fast httprouter multiplexer and a list of global middlewares.
	Engine struct {
		*RouterGroup
		handlers404   []HandlerFunc
		router        *httprouter.Router
		HTMLTemplates *template.Template
	}
)

func (a ErrorMsgs) String() string {
	var buffer bytes.Buffer
	for i, msg := range a {
		text := fmt.Sprintf("Error #%02d: %s \n     Meta: %v\n\n", (i + 1), msg.Err, msg.Meta)
		buffer.WriteString(text)
	}
	return buffer.String()
}

// Returns a new blank Engine instance without any middleware attached.
// The most basic configuration
func New() *Engine {
	engine := &Engine{}
	engine.RouterGroup = &RouterGroup{nil, "/", nil, engine}
	engine.router = httprouter.New()
	engine.router.NotFound = engine.handle404
	return engine
}

// Returns a Engine instance with the Logger and Recovery already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) LoadHTMLTemplates(pattern string) {
	engine.HTMLTemplates = template.Must(template.ParseGlob(pattern))
}

// Adds handlers for NotFound. It return a 404 code by default.
func (engine *Engine) NotFound404(handlers ...HandlerFunc) {
	engine.handlers404 = handlers
}

func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
	handlers := engine.combineHandlers(engine.handlers404)
	c := engine.createContext(w, req, nil, handlers)
	if engine.handlers404 == nil {
		http.NotFound(c.Writer, c.Req)
	} else {
		c.Writer.WriteHeader(404)
	}

	c.Next()
}

// ServeFiles serves files from the given file system root.
// The path must end with "/*filepath", files are then served from the local
// path /defined/root/dir/*filepath.
// For example if root is "/etc" and *filepath is "passwd", the local file
// "/etc/passwd" would be served.
// Internally a http.FileServer is used, therefore http.NotFound is used instead
// of the Router's NotFound handler.
// To use the operating system's file system implementation,
// use http.Dir:
//     router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
func (engine *Engine) ServeFiles(path string, root http.FileSystem) {
	engine.router.ServeFiles(path, root)
}

// ServeHTTP makes the router implement the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	engine.router.ServeHTTP(w, req)
}

func (engine *Engine) Run(addr string) {
	http.ListenAndServe(addr, engine)
}

/************************************/
/********** ROUTES GROUPING *********/
/************************************/

func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
	return &Context{
		Writer:   w,
		Req:      req,
		index:    -1,
		engine:   group.engine,
		Params:   params,
		handlers: handlers,
	}
}

// Adds middlewares to the group, see example code in github.
func (group *RouterGroup) Use(middlewares ...HandlerFunc) {
	group.Handlers = append(group.Handlers, middlewares...)
}

// Greates a new router group. You should create add all the routes that share that have common middlwares or same path prefix.
// For example, all the routes that use a common middlware for authorization could be grouped.
func (group *RouterGroup) Group(component string, handlers ...HandlerFunc) *RouterGroup {
	prefix := path.Join(group.prefix, component)
	return &RouterGroup{
		Handlers: group.combineHandlers(handlers),
		parent:   group,
		prefix:   prefix,
		engine:   group.engine,
	}
}

// Handle registers a new request handle and middlewares with the given path and method.
// The last handler should be the real handler, the other ones should be middlewares that can and should be shared among different routes.
// See the example code in github.
//
// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut
// functions can be used.
//
// This function is intended for bulk loading and to allow the usage of less
// frequently used, non-standardized or custom methods (e.g. for internal
// communication with a proxy).
func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
	p = path.Join(group.prefix, p)
	handlers = group.combineHandlers(handlers)
	group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
		group.createContext(w, req, params, handlers).Next()
	})
}

// POST is a shortcut for router.Handle("POST", path, handle)
func (group *RouterGroup) POST(path string, handlers ...HandlerFunc) {
	group.Handle("POST", path, handlers)
}

// GET is a shortcut for router.Handle("GET", path, handle)
func (group *RouterGroup) GET(path string, handlers ...HandlerFunc) {
	group.Handle("GET", path, handlers)
}

// DELETE is a shortcut for router.Handle("DELETE", path, handle)
func (group *RouterGroup) DELETE(path string, handlers ...HandlerFunc) {
	group.Handle("DELETE", path, handlers)
}

// PATCH is a shortcut for router.Handle("PATCH", path, handle)
func (group *RouterGroup) PATCH(path string, handlers ...HandlerFunc) {
	group.Handle("PATCH", path, handlers)
}

// PUT is a shortcut for router.Handle("PUT", path, handle)
func (group *RouterGroup) PUT(path string, handlers ...HandlerFunc) {
	group.Handle("PUT", path, handlers)
}

func (group *RouterGroup) combineHandlers(handlers []HandlerFunc) []HandlerFunc {
	s := len(group.Handlers) + len(handlers)
	h := make([]HandlerFunc, 0, s)
	h = append(h, group.Handlers...)
	h = append(h, handlers...)
	return h
}

/************************************/
/****** FLOW AND ERROR MANAGEMENT****/
/************************************/

// Next should be used only in the middlewares.
// It executes the pending handlers in the chain inside the calling handler.
// See example in github.
func (c *Context) Next() {
	c.index++
	s := int8(len(c.handlers))
	for ; c.index < s; c.index++ {
		c.handlers[c.index](c)
	}
}

// Forces the system to do not continue calling the pending handlers.
// For example, the first handler checks if the request is authorized. If it's not, context.Abort(401) should be called.
// The rest of pending handlers would never be called for that request.
func (c *Context) Abort(code int) {
	c.Writer.WriteHeader(code)
	c.index = AbortIndex
}

// Fail is the same than Abort plus an error message.
// Calling `context.Fail(500, err)` is equivalent to:
// ```
// context.Error("Operation aborted", err)
// context.Abort(500)
// ```
func (c *Context) Fail(code int, err error) {
	c.Error(err, "Operation aborted")
	c.Abort(code)
}

// Attachs an error to the current context. The error is pushed to a list of errors.
// It's a gooc idea to call Error for each error ocurred during the resolution of a request.
// A middleware can be used to collect all the errors and push them to a database together, print a log, or append it in the HTTP response.
func (c *Context) Error(err error, meta interface{}) {
	c.Errors = append(c.Errors, ErrorMsg{
		Err:  err.Error(),
		Meta: meta,
	})
}

func (c *Context) LastError() error {
	s := len(c.Errors)
	if s > 0 {
		return errors.New(c.Errors[s-1].Err)
	} else {
		return nil
	}
}

/************************************/
/******** METADATA MANAGEMENT********/
/************************************/

// Sets a new pair key/value just for the specefied context.
// It also lazy initializes the hashmap
func (c *Context) Set(key string, item interface{}) {
	if c.Keys == nil {
		c.Keys = make(map[string]interface{})
	}
	c.Keys[key] = item
}

// Returns the value for the given key.
// It panics if the value doesn't exist.
func (c *Context) Get(key string) interface{} {
	var ok bool
	var item interface{}
	if c.Keys != nil {
		item, ok = c.Keys[key]
	} else {
		item, ok = nil, false
	}
	if !ok || item == nil {
		log.Panicf("Key %s doesn't exist", key)
	}
	return item
}

/************************************/
/******** ENCOGING MANAGEMENT********/
/************************************/

// Like ParseBody() but this method also writes a 400 error if the json is not valid.
func (c *Context) EnsureBody(item interface{}) bool {
	if err := c.ParseBody(item); err != nil {
		c.Fail(400, err)
		return false
	}
	return true
}

// Parses the body content as a JSON input. It decodes the json payload into the struct specified as a pointer.
func (c *Context) ParseBody(item interface{}) error {
	decoder := json.NewDecoder(c.Req.Body)
	if err := decoder.Decode(&item); err == nil {
		return Validate(c, item)
	} else {
		return err
	}
}

// Serializes the given struct as a JSON into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/json"
func (c *Context) JSON(code int, obj interface{}) {
	c.Writer.Header().Set("Content-Type", "application/json")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	encoder := json.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		c.Error(err, obj)
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Serializes the given struct as a XML into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/xml"
func (c *Context) XML(code int, obj interface{}) {
	c.Writer.Header().Set("Content-Type", "application/xml")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	encoder := xml.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		c.Error(err, obj)
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Renders the HTTP template specified by his file name.
// It also update the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (c *Context) HTML(code int, name string, data interface{}) {
	c.Writer.Header().Set("Content-Type", "text/html")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	if err := c.engine.HTMLTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
		c.Error(err, map[string]interface{}{
			"name": name,
			"data": data,
		})
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Writes the given string into the response body and sets the Content-Type to "text/plain"
func (c *Context) String(code int, msg string) {
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	c.Writer.Header().Set("Content-Type", "text/plain")
	c.Writer.Write([]byte(msg))
}

// Writes some data into the body stream and updates the HTTP code
func (c *Context) Data(code int, data []byte) {
	c.Writer.WriteHeader(code)
	c.Writer.Write(data)
}
<commit_msg>Run() crashes if server can't be setup<commit_after>package gin

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/julienschmidt/httprouter"
	"html/template"
	"log"
	"math"
	"net/http"
	"path"
)

const (
	AbortIndex = math.MaxInt8 / 2
)

type (
	HandlerFunc func(*Context)

	H map[string]interface{}

	// Used internally to collect a error ocurred during a http request.
	ErrorMsg struct {
		Err  string      `json:"error"`
		Meta interface{} `json:"meta"`
	}

	ErrorMsgs []ErrorMsg

	// Context is the most important part of gin. It allows us to pass variables between middleware,
	// manage the flow, validate the JSON of a request and render a JSON response for example.
	Context struct {
		Req      *http.Request
		Writer   http.ResponseWriter
		Keys     map[string]interface{}
		Errors   ErrorMsgs
		Params   httprouter.Params
		handlers []HandlerFunc
		engine   *Engine
		index    int8
	}

	// Used internally to configure router, a RouterGroup is associated with a prefix
	// and an array of handlers (middlewares)
	RouterGroup struct {
		Handlers []HandlerFunc
		prefix   string
		parent   *RouterGroup
		engine   *Engine
	}

	// Represents the web framework, it wrappers the blazing fast httprouter multiplexer and a list of global middlewares.
	Engine struct {
		*RouterGroup
		handlers404   []HandlerFunc
		router        *httprouter.Router
		HTMLTemplates *template.Template
	}
)

func (a ErrorMsgs) String() string {
	var buffer bytes.Buffer
	for i, msg := range a {
		text := fmt.Sprintf("Error #%02d: %s \n     Meta: %v\n\n", (i + 1), msg.Err, msg.Meta)
		buffer.WriteString(text)
	}
	return buffer.String()
}

// Returns a new blank Engine instance without any middleware attached.
// The most basic configuration
func New() *Engine {
	engine := &Engine{}
	engine.RouterGroup = &RouterGroup{nil, "/", nil, engine}
	engine.router = httprouter.New()
	engine.router.NotFound = engine.handle404
	return engine
}

// Returns a Engine instance with the Logger and Recovery already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) LoadHTMLTemplates(pattern string) {
	engine.HTMLTemplates = template.Must(template.ParseGlob(pattern))
}

// Adds handlers for NotFound. It return a 404 code by default.
func (engine *Engine) NotFound404(handlers ...HandlerFunc) {
	engine.handlers404 = handlers
}

func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
	handlers := engine.combineHandlers(engine.handlers404)
	c := engine.createContext(w, req, nil, handlers)
	if engine.handlers404 == nil {
		http.NotFound(c.Writer, c.Req)
	} else {
		c.Writer.WriteHeader(404)
	}

	c.Next()
}

// ServeFiles serves files from the given file system root.
// The path must end with "/*filepath", files are then served from the local
// path /defined/root/dir/*filepath.
// For example if root is "/etc" and *filepath is "passwd", the local file
// "/etc/passwd" would be served.
// Internally a http.FileServer is used, therefore http.NotFound is used instead
// of the Router's NotFound handler.
// To use the operating system's file system implementation,
// use http.Dir:
//     router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
func (engine *Engine) ServeFiles(path string, root http.FileSystem) {
	engine.router.ServeFiles(path, root)
}

// ServeHTTP makes the router implement the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	engine.router.ServeHTTP(w, req)
}

func (engine *Engine) Run(addr string) {
	if err := http.ListenAndServe(addr, engine); err != nil {
		panic(err)
	}
}

/************************************/
/********** ROUTES GROUPING *********/
/************************************/

func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
	return &Context{
		Writer:   w,
		Req:      req,
		index:    -1,
		engine:   group.engine,
		Params:   params,
		handlers: handlers,
	}
}

// Adds middlewares to the group, see example code in github.
func (group *RouterGroup) Use(middlewares ...HandlerFunc) {
	group.Handlers = append(group.Handlers, middlewares...)
}

// Greates a new router group. You should create add all the routes that share that have common middlwares or same path prefix.
// For example, all the routes that use a common middlware for authorization could be grouped.
func (group *RouterGroup) Group(component string, handlers ...HandlerFunc) *RouterGroup {
	prefix := path.Join(group.prefix, component)
	return &RouterGroup{
		Handlers: group.combineHandlers(handlers),
		parent:   group,
		prefix:   prefix,
		engine:   group.engine,
	}
}

// Handle registers a new request handle and middlewares with the given path and method.
// The last handler should be the real handler, the other ones should be middlewares that can and should be shared among different routes.
// See the example code in github.
//
// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut
// functions can be used.
//
// This function is intended for bulk loading and to allow the usage of less
// frequently used, non-standardized or custom methods (e.g. for internal
// communication with a proxy).
func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
	p = path.Join(group.prefix, p)
	handlers = group.combineHandlers(handlers)
	group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
		group.createContext(w, req, params, handlers).Next()
	})
}

// POST is a shortcut for router.Handle("POST", path, handle)
func (group *RouterGroup) POST(path string, handlers ...HandlerFunc) {
	group.Handle("POST", path, handlers)
}

// GET is a shortcut for router.Handle("GET", path, handle)
func (group *RouterGroup) GET(path string, handlers ...HandlerFunc) {
	group.Handle("GET", path, handlers)
}

// DELETE is a shortcut for router.Handle("DELETE", path, handle)
func (group *RouterGroup) DELETE(path string, handlers ...HandlerFunc) {
	group.Handle("DELETE", path, handlers)
}

// PATCH is a shortcut for router.Handle("PATCH", path, handle)
func (group *RouterGroup) PATCH(path string, handlers ...HandlerFunc) {
	group.Handle("PATCH", path, handlers)
}

// PUT is a shortcut for router.Handle("PUT", path, handle)
func (group *RouterGroup) PUT(path string, handlers ...HandlerFunc) {
	group.Handle("PUT", path, handlers)
}

func (group *RouterGroup) combineHandlers(handlers []HandlerFunc) []HandlerFunc {
	s := len(group.Handlers) + len(handlers)
	h := make([]HandlerFunc, 0, s)
	h = append(h, group.Handlers...)
	h = append(h, handlers...)
	return h
}

/************************************/
/****** FLOW AND ERROR MANAGEMENT****/
/************************************/

// Next should be used only in the middlewares.
// It executes the pending handlers in the chain inside the calling handler.
// See example in github.
func (c *Context) Next() {
	c.index++
	s := int8(len(c.handlers))
	for ; c.index < s; c.index++ {
		c.handlers[c.index](c)
	}
}

// Forces the system to do not continue calling the pending handlers.
// For example, the first handler checks if the request is authorized. If it's not, context.Abort(401) should be called.
// The rest of pending handlers would never be called for that request.
func (c *Context) Abort(code int) {
	c.Writer.WriteHeader(code)
	c.index = AbortIndex
}

// Fail is the same than Abort plus an error message.
// Calling `context.Fail(500, err)` is equivalent to:
// ```
// context.Error("Operation aborted", err)
// context.Abort(500)
// ```
func (c *Context) Fail(code int, err error) {
	c.Error(err, "Operation aborted")
	c.Abort(code)
}

// Attachs an error to the current context. The error is pushed to a list of errors.
// It's a gooc idea to call Error for each error ocurred during the resolution of a request.
// A middleware can be used to collect all the errors and push them to a database together, print a log, or append it in the HTTP response.
func (c *Context) Error(err error, meta interface{}) {
	c.Errors = append(c.Errors, ErrorMsg{
		Err:  err.Error(),
		Meta: meta,
	})
}

func (c *Context) LastError() error {
	s := len(c.Errors)
	if s > 0 {
		return errors.New(c.Errors[s-1].Err)
	} else {
		return nil
	}
}

/************************************/
/******** METADATA MANAGEMENT********/
/************************************/

// Sets a new pair key/value just for the specefied context.
// It also lazy initializes the hashmap
func (c *Context) Set(key string, item interface{}) {
	if c.Keys == nil {
		c.Keys = make(map[string]interface{})
	}
	c.Keys[key] = item
}

// Returns the value for the given key.
// It panics if the value doesn't exist.
func (c *Context) Get(key string) interface{} {
	var ok bool
	var item interface{}
	if c.Keys != nil {
		item, ok = c.Keys[key]
	} else {
		item, ok = nil, false
	}
	if !ok || item == nil {
		log.Panicf("Key %s doesn't exist", key)
	}
	return item
}

/************************************/
/******** ENCOGING MANAGEMENT********/
/************************************/

// Like ParseBody() but this method also writes a 400 error if the json is not valid.
func (c *Context) EnsureBody(item interface{}) bool {
	if err := c.ParseBody(item); err != nil {
		c.Fail(400, err)
		return false
	}
	return true
}

// Parses the body content as a JSON input. It decodes the json payload into the struct specified as a pointer.
func (c *Context) ParseBody(item interface{}) error {
	decoder := json.NewDecoder(c.Req.Body)
	if err := decoder.Decode(&item); err == nil {
		return Validate(c, item)
	} else {
		return err
	}
}

// Serializes the given struct as a JSON into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/json"
func (c *Context) JSON(code int, obj interface{}) {
	c.Writer.Header().Set("Content-Type", "application/json")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	encoder := json.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		c.Error(err, obj)
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Serializes the given struct as a XML into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/xml"
func (c *Context) XML(code int, obj interface{}) {
	c.Writer.Header().Set("Content-Type", "application/xml")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	encoder := xml.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		c.Error(err, obj)
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Renders the HTTP template specified by his file name.
// It also update the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (c *Context) HTML(code int, name string, data interface{}) {
	c.Writer.Header().Set("Content-Type", "text/html")
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	if err := c.engine.HTMLTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
		c.Error(err, map[string]interface{}{
			"name": name,
			"data": data,
		})
		http.Error(c.Writer, err.Error(), 500)
	}
}

// Writes the given string into the response body and sets the Content-Type to "text/plain"
func (c *Context) String(code int, msg string) {
	if code >= 0 {
		c.Writer.WriteHeader(code)
	}
	c.Writer.Header().Set("Content-Type", "text/plain")
	c.Writer.Write([]byte(msg))
}

// Writes some data into the body stream and updates the HTTP code
func (c *Context) Data(code int, data []byte) {
	c.Writer.WriteHeader(code)
	c.Writer.Write(data)
}
<|endoftext|>


<commit_before>package main

import (
	"sdl"
	"time"
)

const (
	modeHBlank = byte(iota)
	modeVBlank
	modeOAM
	modeVRAM
)

const (
	tilesX = 20
	tilesY = 18
	tileW = 8
	tileH = 8
	mapW = 32
	mapH = 32
	lcdW = tileW * tilesX
	lcdH = tileH * tilesY

	scale = 3

	screenW = lcdW * scale
	screenH = lcdH * scale

	hblankTicks = 204/4
	vblankTicks = 4560/4
	oamTicks    = 80/4
	vramTicks   = 172/4

	scanlineTicks = oamTicks + vramTicks + hblankTicks
	refreshTicks  = scanlineTicks * screenH + vblankTicks
)

type GPU struct {
	clock int
	pal []uint32
	screen *sdl.Surface
	mmu *MBC
	frameTime int64
}

func NewGPU(m *MBC) *GPU {
	screen := sdl.SetVideoMode(screenW, screenH, 0, sdl.DOUBLEBUF)
	pal := make([]uint32, 4)
	pal[0] = sdl.MapRGBA(screen.Format, 0x9B, 0xBC, 0x0F, 0)
	pal[1] = sdl.MapRGBA(screen.Format, 0x8B, 0xAC, 0x0F, 0)
	pal[2] = sdl.MapRGBA(screen.Format, 0x30, 0x62, 0x30, 0)
	pal[3] = sdl.MapRGBA(screen.Format, 0x0F, 0x38, 0x0F, 0)
	screen.FillRect(nil, pal[0])
	screen.Flip()
	time := time.Nanoseconds()
	return &GPU{pal: pal, screen: screen, mmu: m, frameTime: time}
}

func (gpu *GPU) Step(t int) {
	gpu.clock += t
	if gpu.clock >= refreshTicks {
		gpu.clock -= refreshTicks
	}

	mem := gpu.mmu
	ly := byte(gpu.clock / scanlineTicks)
	mem.WritePort(PortLY, ly)
	mode := calcMode(gpu.clock, ly)
	if mode == mem.LCDMode {
		return;
	}
	mem.LCDMode = mode

	stat := mem.ReadPort(PortSTAT) &^ 3 | mode
	irq := mem.ReadPort(PortIF)

	switch mode {
	case modeOAM:
		if mem.OAMInterrupt {
			mem.WritePort(PortIF, irq | 0x02)
		}
		if lyc := mem.ReadPort(PortLYC); ly-1 == lyc {
			stat |= 0x04
			if mem.LYCInterrupt {
				mem.WritePort(PortIF, irq | 0x02)
			}
		} else {
			stat &^= 0x04
		}
	case modeVRAM:
		if mem.LCDEnable {
			gpu.scanline(ly)
		}
	case modeHBlank:
		if mem.HBlankInterrupt {
			mem.WritePort(PortIF, irq | 0x02)
		}
	case modeVBlank:
		if mem.VBlankInterrupt {
			irq |= 0x02
		}
		mem.WritePort(PortIF, irq | 0x01)
		if !mem.LCDEnable {
			gpu.screen.FillRect(nil, gpu.pal[0])
		}
		gpu.screen.Flip()
		gpu.delay()
	}

	mem.WritePort(PortSTAT, stat)
}

func (gpu *GPU) delay() {
	now := time.Nanoseconds()
	delta := now - gpu.frameTime
	target := 16742706 - delta
	if target > 0 {
		time.Sleep(target)
	}
	gpu.frameTime = time.Nanoseconds()
}

func (gpu *GPU) scanline(ly byte) {
	mem := gpu.mmu

	scy := mem.ReadPort(PortSCY)
	scx := mem.ReadPort(PortSCX)
	wy := mem.ReadPort(PortWY)
	wx := mem.ReadPort(PortWX)

	if mem.BGEnable {
		gpu.rleline(mem.BGMap, byte(0), ly, scx, scy)
	}

	if mem.WindowEnable && wx < 167 && wy < 144 && ly >= wy {
		x := int(wx) - 7
		xoff := -x
		if x < 0 { x = 0 }
		gpu.rleline(mem.WindowMap, byte(x), ly, byte(xoff), byte(-wy))
	}

	if mem.SpriteEnable {
		// TODO
	}
}

func (gpu *GPU) rleline(map1 bool, x, y, xoff, yoff byte) {
	r := &sdl.Rect{ X: int16(x) * scale,
		Y: int16(y) * scale, W: scale, H: scale }
	y += yoff
	cur := gpu.mapAt(map1, int(x + xoff), int(y))
	for x++; x < lcdW; x++ {
		b := gpu.mapAt(map1, int(x + xoff), int(y))
		if b != cur {
			gpu.screen.FillRect(r, gpu.pal[gpu.mmu.BGP[cur]])
			cur = b
			r.X = int16(x) * scale
			r.W = scale
		} else {
			r.W += scale
		}
	}
	gpu.screen.FillRect(r, gpu.pal[gpu.mmu.BGP[cur]])
}

func (gpu *GPU) mapAt(map1 bool, x, y int) byte {
	mem := gpu.mmu
	idx := (y / tileH) * mapW + x / tileW
	if map1 {
		idx += 0x1C00
	} else {
		idx += 0x1800
	}
	tile := mem.vram[idx]
	if mem.TileData {
		idx = int(tile) * 16
	} else {
		idx = 0x1000 + int(int8(tile)) * 16
	}
	idx += (y % tileH) * 2
	bit := uint(tileW - 1 - x % tileW)
	px := (mem.vram[idx] >> bit) & 1
	px |= ((mem.vram[idx+1] >> bit) & 1) << 1
	return px
}

func calcMode(t int, ly byte) byte {
	if ly >= lcdH {
		return modeVBlank
	}
	t %= scanlineTicks
	if t < oamTicks {
		return modeOAM
	}
	if t < oamTicks + vramTicks {
		return modeVRAM
	}
	return modeHBlank
}
<commit_msg>Implement sprite rendering<commit_after>package main

import (
	"sdl"
	"time"
)

const (
	modeHBlank = byte(iota)
	modeVBlank
	modeOAM
	modeVRAM
)

const (
	tilesX = 20
	tilesY = 18
	tileW = 8
	tileH = 8
	mapW = 32
	mapH = 32
	lcdW = tileW * tilesX
	lcdH = tileH * tilesY

	scale = 3

	screenW = lcdW * scale
	screenH = lcdH * scale

	hblankTicks = 204/4
	vblankTicks = 4560/4
	oamTicks    = 80/4
	vramTicks   = 172/4

	scanlineTicks = oamTicks + vramTicks + hblankTicks
	refreshTicks  = scanlineTicks * screenH + vblankTicks
)

type GPU struct {
	clock int
	pal []uint32
	screen *sdl.Surface
	mmu *MBC
	frameTime int64
}

func NewGPU(m *MBC) *GPU {
	screen := sdl.SetVideoMode(screenW, screenH, 0, sdl.DOUBLEBUF)
	pal := make([]uint32, 4)
	pal[0] = sdl.MapRGBA(screen.Format, 0x9B, 0xBC, 0x0F, 0)
	pal[1] = sdl.MapRGBA(screen.Format, 0x8B, 0xAC, 0x0F, 0)
	pal[2] = sdl.MapRGBA(screen.Format, 0x30, 0x62, 0x30, 0)
	pal[3] = sdl.MapRGBA(screen.Format, 0x0F, 0x38, 0x0F, 0)
	screen.FillRect(nil, pal[0])
	screen.Flip()
	time := time.Nanoseconds()
	return &GPU{pal: pal, screen: screen, mmu: m, frameTime: time}
}

func (gpu *GPU) Step(t int) {
	gpu.clock += t
	if gpu.clock >= refreshTicks {
		gpu.clock -= refreshTicks
	}

	mem := gpu.mmu
	ly := byte(gpu.clock / scanlineTicks)
	mem.WritePort(PortLY, ly)
	mode := calcMode(gpu.clock, ly)
	if mode == mem.LCDMode {
		return;
	}
	mem.LCDMode = mode

	stat := mem.ReadPort(PortSTAT) &^ 3 | mode
	irq := mem.ReadPort(PortIF)

	switch mode {
	case modeOAM:
		if mem.OAMInterrupt {
			mem.WritePort(PortIF, irq | 0x02)
		}
		if lyc := mem.ReadPort(PortLYC); ly-1 == lyc {
			stat |= 0x04
			if mem.LYCInterrupt {
				mem.WritePort(PortIF, irq | 0x02)
			}
		} else {
			stat &^= 0x04
		}
	case modeVRAM:
		if mem.LCDEnable {
			gpu.scanline(ly)
		}
	case modeHBlank:
		if mem.HBlankInterrupt {
			mem.WritePort(PortIF, irq | 0x02)
		}
	case modeVBlank:
		if mem.VBlankInterrupt {
			irq |= 0x02
		}
		mem.WritePort(PortIF, irq | 0x01)
		if !mem.LCDEnable {
			gpu.screen.FillRect(nil, gpu.pal[0])
		}
		gpu.screen.Flip()
		gpu.delay()
	}

	mem.WritePort(PortSTAT, stat)
}

func (gpu *GPU) delay() {
	now := time.Nanoseconds()
	delta := now - gpu.frameTime
	target := 16742706 - delta
	if target > 0 {
		time.Sleep(target)
	}
	gpu.frameTime = time.Nanoseconds()
}

func (gpu *GPU) scanline(ly byte) {
	mem := gpu.mmu

	scy := mem.ReadPort(PortSCY)
	scx := mem.ReadPort(PortSCX)
	wy := mem.ReadPort(PortWY)
	wx := mem.ReadPort(PortWX)

	if mem.BGEnable {
		gpu.rleline(mem.BGMap, byte(0), ly, scx, scy)
	}

	if mem.WindowEnable && wx < 167 && wy < 144 && ly >= wy {
		x := int(wx) - 7
		xoff := -x
		if x < 0 { x = 0 }
		gpu.rleline(mem.WindowMap, byte(x), ly, byte(xoff), byte(-wy))
	}

	if mem.SpriteEnable {
		count := 0
		idx := 0
		// TODO sprite priorities for overlapping sprites at
		// different x-coordinates (lower x-coordinate wins)
		for idx < 0xA0 && count < 10 {
			y := int(mem.oam[idx]) - 16; idx++
			x := int(mem.oam[idx]) - 8; idx++
			tile := int(mem.oam[idx]); idx++
			info := mem.oam[idx]; idx++
			h := 8
			if mem.SpriteSize { h = 16; tile &= 0xFE }
			if int(ly) < y || int(ly) >= y + h { continue }
			count++
			if x == -8 || x >= 168 { continue }
			masked := info & 0x80 == 0x80
			yflip := info & 0x40 == 0x40
			xflip := info & 0x20 == 0x20
			palidx := (info >> 4) & 1
			tiley := int(ly) - y
			if yflip { tiley = h - tiley }
			tile = tile * 16 + tiley * 2
			rect := &sdl.Rect{Y:int16(ly)*scale, W:scale, H:scale}
			for i := 0; i < 8; i++ {
				xi := x + i
				if xi < 0 { continue }
				if xi >= screenW { continue }
				if masked {
					px := gpu.mapAt(mem.BGMap,
						xi + int(scx),
						int(ly) + int(scy))
					if px != 0 ||
						xi > int(wx) ||
						ly >= wy { continue }
				}
				bit := uint(i)
				if !xflip { bit = uint(7 - i) }
				px := (mem.vram[tile] >> bit) & 1
				px |= ((mem.vram[tile+1] >> bit) & 1) << 1
				if px != 0 {
					color := gpu.pal[mem.OBP[palidx][px]]
					rect.X = int16(xi) * scale
					gpu.screen.FillRect(rect, color)
				}
			}
		}
	}
}

func (gpu *GPU) rleline(map1 bool, x, y, xoff, yoff byte) {
	r := &sdl.Rect{ X: int16(x) * scale,
		Y: int16(y) * scale, W: scale, H: scale }
	y += yoff
	cur := gpu.mapAt(map1, int(x + xoff), int(y))
	for x++; x < lcdW; x++ {
		b := gpu.mapAt(map1, int(x + xoff), int(y))
		if b != cur {
			gpu.screen.FillRect(r, gpu.pal[gpu.mmu.BGP[cur]])
			cur = b
			r.X = int16(x) * scale
			r.W = scale
		} else {
			r.W += scale
		}
	}
	gpu.screen.FillRect(r, gpu.pal[gpu.mmu.BGP[cur]])
}

func (gpu *GPU) mapAt(map1 bool, x, y int) byte {
	mem := gpu.mmu
	idx := (y / tileH) * mapW + x / tileW
	if map1 {
		idx += 0x1C00
	} else {
		idx += 0x1800
	}
	tile := mem.vram[idx]
	if mem.TileData {
		idx = int(tile) * 16
	} else {
		idx = 0x1000 + int(int8(tile)) * 16
	}
	idx += (y % tileH) * 2
	bit := uint(tileW - 1 - x % tileW)
	px := (mem.vram[idx] >> bit) & 1
	px |= ((mem.vram[idx+1] >> bit) & 1) << 1
	return px
}

func calcMode(t int, ly byte) byte {
	if ly >= lcdH {
		return modeVBlank
	}
	t %= scanlineTicks
	if t < oamTicks {
		return modeOAM
	}
	if t < oamTicks + vramTicks {
		return modeVRAM
	}
	return modeHBlank
}
<|endoftext|>


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

package hplot

import (
	"errors"
	"fmt"
	"image/color"

	"github.com/go-hep/hbook"
	"github.com/gonum/plot"
	"github.com/gonum/plot/plotter"
	"github.com/gonum/plot/vg"
	"github.com/gonum/plot/vg/draw"
)

// H1D implements the plotter.Plotter interface,
// drawing a histogram of the data.
type H1D struct {
	// Hist is the histogramming data
	Hist *hbook.H1D

	// FillColor is the color used to fill each
	// bar of the histogram.  If the color is nil
	// then the bars are not filled.
	FillColor color.Color

	// LineStyle is the style of the outline of each
	// bar of the histogram.
	draw.LineStyle

	// InfoStyle is the style of infos displayed for
	// the histogram (entries, mean, rms)
	Infos HInfos
}

type HInfoStyle int

const (
	HInfoNone    HInfoStyle = 0
	HInfoEntries HInfoStyle = iota << 1
	HInfoMean
	HInfoRMS
	HInfoSummary // HInfoEntries | HInfoMean | HInfoRMS
)

type HInfos struct {
	Style HInfoStyle
}

// NewH1FromXYer returns a new histogram
// that represents the distribution of values
// using the given number of bins.
//
// Each y value is assumed to be the frequency
// count for the corresponding x.
//
// If the number of bins is non-positive than
// a reasonable default is used.
func NewH1FromXYer(xy plotter.XYer, n int) (*H1D, error) {
	if n <= 0 {
		return nil, errors.New("Histogram with non-positive number of bins")
	}
	h := newHistFromXYer(xy, n)
	return NewH1D(h)
}

// NewH1FromValuer returns a new histogram, as in
// NewH1FromXYer, except that it accepts a plotter.Valuer
// instead of an XYer.
func NewH1FromValuer(vs plotter.Valuer, n int) (*H1D, error) {
	return NewH1FromXYer(unitYs{vs}, n)
}

type unitYs struct {
	plotter.Valuer
}

func (u unitYs) XY(i int) (float64, float64) {
	return u.Value(i), 1.0
}

// NewH1D returns a new histogram, as in
// NewH1DFromXYer, except that it accepts a hbook.H1D
// instead of a plotter.XYer
func NewH1D(h *hbook.H1D) (*H1D, error) {
	return &H1D{
		Hist:      h,
		FillColor: color.White,
		LineStyle: plotter.DefaultLineStyle,
	}, nil
}

// DataRange returns the minimum and maximum X and Y values
func (h *H1D) DataRange() (xmin, xmax, ymin, ymax float64) {
	return h.Hist.DataRange()
}

// Plot implements the Plotter interface, drawing a line
// that connects each point in the Line.
func (h *H1D) Plot(c draw.Canvas, p *plot.Plot) {
	trX, trY := p.Transforms(&c)
	var pts []vg.Point
	hist := h.Hist
	bins := h.Hist.Binning().Bins()
	nbins := len(bins)
	for i, bin := range bins {
		switch i {
		case 0:
			pts = append(pts, vg.Point{trX(bin.XMin()), trY(0)})
			pts = append(pts, vg.Point{trX(bin.XMin()), trY(bin.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMax()), trY(bin.SumW())})

		case nbins - 1:
			lft := bins[i-1]
			pts = append(pts, vg.Point{trX(lft.XMax()), trY(lft.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMin()), trY(bin.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMax()), trY(bin.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMax()), trY(0.)})

		default:
			lft := bins[i-1]
			pts = append(pts, vg.Point{trX(lft.XMax()), trY(lft.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMin()), trY(bin.SumW())})
			pts = append(pts, vg.Point{trX(bin.XMax()), trY(bin.SumW())})
		}
	}

	if h.FillColor != nil {
		c.FillPolygon(h.FillColor, c.ClipPolygonXY(pts))
	}
	c.StrokeLines(h.LineStyle, c.ClipLinesXY(pts)...)

	if h.Infos.Style != HInfoNone {
		fnt, err := vg.MakeFont(plotter.DefaultFont, plotter.DefaultFontSize)
		if err == nil {
			sty := draw.TextStyle{Font: fnt}
			legend := histLegend{
				ColWidth:  plotter.DefaultFontSize,
				TextStyle: sty,
			}

			switch h.Infos.Style {
			case HInfoSummary:
				legend.Add("Entries", hist.Entries())
				legend.Add("Mean", hist.XMean())
				legend.Add("RMS", hist.XRMS())
			case HInfoEntries:
				legend.Add("Entries", hist.Entries())
			case HInfoMean:
				legend.Add("Mean", hist.XMean())
			case HInfoRMS:
				legend.Add("RMS", hist.XRMS())
			default:
			}
			legend.Top = true

			legend.draw(c)
		}
	}
}

// GlyphBoxes returns a slice of GlyphBoxes,
// one for each of the bins, implementing the
// plot.GlyphBoxer interface.
func (h *H1D) GlyphBoxes(p *plot.Plot) []plot.GlyphBox {
	bins := h.Hist.Binning().Bins()
	bs := make([]plot.GlyphBox, len(bins))
	for i := range bs {
		bin := bins[i]
		y := bin.SumW()
		xmin := bin.XMin()
		w := p.X.Norm(bin.XWidth())
		bs[i].X = p.X.Norm(xmin + 0.5*w)
		bs[i].Y = p.Y.Norm(y)
		//h := vg.Points(1e-5) //1 //p.Y.Norm(axis.BinWidth(i))
		bs[i].Rectangle.Min.X = vg.Length(xmin - 0.5*w)
		bs[i].Rectangle.Min.Y = vg.Length(y - 0.5*w)
		bs[i].Rectangle.Max.X = vg.Length(w)
		bs[i].Rectangle.Max.Y = vg.Length(0)

		r := vg.Points(5)
		//r = vg.Length(w)
		bs[i].Rectangle.Min = vg.Point{0, 0}
		bs[i].Rectangle.Max = vg.Point{0, r}
	}
	return bs
}

// Normalize normalizes the histogram so that the
// total area beneath it sums to a given value.
// func (h *Histogram) Normalize(sum float64) {
// 	mass := 0.0
// 	for _, b := range h.Bins {
// 		mass += b.Weight
// 	}
// 	for i := range h.Bins {
// 		h.Bins[i].Weight *= sum / (h.Width * mass)
// 	}
// }

func newHistFromXYer(xys plotter.XYer, n int) *hbook.H1D {
	xmin, xmax := plotter.Range(plotter.XValues{xys})
	h := hbook.NewH1D(n, xmin, xmax)

	for i := 0; i < xys.Len(); i++ {
		x, y := xys.XY(i)
		h.Fill(x, y)
	}

	return h
}

// A Legend gives a description of the meaning of different
// data elements of the plot.  Each legend entry has a name
// and a thumbnail, where the thumbnail shows a small
// sample of the display style of the corresponding data.
type histLegend struct {
	// TextStyle is the style given to the legend
	// entry texts.
	draw.TextStyle

	// Padding is the amount of padding to add
	// betweeneach entry of the legend.  If Padding
	// is zero then entries are spaced based on the
	// font size.
	Padding vg.Length

	// Top and Left specify the location of the legend.
	// If Top is true the legend is located along the top
	// edge of the plot, otherwise it is located along
	// the bottom edge.  If Left is true then the legend
	// is located along the left edge of the plot, and the
	// text is positioned after the icons, otherwise it is
	// located along the right edge and the text is
	// positioned before the icons.
	Top, Left bool

	// XOffs and YOffs are added to the legend's
	// final position.
	XOffs, YOffs vg.Length

	// ColWidth is the width of legend names
	ColWidth vg.Length

	// entries are all of the legendEntries described
	// by this legend.
	entries []legendEntry
}

// A legendEntry represents a single line of a legend, it
// has a name and an icon.
type legendEntry struct {
	// text is the text associated with this entry.
	text string

	// value is the value associated with this entry
	value string
}

// draw draws the legend to the given canvas.
func (l *histLegend) draw(c draw.Canvas) {
	textx := c.Min.X
	hdr := l.entryWidth() //+ l.TextStyle.Width(" ")
	l.ColWidth = hdr
	valx := textx + l.ColWidth + l.TextStyle.Width(" ")
	if !l.Left {
		textx = c.Max.X - l.ColWidth
		valx = textx - l.TextStyle.Width(" ")
	}
	valx += l.XOffs
	textx += l.XOffs

	enth := l.entryHeight()
	y := c.Max.Y - enth
	if !l.Top {
		y = c.Min.Y + (enth+l.Padding)*(vg.Length(len(l.entries))-1)
	}
	y += l.YOffs

	colx := &draw.Canvas{
		Canvas: c.Canvas,
		Rectangle: vg.Rectangle{
			Min: vg.Point{c.Min.X, y},
			Max: vg.Point{2 * l.ColWidth, enth},
		},
	}
	for _, e := range l.entries {
		yoffs := (enth - l.TextStyle.Height(e.text)) / 2
		txt := l.TextStyle
		txt.XAlign = draw.XLeft
		c.FillText(txt, vg.Point{textx - hdr, colx.Min.Y + yoffs}, e.text)
		txt.XAlign = draw.XRight
		c.FillText(txt, vg.Point{textx + hdr, colx.Min.Y + yoffs}, e.value)
		colx.Min.Y -= enth + l.Padding
	}

	bboxXmin := textx - hdr - l.TextStyle.Width(" ")
	bboxXmax := c.Max.X
	bboxYmin := colx.Min.Y + enth
	bboxYmax := c.Max.Y
	bbox := []vg.Point{
		{bboxXmin, bboxYmax},
		{bboxXmin, bboxYmin},
		{bboxXmax, bboxYmin},
		{bboxXmax, bboxYmax},
		{bboxXmin, bboxYmax},
	}
	c.StrokeLines(plotter.DefaultLineStyle, bbox)
}

// entryHeight returns the height of the tallest legend
// entry text.
func (l *histLegend) entryHeight() (height vg.Length) {
	for _, e := range l.entries {
		if h := l.TextStyle.Height(e.text); h > height {
			height = h
		}
	}
	return
}

// entryWidth returns the width of the largest legend
// entry text.
func (l *histLegend) entryWidth() (width vg.Length) {
	for _, e := range l.entries {
		if w := l.TextStyle.Width(e.value); w > width {
			width = w
		}
	}
	return
}

// Add adds an entry to the legend with the given name.
// The entry's thumbnail is drawn as the composite of all of the
// thumbnails.
func (l *histLegend) Add(name string, value interface{}) {
	str := ""
	switch value.(type) {
	case float64, float32:
		str = fmt.Sprintf("%6.4g ", value)
	default:
		str = fmt.Sprintf("%v ", value)
	}
	l.entries = append(l.entries, legendEntry{text: name, value: str})
}
<commit_msg>hplot: govet fixes<commit_after>// Copyright ©2016 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hplot

import (
	"errors"
	"fmt"
	"image/color"

	"github.com/go-hep/hbook"
	"github.com/gonum/plot"
	"github.com/gonum/plot/plotter"
	"github.com/gonum/plot/vg"
	"github.com/gonum/plot/vg/draw"
)

// H1D implements the plotter.Plotter interface,
// drawing a histogram of the data.
type H1D struct {
	// Hist is the histogramming data
	Hist *hbook.H1D

	// FillColor is the color used to fill each
	// bar of the histogram.  If the color is nil
	// then the bars are not filled.
	FillColor color.Color

	// LineStyle is the style of the outline of each
	// bar of the histogram.
	draw.LineStyle

	// InfoStyle is the style of infos displayed for
	// the histogram (entries, mean, rms)
	Infos HInfos
}

type HInfoStyle int

const (
	HInfoNone    HInfoStyle = 0
	HInfoEntries HInfoStyle = iota << 1
	HInfoMean
	HInfoRMS
	HInfoSummary // HInfoEntries | HInfoMean | HInfoRMS
)

type HInfos struct {
	Style HInfoStyle
}

// NewH1FromXYer returns a new histogram
// that represents the distribution of values
// using the given number of bins.
//
// Each y value is assumed to be the frequency
// count for the corresponding x.
//
// If the number of bins is non-positive than
// a reasonable default is used.
func NewH1FromXYer(xy plotter.XYer, n int) (*H1D, error) {
	if n <= 0 {
		return nil, errors.New("Histogram with non-positive number of bins")
	}
	h := newHistFromXYer(xy, n)
	return NewH1D(h)
}

// NewH1FromValuer returns a new histogram, as in
// NewH1FromXYer, except that it accepts a plotter.Valuer
// instead of an XYer.
func NewH1FromValuer(vs plotter.Valuer, n int) (*H1D, error) {
	return NewH1FromXYer(unitYs{vs}, n)
}

type unitYs struct {
	plotter.Valuer
}

func (u unitYs) XY(i int) (float64, float64) {
	return u.Value(i), 1.0
}

// NewH1D returns a new histogram, as in
// NewH1DFromXYer, except that it accepts a hbook.H1D
// instead of a plotter.XYer
func NewH1D(h *hbook.H1D) (*H1D, error) {
	return &H1D{
		Hist:      h,
		FillColor: color.White,
		LineStyle: plotter.DefaultLineStyle,
	}, nil
}

// DataRange returns the minimum and maximum X and Y values
func (h *H1D) DataRange() (xmin, xmax, ymin, ymax float64) {
	return h.Hist.DataRange()
}

// Plot implements the Plotter interface, drawing a line
// that connects each point in the Line.
func (h *H1D) Plot(c draw.Canvas, p *plot.Plot) {
	trX, trY := p.Transforms(&c)
	var pts []vg.Point
	hist := h.Hist
	bins := h.Hist.Binning().Bins()
	nbins := len(bins)
	for i, bin := range bins {
		switch i {
		case 0:
			pts = append(pts, vg.Point{X: trX(bin.XMin()), Y: trY(0)})
			pts = append(pts, vg.Point{X: trX(bin.XMin()), Y: trY(bin.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMax()), Y: trY(bin.SumW())})

		case nbins - 1:
			lft := bins[i-1]
			pts = append(pts, vg.Point{X: trX(lft.XMax()), Y: trY(lft.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMin()), Y: trY(bin.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMax()), Y: trY(bin.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMax()), Y: trY(0.)})

		default:
			lft := bins[i-1]
			pts = append(pts, vg.Point{X: trX(lft.XMax()), Y: trY(lft.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMin()), Y: trY(bin.SumW())})
			pts = append(pts, vg.Point{X: trX(bin.XMax()), Y: trY(bin.SumW())})
		}
	}

	if h.FillColor != nil {
		c.FillPolygon(h.FillColor, c.ClipPolygonXY(pts))
	}
	c.StrokeLines(h.LineStyle, c.ClipLinesXY(pts)...)

	if h.Infos.Style != HInfoNone {
		fnt, err := vg.MakeFont(plotter.DefaultFont, plotter.DefaultFontSize)
		if err == nil {
			sty := draw.TextStyle{Font: fnt}
			legend := histLegend{
				ColWidth:  plotter.DefaultFontSize,
				TextStyle: sty,
			}

			switch h.Infos.Style {
			case HInfoSummary:
				legend.Add("Entries", hist.Entries())
				legend.Add("Mean", hist.XMean())
				legend.Add("RMS", hist.XRMS())
			case HInfoEntries:
				legend.Add("Entries", hist.Entries())
			case HInfoMean:
				legend.Add("Mean", hist.XMean())
			case HInfoRMS:
				legend.Add("RMS", hist.XRMS())
			default:
			}
			legend.Top = true

			legend.draw(c)
		}
	}
}

// GlyphBoxes returns a slice of GlyphBoxes,
// one for each of the bins, implementing the
// plot.GlyphBoxer interface.
func (h *H1D) GlyphBoxes(p *plot.Plot) []plot.GlyphBox {
	bins := h.Hist.Binning().Bins()
	bs := make([]plot.GlyphBox, len(bins))
	for i := range bs {
		bin := bins[i]
		y := bin.SumW()
		xmin := bin.XMin()
		w := p.X.Norm(bin.XWidth())
		bs[i].X = p.X.Norm(xmin + 0.5*w)
		bs[i].Y = p.Y.Norm(y)
		//h := vg.Points(1e-5) //1 //p.Y.Norm(axis.BinWidth(i))
		bs[i].Rectangle.Min.X = vg.Length(xmin - 0.5*w)
		bs[i].Rectangle.Min.Y = vg.Length(y - 0.5*w)
		bs[i].Rectangle.Max.X = vg.Length(w)
		bs[i].Rectangle.Max.Y = vg.Length(0)

		r := vg.Points(5)
		//r = vg.Length(w)
		bs[i].Rectangle.Min = vg.Point{X: 0, Y: 0}
		bs[i].Rectangle.Max = vg.Point{X: 0, Y: r}
	}
	return bs
}

// Normalize normalizes the histogram so that the
// total area beneath it sums to a given value.
// func (h *Histogram) Normalize(sum float64) {
// 	mass := 0.0
// 	for _, b := range h.Bins {
// 		mass += b.Weight
// 	}
// 	for i := range h.Bins {
// 		h.Bins[i].Weight *= sum / (h.Width * mass)
// 	}
// }

func newHistFromXYer(xys plotter.XYer, n int) *hbook.H1D {
	xmin, xmax := plotter.Range(plotter.XValues{xys})
	h := hbook.NewH1D(n, xmin, xmax)

	for i := 0; i < xys.Len(); i++ {
		x, y := xys.XY(i)
		h.Fill(x, y)
	}

	return h
}

// A Legend gives a description of the meaning of different
// data elements of the plot.  Each legend entry has a name
// and a thumbnail, where the thumbnail shows a small
// sample of the display style of the corresponding data.
type histLegend struct {
	// TextStyle is the style given to the legend
	// entry texts.
	draw.TextStyle

	// Padding is the amount of padding to add
	// betweeneach entry of the legend.  If Padding
	// is zero then entries are spaced based on the
	// font size.
	Padding vg.Length

	// Top and Left specify the location of the legend.
	// If Top is true the legend is located along the top
	// edge of the plot, otherwise it is located along
	// the bottom edge.  If Left is true then the legend
	// is located along the left edge of the plot, and the
	// text is positioned after the icons, otherwise it is
	// located along the right edge and the text is
	// positioned before the icons.
	Top, Left bool

	// XOffs and YOffs are added to the legend's
	// final position.
	XOffs, YOffs vg.Length

	// ColWidth is the width of legend names
	ColWidth vg.Length

	// entries are all of the legendEntries described
	// by this legend.
	entries []legendEntry
}

// A legendEntry represents a single line of a legend, it
// has a name and an icon.
type legendEntry struct {
	// text is the text associated with this entry.
	text string

	// value is the value associated with this entry
	value string
}

// draw draws the legend to the given canvas.
func (l *histLegend) draw(c draw.Canvas) {
	textx := c.Min.X
	hdr := l.entryWidth() //+ l.TextStyle.Width(" ")
	l.ColWidth = hdr
	valx := textx + l.ColWidth + l.TextStyle.Width(" ")
	if !l.Left {
		textx = c.Max.X - l.ColWidth
		valx = textx - l.TextStyle.Width(" ")
	}
	valx += l.XOffs
	textx += l.XOffs

	enth := l.entryHeight()
	y := c.Max.Y - enth
	if !l.Top {
		y = c.Min.Y + (enth+l.Padding)*(vg.Length(len(l.entries))-1)
	}
	y += l.YOffs

	colx := &draw.Canvas{
		Canvas: c.Canvas,
		Rectangle: vg.Rectangle{
			Min: vg.Point{c.Min.X, y},
			Max: vg.Point{2 * l.ColWidth, enth},
		},
	}
	for _, e := range l.entries {
		yoffs := (enth - l.TextStyle.Height(e.text)) / 2
		txt := l.TextStyle
		txt.XAlign = draw.XLeft
		c.FillText(txt, vg.Point{textx - hdr, colx.Min.Y + yoffs}, e.text)
		txt.XAlign = draw.XRight
		c.FillText(txt, vg.Point{textx + hdr, colx.Min.Y + yoffs}, e.value)
		colx.Min.Y -= enth + l.Padding
	}

	bboxXmin := textx - hdr - l.TextStyle.Width(" ")
	bboxXmax := c.Max.X
	bboxYmin := colx.Min.Y + enth
	bboxYmax := c.Max.Y
	bbox := []vg.Point{
		{bboxXmin, bboxYmax},
		{bboxXmin, bboxYmin},
		{bboxXmax, bboxYmin},
		{bboxXmax, bboxYmax},
		{bboxXmin, bboxYmax},
	}
	c.StrokeLines(plotter.DefaultLineStyle, bbox)
}

// entryHeight returns the height of the tallest legend
// entry text.
func (l *histLegend) entryHeight() (height vg.Length) {
	for _, e := range l.entries {
		if h := l.TextStyle.Height(e.text); h > height {
			height = h
		}
	}
	return
}

// entryWidth returns the width of the largest legend
// entry text.
func (l *histLegend) entryWidth() (width vg.Length) {
	for _, e := range l.entries {
		if w := l.TextStyle.Width(e.value); w > width {
			width = w
		}
	}
	return
}

// Add adds an entry to the legend with the given name.
// The entry's thumbnail is drawn as the composite of all of the
// thumbnails.
func (l *histLegend) Add(name string, value interface{}) {
	str := ""
	switch value.(type) {
	case float64, float32:
		str = fmt.Sprintf("%6.4g ", value)
	default:
		str = fmt.Sprintf("%v ", value)
	}
	l.entries = append(l.entries, legendEntry{text: name, value: str})
}
<|endoftext|>


<commit_before>// Copyright 2009 Thomas Jager <mail@jager.no>  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
This package provides an event based IRC client library. It allows to
register callbacks for the events you need to handle. Its features
include handling standard CTCP, reconnecting on errors and detecting
stones servers.
Details of the IRC protocol can be found in the following RFCs:
https://tools.ietf.org/html/rfc1459
https://tools.ietf.org/html/rfc2810
https://tools.ietf.org/html/rfc2811
https://tools.ietf.org/html/rfc2812
https://tools.ietf.org/html/rfc2813
The details of the client-to-client protocol (CTCP) can be found here: http://www.irchelp.org/irchelp/rfc/ctcpspec.html
*/

package irc

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	VERSION = "go-ircevent v2.1"
)

// Read data from a connection. To be used as a goroutine.
func (irc *Connection) readLoop() {
	defer irc.Done()
	br := bufio.NewReaderSize(irc.socket, 512)

	for {
		select {
		case <-irc.end:
			return
		default:
			// Set a read deadline based on the combined timeout and ping frequency
			// We should ALWAYS have received a response from the server within the timeout
			// after our own pings
			if irc.socket != nil {
				irc.socket.SetReadDeadline(time.Now().Add(irc.Timeout + irc.PingFreq))
			}

			msg, err := br.ReadString('\n')

			// We got past our blocking read, so bin timeout
			if irc.socket != nil {
				var zero time.Time
				irc.socket.SetReadDeadline(zero)
			}

			if err != nil {
				irc.Error <- err
				break
			}

			irc.lastMessage = time.Now()
			msg = msg[:len(msg)-2] //Remove \r\n
			event := &Event{Raw: msg}
			if msg[0] == ':' {
				if i := strings.Index(msg, " "); i > -1 {
					event.Source = msg[1:i]
					msg = msg[i+1 : len(msg)]

				} else {
					irc.Log.Printf("Misformed msg from server: %#s\n", msg)
				}

				if i, j := strings.Index(event.Source, "!"), strings.Index(event.Source, "@"); i > -1 && j > -1 {
					event.Nick = event.Source[0:i]
					event.User = event.Source[i+1 : j]
					event.Host = event.Source[j+1 : len(event.Source)]
				}
			}

			split := strings.SplitN(msg, " :", 2)
			args := strings.Split(split[0], " ")
			event.Code = strings.ToUpper(args[0])
			event.Arguments = args[1:]
			if len(split) > 1 {
				event.Arguments = append(event.Arguments, split[1])
			}

			/* XXX: len(args) == 0: args should be empty */

			irc.RunCallbacks(event)
		}
	}
	return
}

// Loop to write to a connection. To be used as a goroutine.
func (irc *Connection) writeLoop() {
	defer irc.Done()
	for {
		select {
		case <-irc.end:
			return
		default:
			b, ok := <-irc.pwrite
			if !ok || b == "" || irc.socket == nil {
				return
			}

			if irc.Debug {
				irc.Log.Printf("--> %s\n", b)
			}

			// Set a write deadline based on the time out
			irc.socket.SetWriteDeadline(time.Now().Add(irc.Timeout))

			_, err := irc.socket.Write([]byte(b))

			// Past blocking write, bin timeout
			var zero time.Time
			irc.socket.SetWriteDeadline(zero)

			if err != nil {
				irc.Error <- err
				return
			}
		}
	}
	return
}

// Pings the server if we have not received any messages for 5 minutes
// to keep the connection alive. To be used as a goroutine.
func (irc *Connection) pingLoop() {
	defer irc.Done()
	ticker := time.NewTicker(1 * time.Minute) // Tick every minute for monitoring
	ticker2 := time.NewTicker(irc.PingFreq)   // Tick at the ping frequency.
	for {
		select {
		case <-ticker.C:
			//Ping if we haven't received anything from the server within the keep alive period
			if time.Since(irc.lastMessage) >= irc.KeepAlive {
				irc.SendRawf("PING %d", time.Now().UnixNano())
			}
		case <-ticker2.C:
			//Ping at the ping frequency
			irc.SendRawf("PING %d", time.Now().UnixNano())
			//Try to recapture nickname if it's not as configured.
			if irc.nick != irc.nickcurrent {
				irc.nickcurrent = irc.nick
				irc.SendRawf("NICK %s", irc.nick)
			}
		case <-irc.end:
			ticker.Stop()
			ticker2.Stop()
			return
		}
	}
}

// Main loop to control the connection.
func (irc *Connection) Loop() {
	for !irc.stopped {
		err := <-irc.Error
		if irc.stopped {
			break
		}
		irc.Log.Printf("Error, disconnected: %s\n", err)
		//irc.Disconnect()
		for !irc.stopped {
			if err = irc.Reconnect(); err != nil {
				irc.Log.Printf("Error while reconnecting: %s\n", err)
				time.Sleep(1 * time.Second)
			} else {
				break
			}
		}
	}
}

// Quit the current connection and disconnect from the server
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.6
func (irc *Connection) Quit() {
	irc.SendRaw("QUIT")
	irc.stopped = true
}

// Use the connection to join a given channel.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.1
func (irc *Connection) Join(channel string) {
	irc.pwrite <- fmt.Sprintf("JOIN %s\r\n", channel)
}

// Leave a given channel.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.2
func (irc *Connection) Part(channel string) {
	irc.pwrite <- fmt.Sprintf("PART %s\r\n", channel)
}

// Send a notification to a nickname. This is similar to Privmsg but must not receive replies.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
func (irc *Connection) Notice(target, message string) {
	irc.pwrite <- fmt.Sprintf("NOTICE %s :%s\r\n", target, message)
}

// Send a formated notification to a nickname.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
func (irc *Connection) Noticef(target, format string, a ...interface{}) {
	irc.Notice(target, fmt.Sprintf(format, a...))
}

// Send (action) message to a target (channel or nickname).
// No clear RFC on this one...
func (irc *Connection) Action(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :\001ACTION %s\001\r\n", target, message)
}

// Send (private) message to a target (channel or nickname).
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.1
func (irc *Connection) Privmsg(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :%s\r\n", target, message)
}

// Send formated string to specified target (channel or nickname).
func (irc *Connection) Privmsgf(target, format string, a ...interface{}) {
	irc.Privmsg(target, fmt.Sprintf(format, a...))
}

// Send raw string.
func (irc *Connection) SendRaw(message string) {
	irc.pwrite <- message + "\r\n"
}

// Send raw formated string.
func (irc *Connection) SendRawf(format string, a ...interface{}) {
	irc.SendRaw(fmt.Sprintf(format, a...))
}

// Set (new) nickname.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.2
func (irc *Connection) Nick(n string) {
	irc.nick = n
	irc.SendRawf("NICK %s", n)
}

// Determine nick currently used with the connection.
func (irc *Connection) GetNick() string {
	return irc.nickcurrent
}

// Query information about a particular nickname.
// RFC 1459: https://tools.ietf.org/html/rfc1459#section-4.5.2
func (irc *Connection) Whois(nick string) {
	irc.SendRawf("WHOIS %s", nick)
}

// Query information about a given nickname in the server.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.5.1
func (irc *Connection) Who(nick string) {
	irc.SendRawf("WHO %s", nick)
}

// Set different modes for a target (channel or nickname).
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.3
func (irc *Connection) Mode(target string, modestring ...string) {
	if len(modestring) > 0 {
		mode := strings.Join(modestring, " ")
		irc.SendRawf("MODE %s %s", target, mode)
		return
	}
	irc.SendRawf("MODE %s", target)
}

// A disconnect sends all buffered messages (if possible),
// stops all goroutines and then closes the socket.
func (irc *Connection) Disconnect() {
	close(irc.end)
	close(irc.pwrite)
	close(irc.pread)

	irc.Wait()
	irc.socket.Close()
	irc.socket = nil
	if irc.netsock != nil {
		irc.netsock.Close()
		irc.netsock = nil
	}
	irc.Error <- errors.New("Disconnect Called")
}

// Reconnect to a server using the current connection.
func (irc *Connection) Reconnect() error {
	irc.end = make(chan struct{})
	return irc.Connect(irc.server)
}

// Connect to a given server using the current connection configuration.
// This function also takes care of identification if a password is provided.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1
func (irc *Connection) Connect(server string) error {
	irc.server = server
	irc.stopped = false

	// make sure everything is ready for connection
	if len(irc.server) == 0 {
		return errors.New("empty 'server'")
	}
	if strings.Count(irc.server, ":") != 1 {
		return errors.New("wrong number of ':' in address")
	}
	if strings.Index(irc.server, ":") == 0 {
		return errors.New("hostname is missing")
	}
	if strings.Index(irc.server, ":") == len(irc.server)-1 {
		return errors.New("port missing")
	}
	// check for valid range
	ports := strings.Split(irc.server, ":")[1]
	port, err := strconv.Atoi(ports)
	if err != nil {
		return errors.New("extracting port failed")
	}
	if !((port >= 0) && (port <= 65535)) {
		return errors.New("port number outside valid range")
	}
	if irc.Log == nil {
		return errors.New("'Log' points to nil")
	}
	if len(irc.nick) == 0 {
		return errors.New("empty 'user'")
	}
	if len(irc.user) == 0 {
		return errors.New("empty 'user'")
	}

	if irc.UseTLS {
		if irc.netsock, err = net.DialTimeout("tcp", irc.server, irc.Timeout); err == nil {
			irc.socket = tls.Client(irc.netsock, irc.TLSConfig)
		}
	} else {
		irc.socket, err = net.DialTimeout("tcp", irc.server, irc.Timeout)
	}
	if err != nil {
		return err
	}
	irc.Log.Printf("Connected to %s (%s)\n", irc.server, irc.socket.RemoteAddr())

	irc.pread = make(chan string, 10)
	irc.pwrite = make(chan string, 10)
	irc.Error = make(chan error, 2)
	irc.Add(3)
	go irc.readLoop()
	go irc.writeLoop()
	go irc.pingLoop()
	if len(irc.Password) > 0 {
		irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
	}
	irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
	irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
	return nil
}

// Create a connection with the (publicly visible) nickname and username.
// The nickname is later used to address the user. Returns nil if nick
// or user are empty.
func IRC(nick, user string) *Connection {
	// catch invalid values
	if len(nick) == 0 {
		return nil
	}
	if len(user) == 0 {
		return nil
	}

	irc := &Connection{
		nick:      nick,
		user:      user,
		Log:       log.New(os.Stdout, "", log.LstdFlags),
		end:       make(chan struct{}),
		Version:   VERSION,
		KeepAlive: 4 * time.Minute,
		Timeout:   1 * time.Minute,
		PingFreq:  15 * time.Minute,
	}
	irc.setupCallbacks()
	return irc
}
<commit_msg>removed irc.Disconnect() comment<commit_after>// Copyright 2009 Thomas Jager <mail@jager.no>  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
This package provides an event based IRC client library. It allows to
register callbacks for the events you need to handle. Its features
include handling standard CTCP, reconnecting on errors and detecting
stones servers.
Details of the IRC protocol can be found in the following RFCs:
https://tools.ietf.org/html/rfc1459
https://tools.ietf.org/html/rfc2810
https://tools.ietf.org/html/rfc2811
https://tools.ietf.org/html/rfc2812
https://tools.ietf.org/html/rfc2813
The details of the client-to-client protocol (CTCP) can be found here: http://www.irchelp.org/irchelp/rfc/ctcpspec.html
*/

package irc

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	VERSION = "go-ircevent v2.1"
)

// Read data from a connection. To be used as a goroutine.
func (irc *Connection) readLoop() {
	defer irc.Done()
	br := bufio.NewReaderSize(irc.socket, 512)

	for {
		select {
		case <-irc.end:
			return
		default:
			// Set a read deadline based on the combined timeout and ping frequency
			// We should ALWAYS have received a response from the server within the timeout
			// after our own pings
			if irc.socket != nil {
				irc.socket.SetReadDeadline(time.Now().Add(irc.Timeout + irc.PingFreq))
			}

			msg, err := br.ReadString('\n')

			// We got past our blocking read, so bin timeout
			if irc.socket != nil {
				var zero time.Time
				irc.socket.SetReadDeadline(zero)
			}

			if err != nil {
				irc.Error <- err
				break
			}

			irc.lastMessage = time.Now()
			msg = msg[:len(msg)-2] //Remove \r\n
			event := &Event{Raw: msg}
			if msg[0] == ':' {
				if i := strings.Index(msg, " "); i > -1 {
					event.Source = msg[1:i]
					msg = msg[i+1 : len(msg)]

				} else {
					irc.Log.Printf("Misformed msg from server: %#s\n", msg)
				}

				if i, j := strings.Index(event.Source, "!"), strings.Index(event.Source, "@"); i > -1 && j > -1 {
					event.Nick = event.Source[0:i]
					event.User = event.Source[i+1 : j]
					event.Host = event.Source[j+1 : len(event.Source)]
				}
			}

			split := strings.SplitN(msg, " :", 2)
			args := strings.Split(split[0], " ")
			event.Code = strings.ToUpper(args[0])
			event.Arguments = args[1:]
			if len(split) > 1 {
				event.Arguments = append(event.Arguments, split[1])
			}

			/* XXX: len(args) == 0: args should be empty */

			irc.RunCallbacks(event)
		}
	}
	return
}

// Loop to write to a connection. To be used as a goroutine.
func (irc *Connection) writeLoop() {
	defer irc.Done()
	for {
		select {
		case <-irc.end:
			return
		default:
			b, ok := <-irc.pwrite
			if !ok || b == "" || irc.socket == nil {
				return
			}

			if irc.Debug {
				irc.Log.Printf("--> %s\n", b)
			}

			// Set a write deadline based on the time out
			irc.socket.SetWriteDeadline(time.Now().Add(irc.Timeout))

			_, err := irc.socket.Write([]byte(b))

			// Past blocking write, bin timeout
			var zero time.Time
			irc.socket.SetWriteDeadline(zero)

			if err != nil {
				irc.Error <- err
				return
			}
		}
	}
	return
}

// Pings the server if we have not received any messages for 5 minutes
// to keep the connection alive. To be used as a goroutine.
func (irc *Connection) pingLoop() {
	defer irc.Done()
	ticker := time.NewTicker(1 * time.Minute) // Tick every minute for monitoring
	ticker2 := time.NewTicker(irc.PingFreq)   // Tick at the ping frequency.
	for {
		select {
		case <-ticker.C:
			//Ping if we haven't received anything from the server within the keep alive period
			if time.Since(irc.lastMessage) >= irc.KeepAlive {
				irc.SendRawf("PING %d", time.Now().UnixNano())
			}
		case <-ticker2.C:
			//Ping at the ping frequency
			irc.SendRawf("PING %d", time.Now().UnixNano())
			//Try to recapture nickname if it's not as configured.
			if irc.nick != irc.nickcurrent {
				irc.nickcurrent = irc.nick
				irc.SendRawf("NICK %s", irc.nick)
			}
		case <-irc.end:
			ticker.Stop()
			ticker2.Stop()
			return
		}
	}
}

// Main loop to control the connection.
func (irc *Connection) Loop() {
	for !irc.stopped {
		err := <-irc.Error
		if irc.stopped {
			break
		}
		irc.Log.Printf("Error, disconnected: %s\n", err)
		for !irc.stopped {
			if err = irc.Reconnect(); err != nil {
				irc.Log.Printf("Error while reconnecting: %s\n", err)
				time.Sleep(1 * time.Second)
			} else {
				break
			}
		}
	}
}

// Quit the current connection and disconnect from the server
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.6
func (irc *Connection) Quit() {
	irc.SendRaw("QUIT")
	irc.stopped = true
}

// Use the connection to join a given channel.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.1
func (irc *Connection) Join(channel string) {
	irc.pwrite <- fmt.Sprintf("JOIN %s\r\n", channel)
}

// Leave a given channel.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.2
func (irc *Connection) Part(channel string) {
	irc.pwrite <- fmt.Sprintf("PART %s\r\n", channel)
}

// Send a notification to a nickname. This is similar to Privmsg but must not receive replies.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
func (irc *Connection) Notice(target, message string) {
	irc.pwrite <- fmt.Sprintf("NOTICE %s :%s\r\n", target, message)
}

// Send a formated notification to a nickname.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
func (irc *Connection) Noticef(target, format string, a ...interface{}) {
	irc.Notice(target, fmt.Sprintf(format, a...))
}

// Send (action) message to a target (channel or nickname).
// No clear RFC on this one...
func (irc *Connection) Action(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :\001ACTION %s\001\r\n", target, message)
}

// Send (private) message to a target (channel or nickname).
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.1
func (irc *Connection) Privmsg(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :%s\r\n", target, message)
}

// Send formated string to specified target (channel or nickname).
func (irc *Connection) Privmsgf(target, format string, a ...interface{}) {
	irc.Privmsg(target, fmt.Sprintf(format, a...))
}

// Send raw string.
func (irc *Connection) SendRaw(message string) {
	irc.pwrite <- message + "\r\n"
}

// Send raw formated string.
func (irc *Connection) SendRawf(format string, a ...interface{}) {
	irc.SendRaw(fmt.Sprintf(format, a...))
}

// Set (new) nickname.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.2
func (irc *Connection) Nick(n string) {
	irc.nick = n
	irc.SendRawf("NICK %s", n)
}

// Determine nick currently used with the connection.
func (irc *Connection) GetNick() string {
	return irc.nickcurrent
}

// Query information about a particular nickname.
// RFC 1459: https://tools.ietf.org/html/rfc1459#section-4.5.2
func (irc *Connection) Whois(nick string) {
	irc.SendRawf("WHOIS %s", nick)
}

// Query information about a given nickname in the server.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.5.1
func (irc *Connection) Who(nick string) {
	irc.SendRawf("WHO %s", nick)
}

// Set different modes for a target (channel or nickname).
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.3
func (irc *Connection) Mode(target string, modestring ...string) {
	if len(modestring) > 0 {
		mode := strings.Join(modestring, " ")
		irc.SendRawf("MODE %s %s", target, mode)
		return
	}
	irc.SendRawf("MODE %s", target)
}

// A disconnect sends all buffered messages (if possible),
// stops all goroutines and then closes the socket.
func (irc *Connection) Disconnect() {
	close(irc.end)
	close(irc.pwrite)
	close(irc.pread)

	irc.Wait()
	irc.socket.Close()
	irc.socket = nil
	if irc.netsock != nil {
		irc.netsock.Close()
		irc.netsock = nil
	}
	irc.Error <- errors.New("Disconnect Called")
}

// Reconnect to a server using the current connection.
func (irc *Connection) Reconnect() error {
	irc.end = make(chan struct{})
	return irc.Connect(irc.server)
}

// Connect to a given server using the current connection configuration.
// This function also takes care of identification if a password is provided.
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1
func (irc *Connection) Connect(server string) error {
	irc.server = server
	irc.stopped = false

	// make sure everything is ready for connection
	if len(irc.server) == 0 {
		return errors.New("empty 'server'")
	}
	if strings.Count(irc.server, ":") != 1 {
		return errors.New("wrong number of ':' in address")
	}
	if strings.Index(irc.server, ":") == 0 {
		return errors.New("hostname is missing")
	}
	if strings.Index(irc.server, ":") == len(irc.server)-1 {
		return errors.New("port missing")
	}
	// check for valid range
	ports := strings.Split(irc.server, ":")[1]
	port, err := strconv.Atoi(ports)
	if err != nil {
		return errors.New("extracting port failed")
	}
	if !((port >= 0) && (port <= 65535)) {
		return errors.New("port number outside valid range")
	}
	if irc.Log == nil {
		return errors.New("'Log' points to nil")
	}
	if len(irc.nick) == 0 {
		return errors.New("empty 'user'")
	}
	if len(irc.user) == 0 {
		return errors.New("empty 'user'")
	}

	if irc.UseTLS {
		if irc.netsock, err = net.DialTimeout("tcp", irc.server, irc.Timeout); err == nil {
			irc.socket = tls.Client(irc.netsock, irc.TLSConfig)
		}
	} else {
		irc.socket, err = net.DialTimeout("tcp", irc.server, irc.Timeout)
	}
	if err != nil {
		return err
	}
	irc.Log.Printf("Connected to %s (%s)\n", irc.server, irc.socket.RemoteAddr())

	irc.pread = make(chan string, 10)
	irc.pwrite = make(chan string, 10)
	irc.Error = make(chan error, 2)
	irc.Add(3)
	go irc.readLoop()
	go irc.writeLoop()
	go irc.pingLoop()
	if len(irc.Password) > 0 {
		irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
	}
	irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
	irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
	return nil
}

// Create a connection with the (publicly visible) nickname and username.
// The nickname is later used to address the user. Returns nil if nick
// or user are empty.
func IRC(nick, user string) *Connection {
	// catch invalid values
	if len(nick) == 0 {
		return nil
	}
	if len(user) == 0 {
		return nil
	}

	irc := &Connection{
		nick:      nick,
		user:      user,
		Log:       log.New(os.Stdout, "", log.LstdFlags),
		end:       make(chan struct{}),
		Version:   VERSION,
		KeepAlive: 4 * time.Minute,
		Timeout:   1 * time.Minute,
		PingFreq:  15 * time.Minute,
	}
	irc.setupCallbacks()
	return irc
}
<|endoftext|>


<commit_before>package gojenkins

type Build struct {
	Id     string `json:"id"`
	Number int    `json:"number"`
	Url    string `json:"url"`

	FullDisplayName string `json:"fullDisplayName"`
	Description     string `json:"description"`

	Timestamp         int `json:"timestamp"`
	Duration          int `json:"duration"`
	EstimatedDuration int `json:"estimatedDuration"`

	Building bool   `json:"building"`
	KeepLog  bool   `json:"keepLog"`
	Result   string `json:"result"`
}

type Job struct {
	Name  string `json:"name"`
	Url   string `json:"url"`
	Color string `json:"color"`

	Buildable   bool   `json:"buildable"`
	DisplayName string `json:"displayName"`
	Description string `json:"description"`

	LastCompletedBuild    Build `json:"lastCompletedBuild"`
	LastFailedBuild       Build `json:"lastFailedBuild"`
	LastStableBuild       Build `json:"lastStableBuild"`
	LastSuccessfulBuild   Build `json:"lastSuccessfulBuild"`
	LastUnstableBuild     Build `json:"lastUnstableBuild"`
	LastUnsuccessfulBuild Build `json:"lastUnsuccessfulBuild"`
}

type MavenJobItem struct {
	XMLName                          struct{}             `xml:"maven2-moduleset"`
	Plugin                           string               `xml:"plugin,attr"`
	Actions                          string               `xml:"actions"`
	Description                      string               `xml:"description"`
	KeepDependencies                 string               `xml:"keepDependencies"`
	Properties                       JobProperties        `xml:"properties"`
	Scm                              Scm                  `xml:"scm"`
	CanRoam                          string               `xml:"canRoam"`
	Disabled                         string               `xml:"disabled"`
	BlockBuildWhenDownstreamBuilding string               `xml:"blockBuildWhenDownstreamBuilding"`
	BlockBuildWhenUpstreamBuilding   string               `xml:"blockBuildWhenUpstreamBuilding"`
	Triggers                         Triggers             `xml:"triggers"`
	ConcurrentBuild                  string               `xml:"concurrentBuild"`
	Goals                            string               `xml:"goals"`
	AggregatorStyleBuild             string               `xml:"aggregatorStyleBuild"`
	IncrementalBuild                 string               `xml:"incrementalBuild"`
	IgnoreUpstremChanges             string               `xml:"ignoreUpstremChanges"`
	ArchivingDisabled                string               `xml:"archivingDisabled"`
	SiteArchivingDisabled            string               `xml:"siteArchivingDisabled"`
	FingerprintingDisabled           string               `xml:"fingerprintingDisabled"`
	ResolveDependencies              string               `xml:"resolveDependencies"`
	ProcessPlugins                   string               `xml:"processPlugins"`
	MavenValidationLevel             string               `xml:"mavenValidationLevel"`
	RunHeadless                      string               `xml:"runHeadless"`
	DisableTriggerDownstreamProjects string               `xml:"disableTriggerDownstreamProjects"`
	Settings                         JobSettings          `xml:"settings"`
	GlobalSettings                   JobSettings          `xml:"globalSettings"`
	RunPostStepsIfResult             RunPostStepsIfResult `xml:"runPostStepsIfResult"`
}

type Scm struct {
	Locations              Locations        `xml:"locations"`
	Class                  string           `xml:"class,attr"`
	Plugin                 string           `xml:"plugin,attr"`
	ExcludedRegions        string           `xml:"excludedRegions"`
	IncludedRegions        string           `xml:"includedRegions"`
	ExcludedUsers          string           `xml:"excludedUsers"`
	ExcludedRevprop        string           `xml:"excludedRevprop"`
	ExcludedCommitMessages string           `xml:"excludedCommitMessages"`
	WorkspaceUpdater       WorkspaceUpdater `xml:"workspaceUpdater"`
	IgnoreDirPropChanges   string           `xml:"ignoreDirPropChanges"`
	FilterChanglog         string           `xml:"filterChangelog"`
}

type WorkspaceUpdater struct {
	Class string `xml:"class,attr"`
}
type Locations struct {
	Location []Location
}
type Location interface {
}
type ScmSvnLocation struct {
	XMLName               struct{} `xml:"hudson.scm.SubversionSCM_-ModuleLocation"`
	Remote                string   `xml:"remote"`
	Local                 string   `xml:"local"`
	DepthOption           string   `xml:"depthOption"`
	IgnoreExternalsOption string   `xml:"ignoreExternalsOption"`
}
type JobSettings struct {
	Class      string `xml:"class,attr"`
	JobSetting []JobSetting
}

type JobSetting struct {
}
type JobProperties struct {
}
type Triggers struct {
	Trigger []Trigger
}
type Trigger interface {
}
type ScmTrigger struct {
	XMLName               struct{} `xml:"hudson.triggers.SCMTrigger"`
	Spec                  string   `xml:"spec"`
	IgnorePostCommitHooks string   `xml:"ignorePostCommitHooks"`
}
type RunPostStepsIfResult struct {
	Name          string `xml:"name"`
	Ordinal       string `xml:"ordinal"`
	Color         string `xml:"color"`
	CompleteBuild string `xml:"completeBuild"`
}
<commit_msg>Add postbuilder tag when creating a new job<commit_after>package gojenkins

import "encoding/xml"

type Build struct {
	Id     string `json:"id"`
	Number int    `json:"number"`
	Url    string `json:"url"`

	FullDisplayName string `json:"fullDisplayName"`
	Description     string `json:"description"`

	Timestamp         int `json:"timestamp"`
	Duration          int `json:"duration"`
	EstimatedDuration int `json:"estimatedDuration"`

	Building bool   `json:"building"`
	KeepLog  bool   `json:"keepLog"`
	Result   string `json:"result"`
}

type Job struct {
	Name  string `json:"name"`
	Url   string `json:"url"`
	Color string `json:"color"`

	Buildable   bool   `json:"buildable"`
	DisplayName string `json:"displayName"`
	Description string `json:"description"`

	LastCompletedBuild    Build `json:"lastCompletedBuild"`
	LastFailedBuild       Build `json:"lastFailedBuild"`
	LastStableBuild       Build `json:"lastStableBuild"`
	LastSuccessfulBuild   Build `json:"lastSuccessfulBuild"`
	LastUnstableBuild     Build `json:"lastUnstableBuild"`
	LastUnsuccessfulBuild Build `json:"lastUnsuccessfulBuild"`
}

type MavenJobItem struct {
	XMLName                          struct{}             `xml:"maven2-moduleset"`
	Plugin                           string               `xml:"plugin,attr"`
	Actions                          string               `xml:"actions"`
	Description                      string               `xml:"description"`
	KeepDependencies                 string               `xml:"keepDependencies"`
	Properties                       JobProperties        `xml:"properties"`
	Scm                              Scm                  `xml:"scm"`
	CanRoam                          string               `xml:"canRoam"`
	Disabled                         string               `xml:"disabled"`
	BlockBuildWhenDownstreamBuilding string               `xml:"blockBuildWhenDownstreamBuilding"`
	BlockBuildWhenUpstreamBuilding   string               `xml:"blockBuildWhenUpstreamBuilding"`
	Triggers                         Triggers             `xml:"triggers"`
	ConcurrentBuild                  string               `xml:"concurrentBuild"`
	Goals                            string               `xml:"goals"`
	AggregatorStyleBuild             string               `xml:"aggregatorStyleBuild"`
	IncrementalBuild                 string               `xml:"incrementalBuild"`
	IgnoreUpstremChanges             string               `xml:"ignoreUpstremChanges"`
	ArchivingDisabled                string               `xml:"archivingDisabled"`
	SiteArchivingDisabled            string               `xml:"siteArchivingDisabled"`
	FingerprintingDisabled           string               `xml:"fingerprintingDisabled"`
	ResolveDependencies              string               `xml:"resolveDependencies"`
	ProcessPlugins                   string               `xml:"processPlugins"`
	MavenValidationLevel             string               `xml:"mavenValidationLevel"`
	RunHeadless                      string               `xml:"runHeadless"`
	DisableTriggerDownstreamProjects string               `xml:"disableTriggerDownstreamProjects"`
	Settings                         JobSettings          `xml:"settings"`
	GlobalSettings                   JobSettings          `xml:"globalSettings"`
	RunPostStepsIfResult             RunPostStepsIfResult `xml:"runPostStepsIfResult"`
	Postbuilders                     PostBuilders         `xml:"postbuilders"`
}

type Scm struct {
	Locations              Locations        `xml:"locations"`
	Class                  string           `xml:"class,attr"`
	Plugin                 string           `xml:"plugin,attr"`
	ExcludedRegions        string           `xml:"excludedRegions"`
	IncludedRegions        string           `xml:"includedRegions"`
	ExcludedUsers          string           `xml:"excludedUsers"`
	ExcludedRevprop        string           `xml:"excludedRevprop"`
	ExcludedCommitMessages string           `xml:"excludedCommitMessages"`
	WorkspaceUpdater       WorkspaceUpdater `xml:"workspaceUpdater"`
	IgnoreDirPropChanges   string           `xml:"ignoreDirPropChanges"`
	FilterChanglog         string           `xml:"filterChangelog"`
}

type WorkspaceUpdater struct {
	Class string `xml:"class,attr"`
}
type Locations struct {
	Location []Location
}
type Location interface {
}
type ScmSvnLocation struct {
	XMLName               struct{} `xml:"hudson.scm.SubversionSCM_-ModuleLocation"`
	Remote                string   `xml:"remote"`
	Local                 string   `xml:"local"`
	DepthOption           string   `xml:"depthOption"`
	IgnoreExternalsOption string   `xml:"ignoreExternalsOption"`
}

type PostBuilders struct {
	XMLName     xml.Name `xml:"postbuilders"`
	PostBuilder []PostBuilder
}

type PostBuilder interface {
}

type ShellBuilder struct {
	XMLName xml.Name `xml:"hudson.tasks.Shell"`
	Command string   `xml:"command"`
}

type JobSettings struct {
	Class      string `xml:"class,attr"`
	JobSetting []JobSetting
}

type JobSetting struct {
}
type JobProperties struct {
}
type Triggers struct {
	Trigger []Trigger
}
type Trigger interface {
}
type ScmTrigger struct {
	XMLName               struct{} `xml:"hudson.triggers.SCMTrigger"`
	Spec                  string   `xml:"spec"`
	IgnorePostCommitHooks string   `xml:"ignorePostCommitHooks"`
}
type RunPostStepsIfResult struct {
	Name          string `xml:"name"`
	Ordinal       string `xml:"ordinal"`
	Color         string `xml:"color"`
	CompleteBuild string `xml:"completeBuild"`
}
<|endoftext|>


<commit_before>package caffmux

import (
	"caffmux/logs"
	"strings"
)

const (
	LevelError = iota
	LevelWarning
	LevelInfo
	LevelDebug
)

var CaffLogger *logs.CaffLogger

func SetLevel(l int) {
	CaffLogger.SetLevel(l)
}

func SetLogger(adapter string, jsonconf string) error {
	err := CaffLogger.SetLogger(adapter, jsonconf)
	if err != nil {
		return err
	}
	return nil
}

func Error(v ...interface{}) {
	CaffLogger.Error(generateFormatString(len(v)), v...)
}

func Warning(v ...interface{}) {
	CaffLogger.Warning(generateFormatString(len(v)), v...)
}

func Info(v ...interface{}) {
	CaffLogger.Info(generateFormatString(len(v)), v...)
}

func Debug(v ...interface{}) {
	CaffLogger.Debug(generateFormatString(len(v)), v...)
}

func generateFormatString(n int) string {
	return strings.Repeat("%v ", n)
}
<commit_msg>modify logs package<commit_after>package caffmux

import (
	"github.com/caffmux/logs"
	"strings"
)

const (
	LevelError = iota
	LevelWarning
	LevelInfo
	LevelDebug
)

var CaffLogger *logs.CaffLogger

func SetLevel(l int) {
	CaffLogger.SetLevel(l)
}

func SetLogger(adapter string, jsonconf string) error {
	err := CaffLogger.SetLogger(adapter, jsonconf)
	if err != nil {
		return err
	}
	return nil
}

func Error(v ...interface{}) {
	CaffLogger.Error(generateFormatString(len(v)), v...)
}

func Warning(v ...interface{}) {
	CaffLogger.Warning(generateFormatString(len(v)), v...)
}

func Info(v ...interface{}) {
	CaffLogger.Info(generateFormatString(len(v)), v...)
}

func Debug(v ...interface{}) {
	CaffLogger.Debug(generateFormatString(len(v)), v...)
}

func generateFormatString(n int) string {
	return strings.Repeat("%v ", n)
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"os"
)

func isDebug() bool {
	if len(os.Getenv("BOT_DEBUG")) > 0 {
		return true
	}
	return false
}

func logSetup() {
	log.SetOutput(os.Stderr)
	if !isDebug() {
		temp, e := ioutil.TempFile("", "review-bot-log.")
		if e != nil {
			panic(e)
		}
		log.Println("Log file at", temp.Name())
		log.SetOutput(temp)
	}
}
<commit_msg>log name<commit_after>package main

import (
	"io/ioutil"
	"log"
	"os"
)

func isDebug() bool {
	if len(os.Getenv("BOT_DEBUG")) > 0 {
		return true
	}
	return false
}

func logSetup() {
	log.SetOutput(os.Stderr)
	if !isDebug() {
		temp, e := ioutil.TempFile("", "rivi-bot-log.")
		if e != nil {
			panic(e)
		}
		log.Println("Log file at", temp.Name())
		log.SetOutput(temp)
	}
}
<|endoftext|>