<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path"

	"github.com/howeyc/gopass"
)

const holbertonDirName string = ".holberton"
const holbertonIntranetTokenFile string = "intranet_token"

// To unmarshal the responses from the server about tokens
type tokenAuthFromServer struct {
	Success bool   `json:"success"`
	Token   string `json:"token"`
	Message string `json:"message"`
}

// To marshal and unmarshal to and from the config file
type tokenAuth struct {
	Email string `json:"email"`
	Token string `json:"token"`
}

// Will get the URL, handle all of the Holberton intranet auth, and return the body
func getWithHolbertonAuth(urlToGet string) (string, error) {
	auth, err := getEmailAndToken()
	if err != nil {
		return "", err
	}

	urlToGetWithParams := urlToGet + "?user_email=" + auth.Email + "&user_token=" + auth.Token

	resp, err := http.Get(urlToGetWithParams)
	if err != nil {
		return "", err
	}

	if resp.StatusCode == 401 { // Unauthorized = try again
		fmt.Println("Authentication was refused, probably because your token expired.")
		// login (will overwrite the config file), and make the call again
		if _, err := login(); err != nil {
			return "", err
		}
		return getWithHolbertonAuth(urlToGet)
	}

	// 200 = let's proceed
	if resp.StatusCode == 200 {
		buf := new(bytes.Buffer)
		buf.ReadFrom(resp.Body)
		return buf.String(), nil // we did not close resp.Body
	}

	var m tokenAuthFromServer
	if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return "", err
	}
	// Other HTTP error code = get the error message and stop there
	return "", errors.New(m.Message)
}

// Will get it one way or another: will try getting the file first, fetch it later
// Returns the email of the user and its token
func getEmailAndToken() (tokenAuth, error) {
	holbertonDirPath, err := ensureHolbertonPersonalDirectory()
	if err != nil {
		return tokenAuth{}, err
	}
	holbertonIntranetTokenFilePath := path.Join(holbertonDirPath, holbertonIntranetTokenFile)
	if _, err := os.Stat(holbertonIntranetTokenFilePath); os.IsNotExist(err) { // File doesn't exist
		fmt.Println("You never authenticated on this computer before.")
		auth, err := login()
		if err != nil {
			return tokenAuth{}, err
		}
		return auth, nil // Returning the token we got from the login
	}

	// File exists -> read in the file
	fmt.Println("Auth token found on this computer.")

	configFile, err := os.Open(holbertonIntranetTokenFilePath)
	if err != nil {
		return tokenAuth{}, err
	}
	defer configFile.Close()

	var t tokenAuth

	if err := json.NewDecoder(configFile).Decode(&t); err != nil {
		return tokenAuth{}, err
	}

	return t, nil
}

// Ensures the config repository (~/.holberton) exists, creates it otherwise
func ensureHolbertonPersonalDirectory() (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}
	holbertonDirPath := path.Join(usr.HomeDir, holbertonDirName)
	if _, err := os.Stat(holbertonDirPath); os.IsNotExist(err) {
		if err := os.Mkdir(holbertonDirPath, 0700); err != nil {
			return "", err
		}
	}
	return holbertonDirPath, nil
}

// Will login, fetch the token from the intranet, write it to the config file with the user's email, and return them both
func login() (tokenAuth, error) {

	// Prompting the user for login info
	var email string
	var password []byte

	fmt.Println("Please login with your intranet's credentials.")
	fmt.Print("Email: ")
	fmt.Scanln(&email)

	fmt.Print("Password: ")
	password, err := gopass.GetPasswd()
	if err != nil {
		return tokenAuth{}, err
	}

	// Fetch the token from the endpoint
	resp, err := http.PostForm("https://intranet.hbtn.io/token", url.Values{"email": {email}, "password": {string(password)}})
	if err != nil {
		return tokenAuth{}, err
	}
	defer resp.Body.Close()

	var m tokenAuthFromServer
	if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return tokenAuth{}, err
	}

	// Deal with errors informed by the server (Invalid credentials, ...)
	if !m.Success {
		return tokenAuth{}, errors.New(m.Message)
	}
	token := m.Token

	// We want to store the email AND the token
	tokenToWrite, err := json.Marshal(tokenAuth{Email: email, Token: token})
	if err != nil {
		return tokenAuth{}, err
	}

	// Let's make sure the config directory exists first, and get the path we want
	holbertonDirPath, err := ensureHolbertonPersonalDirectory()
	if err != nil {
		return tokenAuth{}, err
	}
	holbertonIntranetTokenFilePath := path.Join(holbertonDirPath, holbertonIntranetTokenFile)
	if err := ioutil.WriteFile(holbertonIntranetTokenFilePath, []byte(tokenToWrite), 0700); err != nil {
		return tokenAuth{}, err
	}

	return tokenAuth{Email: email, Token: token}, nil
}
<commit_msg>Replacing a costly string concat with a cheaper sprintf<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path"

	"github.com/howeyc/gopass"
)

const holbertonDirName string = ".holberton"
const holbertonIntranetTokenFile string = "intranet_token"

// To unmarshal the responses from the server about tokens
type tokenAuthFromServer struct {
	Success bool   `json:"success"`
	Token   string `json:"token"`
	Message string `json:"message"`
}

// To marshal and unmarshal to and from the config file
type tokenAuth struct {
	Email string `json:"email"`
	Token string `json:"token"`
}

// Will get the URL, handle all of the Holberton intranet auth, and return the body
func getWithHolbertonAuth(urlToGet string) (string, error) {
	auth, err := getEmailAndToken()
	if err != nil {
		return "", err
	}

	urlToGetWithParams := fmt.Sprintf("%s?user_email=%s&user_token=%s", urlToGet, auth.Email, auth.Token)

	resp, err := http.Get(urlToGetWithParams)
	if err != nil {
		return "", err
	}

	if resp.StatusCode == 401 { // Unauthorized = try again
		fmt.Println("Authentication was refused, probably because your token expired.")
		// login (will overwrite the config file), and make the call again
		if _, err := login(); err != nil {
			return "", err
		}
		return getWithHolbertonAuth(urlToGet)
	}

	// 200 = let's proceed
	if resp.StatusCode == 200 {
		buf := new(bytes.Buffer)
		buf.ReadFrom(resp.Body)
		return buf.String(), nil // we did not close resp.Body
	}

	var m tokenAuthFromServer
	if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return "", err
	}
	// Other HTTP error code = get the error message and stop there
	return "", errors.New(m.Message)
}

// Will get it one way or another: will try getting the file first, fetch it later
// Returns the email of the user and its token
func getEmailAndToken() (tokenAuth, error) {
	holbertonDirPath, err := ensureHolbertonPersonalDirectory()
	if err != nil {
		return tokenAuth{}, err
	}
	holbertonIntranetTokenFilePath := path.Join(holbertonDirPath, holbertonIntranetTokenFile)
	if _, err := os.Stat(holbertonIntranetTokenFilePath); os.IsNotExist(err) { // File doesn't exist
		fmt.Println("You never authenticated on this computer before.")
		auth, err := login()
		if err != nil {
			return tokenAuth{}, err
		}
		return auth, nil // Returning the token we got from the login
	}

	// File exists -> read in the file
	fmt.Println("Auth token found on this computer.")

	configFile, err := os.Open(holbertonIntranetTokenFilePath)
	if err != nil {
		return tokenAuth{}, err
	}
	defer configFile.Close()

	var t tokenAuth

	if err := json.NewDecoder(configFile).Decode(&t); err != nil {
		return tokenAuth{}, err
	}

	return t, nil
}

// Ensures the config repository (~/.holberton) exists, creates it otherwise
func ensureHolbertonPersonalDirectory() (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}
	holbertonDirPath := path.Join(usr.HomeDir, holbertonDirName)
	if _, err := os.Stat(holbertonDirPath); os.IsNotExist(err) {
		if err := os.Mkdir(holbertonDirPath, 0700); err != nil {
			return "", err
		}
	}
	return holbertonDirPath, nil
}

// Will login, fetch the token from the intranet, write it to the config file with the user's email, and return them both
func login() (tokenAuth, error) {

	// Prompting the user for login info
	var email string
	var password []byte

	fmt.Println("Please login with your intranet's credentials.")
	fmt.Print("Email: ")
	fmt.Scanln(&email)

	fmt.Print("Password: ")
	password, err := gopass.GetPasswd()
	if err != nil {
		return tokenAuth{}, err
	}

	// Fetch the token from the endpoint
	resp, err := http.PostForm("https://intranet.hbtn.io/token", url.Values{"email": {email}, "password": {string(password)}})
	if err != nil {
		return tokenAuth{}, err
	}
	defer resp.Body.Close()

	var m tokenAuthFromServer
	if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return tokenAuth{}, err
	}

	// Deal with errors informed by the server (Invalid credentials, ...)
	if !m.Success {
		return tokenAuth{}, errors.New(m.Message)
	}
	token := m.Token

	// We want to store the email AND the token
	tokenToWrite, err := json.Marshal(tokenAuth{Email: email, Token: token})
	if err != nil {
		return tokenAuth{}, err
	}

	// Let's make sure the config directory exists first, and get the path we want
	holbertonDirPath, err := ensureHolbertonPersonalDirectory()
	if err != nil {
		return tokenAuth{}, err
	}
	holbertonIntranetTokenFilePath := path.Join(holbertonDirPath, holbertonIntranetTokenFile)
	if err := ioutil.WriteFile(holbertonIntranetTokenFilePath, []byte(tokenToWrite), 0700); err != nil {
		return tokenAuth{}, err
	}

	return tokenAuth{Email: email, Token: token}, nil
}
<|endoftext|>


<commit_before>package http

import (
	"context"
	"database/sql"
	"encoding/json"
	"net/http"
	"time"

	"github.com/amitu/amalgam"
	"github.com/amitu/amalgam/django"
	"github.com/juju/errors"
)

type shttp struct {
	mux      *http.ServeMux
	addr     string
	proxies  map[string]string
	ctx      context.Context
	sessions django.SessionStore
}

func NewHTTPService(
	addr string, ctx context.Context, sessions django.SessionStore,
) HTTPService {
	h := &shttp{
		http.NewServeMux(), addr, make(map[string]string), ctx, sessions,
	}
	h.register()
	return h
}

func (s *shttp) ListenAndServe(listen string) {
	http.ListenAndServe(listen, s)
}

func (s *shttp) Redirect(w http.ResponseWriter, r *http.Request, url string, code int) {
	http.Redirect(w, r, url, code)
}

func (s *shttp) Register(pattern string, fn http.HandlerFunc) {
	amalgam.LOGGER.Debug("registering pattern", "pattern", pattern)
	s.mux.HandleFunc(pattern, fn)
}

func (s *shttp) GetOrCreateTracker(
	ctx context.Context, r *http.Request,
) (string, error) {
	var tracker string = ""
	cookies := r.Cookies()
	for i := 0; i < len(cookies); i++ {
		cookie := cookies[i]
		if cookie.Name == "trackerid" {
			tracker = cookie.Value
			break
		}
	}

	if tracker != "" {
		return tracker, nil
	}

	// This code should / will get executed only if the user is rBot.
	api_key := r.URL.Query()["api_key"]
	if len(api_key) == 0 {
		return "", nil
	}

	user, err := s.GetUser(ctx)
	if err != nil {
		return "", errors.Trace(err)
	}

	tr, err := amalgam.QueryIntoInt(
		ctx,
		`
			SELECT
				id
			FROM
				acko_tracker
			WHERE
				user_id = $1
			LIMIT 1

		`, user.ID(),
	)
	if err != nil {
		if err.Error() != sql.ErrNoRows.Error() {
			return "", errors.Trace(err)
		}

		tid, err := amalgam.QueryIntoInt(
			ctx,
			`
				INSERT INTO
					acko_tracker(user_id, code_version, landing_page,
						initial_ip, is_mobile, is_app, device, os,
						created_on, browser, browser_version, referer)
				VALUES
					($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
				RETURNING
					id

			`, user.ID(), "", "http://127.0.0.1", "127.0.0.1", false, false,
			"api", "Ubuntu", time.Now(), "", "", "",
		)
		if err != nil {
			return "", errors.Trace(err)
		}

		return amalgam.EncodeID(int64(tid), "acko_tracker"), nil
	}

	return amalgam.EncodeID(int64(tr), "acko_tracker"), nil
}

type EResult struct {
	Result  interface{}                 `json:"result,omitempty"`
	Errors  map[string][]amalgam.AError `json:"errors,omitempty"`
	Success bool                        `json:"success"`
}

func (s *shttp) Reject(
	w http.ResponseWriter,
	reason map[string][]amalgam.AError,
) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	j, err := json.Marshal(&EResult{Errors: reason, Success: false})
	if err != nil {
		amalgam.LOGGER.Error(
			"reject_json_failed", "err", errors.ErrorStack(err),
		)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Error(w, string(j), http.StatusOK)
}

func (s *shttp) Respond(w http.ResponseWriter, result interface{}) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	j, err := json.Marshal(&EResult{Result: result, Success: true})
	if err != nil {
		amalgam.LOGGER.Error(
			"respond_json_failed", "err", errors.ErrorStack(err),
		)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(j)
}
<commit_msg>tracker fixes for now<commit_after>package http

import (
	"context"
	"database/sql"
	"encoding/json"
	"net/http"
	"time"

	"github.com/amitu/amalgam"
	"github.com/amitu/amalgam/django"
	"github.com/juju/errors"
)

type shttp struct {
	mux      *http.ServeMux
	addr     string
	proxies  map[string]string
	ctx      context.Context
	sessions django.SessionStore
}

func NewHTTPService(
	addr string, ctx context.Context, sessions django.SessionStore,
) HTTPService {
	h := &shttp{
		http.NewServeMux(), addr, make(map[string]string), ctx, sessions,
	}
	h.register()
	return h
}

func (s *shttp) ListenAndServe(listen string) {
	http.ListenAndServe(listen, s)
}

func (s *shttp) Redirect(w http.ResponseWriter, r *http.Request, url string, code int) {
	http.Redirect(w, r, url, code)
}

func (s *shttp) Register(pattern string, fn http.HandlerFunc) {
	amalgam.LOGGER.Debug("registering pattern", "pattern", pattern)
	s.mux.HandleFunc(pattern, fn)
}

func (s *shttp) GetOrCreateTracker(
	ctx context.Context, r *http.Request,
) (string, error) {
	var tracker string = ""
	cookies := r.Cookies()
	for i := 0; i < len(cookies); i++ {
		cookie := cookies[i]
		if cookie.Name == "trackerid" {
			tracker = cookie.Value
			break
		}
	}

	if tracker != "" {
		return tracker, nil
	}

	// This code should / will get executed only if the user is rBot.
	api_key := r.URL.Query()["api_key"]
	if len(api_key) == 0 {
		return "", nil
	}

	user, err := s.GetUser(ctx)
	if err != nil {
		return "", errors.Trace(err)
	}

	tr, err := amalgam.QueryIntoInt(
		ctx,
		`
			SELECT
				id
			FROM
				acko_tracker
			WHERE
				user_id = $1
			LIMIT 1

		`, user.ID(),
	)
	if err != nil {
		if err.Error() != sql.ErrNoRows.Error() {
			return "", errors.Trace(err)
		}

		tid, err := amalgam.QueryIntoInt(
			ctx,
			`
				INSERT INTO
					acko_tracker(user_id, code_version, landing_page,
						initial_ip, is_mobile, is_app, device, os,
						created_on, browser, browser_version, referer,
						user_agent, updated_on)
				VALUES
					($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
				RETURNING
					id

			`, user.ID(), "", "http://127.0.0.1", "127.0.0.1", false, false,
			"api", "Ubuntu", time.Now(), "", "", "", "", time.Now(),
		)
		if err != nil {
			return "", errors.Trace(err)
		}

		return amalgam.EncodeID(int64(tid), "acko_tracker"), nil
	}

	return amalgam.EncodeID(int64(tr), "acko_tracker"), nil
}

type EResult struct {
	Result  interface{}                 `json:"result,omitempty"`
	Errors  map[string][]amalgam.AError `json:"errors,omitempty"`
	Success bool                        `json:"success"`
}

func (s *shttp) Reject(
	w http.ResponseWriter,
	reason map[string][]amalgam.AError,
) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	j, err := json.Marshal(&EResult{Errors: reason, Success: false})
	if err != nil {
		amalgam.LOGGER.Error(
			"reject_json_failed", "err", errors.ErrorStack(err),
		)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Error(w, string(j), http.StatusOK)
}

func (s *shttp) Respond(w http.ResponseWriter, result interface{}) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	j, err := json.Marshal(&EResult{Result: result, Success: true})
	if err != nil {
		amalgam.LOGGER.Error(
			"respond_json_failed", "err", errors.ErrorStack(err),
		)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(j)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/urfave/cli.v1"
)

const (
	cliVersion = "0.0.1"
	envTypeDev = "dev"

	flagNameEnv        = "env"
	flagNameRepoPath   = "repo-path"
	flagNameForeground = "foreground"

	commandNameBuild   = "build"
	commandDescBuild   = "Updates module images"
	commandNameLog     = "log"
	commandDescLog     = "Logs module's container output to stdout"
	commandNameRestart = "restart"
	commandDescRestart = "Restarts module containers"
	commandNameSSH     = "ssh"
	commandDescSSH     = "Starts a shell session within a module's container"
	commandNameStart   = "start"
	commandDescStart   = "Start module containers"
	commandNameStop    = "stop"
	commandDescStop    = "Stops module containers"
	commandNameTest    = "test"
	commandDescTest    = "Runs module tests"
)

var (
	moduleCommandArgsUsage           = fmt.Sprintf("[module (%s)] [arguments...]", modulesToString(false))
	moduleCommandArgsUsageWithoutAll = fmt.Sprintf("[module (%s)] [arguments...]", modulesToString(true))
)

func main() {
	var (
		app    = cli.NewApp()
		gopath = os.Getenv("GOPATH")

		defaultRepoPath string
	)

	// First, make sure that there is a go path.
	if len(gopath) < 1 {
		exit(1, nil, "", "$GOPATH must be defined for gophrctl to work.")
	}

	// Next, create the default repo path
	defaultRepoPath = filepath.Join(gopath, "src/github.com/skeswa/gophr")

	// Then, describe command metadata.
	app.Name = "gophrctl"
	app.Usage = "Manages the gophr development and deployment environment."
	app.Version = cliVersion
	app.HelpName = "gophrctl"

	// After that, set the global flags for gophrctl.
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  flagNameEnv,
			Value: envTypeDev,
			Usage: "gophr execution environment",
		},
		cli.StringFlag{
			Name:  flagNameRepoPath,
			Value: defaultRepoPath,
			Usage: "path to the gophr repository",
		},
	}

	// Next, reference every command capable to gophrctl.
	app.Commands = []cli.Command{
		// Build command.
		{
			Name:      commandNameBuild,
			Usage:     commandDescBuild,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameBuild, c)
				if err != nil {
					exit(exitCodeBuildFailed, c, commandNameBuild, err)
				}

				m.build(c, false)
				return nil
			},
		},

		// Log command.
		{
			Name:      commandNameLog,
			Usage:     commandDescLog,
			ArgsUsage: moduleCommandArgsUsageWithoutAll,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameLog, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Restart command.
		{
			Name:      commandNameRestart,
			Usage:     commandDescRestart,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameRestart, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// SSH command.
		{
			Name:      commandNameSSH,
			Usage:     commandDescSSH,
			ArgsUsage: moduleCommandArgsUsageWithoutAll,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameSSH, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Start command.
		{
			Name:      commandNameStart,
			Usage:     commandDescStart,
			ArgsUsage: moduleCommandArgsUsage,

			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  flagNameForeground + ",-f",
					Usage: "makes the container run in the foreground",
				},
			},

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameStart, c)
				if err != nil {
					exit(exitCodeStartFailed, c, commandNameStart, err)
				}

				m.start(c, false)
				return nil
			},
		},

		// Stop command.
		{
			Name:      commandNameStop,
			Usage:     commandDescStop,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameStop, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Test command.
		{
			Name:      commandNameTest,
			Usage:     commandDescTest,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameTest, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},
	}

	// Lastly, execute the command line application.
	app.Run(os.Args)
}
<commit_msg>fixed an oopsie with the cli<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/urfave/cli.v1"
)

const (
	cliVersion = "0.0.1"
	envTypeDev = "dev"

	flagNameEnv        = "env"
	flagNameRepoPath   = "repo-path"
	flagNameForeground = "foreground"

	commandNameBuild   = "build"
	commandDescBuild   = "Updates module images"
	commandNameLog     = "log"
	commandDescLog     = "Logs module's container output to stdout"
	commandNameRestart = "restart"
	commandDescRestart = "Restarts module containers"
	commandNameSSH     = "ssh"
	commandDescSSH     = "Starts a shell session within a module's container"
	commandNameStart   = "start"
	commandDescStart   = "Start module containers"
	commandNameStop    = "stop"
	commandDescStop    = "Stops module containers"
	commandNameTest    = "test"
	commandDescTest    = "Runs module tests"
)

var (
	moduleCommandArgsUsage           = fmt.Sprintf("[%s] [arguments...]", modulesToString(false))
	moduleCommandArgsUsageWithoutAll = fmt.Sprintf("[%s] [arguments...]", modulesToString(true))
)

func main() {
	var (
		app    = cli.NewApp()
		gopath = os.Getenv("GOPATH")

		defaultRepoPath string
	)

	// First, make sure that there is a go path.
	if len(gopath) < 1 {
		exit(1, nil, "", "$GOPATH must be defined for gophrctl to work.")
	}

	// Next, create the default repo path
	defaultRepoPath = filepath.Join(gopath, "src/github.com/skeswa/gophr")

	// Then, describe command metadata.
	app.Name = "gophrctl"
	app.Usage = "Manages the gophr development and deployment environment."
	app.Version = cliVersion
	app.HelpName = "gophrctl"

	// After that, set the global flags for gophrctl.
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  flagNameEnv,
			Value: envTypeDev,
			Usage: "gophr execution environment",
		},
		cli.StringFlag{
			Name:  flagNameRepoPath,
			Value: defaultRepoPath,
			Usage: "path to the gophr repository",
		},
	}

	// Next, reference every command capable to gophrctl.
	app.Commands = []cli.Command{
		// Build command.
		{
			Name:      commandNameBuild,
			Usage:     commandDescBuild,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameBuild, c)
				if err != nil {
					exit(exitCodeBuildFailed, c, commandNameBuild, err)
				}

				m.build(c, false)
				return nil
			},
		},

		// Log command.
		{
			Name:      commandNameLog,
			Usage:     commandDescLog,
			ArgsUsage: moduleCommandArgsUsageWithoutAll,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameLog, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Restart command.
		{
			Name:      commandNameRestart,
			Usage:     commandDescRestart,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameRestart, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// SSH command.
		{
			Name:      commandNameSSH,
			Usage:     commandDescSSH,
			ArgsUsage: moduleCommandArgsUsageWithoutAll,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameSSH, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Start command.
		{
			Name:      commandNameStart,
			Usage:     commandDescStart,
			ArgsUsage: moduleCommandArgsUsage,

			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  flagNameForeground + ",f",
					Usage: "makes the container run in the foreground",
				},
			},

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameStart, c)
				if err != nil {
					exit(exitCodeStartFailed, c, commandNameStart, err)
				}

				m.start(c, false)
				return nil
			},
		},

		// Stop command.
		{
			Name:      commandNameStop,
			Usage:     commandDescStop,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameStop, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},

		// Test command.
		{
			Name:      commandNameTest,
			Usage:     commandDescTest,
			ArgsUsage: moduleCommandArgsUsage,

			Action: func(c *cli.Context) error {
				// Read the module.
				m, err := readModule(commandNameTest, c)
				if err != nil {
					return err
				}

				return m.build(c, false)
			},
		},
	}

	// Lastly, execute the command line application.
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package ethstate

import (
	"math/big"

	"github.com/ethereum/eth-go/ethcrypto"
	"github.com/ethereum/eth-go/ethlog"
	"github.com/ethereum/eth-go/ethtrie"
	"github.com/ethereum/eth-go/ethutil"
)

var statelogger = ethlog.NewLogger("STATE")

// States within the ethereum protocol are used to store anything
// within the merkle trie. States take care of caching and storing
// nested states. It's the general query interface to retrieve:
// * Contracts
// * Accounts
type State struct {
	// The trie for this structure
	Trie *ethtrie.Trie

	stateObjects map[string]*StateObject

	manifest *Manifest
}

// Create a new state from a given trie
func New(trie *ethtrie.Trie) *State {
	return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
}

// Retrieve the balance from the given address or 0 if object not found
func (self *State) GetBalance(addr []byte) *big.Int {
	stateObject := self.GetStateObject(addr)
	if stateObject != nil {
		return stateObject.Balance
	}

	return ethutil.Big0
}

func (self *State) GetNonce(addr []byte) uint64 {
	stateObject := self.GetStateObject(addr)
	if stateObject != nil {
		return stateObject.Nonce
	}

	return 0
}

//
// Setting, updating & deleting state object methods
//

// Update the given state object and apply it to state trie
func (self *State) UpdateStateObject(stateObject *StateObject) {
	addr := stateObject.Address()

	ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)

	self.Trie.Update(string(addr), string(stateObject.RlpEncode()))
}

// Delete the given state object and delete it from the state trie
func (self *State) DeleteStateObject(stateObject *StateObject) {
	self.Trie.Delete(string(stateObject.Address()))

	delete(self.stateObjects, string(stateObject.Address()))
}

// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
	addr = ethutil.Address(addr)

	stateObject := self.stateObjects[string(addr)]
	if stateObject != nil {
		return stateObject
	}

	data := self.Trie.Get(string(addr))
	if len(data) == 0 {
		return nil
	}

	stateObject = NewStateObjectFromBytes(addr, []byte(data))
	self.stateObjects[string(addr)] = stateObject

	return stateObject
}

// Retrieve a state object or create a new state object if nil
func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
	stateObject := self.GetStateObject(addr)
	if stateObject == nil {
		stateObject = self.NewStateObject(addr)
	}

	return stateObject
}

// Create a state object whether it exist in the trie or not
func (self *State) NewStateObject(addr []byte) *StateObject {
	addr = ethutil.Address(addr)

	statelogger.Infof("(+) %x\n", addr)

	stateObject := NewStateObject(addr)
	self.stateObjects[string(addr)] = stateObject

	return stateObject
}

// Deprecated
func (self *State) GetAccount(addr []byte) *StateObject {
	return self.GetOrNewStateObject(addr)
}

//
// Setting, copying of the state methods
//

func (s *State) Cmp(other *State) bool {
	return s.Trie.Cmp(other.Trie)
}

func (self *State) Copy() *State {
	if self.Trie != nil {
		state := New(self.Trie.Copy())
		for k, stateObject := range self.stateObjects {
			state.stateObjects[k] = stateObject.Copy()
		}

		return state
	}

	return nil
}

func (self *State) Set(state *State) {
	if state == nil {
		panic("Tried setting 'state' to nil through 'Set'")
	}

	self.Trie = state.Trie
	self.stateObjects = state.stateObjects
}

func (s *State) Root() interface{} {
	return s.Trie.Root
}

// Resets the trie and all siblings
func (s *State) Reset() {
	s.Trie.Undo()

	// Reset all nested states
	for _, stateObject := range s.stateObjects {
		if stateObject.State == nil {
			continue
		}

		//stateObject.state.Reset()
		stateObject.Reset()
	}

	s.Empty()
}

// Syncs the trie and all siblings
func (s *State) Sync() {
	// Sync all nested states
	for _, stateObject := range s.stateObjects {
		//s.UpdateStateObject(stateObject)

		if stateObject.State == nil {
			continue
		}

		stateObject.State.Sync()
	}

	s.Trie.Sync()

	s.Empty()
}

func (self *State) Empty() {
	self.stateObjects = make(map[string]*StateObject)
}

func (self *State) Update() {
	for _, stateObject := range self.stateObjects {
		if stateObject.remove {
			self.DeleteStateObject(stateObject)
		} else {
			stateObject.Sync()

			self.UpdateStateObject(stateObject)
		}
	}

	// FIXME trie delete is broken
	valid, t2 := ethtrie.ParanoiaCheck(self.Trie)
	if !valid {
		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.Trie.Root, t2.Root)

		self.Trie = t2
	}
}

func (self *State) Manifest() *Manifest {
	return self.manifest
}

// Debug stuff
func (self *State) CreateOutputForDiff() {
	for _, stateObject := range self.stateObjects {
		stateObject.CreateOutputForDiff()
	}
}
<commit_msg>Changed log statements<commit_after>package ethstate

import (
	"math/big"

	"github.com/ethereum/eth-go/ethcrypto"
	"github.com/ethereum/eth-go/ethlog"
	"github.com/ethereum/eth-go/ethtrie"
	"github.com/ethereum/eth-go/ethutil"
)

var statelogger = ethlog.NewLogger("STATE")

// States within the ethereum protocol are used to store anything
// within the merkle trie. States take care of caching and storing
// nested states. It's the general query interface to retrieve:
// * Contracts
// * Accounts
type State struct {
	// The trie for this structure
	Trie *ethtrie.Trie

	stateObjects map[string]*StateObject

	manifest *Manifest
}

// Create a new state from a given trie
func New(trie *ethtrie.Trie) *State {
	return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
}

// Retrieve the balance from the given address or 0 if object not found
func (self *State) GetBalance(addr []byte) *big.Int {
	stateObject := self.GetStateObject(addr)
	if stateObject != nil {
		return stateObject.Balance
	}

	return ethutil.Big0
}

func (self *State) GetNonce(addr []byte) uint64 {
	stateObject := self.GetStateObject(addr)
	if stateObject != nil {
		return stateObject.Nonce
	}

	return 0
}

//
// Setting, updating & deleting state object methods
//

// Update the given state object and apply it to state trie
func (self *State) UpdateStateObject(stateObject *StateObject) {
	addr := stateObject.Address()

	ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)

	self.Trie.Update(string(addr), string(stateObject.RlpEncode()))
}

// Delete the given state object and delete it from the state trie
func (self *State) DeleteStateObject(stateObject *StateObject) {
	self.Trie.Delete(string(stateObject.Address()))

	delete(self.stateObjects, string(stateObject.Address()))
}

// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
	addr = ethutil.Address(addr)

	stateObject := self.stateObjects[string(addr)]
	if stateObject != nil {
		return stateObject
	}

	data := self.Trie.Get(string(addr))
	if len(data) == 0 {
		return nil
	}

	stateObject = NewStateObjectFromBytes(addr, []byte(data))
	self.stateObjects[string(addr)] = stateObject

	return stateObject
}

// Retrieve a state object or create a new state object if nil
func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
	stateObject := self.GetStateObject(addr)
	if stateObject == nil {
		stateObject = self.NewStateObject(addr)
	}

	return stateObject
}

// Create a state object whether it exist in the trie or not
func (self *State) NewStateObject(addr []byte) *StateObject {
	addr = ethutil.Address(addr)

	statelogger.Debugf("(+) %x\n", addr)

	stateObject := NewStateObject(addr)
	self.stateObjects[string(addr)] = stateObject

	return stateObject
}

// Deprecated
func (self *State) GetAccount(addr []byte) *StateObject {
	return self.GetOrNewStateObject(addr)
}

//
// Setting, copying of the state methods
//

func (s *State) Cmp(other *State) bool {
	return s.Trie.Cmp(other.Trie)
}

func (self *State) Copy() *State {
	if self.Trie != nil {
		state := New(self.Trie.Copy())
		for k, stateObject := range self.stateObjects {
			state.stateObjects[k] = stateObject.Copy()
		}

		return state
	}

	return nil
}

func (self *State) Set(state *State) {
	if state == nil {
		panic("Tried setting 'state' to nil through 'Set'")
	}

	self.Trie = state.Trie
	self.stateObjects = state.stateObjects
}

func (s *State) Root() interface{} {
	return s.Trie.Root
}

// Resets the trie and all siblings
func (s *State) Reset() {
	s.Trie.Undo()

	// Reset all nested states
	for _, stateObject := range s.stateObjects {
		if stateObject.State == nil {
			continue
		}

		//stateObject.state.Reset()
		stateObject.Reset()
	}

	s.Empty()
}

// Syncs the trie and all siblings
func (s *State) Sync() {
	// Sync all nested states
	for _, stateObject := range s.stateObjects {
		//s.UpdateStateObject(stateObject)

		if stateObject.State == nil {
			continue
		}

		stateObject.State.Sync()
	}

	s.Trie.Sync()

	s.Empty()
}

func (self *State) Empty() {
	self.stateObjects = make(map[string]*StateObject)
}

func (self *State) Update() {
	for _, stateObject := range self.stateObjects {
		if stateObject.remove {
			self.DeleteStateObject(stateObject)
		} else {
			stateObject.Sync()

			self.UpdateStateObject(stateObject)
		}
	}

	// FIXME trie delete is broken
	valid, t2 := ethtrie.ParanoiaCheck(self.Trie)
	if !valid {
		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.Trie.Root, t2.Root)

		self.Trie = t2
	}
}

func (self *State) Manifest() *Manifest {
	return self.manifest
}

// Debug stuff
func (self *State) CreateOutputForDiff() {
	for _, stateObject := range self.stateObjects {
		stateObject.CreateOutputForDiff()
	}
}
<|endoftext|>


<commit_before>package eval

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"syscall"

	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/util"
)

// Exception represents an elvish exception. It is both a Value accessible to
// elvishscript, and the type of error returned by public facing evaluation
// methods like (*Evaler)PEval.
type Exception struct {
	Cause     error
	Traceback *util.SourceContext
}

// OK is a pointer to the zero value of Exception, representing the absense of
// exception.
var OK = &Exception{}

func (exc *Exception) Error() string {
	return exc.Cause.Error()
}

func (exc *Exception) Pprint(indent string) string {
	buf := new(bytes.Buffer)
	// Error message
	var msg string
	if pprinter, ok := exc.Cause.(util.Pprinter); ok {
		msg = pprinter.Pprint(indent)
	} else {
		msg = "\033[31;1m" + exc.Cause.Error() + "\033[m"
	}
	fmt.Fprintf(buf, "Exception: %s\n", msg)
	buf.WriteString("Traceback:")

	for tb := exc.Traceback; tb != nil; tb = tb.Next {
		buf.WriteString("\n" + indent + "  ")
		tb.Pprint(buf, indent+"    ")
	}

	return buf.String()
}

func (exc *Exception) Kind() string {
	return "exception"
}

func (exc *Exception) Repr(indent int) string {
	if exc.Cause == nil {
		return "$ok"
	}
	if r, ok := exc.Cause.(Reprer); ok {
		return r.Repr(indent)
	}
	return "?(error " + parse.Quote(exc.Cause.Error()) + ")"
}

func (exc *Exception) Bool() bool {
	return exc.Cause == nil
}

// PipelineError represents the errors of pipelines, in which multiple commands
// may error.
type PipelineError struct {
	Errors []*Exception
}

func (pe PipelineError) Repr(indent int) string {
	// TODO Make a more generalized ListReprBuilder and use it here.
	b := new(bytes.Buffer)
	b.WriteString("?(multi-error")
	elemIndent := indent + len("?(multi-error ")
	for _, e := range pe.Errors {
		if indent > 0 {
			b.WriteString("\n" + strings.Repeat(" ", elemIndent))
		} else {
			b.WriteString(" ")
		}
		b.WriteString(e.Repr(elemIndent))
	}
	b.WriteString(")")
	return b.String()
}

func (pe PipelineError) Error() string {
	b := new(bytes.Buffer)
	b.WriteString("(")
	for i, e := range pe.Errors {
		if i > 0 {
			b.WriteString(" | ")
		}
		if e == nil || e.Cause == nil {
			b.WriteString("<nil>")
		} else {
			b.WriteString(e.Error())
		}
	}
	b.WriteString(")")
	return b.String()
}

// ComposeExceptionsFromPipeline takes a slice of Exception pointers and
// composes a suitable error. If all elements of the slice are either nil or OK,
// a nil is returned. If there is exactly non-nil non-OK Exception, it is
// returned. Otherwise, a PipelineError built from the slice is returned, with
// nil items turned into OK's for easier access from elvishscript.
func ComposeExceptionsFromPipeline(excs []*Exception) error {
	newexcs := make([]*Exception, len(excs))
	notOK, lastNotOK := 0, 0
	for i, e := range excs {
		if e == nil {
			newexcs[i] = OK
		} else {
			newexcs[i] = e
			if e.Cause != nil {
				notOK++
				lastNotOK = i
			}
		}
	}
	switch notOK {
	case 0:
		return nil
	case 1:
		return newexcs[lastNotOK]
	default:
		return PipelineError{newexcs}
	}
}

// Flow is a special type of error used for control flows.
type Flow uint

// Control flows.
const (
	Return Flow = iota
	Break
	Continue
)

var flowNames = [...]string{
	"return", "break", "continue",
}

func (f Flow) Repr(int) string {
	return "?(" + f.Error() + ")"
}

func (f Flow) Error() string {
	if f >= Flow(len(flowNames)) {
		return fmt.Sprintf("!(BAD FLOW: %v)", f)
	}
	return flowNames[f]
}

func (f Flow) Pprint(string) string {
	return "\033[33;1m" + f.Error() + "\033[m"
}

// ExternalCmdExit contains the exit status of external commands. If the
// command was stopped rather than terminated, the Pid field contains the pid
// of the process.
type ExternalCmdExit struct {
	syscall.WaitStatus
	CmdName string
	Pid     int
}

func NewExternalCmdExit(name string, ws syscall.WaitStatus, pid int) error {
	if ws.Exited() && ws.ExitStatus() == 0 {
		return nil
	}
	if !ws.Stopped() {
		pid = 0
	}
	return ExternalCmdExit{ws, name, pid}
}

func FakeExternalCmdExit(name string, exit int, sig syscall.Signal) ExternalCmdExit {
	return ExternalCmdExit{syscall.WaitStatus(exit<<8 + int(sig)), name, 0}
}

func (exit ExternalCmdExit) Error() string {
	ws := exit.WaitStatus
	quotedName := parse.Quote(exit.CmdName)
	switch {
	case ws.Exited():
		return quotedName + " exited with " + strconv.Itoa(ws.ExitStatus())
	case ws.Signaled():
		msg := quotedName + " killed by signal " + ws.Signal().String()
		if ws.CoreDump() {
			msg += " (core dumped)"
		}
		return msg
	case ws.Stopped():
		msg := quotedName + " stopped by signal " + fmt.Sprintf("%s (pid=%d)", ws.StopSignal(), exit.Pid)
		trap := ws.TrapCause()
		if trap != -1 {
			msg += fmt.Sprintf(" (trapped %v)", trap)
		}
		return msg
	default:
		return fmt.Sprint(quotedName, " has unknown WaitStatus ", ws)
	}
}
<commit_msg>Print causes when pprinting PipelineError.<commit_after>package eval

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"syscall"

	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/util"
)

// Exception represents an elvish exception. It is both a Value accessible to
// elvishscript, and the type of error returned by public facing evaluation
// methods like (*Evaler)PEval.
type Exception struct {
	Cause     error
	Traceback *util.SourceContext
}

// OK is a pointer to the zero value of Exception, representing the absense of
// exception.
var OK = &Exception{}

func (exc *Exception) Error() string {
	return exc.Cause.Error()
}

func (exc *Exception) Pprint(indent string) string {
	buf := new(bytes.Buffer)
	// Error message
	var msg string
	if pprinter, ok := exc.Cause.(util.Pprinter); ok {
		msg = pprinter.Pprint(indent)
	} else {
		msg = "\033[31;1m" + exc.Cause.Error() + "\033[m"
	}
	fmt.Fprintf(buf, "Exception: %s\n", msg)
	buf.WriteString(indent + "Traceback:")

	for tb := exc.Traceback; tb != nil; tb = tb.Next {
		buf.WriteString("\n" + indent + "  ")
		tb.Pprint(buf, indent+"    ")
	}

	if pipeExcs, ok := exc.Cause.(PipelineError); ok {
		buf.WriteString("\n" + indent + "Caused by:")
		for _, e := range pipeExcs.Errors {
			buf.WriteString("\n" + indent + "  " + e.Pprint(indent+"  "))
		}
	}

	return buf.String()
}

func (exc *Exception) Kind() string {
	return "exception"
}

func (exc *Exception) Repr(indent int) string {
	if exc.Cause == nil {
		return "$ok"
	}
	if r, ok := exc.Cause.(Reprer); ok {
		return r.Repr(indent)
	}
	return "?(error " + parse.Quote(exc.Cause.Error()) + ")"
}

func (exc *Exception) Bool() bool {
	return exc.Cause == nil
}

// PipelineError represents the errors of pipelines, in which multiple commands
// may error.
type PipelineError struct {
	Errors []*Exception
}

func (pe PipelineError) Repr(indent int) string {
	// TODO Make a more generalized ListReprBuilder and use it here.
	b := new(bytes.Buffer)
	b.WriteString("?(multi-error")
	elemIndent := indent + len("?(multi-error ")
	for _, e := range pe.Errors {
		if indent > 0 {
			b.WriteString("\n" + strings.Repeat(" ", elemIndent))
		} else {
			b.WriteString(" ")
		}
		b.WriteString(e.Repr(elemIndent))
	}
	b.WriteString(")")
	return b.String()
}

func (pe PipelineError) Error() string {
	b := new(bytes.Buffer)
	b.WriteString("(")
	for i, e := range pe.Errors {
		if i > 0 {
			b.WriteString(" | ")
		}
		if e == nil || e.Cause == nil {
			b.WriteString("<nil>")
		} else {
			b.WriteString(e.Error())
		}
	}
	b.WriteString(")")
	return b.String()
}

// ComposeExceptionsFromPipeline takes a slice of Exception pointers and
// composes a suitable error. If all elements of the slice are either nil or OK,
// a nil is returned. If there is exactly non-nil non-OK Exception, it is
// returned. Otherwise, a PipelineError built from the slice is returned, with
// nil items turned into OK's for easier access from elvishscript.
func ComposeExceptionsFromPipeline(excs []*Exception) error {
	newexcs := make([]*Exception, len(excs))
	notOK, lastNotOK := 0, 0
	for i, e := range excs {
		if e == nil {
			newexcs[i] = OK
		} else {
			newexcs[i] = e
			if e.Cause != nil {
				notOK++
				lastNotOK = i
			}
		}
	}
	switch notOK {
	case 0:
		return nil
	case 1:
		return newexcs[lastNotOK]
	default:
		return PipelineError{newexcs}
	}
}

// Flow is a special type of error used for control flows.
type Flow uint

// Control flows.
const (
	Return Flow = iota
	Break
	Continue
)

var flowNames = [...]string{
	"return", "break", "continue",
}

func (f Flow) Repr(int) string {
	return "?(" + f.Error() + ")"
}

func (f Flow) Error() string {
	if f >= Flow(len(flowNames)) {
		return fmt.Sprintf("!(BAD FLOW: %v)", f)
	}
	return flowNames[f]
}

func (f Flow) Pprint(string) string {
	return "\033[33;1m" + f.Error() + "\033[m"
}

// ExternalCmdExit contains the exit status of external commands. If the
// command was stopped rather than terminated, the Pid field contains the pid
// of the process.
type ExternalCmdExit struct {
	syscall.WaitStatus
	CmdName string
	Pid     int
}

func NewExternalCmdExit(name string, ws syscall.WaitStatus, pid int) error {
	if ws.Exited() && ws.ExitStatus() == 0 {
		return nil
	}
	if !ws.Stopped() {
		pid = 0
	}
	return ExternalCmdExit{ws, name, pid}
}

func FakeExternalCmdExit(name string, exit int, sig syscall.Signal) ExternalCmdExit {
	return ExternalCmdExit{syscall.WaitStatus(exit<<8 + int(sig)), name, 0}
}

func (exit ExternalCmdExit) Error() string {
	ws := exit.WaitStatus
	quotedName := parse.Quote(exit.CmdName)
	switch {
	case ws.Exited():
		return quotedName + " exited with " + strconv.Itoa(ws.ExitStatus())
	case ws.Signaled():
		msg := quotedName + " killed by signal " + ws.Signal().String()
		if ws.CoreDump() {
			msg += " (core dumped)"
		}
		return msg
	case ws.Stopped():
		msg := quotedName + " stopped by signal " + fmt.Sprintf("%s (pid=%d)", ws.StopSignal(), exit.Pid)
		trap := ws.TrapCause()
		if trap != -1 {
			msg += fmt.Sprintf(" (trapped %v)", trap)
		}
		return msg
	default:
		return fmt.Sprint(quotedName, " has unknown WaitStatus ", ws)
	}
}
<|endoftext|>


<commit_before>//
// instagram.go
// Copyright 2017 Konstantin Dovnar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// http://www.apache.org/licenses/LICENSE-2.0
//

// Package instagram helps you with requesting to Instagram without a key.
package instagram

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// GetAccountByUsername try to find account by username.
func GetAccountByUsername(username string) (Account, error) {
	url := fmt.Sprintf(accountInfoURL, username)
	info, err := getJSONFromURL(url)
	if err != nil {
		return Account{}, err
	}
	account, ok := getFromAccountPage(info)
	if !ok {
		return account, errors.New("Can't parse account")
	}
	return account, nil
}

// GetMediaByURL try to find media by url.
// URL should be like https://www.instagram.com/p/12376OtT5o/
func GetMediaByURL(url string) (Media, error) {
	code := strings.Split(url, "/")[4]
	return GetMediaByCode(code)
}

// GetMediaByCode try to find media by code.
// Code can be find in URL to media, after p/.
// If URL to media is https://www.instagram.com/p/12376OtT5o/,
// then code of the media is 12376OtT5o.
func GetMediaByCode(code string) (Media, error) {
	url := fmt.Sprintf(mediaInfoURL, code)
	info, err := getJSONFromURL(url)
	if err != nil {
		return Media{}, err
	}
	media, ok := getFromMediaPage(info)
	if !ok {
		return media, errors.New("Can't parse media")
	}
	return media, nil
}

// GetAccountMedia try to get slice of user's media.
// Limit set how much media you need.
func GetAccountMedia(username string, limit uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	available := true
	medias := []Media{}
	for available && count < limit {
		url := fmt.Sprintf(accountMediaURL, username, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		available, _ = jsonBody["more_available"].(bool)

		items, _ := jsonBody["items"].([]interface{})
		for _, item := range items {
			if count >= limit {
				return medias, nil
			}
			count++
			media, ok := getFromAccountMediaList(item)
			if ok {
				medias = append(medias, media)
				maxID = media.ID
			}
		}
	}
	return medias, nil
}

// GetAllAccountMedia try to get slice of all user's media.
// It's function the same as GetAccountMedia,
// except limit = count of user's media.
func GetAllAccountMedia(username string) ([]Media, error) {
	account, err := GetAccountByUsername(username)
	if err != nil {
		return nil, err
	}
	count := uint16(account.MediaCount)
	medias, err := GetAccountMedia(username, count)
	if err != nil {
		return nil, err
	}
	return medias, nil
}

// GetLocationMedia try to get slice of last location's media.
// The id is a facebook location id.
// The limit set how much media you need.
func GetLocationMedia(id string, limit uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	hasNext := true
	medias := []Media{}
	for hasNext && count < limit {
		url := fmt.Sprintf(locationURL, id, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		jsonBody, _ = jsonBody["location"].(map[string]interface{})
		jsonBody, _ = jsonBody["media"].(map[string]interface{})

		nodes, _ := jsonBody["nodes"].([]interface{})
		for _, node := range nodes {
			if count >= limit {
				return medias, nil
			}
			count++
			media, ok := getFromSearchMediaList(node)
			if ok {
				medias = append(medias, media)
			}
		}

		jsonBody, _ = jsonBody["page_info"].(map[string]interface{})
		hasNext, _ = jsonBody["has_next_page"].(bool)
		maxID, _ = jsonBody["end_cursor"].(string)
	}
	return medias, nil
}

// GetLocationTopMedia try to get array of top location's media.
// The id is a facebook location id.
// Length of returned array is 9.
func GetLocationTopMedia(id string) ([9]Media, error) {
	url := fmt.Sprintf(locationURL, id, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return [9]Media{}, err
	}
	jsonBody, _ = jsonBody["location"].(map[string]interface{})
	jsonBody, _ = jsonBody["top_posts"].(map[string]interface{})

	medias := [9]Media{}
	nodes, _ := jsonBody["nodes"].([]interface{})
	for i, node := range nodes {
		media, ok := getFromSearchMediaList(node)
		if ok {
			medias[i] = media
		}
	}
	return medias, nil
}

// GetLocationByID try to find location info by id.
// The id is a facebook location id.
func GetLocationByID(id string) (Location, error) {
	url := fmt.Sprintf(locationURL, id, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return Location{}, err
	}

	location, ok := getFromLocationPage(jsonBody)
	if !ok {
		return Location{}, errors.New("Can't parse location")
	}
	return location, nil
}

// GetTagMedia try to get slice of last tag's media.
// The limit set how much media you need.
func GetTagMedia(tag string, quantity uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	hasNext := true
	medias := []Media{}
	for hasNext && count < quantity {
		url := fmt.Sprintf(tagURL, tag, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		jsonBody, _ = jsonBody["tag"].(map[string]interface{})
		jsonBody, _ = jsonBody["media"].(map[string]interface{})

		nodes, _ := jsonBody["nodes"].([]interface{})
		for _, node := range nodes {
			if count >= quantity {
				return medias, nil
			}
			count++
			media, ok := getFromSearchMediaList(node)
			if ok {
				medias = append(medias, media)
			}
		}

		jsonBody, _ = jsonBody["page_info"].(map[string]interface{})
		hasNext, _ = jsonBody["has_next_page"].(bool)
		maxID, _ = jsonBody["end_cursor"].(string)
	}
	return medias, nil
}

// GetTagTopMedia try to get array of top tag's media.
// Length of returned array is 9.
func GetTagTopMedia(tag string) ([9]Media, error) {
	url := fmt.Sprintf(tagURL, tag, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return [9]Media{}, err
	}
	jsonBody, _ = jsonBody["tag"].(map[string]interface{})
	jsonBody, _ = jsonBody["top_posts"].(map[string]interface{})

	medias := [9]Media{}
	nodes, _ := jsonBody["nodes"].([]interface{})
	for i, node := range nodes {
		media, ok := getFromSearchMediaList(node)
		if ok {
			medias[i] = media
		}
	}
	return medias, nil
}

// SearchForUsers try to find users by given username.
// Return slice of Account with length of 0 or more.
func SearchForUsers(username string) ([]Account, error) {
	url := fmt.Sprintf(searchURL, username)
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return nil, err
	}
	accounts := []Account{}
	users, _ := jsonBody["users"].([]interface{})
	for _, user := range users {
		account, ok := getFromSearchPage(user.(map[string]interface{}))
		if ok {
			accounts = append(accounts, account)
		}
	}
	return accounts, nil
}

func getJSONFromURL(url string) (map[string]interface{}, error) {
	resp, err := http.Get(url)
	if err != nil || resp.StatusCode == 404 {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var jsonBody map[string]interface{}
	err = json.Unmarshal(body, &jsonBody)
	if err != nil {
		return nil, err
	}

	return jsonBody, nil
}
<commit_msg>Func to get data ([]byte) from url, instead of json.<commit_after>//
// instagram.go
// Copyright 2017 Konstantin Dovnar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// http://www.apache.org/licenses/LICENSE-2.0
//

// Package instagram helps you with requesting to Instagram without a key.
package instagram

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// GetAccountByUsername try to find account by username.
func GetAccountByUsername(username string) (Account, error) {
	url := fmt.Sprintf(accountInfoURL, username)
	info, err := getJSONFromURL(url)
	if err != nil {
		return Account{}, err
	}
	account, ok := getFromAccountPage(info)
	if !ok {
		return account, errors.New("Can't parse account")
	}
	return account, nil
}

// GetMediaByURL try to find media by url.
// URL should be like https://www.instagram.com/p/12376OtT5o/
func GetMediaByURL(url string) (Media, error) {
	code := strings.Split(url, "/")[4]
	return GetMediaByCode(code)
}

// GetMediaByCode try to find media by code.
// Code can be find in URL to media, after p/.
// If URL to media is https://www.instagram.com/p/12376OtT5o/,
// then code of the media is 12376OtT5o.
func GetMediaByCode(code string) (Media, error) {
	url := fmt.Sprintf(mediaInfoURL, code)
	info, err := getJSONFromURL(url)
	if err != nil {
		return Media{}, err
	}
	media, ok := getFromMediaPage(info)
	if !ok {
		return media, errors.New("Can't parse media")
	}
	return media, nil
}

// GetAccountMedia try to get slice of user's media.
// Limit set how much media you need.
func GetAccountMedia(username string, limit uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	available := true
	medias := []Media{}
	for available && count < limit {
		url := fmt.Sprintf(accountMediaURL, username, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		available, _ = jsonBody["more_available"].(bool)

		items, _ := jsonBody["items"].([]interface{})
		for _, item := range items {
			if count >= limit {
				return medias, nil
			}
			count++
			media, ok := getFromAccountMediaList(item)
			if ok {
				medias = append(medias, media)
				maxID = media.ID
			}
		}
	}
	return medias, nil
}

// GetAllAccountMedia try to get slice of all user's media.
// It's function the same as GetAccountMedia,
// except limit = count of user's media.
func GetAllAccountMedia(username string) ([]Media, error) {
	account, err := GetAccountByUsername(username)
	if err != nil {
		return nil, err
	}
	count := uint16(account.MediaCount)
	medias, err := GetAccountMedia(username, count)
	if err != nil {
		return nil, err
	}
	return medias, nil
}

// GetLocationMedia try to get slice of last location's media.
// The id is a facebook location id.
// The limit set how much media you need.
func GetLocationMedia(id string, limit uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	hasNext := true
	medias := []Media{}
	for hasNext && count < limit {
		url := fmt.Sprintf(locationURL, id, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		jsonBody, _ = jsonBody["location"].(map[string]interface{})
		jsonBody, _ = jsonBody["media"].(map[string]interface{})

		nodes, _ := jsonBody["nodes"].([]interface{})
		for _, node := range nodes {
			if count >= limit {
				return medias, nil
			}
			count++
			media, ok := getFromSearchMediaList(node)
			if ok {
				medias = append(medias, media)
			}
		}

		jsonBody, _ = jsonBody["page_info"].(map[string]interface{})
		hasNext, _ = jsonBody["has_next_page"].(bool)
		maxID, _ = jsonBody["end_cursor"].(string)
	}
	return medias, nil
}

// GetLocationTopMedia try to get array of top location's media.
// The id is a facebook location id.
// Length of returned array is 9.
func GetLocationTopMedia(id string) ([9]Media, error) {
	url := fmt.Sprintf(locationURL, id, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return [9]Media{}, err
	}
	jsonBody, _ = jsonBody["location"].(map[string]interface{})
	jsonBody, _ = jsonBody["top_posts"].(map[string]interface{})

	medias := [9]Media{}
	nodes, _ := jsonBody["nodes"].([]interface{})
	for i, node := range nodes {
		media, ok := getFromSearchMediaList(node)
		if ok {
			medias[i] = media
		}
	}
	return medias, nil
}

// GetLocationByID try to find location info by id.
// The id is a facebook location id.
func GetLocationByID(id string) (Location, error) {
	url := fmt.Sprintf(locationURL, id, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return Location{}, err
	}

	location, ok := getFromLocationPage(jsonBody)
	if !ok {
		return Location{}, errors.New("Can't parse location")
	}
	return location, nil
}

// GetTagMedia try to get slice of last tag's media.
// The limit set how much media you need.
func GetTagMedia(tag string, quantity uint16) ([]Media, error) {
	var count uint16
	maxID := ""
	hasNext := true
	medias := []Media{}
	for hasNext && count < quantity {
		url := fmt.Sprintf(tagURL, tag, maxID)
		jsonBody, err := getJSONFromURL(url)
		if err != nil {
			return nil, err
		}
		jsonBody, _ = jsonBody["tag"].(map[string]interface{})
		jsonBody, _ = jsonBody["media"].(map[string]interface{})

		nodes, _ := jsonBody["nodes"].([]interface{})
		for _, node := range nodes {
			if count >= quantity {
				return medias, nil
			}
			count++
			media, ok := getFromSearchMediaList(node)
			if ok {
				medias = append(medias, media)
			}
		}

		jsonBody, _ = jsonBody["page_info"].(map[string]interface{})
		hasNext, _ = jsonBody["has_next_page"].(bool)
		maxID, _ = jsonBody["end_cursor"].(string)
	}
	return medias, nil
}

// GetTagTopMedia try to get array of top tag's media.
// Length of returned array is 9.
func GetTagTopMedia(tag string) ([9]Media, error) {
	url := fmt.Sprintf(tagURL, tag, "")
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return [9]Media{}, err
	}
	jsonBody, _ = jsonBody["tag"].(map[string]interface{})
	jsonBody, _ = jsonBody["top_posts"].(map[string]interface{})

	medias := [9]Media{}
	nodes, _ := jsonBody["nodes"].([]interface{})
	for i, node := range nodes {
		media, ok := getFromSearchMediaList(node)
		if ok {
			medias[i] = media
		}
	}
	return medias, nil
}

// SearchForUsers try to find users by given username.
// Return slice of Account with length of 0 or more.
func SearchForUsers(username string) ([]Account, error) {
	url := fmt.Sprintf(searchURL, username)
	jsonBody, err := getJSONFromURL(url)
	if err != nil {
		return nil, err
	}
	accounts := []Account{}
	users, _ := jsonBody["users"].([]interface{})
	for _, user := range users {
		account, ok := getFromSearchPage(user.(map[string]interface{}))
		if ok {
			accounts = append(accounts, account)
		}
	}
	return accounts, nil
}

func getJSONFromURL(url string) (map[string]interface{}, error) {
	resp, err := http.Get(url)
	if err != nil || resp.StatusCode == 404 {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var jsonBody map[string]interface{}
	err = json.Unmarshal(body, &jsonBody)
	if err != nil {
		return nil, err
	}

	return jsonBody, nil
}

func getDataFromURL(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil || resp.StatusCode == 404 {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}
<|endoftext|>


<commit_before>package sudoku

import (
	"fmt"
	"math"
)

//The actual techniques are intialized in hs_techniques.go, and actually defined in hst_*.go files.
//Techniques is ALL technies. CheapTechniques is techniques that are reasonably cheap to compute.
//ExpensiveTechniques is techniques that should only be used if all else has failed.
var Techniques []SolveTechnique
var CheapTechniques []SolveTechnique
var ExpensiveTechniques []SolveTechnique

var GuessTechnique SolveTechnique

//EVERY technique, even the weird one like Guess
var AllTechniques []SolveTechnique

//Worst case scenario, how many times we'd call HumanSolve to get a difficulty.
var MAX_DIFFICULTY_ITERATIONS int

//How close we have to get to the average to feel comfortable our difficulty is converging.
const DIFFICULTY_CONVERGENCE = 0.0005

func init() {
	MAX_DIFFICULTY_ITERATIONS = 50
}

type SolveDirections []*SolveStep

type SolveStep struct {
	//The cells that will be affected by the techinque
	TargetCells CellList
	//The cells that together lead the techinque to being valid
	PointerCells CellList
	//The numbers we will remove (or, in the case of Fill, add)
	//TODO: shouldn't this be renamed TargetNums?
	TargetNums IntSlice
	//The numbers in pointerCells that lead us to remove TargetNums from TargetCells.
	//This is only very rarely needed (at this time only for hiddenSubset techniques)
	PointerNums IntSlice
	//The general technique that underlies this step.
	Technique SolveTechnique
}

func (self *SolveStep) IsUseful(grid *Grid) bool {
	//Returns true IFF calling Apply with this step and the given grid would result in some useful work. Does not modify the gri.d

	//All of this logic is substantially recreated in Apply.

	if self.Technique == nil {
		return false
	}

	//TODO: test this.
	if self.Technique.IsFill() {
		if len(self.TargetCells) == 0 || len(self.TargetNums) == 0 {
			return false
		}
		cell := self.TargetCells[0].InGrid(grid)
		return self.TargetNums[0] != cell.Number()
	} else {
		useful := false
		for _, cell := range self.TargetCells {
			gridCell := cell.InGrid(grid)
			for _, exclude := range self.TargetNums {
				//It's right to use Possible because it includes the logic of "it's not possible if there's a number in there already"
				//TODO: ensure the comment above is correct logically.
				if gridCell.Possible(exclude) {
					useful = true
				}
			}
		}
		return useful
	}
}

func (self *SolveStep) Apply(grid *Grid) {
	//All of this logic is substantially recreated in IsUseful.
	if self.Technique.IsFill() {
		if len(self.TargetCells) == 0 || len(self.TargetNums) == 0 {
			return
		}
		cell := self.TargetCells[0].InGrid(grid)
		cell.SetNumber(self.TargetNums[0])
	} else {
		for _, cell := range self.TargetCells {
			gridCell := cell.InGrid(grid)
			for _, exclude := range self.TargetNums {
				gridCell.setExcluded(exclude, true)
			}
		}
	}
}

func (self *SolveStep) Description() string {
	result := ""
	if self.Technique.IsFill() {
		result += fmt.Sprintf("We put %s in cell %s ", self.TargetNums.Description(), self.TargetCells.Description())
	} else {
		//TODO: pluralize based on length of lists.
		result += fmt.Sprintf("We remove the possibilities %s from cells %s ", self.TargetNums.Description(), self.TargetCells.Description())
	}
	result += "because " + self.Technique.Description(self) + "."
	return result
}

func (self *SolveStep) normalize() {
	//Puts the solve step in its normal status. In practice this means that the various slices are sorted, so that the Description of them is stable.
	self.PointerCells.Sort()
	self.TargetCells.Sort()
	self.TargetNums.Sort()
	self.PointerNums.Sort()
}

func (self *Grid) HumanWalkthrough() string {
	steps := self.HumanSolution()
	return steps.Walkthrough(self)
}

func (self *Grid) HumanSolution() SolveDirections {
	clone := self.Copy()
	defer clone.Done()
	return clone.HumanSolve()
}

/*
 * The HumanSolve method is very complex due to guessing logic.
 *
 * Without guessing, the approach is very straightforward. Every move either fills a cell
 * or removes possibilities. But nothing does anything contradictory, so if they diverge
 * in path, it doesn't matter--they're still working towards the same end state (denoted by @)
 *
 *
 *
 *                   |
 *                  /|\
 *                 / | \
 *                |  |  |
 *                \  |  /
 *                 \ | /
 *                  \|/
 *                   |
 *                   V
 *                   @
 *
 *
 * In human solve, we first try the cheap techniques, and if we can't find enough options, we then additionally try
 * the expensive set of techniques. But both cheap and expensive techniques are similar in that they move us
 * towards the end state.
 *
 * For simplicity, we'll just show paths like this as a single line, even though realistically they could diverge arbitrarily.
 *
 * This all changes when you introduce branching, because at a branch point you could have chosen the wrong path
 * and at some point down that path you will discover an invalidity, which tells you you chose wrong, and
 * you'll have to unwind.
 *
 * Let's explore a puzzle that needs one branch point.
 *
 * We explore with normal techniques until we run into a point where none of hte normal techinques work.
 * This is a DIRE point, and in some cases we might just give up. But we have one last thing to try:
 * branching.
 * We then run the guess technique, which proposes multiple guess steps (big O's) that we could take.
 *
 * The technique will choose cells with only a small number of possibilities, to reduce the branching factor.
 *
 *                  |
 *                  |
 *                  V
 *                  O O O O O ...
 *
 * We will randomly pick one, and then explore all of its possibilities.
 * CRUCIALLY, at a branch point, we never have to pick another cell to explore its possibilities; for each cell,
 * if you plug in each of the possibilites and solve forward, it must result in either an invalidity (at which
 * point you try another possibility, or if they're all gone you unwind if there's a branch point above), or
 * you picked correctly and the solution lies that way. But it's never the case that picking THIS cell won't uncover
 * either the invalidity or the solution.
 * So in reality, when we come to a branch point, we can choose one cell to focus on and throw out all of the others.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *
 * But within that cell, there are multiple possibilty branches to consider.
 *
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *
 * We go through each in turn and play forward until we find either an invalidity or a solution.
 * Within each branch, we use the normal techniques as normal--remember it's actually branching but
 * converging, like in the first diagram.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *              X       @
 *
 * When we uncover an invalidity, we unwind back to the branch point and then try the next possibility.
 * We should never have to unwind above the top branch, because down one of the branches (possibly somewhere deep)
 * There MUST be a solution (assuming the puzzle is valid)
 * Obviously if we find the solution on our branch, we're good.
 *
 * But what happens if we run out of normal techinques down one of our branches and have to branch again?
 *
 * Nothing much changes, except that you DO unravel if you uncover that all of the possibilities down this
 * side lead to invalidities. You just never unravel past the first branch point.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *              O       O
 *             / \     / \
 *            4   5   6   7
 *           /    |   |    \
 *          |     |   |     |
 *          X     X   X     @
 *
 * Down one of the paths MUST lie a solution.
 *
 * The search will fail if we have a max depth limit of branching to try, because then we might not discover a
 * solution down one of the branches. A good sanity point is DIM*DIM branch points is the absolute highest; an
 * assert at that level makes sense.
 *
 * In this implementation, humanSolveHelper does the work of exploring any branch up to a point where a guess must happen.
 * If we run out of ideas on a branch, we call into guess helper, which will pick a guess and then try all of the versions of it
 * until finding one that works. This keeps humanSolveHelper pretty straighforward and keeps most of the complex guess logic out.
 */

func (self *Grid) HumanSolve() SolveDirections {
	return humanSolveHelper(self)
}

//Do we even need a helper here? Can't we just make HumanSolve actually humanSolveHelper?
//The core worker of human solve, it does all of the solving between branch points.
func humanSolveHelper(grid *Grid) []*SolveStep {

	var results []*SolveStep

	//Note: trying these all in parallel is much slower (~15x) than doing them in sequence.
	//The reason is that in sequence we bailed early as soon as we found one step; now we try them all.

	for !grid.Solved() {
		//TODO: provide hints to the techniques of where to look based on the last filled cell

		if grid.Invalid() {
			//We much have been in a branch and found an invalidity.
			//Bail immediately.
			return nil
		}

		possibilities := runTechniques(CheapTechniques, grid)

		//Now pick one to apply.
		if len(possibilities) == 0 {
			//Okay, let's try the ExpensiveTechniques, as a hail mary.
			possibilities = runTechniques(ExpensiveTechniques, grid)
			if len(possibilities) == 0 {
				//Hmm, didn't find any possivbilities. We failed. :-(
				break
			}
		}

		//TODO: consider if we should stop picking techniques based on their weight here.
		//Now that Find returns a slice instead of a single, we're already much more likely to select an "easy" technique. ... Right?

		possibilitiesWeights := make([]float64, len(possibilities))
		for i, possibility := range possibilities {
			possibilitiesWeights[i] = possibility.Technique.HumanLikelihood()
		}
		step := possibilities[randomIndexWithInvertedWeights(possibilitiesWeights)]

		results = append(results, step)
		step.Apply(grid)

	}
	if !grid.Solved() {
		//We couldn't solve the puzzle.
		//But let's do one last ditch effort and try guessing.
		guessSteps := humanSolveGuess(grid)
		if len(guessSteps) == 0 {
			//Okay, we just totally failed.
			return nil
		}
		return append(results, guessSteps...)
	}
	return results
}

//Called when we have run out of options at a given state and need to guess.
func humanSolveGuess(grid *Grid) []*SolveStep {

	//TODO: consider doing a normal solve forward from here to figure out what the right branch is and just do that.
	guesses := GuessTechnique.Find(grid)

	if len(guesses) == 0 {
		//Coludn't find a guess step, oddly enough.
		return nil
	}

	//Take just the first guess step and forget about the other ones.
	guess := guesses[0]

	//The guess technique passes back the other nums as PointerNums, which is a hack.
	//Unpack them and then nil it out to prevent confusing other people in the future with them.
	otherNums := guess.PointerNums
	guess.PointerNums = nil

	var gridCopy *Grid

	for {
		gridCopy = grid.Copy()

		guess.Apply(gridCopy)

		solveSteps := humanSolveHelper(gridCopy)

		if len(solveSteps) != 0 {
			//Success!
			//Make ourselves look like that grid (to pass back the state of what the solution was) and return.
			grid.replace(gridCopy)
			gridCopy.Done()
			return append([]*SolveStep{guess}, solveSteps...)
		}
		//We need to try the next solution.

		if len(otherNums) == 0 {
			//No more numbers to try. We failed!
			break
		}

		nextNum := otherNums[0]
		otherNums = otherNums[1:]

		//Stuff it into the TargetNums for the branch step.
		guess.TargetNums = IntSlice{nextNum}

		gridCopy.Done()

	}

	gridCopy.Done()

	//We failed to find anything (which should never happen...)
	return nil

}

func runTechniques(techniques []SolveTechnique, grid *Grid) []*SolveStep {
	numTechniques := len(techniques)
	possibilitiesChan := make(chan []*SolveStep)

	var possibilities []*SolveStep

	for _, technique := range techniques {
		go func(theTechnique SolveTechnique) {
			possibilitiesChan <- theTechnique.Find(grid)
		}(technique)
	}

	//Collect all of the results
	for i := 0; i < numTechniques; i++ {
		for _, possibility := range <-possibilitiesChan {
			possibilities = append(possibilities, possibility)
		}
	}

	return possibilities
}

func (self *Grid) Difficulty() float64 {
	//This can be an extremely expensive method. Do not call repeatedly!
	//returns the difficulty of the grid, which is a number between 0.0 and 1.0.
	//This is a probabilistic measure; repeated calls may return different numbers, although generally we wait for the results to converge.

	//We solve the same puzzle N times, then ask each set of steps for their difficulty, and combine those to come up with the overall difficulty.

	accum := 0.0
	average := 0.0
	lastAverage := 0.0

	for i := 0; i < MAX_DIFFICULTY_ITERATIONS; i++ {
		grid := self.Copy()
		steps := grid.HumanSolve()
		difficulty := steps.Difficulty()

		accum += difficulty
		average = accum / (float64(i) + 1.0)

		if math.Abs(average-lastAverage) < DIFFICULTY_CONVERGENCE {
			//Okay, we've already converged. Just return early!
			grid.Done()
			return average
		}

		lastAverage = average
		grid.Done()
	}

	//We weren't converging... oh well!
	return average

}
<commit_msg>Revert "Changed MAX_DIFFICULTY_ITERATIONS to a variable"<commit_after>package sudoku

import (
	"fmt"
	"math"
)

//The actual techniques are intialized in hs_techniques.go, and actually defined in hst_*.go files.
//Techniques is ALL technies. CheapTechniques is techniques that are reasonably cheap to compute.
//ExpensiveTechniques is techniques that should only be used if all else has failed.
var Techniques []SolveTechnique
var CheapTechniques []SolveTechnique
var ExpensiveTechniques []SolveTechnique

var GuessTechnique SolveTechnique

//EVERY technique, even the weird one like Guess
var AllTechniques []SolveTechnique

//Worst case scenario, how many times we'd call HumanSolve to get a difficulty.
const MAX_DIFFICULTY_ITERATIONS = 50

//How close we have to get to the average to feel comfortable our difficulty is converging.
const DIFFICULTY_CONVERGENCE = 0.0005

type SolveDirections []*SolveStep

type SolveStep struct {
	//The cells that will be affected by the techinque
	TargetCells CellList
	//The cells that together lead the techinque to being valid
	PointerCells CellList
	//The numbers we will remove (or, in the case of Fill, add)
	//TODO: shouldn't this be renamed TargetNums?
	TargetNums IntSlice
	//The numbers in pointerCells that lead us to remove TargetNums from TargetCells.
	//This is only very rarely needed (at this time only for hiddenSubset techniques)
	PointerNums IntSlice
	//The general technique that underlies this step.
	Technique SolveTechnique
}

func (self *SolveStep) IsUseful(grid *Grid) bool {
	//Returns true IFF calling Apply with this step and the given grid would result in some useful work. Does not modify the gri.d

	//All of this logic is substantially recreated in Apply.

	if self.Technique == nil {
		return false
	}

	//TODO: test this.
	if self.Technique.IsFill() {
		if len(self.TargetCells) == 0 || len(self.TargetNums) == 0 {
			return false
		}
		cell := self.TargetCells[0].InGrid(grid)
		return self.TargetNums[0] != cell.Number()
	} else {
		useful := false
		for _, cell := range self.TargetCells {
			gridCell := cell.InGrid(grid)
			for _, exclude := range self.TargetNums {
				//It's right to use Possible because it includes the logic of "it's not possible if there's a number in there already"
				//TODO: ensure the comment above is correct logically.
				if gridCell.Possible(exclude) {
					useful = true
				}
			}
		}
		return useful
	}
}

func (self *SolveStep) Apply(grid *Grid) {
	//All of this logic is substantially recreated in IsUseful.
	if self.Technique.IsFill() {
		if len(self.TargetCells) == 0 || len(self.TargetNums) == 0 {
			return
		}
		cell := self.TargetCells[0].InGrid(grid)
		cell.SetNumber(self.TargetNums[0])
	} else {
		for _, cell := range self.TargetCells {
			gridCell := cell.InGrid(grid)
			for _, exclude := range self.TargetNums {
				gridCell.setExcluded(exclude, true)
			}
		}
	}
}

func (self *SolveStep) Description() string {
	result := ""
	if self.Technique.IsFill() {
		result += fmt.Sprintf("We put %s in cell %s ", self.TargetNums.Description(), self.TargetCells.Description())
	} else {
		//TODO: pluralize based on length of lists.
		result += fmt.Sprintf("We remove the possibilities %s from cells %s ", self.TargetNums.Description(), self.TargetCells.Description())
	}
	result += "because " + self.Technique.Description(self) + "."
	return result
}

func (self *SolveStep) normalize() {
	//Puts the solve step in its normal status. In practice this means that the various slices are sorted, so that the Description of them is stable.
	self.PointerCells.Sort()
	self.TargetCells.Sort()
	self.TargetNums.Sort()
	self.PointerNums.Sort()
}

func (self *Grid) HumanWalkthrough() string {
	steps := self.HumanSolution()
	return steps.Walkthrough(self)
}

func (self *Grid) HumanSolution() SolveDirections {
	clone := self.Copy()
	defer clone.Done()
	return clone.HumanSolve()
}

/*
 * The HumanSolve method is very complex due to guessing logic.
 *
 * Without guessing, the approach is very straightforward. Every move either fills a cell
 * or removes possibilities. But nothing does anything contradictory, so if they diverge
 * in path, it doesn't matter--they're still working towards the same end state (denoted by @)
 *
 *
 *
 *                   |
 *                  /|\
 *                 / | \
 *                |  |  |
 *                \  |  /
 *                 \ | /
 *                  \|/
 *                   |
 *                   V
 *                   @
 *
 *
 * In human solve, we first try the cheap techniques, and if we can't find enough options, we then additionally try
 * the expensive set of techniques. But both cheap and expensive techniques are similar in that they move us
 * towards the end state.
 *
 * For simplicity, we'll just show paths like this as a single line, even though realistically they could diverge arbitrarily.
 *
 * This all changes when you introduce branching, because at a branch point you could have chosen the wrong path
 * and at some point down that path you will discover an invalidity, which tells you you chose wrong, and
 * you'll have to unwind.
 *
 * Let's explore a puzzle that needs one branch point.
 *
 * We explore with normal techniques until we run into a point where none of hte normal techinques work.
 * This is a DIRE point, and in some cases we might just give up. But we have one last thing to try:
 * branching.
 * We then run the guess technique, which proposes multiple guess steps (big O's) that we could take.
 *
 * The technique will choose cells with only a small number of possibilities, to reduce the branching factor.
 *
 *                  |
 *                  |
 *                  V
 *                  O O O O O ...
 *
 * We will randomly pick one, and then explore all of its possibilities.
 * CRUCIALLY, at a branch point, we never have to pick another cell to explore its possibilities; for each cell,
 * if you plug in each of the possibilites and solve forward, it must result in either an invalidity (at which
 * point you try another possibility, or if they're all gone you unwind if there's a branch point above), or
 * you picked correctly and the solution lies that way. But it's never the case that picking THIS cell won't uncover
 * either the invalidity or the solution.
 * So in reality, when we come to a branch point, we can choose one cell to focus on and throw out all of the others.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *
 * But within that cell, there are multiple possibilty branches to consider.
 *
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *
 * We go through each in turn and play forward until we find either an invalidity or a solution.
 * Within each branch, we use the normal techniques as normal--remember it's actually branching but
 * converging, like in the first diagram.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *              X       @
 *
 * When we uncover an invalidity, we unwind back to the branch point and then try the next possibility.
 * We should never have to unwind above the top branch, because down one of the branches (possibly somewhere deep)
 * There MUST be a solution (assuming the puzzle is valid)
 * Obviously if we find the solution on our branch, we're good.
 *
 * But what happens if we run out of normal techinques down one of our branches and have to branch again?
 *
 * Nothing much changes, except that you DO unravel if you uncover that all of the possibilities down this
 * side lead to invalidities. You just never unravel past the first branch point.
 *
 *                  |
 *                  |
 *                  V
 *                  O
 *                 / \
 *                1   3
 *               /     \
 *              |       |
 *              O       O
 *             / \     / \
 *            4   5   6   7
 *           /    |   |    \
 *          |     |   |     |
 *          X     X   X     @
 *
 * Down one of the paths MUST lie a solution.
 *
 * The search will fail if we have a max depth limit of branching to try, because then we might not discover a
 * solution down one of the branches. A good sanity point is DIM*DIM branch points is the absolute highest; an
 * assert at that level makes sense.
 *
 * In this implementation, humanSolveHelper does the work of exploring any branch up to a point where a guess must happen.
 * If we run out of ideas on a branch, we call into guess helper, which will pick a guess and then try all of the versions of it
 * until finding one that works. This keeps humanSolveHelper pretty straighforward and keeps most of the complex guess logic out.
 */

func (self *Grid) HumanSolve() SolveDirections {
	return humanSolveHelper(self)
}

//Do we even need a helper here? Can't we just make HumanSolve actually humanSolveHelper?
//The core worker of human solve, it does all of the solving between branch points.
func humanSolveHelper(grid *Grid) []*SolveStep {

	var results []*SolveStep

	//Note: trying these all in parallel is much slower (~15x) than doing them in sequence.
	//The reason is that in sequence we bailed early as soon as we found one step; now we try them all.

	for !grid.Solved() {
		//TODO: provide hints to the techniques of where to look based on the last filled cell

		if grid.Invalid() {
			//We much have been in a branch and found an invalidity.
			//Bail immediately.
			return nil
		}

		possibilities := runTechniques(CheapTechniques, grid)

		//Now pick one to apply.
		if len(possibilities) == 0 {
			//Okay, let's try the ExpensiveTechniques, as a hail mary.
			possibilities = runTechniques(ExpensiveTechniques, grid)
			if len(possibilities) == 0 {
				//Hmm, didn't find any possivbilities. We failed. :-(
				break
			}
		}

		//TODO: consider if we should stop picking techniques based on their weight here.
		//Now that Find returns a slice instead of a single, we're already much more likely to select an "easy" technique. ... Right?

		possibilitiesWeights := make([]float64, len(possibilities))
		for i, possibility := range possibilities {
			possibilitiesWeights[i] = possibility.Technique.HumanLikelihood()
		}
		step := possibilities[randomIndexWithInvertedWeights(possibilitiesWeights)]

		results = append(results, step)
		step.Apply(grid)

	}
	if !grid.Solved() {
		//We couldn't solve the puzzle.
		//But let's do one last ditch effort and try guessing.
		guessSteps := humanSolveGuess(grid)
		if len(guessSteps) == 0 {
			//Okay, we just totally failed.
			return nil
		}
		return append(results, guessSteps...)
	}
	return results
}

//Called when we have run out of options at a given state and need to guess.
func humanSolveGuess(grid *Grid) []*SolveStep {

	//TODO: consider doing a normal solve forward from here to figure out what the right branch is and just do that.
	guesses := GuessTechnique.Find(grid)

	if len(guesses) == 0 {
		//Coludn't find a guess step, oddly enough.
		return nil
	}

	//Take just the first guess step and forget about the other ones.
	guess := guesses[0]

	//The guess technique passes back the other nums as PointerNums, which is a hack.
	//Unpack them and then nil it out to prevent confusing other people in the future with them.
	otherNums := guess.PointerNums
	guess.PointerNums = nil

	var gridCopy *Grid

	for {
		gridCopy = grid.Copy()

		guess.Apply(gridCopy)

		solveSteps := humanSolveHelper(gridCopy)

		if len(solveSteps) != 0 {
			//Success!
			//Make ourselves look like that grid (to pass back the state of what the solution was) and return.
			grid.replace(gridCopy)
			gridCopy.Done()
			return append([]*SolveStep{guess}, solveSteps...)
		}
		//We need to try the next solution.

		if len(otherNums) == 0 {
			//No more numbers to try. We failed!
			break
		}

		nextNum := otherNums[0]
		otherNums = otherNums[1:]

		//Stuff it into the TargetNums for the branch step.
		guess.TargetNums = IntSlice{nextNum}

		gridCopy.Done()

	}

	gridCopy.Done()

	//We failed to find anything (which should never happen...)
	return nil

}

func runTechniques(techniques []SolveTechnique, grid *Grid) []*SolveStep {
	numTechniques := len(techniques)
	possibilitiesChan := make(chan []*SolveStep)

	var possibilities []*SolveStep

	for _, technique := range techniques {
		go func(theTechnique SolveTechnique) {
			possibilitiesChan <- theTechnique.Find(grid)
		}(technique)
	}

	//Collect all of the results
	for i := 0; i < numTechniques; i++ {
		for _, possibility := range <-possibilitiesChan {
			possibilities = append(possibilities, possibility)
		}
	}

	return possibilities
}

func (self *Grid) Difficulty() float64 {
	//This can be an extremely expensive method. Do not call repeatedly!
	//returns the difficulty of the grid, which is a number between 0.0 and 1.0.
	//This is a probabilistic measure; repeated calls may return different numbers, although generally we wait for the results to converge.

	//We solve the same puzzle N times, then ask each set of steps for their difficulty, and combine those to come up with the overall difficulty.

	accum := 0.0
	average := 0.0
	lastAverage := 0.0

	for i := 0; i < MAX_DIFFICULTY_ITERATIONS; i++ {
		grid := self.Copy()
		steps := grid.HumanSolve()
		difficulty := steps.Difficulty()

		accum += difficulty
		average = accum / (float64(i) + 1.0)

		if math.Abs(average-lastAverage) < DIFFICULTY_CONVERGENCE {
			//Okay, we've already converged. Just return early!
			grid.Done()
			return average
		}

		lastAverage = average
		grid.Done()
	}

	//We weren't converging... oh well!
	return average

}
<|endoftext|>


<commit_before>// +build darwin,!kqueue
// +build !fsnotify

package notify

const (
	Create = Event(FSEventsCreated)
	Delete = Event(FSEventsRemoved)
	Write  = Event(FSEventsModified)
	Move   = Event(FSEventsRenamed)

	Recursive = Event(0x80000) // An internal event, in final version won't be exported.
)

const (
	FSEventsMustScanSubDirs = 0x00001
	FSEventsUserDropped     = 0x00002
	FSEventsKernelDropped   = 0x00004
	FSEventsEventIdsWrapped = 0x00008
	FSEventsHistoryDone     = 0x00010
	FSEventsRootChanged     = 0x00020
	FSEventsMount           = 0x00040
	FSEventsUnmount         = 0x00080
	FSEventsCreated         = 0x00100
	FSEventsRemoved         = 0x00200
	FSEventsInodeMetaMod    = 0x00400
	FSEventsRenamed         = 0x00800
	FSEventsModified        = 0x01000
	FSEventsFinderInfoMod   = 0x02000
	FSEventsChangeOwner     = 0x04000
	FSEventsXattrMod        = 0x08000
	FSEventsIsFile          = 0x10000
	FSEventsIsDir           = 0x20000
	FSEventsIsSymlink       = 0x40000
)

var osestr = map[Event]string{
	FSEventsMustScanSubDirs: "notify.FSEventsMustScanSubDirs",
	FSEventsUserDropped:     "notify.FSEventsUserDropped",
	FSEventsKernelDropped:   "notify.FSEventsKernelDropped",
	FSEventsEventIdsWrapped: "notify.FSEventsEventIdsWrapped",
	FSEventsHistoryDone:     "notify.FSEventsHistoryDone",
	FSEventsRootChanged:     "notify.FSEventsRootChanged",
	FSEventsMount:           "notify.FSEventsMount",
	FSEventsUnmount:         "notify.FSEventsUnmount",
	FSEventsCreated:         "notify.FSEventsCreated",
	FSEventsRemoved:         "notify.FSEventsRemoved",
	FSEventsInodeMetaMod:    "notify.FSEventsInodeMetaMod",
	FSEventsRenamed:         "notify.FSEventsRenamed",
	FSEventsModified:        "notify.FSEventsModified",
	FSEventsFinderInfoMod:   "notify.FSEventsFinderInfoMod",
	FSEventsChangeOwner:     "notify.FSEventsChangeOwner",
	FSEventsXattrMod:        "notify.FSEventsXattrMod",
	FSEventsIsFile:          "notify.FSEventsIsFile",
	FSEventsIsDir:           "notify.FSEventsIsDir",
	FSEventsIsSymlink:       "notify.FSEventsIsSymlink",
}

var ekind = map[Event]Event{}

type event struct {
	fse   FSEvent
	event Event
	isdir bool
}

func (ei *event) Event() Event     { return ei.event }
func (ei *event) Path() string     { return ei.fse.Path }
func (ei *event) IsDir() bool      { return ei.isdir }
func (ei *event) Sys() interface{} { return &ei.fse }
<commit_msg>FSEvents: fix TestEventString<commit_after>// +build darwin,!kqueue
// +build !fsnotify

package notify

const (
	Create = Event(FSEventsCreated)
	Delete = Event(FSEventsRemoved)
	Write  = Event(FSEventsModified)
	Move   = Event(FSEventsRenamed)

	Recursive = Event(0x80000) // An internal event, in final version won't be exported.
)

const (
	FSEventsMustScanSubDirs = 0x00001
	FSEventsUserDropped     = 0x00002
	FSEventsKernelDropped   = 0x00004
	FSEventsEventIdsWrapped = 0x00008
	FSEventsHistoryDone     = 0x00010
	FSEventsRootChanged     = 0x00020
	FSEventsMount           = 0x00040
	FSEventsUnmount         = 0x00080
	FSEventsCreated         = 0x00100
	FSEventsRemoved         = 0x00200
	FSEventsInodeMetaMod    = 0x00400
	FSEventsRenamed         = 0x00800
	FSEventsModified        = 0x01000
	FSEventsFinderInfoMod   = 0x02000
	FSEventsChangeOwner     = 0x04000
	FSEventsXattrMod        = 0x08000
	FSEventsIsFile          = 0x10000
	FSEventsIsDir           = 0x20000
	FSEventsIsSymlink       = 0x40000
)

var osestr = map[Event]string{
	FSEventsMustScanSubDirs: "notify.FSEventsMustScanSubDirs",
	FSEventsUserDropped:     "notify.FSEventsUserDropped",
	FSEventsKernelDropped:   "notify.FSEventsKernelDropped",
	FSEventsEventIdsWrapped: "notify.FSEventsEventIdsWrapped",
	FSEventsHistoryDone:     "notify.FSEventsHistoryDone",
	FSEventsRootChanged:     "notify.FSEventsRootChanged",
	FSEventsMount:           "notify.FSEventsMount",
	FSEventsUnmount:         "notify.FSEventsUnmount",
	FSEventsInodeMetaMod:    "notify.FSEventsInodeMetaMod",
	FSEventsFinderInfoMod:   "notify.FSEventsFinderInfoMod",
	FSEventsChangeOwner:     "notify.FSEventsChangeOwner",
	FSEventsXattrMod:        "notify.FSEventsXattrMod",
	FSEventsIsFile:          "notify.FSEventsIsFile",
	FSEventsIsDir:           "notify.FSEventsIsDir",
	FSEventsIsSymlink:       "notify.FSEventsIsSymlink",
}

var ekind = map[Event]Event{}

type event struct {
	fse   FSEvent
	event Event
	isdir bool
}

func (ei *event) Event() Event     { return ei.event }
func (ei *event) Path() string     { return ei.fse.Path }
func (ei *event) IsDir() bool      { return ei.isdir }
func (ei *event) Sys() interface{} { return &ei.fse }
<|endoftext|>