<commit_before>package main

import (
	"errors"
	"fmt"

	"github.com/codegangsta/cli"
	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	immediate  = false
	buildError error
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "port,p",
			Value: 3000,
			Usage: "port for the proxy server",
		},
		cli.IntFlag{
			Name:  "appPort,a",
			Value: 3001,
			Usage: "port for the Go web server",
		},
		cli.StringFlag{
			Name:  "bin,b",
			Value: "gin-bin",
			Usage: "name of generated binary file",
		},
		cli.StringFlag{
			Name:  "path,t",
			Value: ".",
			Usage: "Path to watch files from",
		},
		cli.BoolFlag{
			Name:  "immediate,i",
			Usage: "run the server immediately after it's built",
		},
		cli.BoolFlag{
			Name:  "godep,g",
			Usage: "use godep when building",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	port := c.GlobalInt("port")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))
	immediate = c.GlobalBool("immediate")

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(c.GlobalString("path"), c.GlobalString("bin"), c.GlobalBool("godep"))
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Port:    port,
		ProxyTo: "http://localhost:" + appPort,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	logger.Printf("listening on port %d\n", port)

	shutdown(runner)

	// build right now
	build(builder, runner, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), func(path string) {
		runner.Kill()
		build(builder, runner, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, runner gin.Runner, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Println("ERROR! Build failed.")
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Println("Build Successful")
		}
		buildError = nil
		if immediate {
			runner.Run()
		}
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" {
				return filepath.SkipDir
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if filepath.Ext(path) == ".go" && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<commit_msg>Add exclude paths<commit_after>package main

import (
	"errors"
	"fmt"

	"github.com/codegangsta/cli"
	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	immediate  = false
	buildError error
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "port,p",
			Value: 3000,
			Usage: "port for the proxy server",
		},
		cli.IntFlag{
			Name:  "appPort,a",
			Value: 3001,
			Usage: "port for the Go web server",
		},
		cli.StringFlag{
			Name:  "bin,b",
			Value: "gin-bin",
			Usage: "name of generated binary file",
		},
		cli.StringFlag{
			Name:  "path,t",
			Value: ".",
			Usage: "Path to watch files from",
		},
		cli.StringFlag{
			Name:  "exclude,e",
			Value: "",
			Usage: "Path to exclude files from",
		},
		cli.BoolFlag{
			Name:  "immediate,i",
			Usage: "run the server immediately after it's built",
		},
		cli.BoolFlag{
			Name:  "godep,g",
			Usage: "use godep when building",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	port := c.GlobalInt("port")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))
	immediate = c.GlobalBool("immediate")

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(c.GlobalString("path"), c.GlobalString("bin"), c.GlobalBool("godep"))
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Port:    port,
		ProxyTo: "http://localhost:" + appPort,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	logger.Printf("listening on port %d\n", port)

	shutdown(runner)

	// build right now
	build(builder, runner, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), c.GlobalString("exclude"), func(path string) {
		runner.Kill()
		build(builder, runner, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, runner gin.Runner, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Println("ERROR! Build failed.")
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Println("Build Successful")
		}
		buildError = nil
		if immediate {
			runner.Run()
		}
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, excludePath string, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" {
				return filepath.SkipDir
			}

			// ignore excluded paths
			if filepath.Base(path) == excludePath {
				return filepath.SkipDir
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if filepath.Ext(path) == ".go" && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
)

var templates = template.Must(template.ParseFiles("view/user_show.html"))

func userCreateHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Hello!")
	fmt.Println("The received method is... ", r.Method)
	switch r.Method {
	case "POST":
		r.ParseForm()

		u := User{SteamName: r.PostFormValue("steamname")}
		u.fetchSteamID()
		fmt.Println("Your SteamID is...", u.SteamID)

		u.fetchOwnedGames()
		sort.Sort(sort.Reverse(u.Games))
		fmt.Println("These are the games you own... ", u.Games)
		fmt.Printf("You own %d games\n", len(u.Games))

		templates.ExecuteTemplate(w, "user_show.html", u)
	default:
		http.NotFound(w, r)
	}
}

type User struct {
	SteamName string
	SteamID   string
	Games     Games
}

func (u *User) fetchSteamID() (err error) {
	u.SteamID, err = resolveVanityURL(u.SteamName)
	return
}

func (u *User) fetchOwnedGames() (err error) {
	u.Games, err = getOwnedGames(u.SteamID)
	return
}

type ResolveVanityURLResponse struct {
	Response struct {
		SteamID string `json:"steamid"`
	}
}

func resolveVanityURL(steamName string) (string, error) {
	values := url.Values{}
	values.Add("vanityurl", url.QueryEscape(steamName))

	resolveVanityURLEndpoint := generateSteamAPIURL("ISteamUser/ResolveVanityURL/v0001", values, true)

	resp, err := http.Get(resolveVanityURLEndpoint.String())
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	fmt.Println(string(body))

	structuredResponse := &ResolveVanityURLResponse{}
	err = json.Unmarshal(body, structuredResponse)
	if err != nil {
		return "", err
	}

	return structuredResponse.Response.SteamID, nil
}

type Game struct {
	Name     string
	AppID    int
	Playtime int `json:"playtime_forever"`

	LogoFilename string `json:"img_logo_url"`
}

func (g *Game) LogoURL() string {
	if g.AppID == 0 || g.LogoFilename == "" {
		return "http://digilite.ca/wp-content/uploads/2013/07/squarespace-184x69.jpg"
	}

	return fmt.Sprintf(
		"http://media.steampowered.com/steamcommunity/public/images/apps/%d/%s.jpg",
		g.AppID,
		g.LogoFilename,
	)
}

type Games []Game

func (gs Games) Len() int {
	return len(gs)
}

func (gs Games) Less(i, j int) bool {
	return gs[i].Playtime < gs[j].Playtime
}

func (gs Games) Swap(i, j int) {
	gs[i], gs[j] = gs[j], gs[i]
}

type GetOwnedGamesResponse struct {
	Response struct {
		Games
	}
}

func getOwnedGames(steamID string) (Games, error) {
	values := url.Values{}
	values.Add("steamid", url.QueryEscape(steamID))
	values.Add("include_appinfo", "1")

	getOwnedGamesEndpoint := generateSteamAPIURL("IPlayerService/GetOwnedGames/v0001", values, true)

	resp, err := http.Get(getOwnedGamesEndpoint.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	fmt.Println(string(body))

	structuredResponse := &GetOwnedGamesResponse{}
	err = json.Unmarshal(body, structuredResponse)
	if err != nil {
		return nil, err
	}

	return structuredResponse.Response.Games, nil
}

func generateSteamAPIURL(apiPath string, values url.Values, withKey bool) *url.URL {
	generatedURL := &url.URL{Scheme: "http", Host: "api.steampowered.com", Path: apiPath}

	if withKey {
		values.Add("key", os.Getenv("STEAM_API_KEY"))
	}
	generatedURL.RawQuery = values.Encode()

	fmt.Println("the URL is...", generatedURL.String())
	return generatedURL
}

func main() {
	http.Handle("/", http.FileServer(http.Dir("./view")))
	http.HandleFunc("/user/create", userCreateHandler)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>Factor out api http and unmarshaling logic<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
)

var templates = template.Must(template.ParseFiles("view/user_show.html"))

func userCreateHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Hello!")
	fmt.Println("The received method is... ", r.Method)
	switch r.Method {
	case "POST":
		r.ParseForm()

		u := User{SteamName: r.PostFormValue("steamname")}
		if err := u.FetchSteamID(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		fmt.Println("Your SteamID is...", u.SteamID)

		if err := u.FetchOwnedGames(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		sort.Sort(sort.Reverse(u.Games))
		fmt.Println("These are the games you own... ", u.Games)
		fmt.Printf("You own %d games\n", len(u.Games))

		templates.ExecuteTemplate(w, "user_show.html", u)
	default:
		http.NotFound(w, r)
	}
}

type User struct {
	SteamName string
	SteamID   string
	Games     Games
}

func (u *User) FetchSteamID() (err error) {
	u.SteamID, err = resolveVanityURL(u.SteamName)
	return
}

func (u *User) FetchOwnedGames() (err error) {
	u.Games, err = getOwnedGames(u.SteamID)
	return
}

type ResolveVanityURLResponse struct {
	Response struct {
		SteamID string `json:"steamid"`
		Success uint
	}
}

func resolveVanityURL(steamName string) (string, error) {
	values := url.Values{}
	values.Add("vanityurl", url.QueryEscape(steamName))

	resolveVanityURLEndpoint := generateSteamAPIURL("ISteamUser/ResolveVanityURL/v0001", values, true)
	vanityURLResponse := &ResolveVanityURLResponse{}
	if err := unmarshalSteamAPIResponse(resolveVanityURLEndpoint, vanityURLResponse); err != nil {
		return "", err
	}

	fmt.Printf("vanityURLResponse: %v\n", vanityURLResponse)

	return vanityURLResponse.Response.SteamID, nil
}

type Game struct {
	Name                     string
	AppID                    uint
	Playtime                 uint   `json:"playtime_forever"`
	LogoImageFilename        string `json:"img_logo_url"`
	IconImageFilename        string `json:"img_icon_url"`
	HasCommunityVisibleStats bool   `json:"has_community_visible_stats"`
}

func (g *Game) LogoURL() string {
	if g.AppID == 0 || g.LogoImageFilename == "" {
		return "http://digilite.ca/wp-content/uploads/2013/07/squarespace-184x69.jpg"
	}

	return fmt.Sprintf(
		"http://media.steampowered.com/steamcommunity/public/images/apps/%d/%s.jpg",
		g.AppID,
		g.LogoImageFilename,
	)
}

type Games []Game

func (gs Games) Len() int {
	return len(gs)
}

func (gs Games) Less(i, j int) bool {
	return gs[i].Playtime < gs[j].Playtime
}

func (gs Games) Swap(i, j int) {
	gs[i], gs[j] = gs[j], gs[i]
}

type GetOwnedGamesResponse struct {
	Response struct {
		GameCount uint `json:"game_count"`
		Games
	}
}

func getOwnedGames(steamID string) (Games, error) {
	values := url.Values{}
	values.Add("steamid", url.QueryEscape(steamID))
	values.Add("include_appinfo", "1")

	getOwnedGamesEndpoint := generateSteamAPIURL("IPlayerService/GetOwnedGames/v0001", values, true)
	ownedGamesResponse := &GetOwnedGamesResponse{}
	if err := unmarshalSteamAPIResponse(getOwnedGamesEndpoint, ownedGamesResponse); err != nil {
		return nil, err
	}

	return ownedGamesResponse.Response.Games, nil
}

func generateSteamAPIURL(apiPath string, values url.Values, withKey bool) *url.URL {
	generatedURL := &url.URL{Scheme: "http", Host: "api.steampowered.com", Path: apiPath}

	if withKey {
		values.Add("key", os.Getenv("STEAM_API_KEY"))
	}
	generatedURL.RawQuery = values.Encode()

	fmt.Println("the URL is...", generatedURL.String())
	return generatedURL
}

func unmarshalSteamAPIResponse(apiURL *url.URL, data interface{}) error {
	r, err := http.Get(apiURL.String())
	if err != nil {
		return err
	}
	defer r.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(body))

	err = json.Unmarshal(body, data)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	http.Handle("/", http.FileServer(http.Dir("./view")))
	http.HandleFunc("/user/create", userCreateHandler)

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"github.com/gruntwork-io/terragrunt/shell"
	"github.com/gruntwork-io/terragrunt/util"
	"github.com/gruntwork-io/terragrunt/cli"
	"github.com/gruntwork-io/terragrunt/errors"
)

// This variable is set at build time using -ldflags parameters. For more info, see:
// http://stackoverflow.com/a/11355611/483528
var VERSION string

// The main entrypoint for Terragrunt
func main() {
	defer errors.Recover(checkForErrorsAndExit)

	app := cli.CreateTerragruntCli(VERSION)
	err := app.Run(os.Args)

	checkForErrorsAndExit(err)
}

// If there is an error, display it in the console and exit with a non-zero exit code. Otherwise, exit 0.
func checkForErrorsAndExit(err error) {
	if err == nil {
		os.Exit(0)
	} else {
		logger := util.CreateLogger("")
		if os.Getenv("TERRAGRUNT_DEBUG") != "" {
			logger.Println(errors.PrintErrorWithStackTrace(err))
		} else {
			logger.Println(err)
		}
		// exit with the underlying error code
		exitCode, exitCodeErr := shell.GetExitCode(err)
		if exitCodeErr != nil {
			exitCode = 1
		}
		os.Exit(exitCode)
	}

}<commit_msg>log on exitCodeErr<commit_after>package main

import (
	"os"
	"github.com/gruntwork-io/terragrunt/shell"
	"github.com/gruntwork-io/terragrunt/util"
	"github.com/gruntwork-io/terragrunt/cli"
	"github.com/gruntwork-io/terragrunt/errors"
)

// This variable is set at build time using -ldflags parameters. For more info, see:
// http://stackoverflow.com/a/11355611/483528
var VERSION string

// The main entrypoint for Terragrunt
func main() {
	defer errors.Recover(checkForErrorsAndExit)

	app := cli.CreateTerragruntCli(VERSION)
	err := app.Run(os.Args)

	checkForErrorsAndExit(err)
}

// If there is an error, display it in the console and exit with a non-zero exit code. Otherwise, exit 0.
func checkForErrorsAndExit(err error) {
	if err == nil {
		os.Exit(0)
	} else {
		logger := util.CreateLogger("")
		if os.Getenv("TERRAGRUNT_DEBUG") != "" {
			logger.Println(errors.PrintErrorWithStackTrace(err))
		} else {
			logger.Println(err)
		}
		// exit with the underlying error code
		exitCode, exitCodeErr := shell.GetExitCode(err)
		if exitCodeErr != nil {
			exitCode = 1
			logger.Println("Unable to determine underlying exit code, so Terragrunt will exit with error code 1")
		}
		os.Exit(exitCode)
	}

}<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	_ "net/http/pprof"

	"github.com/gojp/nihongo/lib/dictionary"
	"github.com/golang/gddo/httputil/header"
)

const (
	title       = "Nihongo.io"
	description = "The world's best Japanese dictionary."
)

// Entry is a dictionary entry
type Entry struct {
	Word       string `json:"word"`
	Furigana   string `json:"furigana"`
	Definition string `json:"definition"`
	Common     bool   `json:"common,omitempty"`
}

var dict dictionary.Dictionary

var tmpl = make(map[string]*template.Template)

func initialize() {
	compileTemplates()

	file, err := os.Open("data/edict2.json.gz")
	if err != nil {
		log.Fatal("Could not load edict2.json.gz: ", err)
	}
	defer file.Close()

	reader, err := gzip.NewReader(file)
	if err != nil {
		log.Fatal("Could not create reader: ", err)
	}

	dict, err = dictionary.Load(reader)
	if err != nil {
		log.Fatal("Could not load dictionary: ", err)
	}
}

func compileTemplates() {
	t := func(s string) string {
		return "templates/" + s
	}

	tmpl["home.html"] = template.Must(template.ParseFiles(t("home.html"), t("base.html")))
	tmpl["about.html"] = template.Must(template.ParseFiles(t("about.html"), t("base.html")))
}

type templateData struct {
	Search  string  `json:"search"`
	Entries []Entry `json:"entries"`
}

func home(w http.ResponseWriter, r *http.Request) {
	defer timeTrack(time.Now(), "/")

	if r.URL.Path[1:] != "" {
		http.NotFound(w, r)
		return
	}

	data := templateData{
		Entries: []Entry{},
		Search:  "",
	}
	jsonData, err := json.Marshal(data)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	m := map[string]interface{}{
		"json":        string(jsonData),
		"data":        data,
		"title":       title,
		"description": description,
	}

	tmpl["home.html"].ExecuteTemplate(w, "base", m)
}

func search(w http.ResponseWriter, r *http.Request) {
	defer timeTrack(time.Now(), "/search")

	// check GET and POST parameters for "text" field
	err := r.ParseForm()
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	text := r.Form.Get("text")

	// if no "text" field is present, we check the URL
	if text == "" {
		text = strings.TrimPrefix(r.URL.Path, "/search/")
	}

	// if we still don't have text, we redirect to the home page
	if text == "" {
		log.Println("Redirecting to home")
		http.Redirect(w, r, "/", http.StatusMovedPermanently)
	}

	// get the entries that match our text
	entries := []Entry{}
	results := dict.Search(text, 10)
	for _, r := range results {
		var defs []string
		for _, g := range r.Glosses {
			defs = append(defs, g.English)
		}
		entries = append(entries, Entry{
			Word:       r.Japanese,
			Furigana:   r.Furigana,
			Definition: strings.Join(defs, "; "),
			Common:     r.Common,
		})
	}

	data := templateData{
		Search:  text,
		Entries: entries,
	}
	jsonData, err := json.Marshal(data)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	isXMLHTTP := r.Header.Get("X-Requested-With") == "XMLHttpRequest"
	accepts := header.ParseAccept(r.Header, "Accept")
	wantsJSON, wantsHTML := 0.0, 0.0
	for _, acc := range accepts {
		switch acc.Value {
		case "text/json", "application/json":
			wantsJSON = acc.Q
		case "text/html":
			wantsHTML = acc.Q
		}
	}
	if isXMLHTTP || wantsJSON > wantsHTML {
		w.Header().Set("Content-Type", "application/json")
		w.Write(jsonData)

		return
	}

	pageTitle := text + " in Japanese | " + title
	description := fmt.Sprintf("Japanese to English for %s", text)
	if len(data.Entries) > 0 {
		e := data.Entries[0]
		description = fmt.Sprintf("%s (%s) - %s", e.Word, e.Furigana, e.Definition)
	}

	m := map[string]interface{}{
		"json":        string(jsonData),
		"data":        data,
		"title":       pageTitle,
		"description": description,
	}
	tmpl["home.html"].ExecuteTemplate(w, "base", m)
}

func about(w http.ResponseWriter, r *http.Request) {
	tmpl["about.html"].ExecuteTemplate(w, "base", nil)
}

func main() {
	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()

	var (
		addr string
		dev  bool
	)
	flag.StringVar(&addr, "addr", "127.0.0.1:8080", "address to run on")
	flag.BoolVar(&dev, "dev", false, "whether to run with a reduced dictionary (for faster boot times)")
	flag.Parse()

	initialize()

	http.HandleFunc("/", home)
	http.HandleFunc("/search", search)
	http.HandleFunc("/search/", search)
	http.HandleFunc("/about", about)
	http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("static"))))

	log.Printf("Running server on addr %s", addr)
	if dev {
		log.Println("Running in development mode, templates will automatically reload")
	}
	http.ListenAndServe(addr, nil)
}

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s took %s", name, elapsed)
}
<commit_msg>make error logs more clear<commit_after>package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	_ "net/http/pprof"

	"github.com/gojp/nihongo/lib/dictionary"
	"github.com/golang/gddo/httputil/header"
)

const (
	title       = "Nihongo.io"
	description = "The world's best Japanese dictionary."
)

// Entry is a dictionary entry
type Entry struct {
	Word       string `json:"word"`
	Furigana   string `json:"furigana"`
	Definition string `json:"definition"`
	Common     bool   `json:"common,omitempty"`
}

var dict dictionary.Dictionary

var tmpl = make(map[string]*template.Template)

func initialize() {
	compileTemplates()

	file, err := os.Open("data/edict2.json.gz")
	if err != nil {
		log.Fatal("Could not load edict2.json.gz: ", err)
	}
	defer file.Close()

	reader, err := gzip.NewReader(file)
	if err != nil {
		log.Fatal("Could not create reader: ", err)
	}

	dict, err = dictionary.Load(reader)
	if err != nil {
		log.Fatal("Could not load dictionary: ", err)
	}
}

func compileTemplates() {
	t := func(s string) string {
		return "templates/" + s
	}

	tmpl["home.html"] = template.Must(template.ParseFiles(t("home.html"), t("base.html")))
	tmpl["about.html"] = template.Must(template.ParseFiles(t("about.html"), t("base.html")))
}

type templateData struct {
	Search  string  `json:"search"`
	Entries []Entry `json:"entries"`
}

func home(w http.ResponseWriter, r *http.Request) {
	defer timeTrack(time.Now(), "/")

	if r.URL.Path[1:] != "" {
		http.NotFound(w, r)
		return
	}

	data := templateData{
		Entries: []Entry{},
		Search:  "",
	}
	jsonData, err := json.Marshal(data)
	if err != nil {
		log.Println("ERROR:", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	m := map[string]interface{}{
		"json":        string(jsonData),
		"data":        data,
		"title":       title,
		"description": description,
	}

	tmpl["home.html"].ExecuteTemplate(w, "base", m)
}

func search(w http.ResponseWriter, r *http.Request) {
	defer timeTrack(time.Now(), "/search")

	// check GET and POST parameters for "text" field
	err := r.ParseForm()
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	text := r.Form.Get("text")

	// if no "text" field is present, we check the URL
	if text == "" {
		text = strings.TrimPrefix(r.URL.Path, "/search/")
	}

	// if we still don't have text, we redirect to the home page
	if text == "" {
		log.Println("Redirecting to home")
		http.Redirect(w, r, "/", http.StatusMovedPermanently)
	}

	// get the entries that match our text
	entries := []Entry{}
	results := dict.Search(text, 10)
	for _, r := range results {
		var defs []string
		for _, g := range r.Glosses {
			defs = append(defs, g.English)
		}
		entries = append(entries, Entry{
			Word:       r.Japanese,
			Furigana:   r.Furigana,
			Definition: strings.Join(defs, "; "),
			Common:     r.Common,
		})
	}

	data := templateData{
		Search:  text,
		Entries: entries,
	}
	jsonData, err := json.Marshal(data)
	if err != nil {
		log.Println("ERROR:", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	isXMLHTTP := r.Header.Get("X-Requested-With") == "XMLHttpRequest"
	accepts := header.ParseAccept(r.Header, "Accept")
	wantsJSON, wantsHTML := 0.0, 0.0
	for _, acc := range accepts {
		switch acc.Value {
		case "text/json", "application/json":
			wantsJSON = acc.Q
		case "text/html":
			wantsHTML = acc.Q
		}
	}
	if isXMLHTTP || wantsJSON > wantsHTML {
		w.Header().Set("Content-Type", "application/json")
		w.Write(jsonData)

		return
	}

	pageTitle := text + " in Japanese | " + title
	description := fmt.Sprintf("Japanese to English for %s", text)
	if len(data.Entries) > 0 {
		e := data.Entries[0]
		description = fmt.Sprintf("%s (%s) - %s", e.Word, e.Furigana, e.Definition)
	}

	m := map[string]interface{}{
		"json":        string(jsonData),
		"data":        data,
		"title":       pageTitle,
		"description": description,
	}
	tmpl["home.html"].ExecuteTemplate(w, "base", m)
}

func about(w http.ResponseWriter, r *http.Request) {
	tmpl["about.html"].ExecuteTemplate(w, "base", nil)
}

func main() {
	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()

	var (
		addr string
		dev  bool
	)
	flag.StringVar(&addr, "addr", "127.0.0.1:8080", "address to run on")
	flag.BoolVar(&dev, "dev", false, "whether to run with a reduced dictionary (for faster boot times)")
	flag.Parse()

	initialize()

	http.HandleFunc("/", home)
	http.HandleFunc("/search", search)
	http.HandleFunc("/search/", search)
	http.HandleFunc("/about", about)
	http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("static"))))

	log.Printf("Running server on addr %s", addr)
	if dev {
		log.Println("Running in development mode, templates will automatically reload")
	}
	http.ListenAndServe(addr, nil)
}

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s took %s", name, elapsed)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
)

var (
	proxy string
)

func main() {
	//Check & load .env file
	loadEnv()

	if len(os.Args) == 1 {
		displayUsage()
		os.Exit(0)
	}

	words, withVoice := parseArgs(os.Args)
	//words := strings.Join(os.Args[1:], " ")
	query(words, withVoice, len(os.Args[1:]) > 1)
}
<commit_msg>remove unused code<commit_after>package main

import (
	"os"
)

var (
	proxy string
)

func main() {
	//Check & load .env file
	loadEnv()

	if len(os.Args) == 1 {
		displayUsage()
		os.Exit(0)
	}

	words, withVoice := parseArgs(os.Args)
	query(words, withVoice, len(os.Args[1:]) > 1)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/rightscale/rsc/cmd"
	"github.com/rightscale/rsc/httpclient"
	"github.com/rightscale/rsc/log"
	"gopkg.in/alecthomas/kingpin.v2"

	// phoney reference to make Godep pull this in for the code generators
	_ "bitbucket.org/pkg/inflect"
)

// Command line client entry point.
func main() {
	app := kingpin.New("rsc", "A RightScale API client")
	app.Writer(os.Stdout)
	app.Version(VV)

	cmdLine, err := ParseCommandLine(app)
	if err != nil {
		line := strings.Join(os.Args, " ")
		PrintFatal(line + ": " + err.Error())
	}

	resp, err := ExecuteCommand(app, cmdLine)
	if err != nil {
		PrintFatal(err.Error())
	}
	if resp == nil {
		return // No results, just exit (e.g. setup, printed help...)
	}

	var notExactlyOneError bool
	displayer, err := NewDisplayer(resp)
	if err != nil {
		PrintFatal(err.Error())
	}
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		// Let user know if something went wrong
		fmt.Fprintln(errOut, resp.Status)
		if len(displayer.body) > 0 {
			fmt.Fprintln(errOut, displayer.body)
		}
	} else if cmdLine.ExtractOneSelect != "" {
		err = displayer.ApplySingleExtract(cmdLine.ExtractOneSelect)
		if err != nil {
			notExactlyOneError = strings.Contains(err.Error(),
				"instead of one value") // Ugh, there has to be a better way
			PrintError(err.Error())
		}
		fmt.Fprint(out, displayer.Output())
	} else {
		if cmdLine.ExtractSelector != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelector, false)
		} else if cmdLine.ExtractSelectorJSON != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelectorJSON, true)
		} else if cmdLine.ExtractHeader != "" {
			err = displayer.ApplyHeaderExtract(cmdLine.ExtractHeader)
		}
		if err != nil {
			PrintFatal(err.Error())
		} else if cmdLine.Pretty {
			displayer.Pretty()
		}
		fmt.Fprint(out, displayer.Output())
	}
	// Figure out exit code
	exitStatus := 0
	switch {
	case notExactlyOneError:
		exitStatus = 6
	case resp.StatusCode == 401:
		exitStatus = 1
	case resp.StatusCode == 403:
		exitStatus = 3
	case resp.StatusCode == 404:
		exitStatus = 4
	case resp.StatusCode > 399 && resp.StatusCode < 500:
		exitStatus = 2
	case resp.StatusCode > 499:
		exitStatus = 5
	}
	//fmt.Fprintf(os.Stderr, "exitStatus=%d\n", exitStatus)
	osExit(exitStatus)
}

// Helper that runs command line with give command client
func runCommand(client cmd.CommandClient, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	cmds := strings.Split(cmdLine.Command, " ")
	if cmdLine.ShowHelp {
		err = client.ShowCommandHelp(cmdLine.Command)
	} else if len(cmds) > 1 && cmds[1] == "actions" {
		err = client.ShowAPIActions(cmdLine.Command)
	} else {
		resp, err = client.RunCommand(cmdLine.Command)
	}
	return
}

func ExecuteCommand(app *kingpin.Application, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	app.Writer(errOut)
	log.Interactive()
	topCommand := strings.Split(cmdLine.Command, " ")[0]
	switch topCommand {
	case "setup":
		err = CreateConfig(cmdLine.ConfigPath)
	case "json":
		var b []byte
		b, err = ioutil.ReadAll(os.Stdin)
		if err == nil {
			resp = CreateJSONResponse(b)
		}
	default:
		// retry any failed API response as specified by the retry flag
		for i := 0; i < cmdLine.Retry+1; i++ {
			resp, err = doAPIRequest(topCommand, cmdLine)
			if !shouldRetry(resp, err) {
				break
			}
		}
	}

	return resp, err
}

// Constructs an http response from JSON input from Stdin
func CreateJSONResponse(b []byte) (resp *http.Response) {
	// Remove UTF-8 Byte Order Mark if it exists
	b = bytes.TrimPrefix(b, []byte{0xef, 0xbb, 0xbf})
	resp = &http.Response{
		StatusCode: 200,
		Body:       ioutil.NopCloser(bytes.NewBuffer(b)),
	}
	return resp
}

func shouldRetry(resp *http.Response, err error) bool {
	if err != nil {
		if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
			return true
		}
	}
	if resp != nil {
		if resp.StatusCode == 500 || resp.StatusCode == 503 {
			return true
		}
	}
	return false
}

var doAPIRequest = func(command string, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	httpclient.ResponseHeaderTimeout = time.Duration(cmdLine.Timeout) * time.Second
	client, err := APIClient(command, cmdLine)
	if err == nil {
		resp, err = runCommand(client, cmdLine)
		if err == nil {
			return resp, err
		}
	}
	return nil, err
}
<commit_msg>Actually use format for PrintFatal<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/rightscale/rsc/cmd"
	"github.com/rightscale/rsc/httpclient"
	"github.com/rightscale/rsc/log"
	"gopkg.in/alecthomas/kingpin.v2"

	// phoney reference to make Godep pull this in for the code generators
	_ "bitbucket.org/pkg/inflect"
)

// Command line client entry point.
func main() {
	app := kingpin.New("rsc", "A RightScale API client")
	app.Writer(os.Stdout)
	app.Version(VV)

	cmdLine, err := ParseCommandLine(app)
	if err != nil {
		line := strings.Join(os.Args, " ")
		PrintFatal("%s: %s", line, err.Error())
	}

	resp, err := ExecuteCommand(app, cmdLine)
	if err != nil {
		PrintFatal("%s", err.Error())
	}
	if resp == nil {
		return // No results, just exit (e.g. setup, printed help...)
	}

	var notExactlyOneError bool
	displayer, err := NewDisplayer(resp)
	if err != nil {
		PrintFatal("%s", err.Error())
	}
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		// Let user know if something went wrong
		fmt.Fprintln(errOut, resp.Status)
		if len(displayer.body) > 0 {
			fmt.Fprintln(errOut, displayer.body)
		}
	} else if cmdLine.ExtractOneSelect != "" {
		err = displayer.ApplySingleExtract(cmdLine.ExtractOneSelect)
		if err != nil {
			notExactlyOneError = strings.Contains(err.Error(),
				"instead of one value") // Ugh, there has to be a better way
			PrintError(err.Error())
		}
		fmt.Fprint(out, displayer.Output())
	} else {
		if cmdLine.ExtractSelector != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelector, false)
		} else if cmdLine.ExtractSelectorJSON != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelectorJSON, true)
		} else if cmdLine.ExtractHeader != "" {
			err = displayer.ApplyHeaderExtract(cmdLine.ExtractHeader)
		}
		if err != nil {
			PrintFatal("%s", err.Error())
		} else if cmdLine.Pretty {
			displayer.Pretty()
		}
		fmt.Fprint(out, displayer.Output())
	}
	// Figure out exit code
	exitStatus := 0
	switch {
	case notExactlyOneError:
		exitStatus = 6
	case resp.StatusCode == 401:
		exitStatus = 1
	case resp.StatusCode == 403:
		exitStatus = 3
	case resp.StatusCode == 404:
		exitStatus = 4
	case resp.StatusCode > 399 && resp.StatusCode < 500:
		exitStatus = 2
	case resp.StatusCode > 499:
		exitStatus = 5
	}
	//fmt.Fprintf(os.Stderr, "exitStatus=%d\n", exitStatus)
	osExit(exitStatus)
}

// Helper that runs command line with give command client
func runCommand(client cmd.CommandClient, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	cmds := strings.Split(cmdLine.Command, " ")
	if cmdLine.ShowHelp {
		err = client.ShowCommandHelp(cmdLine.Command)
	} else if len(cmds) > 1 && cmds[1] == "actions" {
		err = client.ShowAPIActions(cmdLine.Command)
	} else {
		resp, err = client.RunCommand(cmdLine.Command)
	}
	return
}

func ExecuteCommand(app *kingpin.Application, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	app.Writer(errOut)
	log.Interactive()
	topCommand := strings.Split(cmdLine.Command, " ")[0]
	switch topCommand {
	case "setup":
		err = CreateConfig(cmdLine.ConfigPath)
	case "json":
		var b []byte
		b, err = ioutil.ReadAll(os.Stdin)
		if err == nil {
			resp = CreateJSONResponse(b)
		}
	default:
		// retry any failed API response as specified by the retry flag
		for i := 0; i < cmdLine.Retry+1; i++ {
			resp, err = doAPIRequest(topCommand, cmdLine)
			if !shouldRetry(resp, err) {
				break
			}
		}
	}

	return resp, err
}

// Constructs an http response from JSON input from Stdin
func CreateJSONResponse(b []byte) (resp *http.Response) {
	// Remove UTF-8 Byte Order Mark if it exists
	b = bytes.TrimPrefix(b, []byte{0xef, 0xbb, 0xbf})
	resp = &http.Response{
		StatusCode: 200,
		Body:       ioutil.NopCloser(bytes.NewBuffer(b)),
	}
	return resp
}

func shouldRetry(resp *http.Response, err error) bool {
	if err != nil {
		if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
			return true
		}
	}
	if resp != nil {
		if resp.StatusCode == 500 || resp.StatusCode == 503 {
			return true
		}
	}
	return false
}

var doAPIRequest = func(command string, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	httpclient.ResponseHeaderTimeout = time.Duration(cmdLine.Timeout) * time.Second
	client, err := APIClient(command, cmdLine)
	if err == nil {
		resp, err = runCommand(client, cmdLine)
		if err == nil {
			return resp, err
		}
	}
	return nil, err
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"errors"
	"fmt"
	"math/rand"
	"time"

	"github.com/go-gl/gl"
	glfw "github.com/go-gl/glfw3"
)

var (
	ship             *Ship
	bullets          []*Bullet
	asteroids        []*Asteroid
	explosions       []*Explosion
	lastBulletFired  float64 = -1
	bulletsPerSecond float64 = 5
	gameWidth        float64
	gameHeight       float64
	fieldSize        float64 = 400
	fullscreen       bool    = false
	altEnter         bool    = false
	colorsInverted   bool    = false
	wireframe        bool    = true
	paused           bool    = false
	rng                      = rand.New(rand.NewSource(time.Now().UnixNano()))
	score            int     = 0
	highscore        int     = 0
	showHighscore    bool    = true
	difficulty       int     = 6
	debug            bool    = true
)

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func main() {
	glfw.SetErrorCallback(errorCallback)

	if !glfw.Init() {
		panic("can't init glfw!")
	}
	defer glfw.Terminate()

	var window *glfw.Window = initGame()
	runGameLoop(window)

	fmt.Printf("Your highscore was %d points!\n", highscore)
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	//fmt.Printf("%v, %v, %v, %v\n", key, scancode, action, mods)

	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}

	if !paused {
		if key == glfw.KeyLeft {
			if action == glfw.Press {
				ship.RotateLeft(true)
			} else if action == glfw.Release {
				ship.RotateLeft(false)
			}
		} else if key == glfw.KeyRight {
			if action == glfw.Press {
				ship.RotateRight(true)
			} else if action == glfw.Release {
				ship.RotateRight(false)
			}
		}

		if key == glfw.KeyUp {
			if action == glfw.Press {
				ship.Accelerate(true)
			} else if action == glfw.Release {
				ship.Accelerate(false)
			}
		} else if key == glfw.KeyDown {
			if action == glfw.Press {
				ship.Decelerate(true)
			} else if action == glfw.Release {
				ship.Decelerate(false)
			}
		}

		if key == glfw.KeySpace && action == glfw.Press && glfw.GetTime() > lastBulletFired+(1/bulletsPerSecond) && ship.IsAlive() {
			bullet := ship.Shoot()
			bullets = append(bullets, bullet)
			lastBulletFired = glfw.GetTime()
		}
	}

	if key == glfw.KeyEnter && action == glfw.Press { //&& mods == glfw.ModAlt {
		altEnter = true
	}

	if key == glfw.KeyF1 && action == glfw.Press {
		switchHighscore()
	}

	if key == glfw.KeyF2 && action == glfw.Press {
		switchColors()
	}

	if key == glfw.KeyF3 && action == glfw.Press {
		switchWireframe()
	}

	if (key == glfw.KeyF9 || key == glfw.KeyR || key == glfw.KeyBackspace) && action == glfw.Press {
		resetGame()
	}

	if (key == glfw.KeyPause || key == glfw.KeyP) && action == glfw.Press {
		paused = !paused
	}

	if key == glfw.KeyN && action == glfw.Press && len(asteroids) == 0 && ship.IsAlive() {
		difficulty += 3
		resetGame()
	}

	if debug && key == glfw.KeyF10 && action == glfw.Press {
		asteroids = nil
	}
}

func reshapeWindow(window *glfw.Window, width, height int) {
	ratio := float64(width) / float64(height)
	gameWidth = ratio * fieldSize
	gameHeight = fieldSize
	gl.Viewport(0, 0, width, height)
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()

	gl.Ortho(0, gameWidth, 0, gameHeight, -1.0, 1.0)
	gl.MatrixMode(gl.MODELVIEW)
	if wireframe {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	}
}

func initWindow() (window *glfw.Window, err error) {
	monitor, err := glfw.GetPrimaryMonitor()
	if err != nil {
		return nil, err
	}
	videomode, err := monitor.GetVideoMode()
	if err != nil {
		return nil, err
	}
	if videomode.Height < 480 || videomode.Width < 640 {
		return nil, errors.New("unsupported resolution!")
	}

	ratio := float64(videomode.Width) / float64(videomode.Height)

	if fullscreen {
		glfw.WindowHint(glfw.Decorated, 0)
		window, err = glfw.CreateWindow(videomode.Width, videomode.Height, "Golang Asteroids!", nil, nil)
		if err != nil {
			return nil, err
		}
		window.SetPosition(0, 0)
	} else {
		glfw.WindowHint(glfw.Decorated, 1)
		window, err = glfw.CreateWindow(int(ratio*480), 480, "Golang Asteroids!", nil, nil)
		if err != nil {
			return nil, err
		}
		window.SetPosition(videomode.Width/2-320, videomode.Height/2-240)
	}

	window.SetKeyCallback(keyCallback)
	window.SetFramebufferSizeCallback(reshapeWindow)
	window.MakeContextCurrent()

	gl.Init()
	gl.ClearColor(gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), 0.0)
	gl.Clear(gl.COLOR_BUFFER_BIT)

	width, height := window.GetFramebufferSize()
	reshapeWindow(window, width, height)

	return window, nil
}

func switchHighscore() {
	showHighscore = !showHighscore
}

func switchColors() {
	colorsInverted = !colorsInverted
	gl.ClearColor(gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), 0.0)
	gl.Clear(gl.COLOR_BUFFER_BIT)
}

func switchWireframe() {
	wireframe = !wireframe
	if wireframe {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	} else {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
	}
}

func initGame() *glfw.Window {
	window, err := initWindow()
	if err != nil {
		panic(err)
	}

	resetGame()

	return window
}

func resetGame() {
	score = 0

	// init ship
	ship = NewShip(gameWidth/2, gameHeight/2, 0, 0.01)

	// create a couple of random asteroids
	asteroids = nil
	for i := 1; i <= difficulty; i++ {
		CreateAsteroid(2+rng.Float64()*8, 3)
	}

	bullets = nil
	explosions = nil
}

func drawHighScore() {
	if score > highscore {
		highscore = score
	}
	if showHighscore {
		DrawString(10, fieldSize-32, 1, Color{0.5, 0.5, 0.5}, fmt.Sprintf("highscore: %d", highscore))
	}
}

func drawCurrentScore() {
	DrawString(10, fieldSize-20, 1, Color{1, 1, 1}, fmt.Sprintf("score: %d", score))
}

func drawWinningScreen() {
	DrawString(fieldSize/2-20, fieldSize/2+10, 5, Color{1, 1, 1}, fmt.Sprintf("You won!"))
	DrawString(fieldSize/2-120, fieldSize/2-20, 2, Color{1, 1, 1}, fmt.Sprintf("Press R to restart current level"))
	DrawString(fieldSize/2-120, fieldSize/2-50, 2, Color{1, 1, 1}, fmt.Sprintf("Press N to advance to next difficulty level"))
}

func addScore(value int) {
	score = score + value
}

func runGameLoop(window *glfw.Window) {
	for !window.ShouldClose() {
		//check if objects are still alive
		var bullets2 []*Bullet
		for _, bullet := range bullets {
			if bullet.IsAlive() {
				bullets2 = append(bullets2, bullet)
			}
		}
		bullets = bullets2

		var asteroids2 []*Asteroid
		for _, asteroid := range asteroids {
			if asteroid.IsAlive() {
				asteroids2 = append(asteroids2, asteroid)
			}
		}
		asteroids = asteroids2

		var explosions2 []*Explosion
		for _, explosion := range explosions {
			if explosion.IsAlive() {
				explosions2 = append(explosions2, explosion)
			}
		}
		explosions = explosions2

		// update objects
		ship.Update()
		for _, bullet := range bullets {
			bullet.Update()
		}
		for _, asteroid := range asteroids {
			asteroid.Update()
		}
		for _, explosion := range explosions {
			explosion.Update()
		}

		// hit detection
		for _, asteroid := range asteroids {
			for _, bullet := range bullets {
				if IsColliding(&asteroid.Entity, &bullet.Entity) {
					asteroid.Destroy()
					bullet.Destroy()
				}
			}
			if ship.IsAlive() && IsColliding(&asteroid.Entity, &ship.Entity) {
				asteroid.Destroy()
				ship.Destroy()
			}
		}

		// ---------------------------------------------------------------
		// draw calls
		gl.Clear(gl.COLOR_BUFFER_BIT)

		ship.Draw(false)
		for _, bullet := range bullets {
			bullet.Draw()
		}
		for _, asteroid := range asteroids {
			asteroid.Draw(true)
		}
		for _, explosion := range explosions {
			explosion.Draw()
		}

		drawCurrentScore()
		drawHighScore()

		if len(asteroids) == 0 && ship.IsAlive() {
			drawWinningScreen()
		}

		gl.Flush()
		window.SwapBuffers()
		glfw.PollEvents()

		// switch resolution
		if altEnter {
			window.Destroy()

			fullscreen = !fullscreen
			var err error
			window, err = initWindow()
			if err != nil {
				panic(err)
			}

			altEnter = false

			gl.LineWidth(1)
			if fullscreen {
				gl.LineWidth(2)
			}
		}
	}
}
<commit_msg>asteroids explode on debug clearing<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"errors"
	"fmt"
	"math/rand"
	"time"

	"github.com/go-gl/gl"
	glfw "github.com/go-gl/glfw3"
)

var (
	ship             *Ship
	bullets          []*Bullet
	asteroids        []*Asteroid
	explosions       []*Explosion
	lastBulletFired  float64 = -1
	bulletsPerSecond float64 = 5
	gameWidth        float64
	gameHeight       float64
	fieldSize        float64 = 400
	fullscreen       bool    = false
	altEnter         bool    = false
	colorsInverted   bool    = false
	wireframe        bool    = true
	paused           bool    = false
	rng                      = rand.New(rand.NewSource(time.Now().UnixNano()))
	score            int     = 0
	highscore        int     = 0
	showHighscore    bool    = true
	difficulty       int     = 6
	debug            bool    = true
)

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func main() {
	glfw.SetErrorCallback(errorCallback)

	if !glfw.Init() {
		panic("can't init glfw!")
	}
	defer glfw.Terminate()

	var window *glfw.Window = initGame()
	runGameLoop(window)

	fmt.Printf("Your highscore was %d points!\n", highscore)
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	//fmt.Printf("%v, %v, %v, %v\n", key, scancode, action, mods)

	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}

	if !paused {
		if key == glfw.KeyLeft {
			if action == glfw.Press {
				ship.RotateLeft(true)
			} else if action == glfw.Release {
				ship.RotateLeft(false)
			}
		} else if key == glfw.KeyRight {
			if action == glfw.Press {
				ship.RotateRight(true)
			} else if action == glfw.Release {
				ship.RotateRight(false)
			}
		}

		if key == glfw.KeyUp {
			if action == glfw.Press {
				ship.Accelerate(true)
			} else if action == glfw.Release {
				ship.Accelerate(false)
			}
		} else if key == glfw.KeyDown {
			if action == glfw.Press {
				ship.Decelerate(true)
			} else if action == glfw.Release {
				ship.Decelerate(false)
			}
		}

		if key == glfw.KeySpace && action == glfw.Press && glfw.GetTime() > lastBulletFired+(1/bulletsPerSecond) && ship.IsAlive() {
			bullet := ship.Shoot()
			bullets = append(bullets, bullet)
			lastBulletFired = glfw.GetTime()
		}
	}

	if key == glfw.KeyEnter && action == glfw.Press { //&& mods == glfw.ModAlt {
		altEnter = true
	}

	if key == glfw.KeyF1 && action == glfw.Press {
		switchHighscore()
	}

	if key == glfw.KeyF2 && action == glfw.Press {
		switchColors()
	}

	if key == glfw.KeyF3 && action == glfw.Press {
		switchWireframe()
	}

	if (key == glfw.KeyF9 || key == glfw.KeyR || key == glfw.KeyBackspace) && action == glfw.Press {
		resetGame()
	}

	if (key == glfw.KeyPause || key == glfw.KeyP) && action == glfw.Press {
		paused = !paused
	}

	if key == glfw.KeyN && action == glfw.Press && len(asteroids) == 0 && ship.IsAlive() {
		difficulty += 3
		resetGame()
	}

	if debug && key == glfw.KeyF10 && action == glfw.Press {
		for _, asteroid := range asteroids {
			if asteroid.IsAlive() {
				asteroid.Destroy()
			}
		}
	}
}

func reshapeWindow(window *glfw.Window, width, height int) {
	ratio := float64(width) / float64(height)
	gameWidth = ratio * fieldSize
	gameHeight = fieldSize
	gl.Viewport(0, 0, width, height)
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()

	gl.Ortho(0, gameWidth, 0, gameHeight, -1.0, 1.0)
	gl.MatrixMode(gl.MODELVIEW)
	if wireframe {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	}
}

func initWindow() (window *glfw.Window, err error) {
	monitor, err := glfw.GetPrimaryMonitor()
	if err != nil {
		return nil, err
	}
	videomode, err := monitor.GetVideoMode()
	if err != nil {
		return nil, err
	}
	if videomode.Height < 480 || videomode.Width < 640 {
		return nil, errors.New("unsupported resolution!")
	}

	ratio := float64(videomode.Width) / float64(videomode.Height)

	if fullscreen {
		glfw.WindowHint(glfw.Decorated, 0)
		window, err = glfw.CreateWindow(videomode.Width, videomode.Height, "Golang Asteroids!", nil, nil)
		if err != nil {
			return nil, err
		}
		window.SetPosition(0, 0)
	} else {
		glfw.WindowHint(glfw.Decorated, 1)
		window, err = glfw.CreateWindow(int(ratio*480), 480, "Golang Asteroids!", nil, nil)
		if err != nil {
			return nil, err
		}
		window.SetPosition(videomode.Width/2-320, videomode.Height/2-240)
	}

	window.SetKeyCallback(keyCallback)
	window.SetFramebufferSizeCallback(reshapeWindow)
	window.MakeContextCurrent()

	gl.Init()
	gl.ClearColor(gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), 0.0)
	gl.Clear(gl.COLOR_BUFFER_BIT)

	width, height := window.GetFramebufferSize()
	reshapeWindow(window, width, height)

	return window, nil
}

func switchHighscore() {
	showHighscore = !showHighscore
}

func switchColors() {
	colorsInverted = !colorsInverted
	gl.ClearColor(gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), gl.GLclampf(Colorize(0)), 0.0)
	gl.Clear(gl.COLOR_BUFFER_BIT)
}

func switchWireframe() {
	wireframe = !wireframe
	if wireframe {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	} else {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
	}
}

func initGame() *glfw.Window {
	window, err := initWindow()
	if err != nil {
		panic(err)
	}

	resetGame()

	return window
}

func resetGame() {
	score = 0

	// init ship
	ship = NewShip(gameWidth/2, gameHeight/2, 0, 0.01)

	// create a couple of random asteroids
	asteroids = nil
	for i := 1; i <= difficulty; i++ {
		CreateAsteroid(2+rng.Float64()*8, 3)
	}

	bullets = nil
	explosions = nil
}

func drawHighScore() {
	if score > highscore {
		highscore = score
	}
	if showHighscore {
		DrawString(10, fieldSize-32, 1, Color{0.5, 0.5, 0.5}, fmt.Sprintf("highscore: %d", highscore))
	}
}

func drawCurrentScore() {
	DrawString(10, fieldSize-20, 1, Color{1, 1, 1}, fmt.Sprintf("score: %d", score))
}

func drawWinningScreen() {
	DrawString(fieldSize/2-20, fieldSize/2+10, 5, Color{1, 1, 1}, fmt.Sprintf("You won!"))
	DrawString(fieldSize/2-120, fieldSize/2-20, 2, Color{1, 1, 1}, fmt.Sprintf("Press R to restart current level"))
	DrawString(fieldSize/2-120, fieldSize/2-50, 2, Color{1, 1, 1}, fmt.Sprintf("Press N to advance to next difficulty level"))
}

func addScore(value int) {
	score = score + value
}

func runGameLoop(window *glfw.Window) {
	for !window.ShouldClose() {
		//check if objects are still alive
		var bullets2 []*Bullet
		for _, bullet := range bullets {
			if bullet.IsAlive() {
				bullets2 = append(bullets2, bullet)
			}
		}
		bullets = bullets2

		var asteroids2 []*Asteroid
		for _, asteroid := range asteroids {
			if asteroid.IsAlive() {
				asteroids2 = append(asteroids2, asteroid)
			}
		}
		asteroids = asteroids2

		var explosions2 []*Explosion
		for _, explosion := range explosions {
			if explosion.IsAlive() {
				explosions2 = append(explosions2, explosion)
			}
		}
		explosions = explosions2

		// update objects
		ship.Update()
		for _, bullet := range bullets {
			bullet.Update()
		}
		for _, asteroid := range asteroids {
			asteroid.Update()
		}
		for _, explosion := range explosions {
			explosion.Update()
		}

		// hit detection
		for _, asteroid := range asteroids {
			for _, bullet := range bullets {
				if IsColliding(&asteroid.Entity, &bullet.Entity) {
					asteroid.Destroy()
					bullet.Destroy()
				}
			}
			if ship.IsAlive() && IsColliding(&asteroid.Entity, &ship.Entity) {
				asteroid.Destroy()
				ship.Destroy()
			}
		}

		// ---------------------------------------------------------------
		// draw calls
		gl.Clear(gl.COLOR_BUFFER_BIT)

		ship.Draw(false)
		for _, bullet := range bullets {
			bullet.Draw()
		}
		for _, asteroid := range asteroids {
			asteroid.Draw(true)
		}
		for _, explosion := range explosions {
			explosion.Draw()
		}

		drawCurrentScore()
		drawHighScore()

		if len(asteroids) == 0 && ship.IsAlive() {
			drawWinningScreen()
		}

		gl.Flush()
		window.SwapBuffers()
		glfw.PollEvents()

		// switch resolution
		if altEnter {
			window.Destroy()

			fullscreen = !fullscreen
			var err error
			window, err = initWindow()
			if err != nil {
				panic(err)
			}

			altEnter = false

			gl.LineWidth(1)
			if fullscreen {
				gl.LineWidth(2)
			}
		}
	}
}
<|endoftext|>


<commit_before>package dbfiles

import (
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/juju/errgo"
)

func init() {
	//	log.SetLevel(log.DebugLevel)
}

type DBFiles struct {
	BaseDir string
	Driver
	Structure
	keys       [][]string
	keysmux    *sync.RWMutex
	WriteQueue chan (record)
}

type record struct {
	values    []string
	key       []string
	errorChan chan (error)
	basedir   string
}

const DefaultBaseDir = "data"

func New() *DBFiles {
	db := new(DBFiles)
	db.BaseDir = DefaultBaseDir
	db.Driver = CSV{}
	db.Structure = NewFolders()
	db.keysmux = new(sync.RWMutex)
	db.WriteQueue = make(chan (record), 10000)

	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()

	return db
}

func (db DBFiles) runQueue() {
	for {
		record := <-db.WriteQueue
		log.Debug("new record: ", record)
		log.Debug("Basedir: ", record.basedir)

		_, err := os.Stat(record.basedir)
		if os.IsNotExist(err) {
			err := db.Structure.Create(record.basedir)
			if err != nil {
				record.errorChan <- errgo.Notef(err, "can not create structure")
				continue
			}
		}

		file, err := db.Structure.File(record.basedir, db.Driver, record.key)
		if err != nil {
			record.errorChan <- errgo.Notef(err, "can not open file")
			continue
		}

		err = db.Driver.Write(file, record.values)
		if err != nil {
			record.errorChan <- errgo.Notef(err, "can not write values")
			continue
		}

		var data []byte
		io.ReadFull(file, data)
		log.Debug("Data: ", string(data))

		record.errorChan <- nil
		log.Debug("finished writing record: ", record)
	}
}

func (db *DBFiles) Put(values []string, key ...string) error {
	errorChan := make(chan (error))

	rec := record{
		values:    values,
		key:       key,
		errorChan: errorChan,
		basedir:   db.BaseDir,
	}

	db.WriteQueue <- rec

	err := <-errorChan

	return err
}

func (db DBFiles) Get(key ...string) ([][]string, error) {
	file, err := db.Structure.File(db.BaseDir, db.Driver, key)
	if err != nil {
		return nil, errgo.Notef(err, "can not open file")
	}

	values, err := db.Driver.Read(file)
	if err != nil {
		return nil, errgo.Notef(err, "can not read values")
	}

	return values, nil
}

func (db DBFiles) Keys() ([][]string, error) {
	_, err := os.Stat(db.BaseDir)
	if os.IsNotExist(err) {
		return [][]string{}, nil
	}

	err = filepath.Walk(db.BaseDir, db.walkPopulateKeys)
	if err != nil {
		return nil, errgo.Notef(err, "can not walk through basedir")
	}

	return db.keys, nil
}

func (db *DBFiles) walkPopulateKeys(path string, info os.FileInfo, err error) error {
	if err != nil {
		return errgo.Notef(err, "error is not empty")
	}

	if info == nil {
		return errgo.New("directory info is empty")
	}

	if info.IsDir() {
		return nil
	}

	// Remove basedir from path
	relpath, err := filepath.Rel(db.BaseDir, path)
	if err != nil {
		return errgo.Notef(err, "can not get relative path")
	}

	// Get driver extention
	driverext := filepath.Ext(relpath)

	// remove driverextention
	nodriverpath := strings.TrimRight(relpath, driverext)

	// Split by path sepperator
	split := strings.Split(nodriverpath, string(os.PathSeparator))

	// Append new key to the db.keys
	db.keysmux.Lock()
	db.keys = append(db.keys, split)
	db.keysmux.Unlock()

	return nil
}

func (db *DBFiles) Destroy() error {
	err := os.RemoveAll(db.BaseDir)
	if err != nil {
		return errgo.Notef(err, "can not remove basedir")
	}

	return nil
}
<commit_msg>Will now skip git folder when scanning for files.<commit_after>package dbfiles

import (
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/juju/errgo"
)

func init() {
	//	log.SetLevel(log.DebugLevel)
}

type DBFiles struct {
	BaseDir string
	Driver
	Structure
	WriteQueue chan (record)

	keysmux *sync.RWMutex
	keys    [][]string
}

type record struct {
	values    []string
	key       []string
	errorChan chan (error)
	basedir   string
}

const DefaultBaseDir = "data"

func New() *DBFiles {
	db := new(DBFiles)
	db.BaseDir = DefaultBaseDir
	db.Driver = CSV{}
	db.Structure = NewFolders()

	db.WriteQueue = make(chan (record), 10000)
	db.keysmux = new(sync.RWMutex)

	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()
	go db.runQueue()

	return db
}

func (db DBFiles) runQueue() {
	for {
		record := <-db.WriteQueue
		log.Debug("new record: ", record)
		log.Debug("Basedir: ", record.basedir)

		_, err := os.Stat(record.basedir)
		if os.IsNotExist(err) {
			err := db.Structure.Create(record.basedir)
			if err != nil {
				record.errorChan <- errgo.Notef(err, "can not create structure")
				continue
			}
		}

		file, err := db.Structure.File(record.basedir, db.Driver, record.key)
		if err != nil {
			record.errorChan <- errgo.Notef(err, "can not open file")
			continue
		}

		err = db.Driver.Write(file, record.values)
		if err != nil {
			record.errorChan <- errgo.Notef(err, "can not write values")
			continue
		}

		var data []byte
		io.ReadFull(file, data)
		log.Debug("Data: ", string(data))

		record.errorChan <- nil
		log.Debug("finished writing record: ", record)
	}
}

func (db *DBFiles) Put(values []string, key ...string) error {
	errorChan := make(chan (error))

	rec := record{
		values:    values,
		key:       key,
		errorChan: errorChan,
		basedir:   db.BaseDir,
	}

	db.WriteQueue <- rec

	err := <-errorChan

	return err
}

func (db DBFiles) Get(key ...string) ([][]string, error) {
	file, err := db.Structure.File(db.BaseDir, db.Driver, key)
	if err != nil {
		return nil, errgo.Notef(err, "can not open file")
	}

	values, err := db.Driver.Read(file)
	if err != nil {
		return nil, errgo.Notef(err, "can not read values")
	}

	return values, nil
}

func (db DBFiles) Keys() ([][]string, error) {
	_, err := os.Stat(db.BaseDir)
	if os.IsNotExist(err) {
		return [][]string{}, nil
	}

	err = filepath.Walk(db.BaseDir, db.walkPopulateKeys)
	if err != nil {
		return nil, errgo.Notef(err, "can not walk through basedir")
	}

	return db.keys, nil
}

func (db *DBFiles) walkPopulateKeys(path string, info os.FileInfo, err error) error {
	if err != nil {
		return errgo.Notef(err, "error is not empty")
	}

	if info == nil {
		return errgo.New("directory info is empty")
	}

	//Skip git folder
	if info.IsDir() && info.Name() == ".git" {
		return filepath.SkipDir
	}

	if info.IsDir() {
		return nil
	}

	// Remove basedir from path
	relpath, err := filepath.Rel(db.BaseDir, path)
	if err != nil {
		return errgo.Notef(err, "can not get relative path")
	}

	// Get driver extention
	driverext := filepath.Ext(relpath)

	// remove driverextention
	nodriverpath := strings.TrimRight(relpath, driverext)

	// Split by path sepperator
	split := strings.Split(nodriverpath, string(os.PathSeparator))

	// Append new key to the db.keys
	db.keysmux.Lock()
	db.keys = append(db.keys, split)
	db.keysmux.Unlock()

	return nil
}

func (db *DBFiles) Destroy() error {
	err := os.RemoveAll(db.BaseDir)
	if err != nil {
		return errgo.Notef(err, "can not remove basedir")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/xml"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"net/http"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/html/charset"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"
)

const (
	namespace = "passenger_nginx"

	nanosecondsPerSecond = 1000000000
)

var (
	timeoutErr = errors.New("passenger-status command timed out")

	processIdentifiers = make(map[string]int)
)

// Exporter collects metrics from a passenger-nginx integration.
type Exporter struct {
	// binary file path for querying passenger state.
	cmd  string
	args []string

	// Passenger command timeout.
	timeout time.Duration

	// Passenger metrics.
	up                  *prometheus.Desc
	version             *prometheus.Desc
	toplevelQueue       *prometheus.Desc
	maxProcessCount     *prometheus.Desc
	currentProcessCount *prometheus.Desc
	appCount            *prometheus.Desc

	// App metrics.
	appQueue         *prometheus.Desc
	appProcsSpawning *prometheus.Desc

	// Process metrics.
	requestsProcessed *prometheus.Desc
	procStartTime     *prometheus.Desc
	procMemory        *prometheus.Desc
}

func NewExporter(cmd string, timeout time.Duration) *Exporter {
	cmdComponents := strings.Split(cmd, " ")

	return &Exporter{
		cmd:     cmdComponents[0],
		args:    cmdComponents[1:],
		timeout: timeout,
		up: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "up"),
			"Could passenger status be queried.",
			nil,
			nil,
		),
		version: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "version"),
			"Version of passenger",
			[]string{"version"},
			nil,
		),
		toplevelQueue: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "top_level_queue"),
			"Number of requests in the top-level queue.",
			nil,
			nil,
		),
		maxProcessCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "max_processes"),
			"Configured maximum number of processes.",
			nil,
			nil,
		),
		currentProcessCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "current_processes"),
			"Current number of processes.",
			nil,
			nil,
		),
		appCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_count"),
			"Number of apps.",
			nil,
			nil,
		),
		appQueue: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_queue"),
			"Number of requests in app process queues.",
			[]string{"name"},
			nil,
		),
		appProcsSpawning: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_procs_spawning"),
			"Number of processes spawning.",
			[]string{"name"},
			nil,
		),
		requestsProcessed: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "requests_processed_total"),
			"Number of processes served by a process.",
			[]string{"name", "id"},
			nil,
		),
		procStartTime: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proc_start_time_seconds"),
			"Number of seconds since processor started.",
			[]string{"name", "id", "codeRevision"},
			nil,
		),
		procMemory: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proc_memory"),
			"Memory consumed by a process",
			[]string{"name", "id"},
			nil,
		),
	}
}

// Collect fetches the statistics from the configured passenger frontend, and
// delivers them as Prometheus metrics. It implements prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	info, err := e.status()
	if err != nil {
		ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
		log.Errorf("failed to collect status from passenger: %s", err)
		return
	}
	ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)

	ch <- prometheus.MustNewConstMetric(e.version, prometheus.GaugeValue, 1, info.PassengerVersion)

	ch <- prometheus.MustNewConstMetric(e.toplevelQueue, prometheus.GaugeValue, parseFloat(info.TopLevelRequestsInQueue))
	ch <- prometheus.MustNewConstMetric(e.maxProcessCount, prometheus.GaugeValue, parseFloat(info.MaxProcessCount))
	ch <- prometheus.MustNewConstMetric(e.currentProcessCount, prometheus.GaugeValue, parseFloat(info.CurrentProcessCount))
	ch <- prometheus.MustNewConstMetric(e.appCount, prometheus.GaugeValue, parseFloat(info.AppCount))

	for _, sg := range info.SuperGroups {
		ch <- prometheus.MustNewConstMetric(e.appQueue, prometheus.GaugeValue, parseFloat(sg.RequestsInQueue), sg.Name)
		ch <- prometheus.MustNewConstMetric(e.appProcsSpawning, prometheus.GaugeValue, parseFloat(sg.Group.ProcessesSpawning), sg.Name)

		// Update process identifiers map.
		processIdentifiers = updateProcesses(processIdentifiers, sg.Group.Processes)
		for _, proc := range sg.Group.Processes {
			if bucketID, ok := processIdentifiers[proc.PID]; ok {
				ch <- prometheus.MustNewConstMetric(e.procMemory, prometheus.GaugeValue, parseFloat(proc.RealMemory), sg.Name, strconv.Itoa(bucketID))
				ch <- prometheus.MustNewConstMetric(e.requestsProcessed, prometheus.CounterValue, parseFloat(proc.RequestsProcessed), sg.Name, strconv.Itoa(bucketID))

				if startTime, err := strconv.Atoi(proc.SpawnStartTime); err == nil {
					ch <- prometheus.MustNewConstMetric(e.procStartTime, prometheus.GaugeValue, float64(startTime/nanosecondsPerSecond),
						sg.Name, strconv.Itoa(bucketID), proc.CodeRevision,
					)
				}
			}
		}
	}

}

func (e *Exporter) status() (*Info, error) {
	var (
		out bytes.Buffer
		cmd = exec.Command(e.cmd, e.args...)
	)
	cmd.Stdout = &out

	err := cmd.Start()
	if err != nil {
		return nil, err
	}

	errc := make(chan error, 1)
	go func(cmd *exec.Cmd, c chan<- error) {
		c <- cmd.Wait()
	}(cmd, errc)

	select {
	case err := <-errc:
		if err != nil {
			return nil, err
		}
	case <-time.After(e.timeout):
		return nil, timeoutErr
	}

	return parseOutput(&out)
}

func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- e.up
	ch <- e.version
	ch <- e.toplevelQueue
	ch <- e.maxProcessCount
	ch <- e.currentProcessCount
	ch <- e.appCount
	ch <- e.appQueue
	ch <- e.appProcsSpawning
	ch <- e.requestsProcessed
	ch <- e.procStartTime
	ch <- e.procMemory
}

func parseOutput(r io.Reader) (*Info, error) {
	var info Info
	decoder := xml.NewDecoder(r)
	decoder.CharsetReader = charset.NewReaderLabel
	err := decoder.Decode(&info)
	if err != nil {
		return nil, err
	}
	return &info, nil
}

func parseFloat(val string) float64 {
	v, err := strconv.ParseFloat(val, 64)
	if err != nil {
		log.Errorf("failed to parse %s: %v", val, err)
		v = math.NaN()
	}
	return v
}

// updateProcesses updates the global map from process id:exporter id. Process
// TTLs cause new processes to be created on a user-defined cycle. When a new
// process replaces an old process, the new process's statistics will be
// bucketed with those of the process it replaced.
// Processes are restarted at an offset, user-defined interval. The
// restarted process is appended to the end of the status output.  For
// maintaining consistent process identifiers between process starts,
// pids are mapped to an identifier based on process count. When a new
// process/pid appears, it is mapped to either the first empty place
// within the global map storing process identifiers, or mapped to
// pid:id pair in the map.
func updateProcesses(old map[string]int, processes []Process) map[string]int {
	var (
		updated = make(map[string]int)
		found   = make([]string, len(old))
		missing []string
	)

	for _, p := range processes {
		if id, ok := old[p.PID]; ok {
			found[id] = p.PID
			// id also serves as an index.
			// By putting the pid at a certain index, we can loop
			// through the array to find the values that are the 0
			// value (empty string).
			// If index i has the empty value, then it was never
			// updated, so we slot the first of the missingPIDs
			// into that position. Passenger-status orders output
			// by pid, increasing. We can then assume that
			// unclaimed pid positions map in order to the missing
			// pids.
		} else {
			missing = append(missing, p.PID)
		}
	}

	j := 0
	for i, pid := range found {
		if pid == "" {
			if j >= len(missing) {
				continue
			}
			pid = missing[j]
			j++
		}
		updated[pid] = i
	}

	// If the number of elements in missing iterated through is less
	// than len(missing), there are new elements to be added to the map.
	// Unused pids from the last collection are not copied from old to
	// updated, thereby cleaning the return value of unused PIDs.
	if j < len(missing) {
		count := len(found)
		for i, pid := range missing[j:] {
			updated[pid] = count + i
		}
	}

	return updated
}

func main() {
	var (
		cmd           = flag.String("passenger.command", "passenger-status --show=xml", "Passenger command for querying passenger status.")
		timeout       = flag.Duration("passenger.command.timeout", 500*time.Millisecond, "Timeout for passenger.command.")
		pidFile       = flag.String("passenger.pid-file", "", "Optional path to a file containing the passenger/nginx PID for additional metrics.")
		metricsPath   = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
		listenAddress = flag.String("web.listen-address", ":9149", "Address to listen on for web interface and telemetry.")
	)
	flag.Parse()

	if *pidFile != "" {
		prometheus.MustRegister(prometheus.NewProcessCollectorPIDFn(
			func() (int, error) {
				content, err := ioutil.ReadFile(*pidFile)
				if err != nil {
					return 0, fmt.Errorf("error reading pidfile %q: %s", *pidFile, err)
				}
				value, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return 0, fmt.Errorf("error parsing pidfile %q: %s", *pidFile, err)
				}
				return value, nil
			},
			namespace),
		)
	}

	prometheus.MustRegister(NewExporter(*cmd, *timeout))

	http.Handle(*metricsPath, prometheus.Handler())

	log.Infoln("starting passenger_exporter_nginx", version.Info())
	log.Infoln("build context", version.BuildContext())
	log.Infoln("listening on", *listenAddress)
	log.Fatal(http.ListenAndServe(*listenAddress, nil))
}
<commit_msg>export the group-nested get_wait_list_size metric (#6)<commit_after>package main

import (
	"bytes"
	"encoding/xml"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"net/http"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/html/charset"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"
)

const (
	namespace = "passenger_nginx"

	nanosecondsPerSecond = 1000000000
)

var (
	timeoutErr = errors.New("passenger-status command timed out")

	processIdentifiers = make(map[string]int)
)

// Exporter collects metrics from a passenger-nginx integration.
type Exporter struct {
	// binary file path for querying passenger state.
	cmd  string
	args []string

	// Passenger command timeout.
	timeout time.Duration

	// Passenger metrics.
	up                  *prometheus.Desc
	version             *prometheus.Desc
	toplevelQueue       *prometheus.Desc
	maxProcessCount     *prometheus.Desc
	currentProcessCount *prometheus.Desc
	appCount            *prometheus.Desc

	// App metrics.
	appQueue         *prometheus.Desc
	appGroupQueue    *prometheus.Desc
	appProcsSpawning *prometheus.Desc

	// Process metrics.
	requestsProcessed *prometheus.Desc
	procStartTime     *prometheus.Desc
	procMemory        *prometheus.Desc
}

func NewExporter(cmd string, timeout time.Duration) *Exporter {
	cmdComponents := strings.Split(cmd, " ")

	return &Exporter{
		cmd:     cmdComponents[0],
		args:    cmdComponents[1:],
		timeout: timeout,
		up: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "up"),
			"Could passenger status be queried.",
			nil,
			nil,
		),
		version: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "version"),
			"Version of passenger",
			[]string{"version"},
			nil,
		),
		toplevelQueue: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "top_level_queue"),
			"Number of requests in the top-level queue.",
			nil,
			nil,
		),
		maxProcessCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "max_processes"),
			"Configured maximum number of processes.",
			nil,
			nil,
		),
		currentProcessCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "current_processes"),
			"Current number of processes.",
			nil,
			nil,
		),
		appCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_count"),
			"Number of apps.",
			nil,
			nil,
		),
		appQueue: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_queue"),
			"Number of requests in app process queues.",
			[]string{"name"},
			nil,
		),
		appGroupQueue: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_group_queue"),
			"Number of requests in app group process queues.",
			[]string{"default"},
			nil,
		),
		appProcsSpawning: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "app_procs_spawning"),
			"Number of processes spawning.",
			[]string{"name"},
			nil,
		),
		requestsProcessed: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "requests_processed_total"),
			"Number of processes served by a process.",
			[]string{"name", "id"},
			nil,
		),
		procStartTime: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proc_start_time_seconds"),
			"Number of seconds since processor started.",
			[]string{"name", "id", "codeRevision"},
			nil,
		),
		procMemory: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proc_memory"),
			"Memory consumed by a process",
			[]string{"name", "id"},
			nil,
		),
	}
}

// Collect fetches the statistics from the configured passenger frontend, and
// delivers them as Prometheus metrics. It implements prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	info, err := e.status()
	if err != nil {
		ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
		log.Errorf("failed to collect status from passenger: %s", err)
		return
	}
	ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)

	ch <- prometheus.MustNewConstMetric(e.version, prometheus.GaugeValue, 1, info.PassengerVersion)

	ch <- prometheus.MustNewConstMetric(e.toplevelQueue, prometheus.GaugeValue, parseFloat(info.TopLevelRequestsInQueue))
	ch <- prometheus.MustNewConstMetric(e.maxProcessCount, prometheus.GaugeValue, parseFloat(info.MaxProcessCount))
	ch <- prometheus.MustNewConstMetric(e.currentProcessCount, prometheus.GaugeValue, parseFloat(info.CurrentProcessCount))
	ch <- prometheus.MustNewConstMetric(e.appCount, prometheus.GaugeValue, parseFloat(info.AppCount))

	for _, sg := range info.SuperGroups {
		ch <- prometheus.MustNewConstMetric(e.appQueue, prometheus.GaugeValue, parseFloat(sg.RequestsInQueue), sg.Name)
		ch <- prometheus.MustNewConstMetric(e.appProcsSpawning, prometheus.GaugeValue, parseFloat(sg.Group.ProcessesSpawning), sg.Name)

		ch <- prometheus.MustNewConstMetric(e.appGroupQueue, prometheus.GaugeValue, parseFloat(sg.Group.GetWaitListSize), sg.Group.Default)

		// Update process identifiers map.
		processIdentifiers = updateProcesses(processIdentifiers, sg.Group.Processes)
		for _, proc := range sg.Group.Processes {
			if bucketID, ok := processIdentifiers[proc.PID]; ok {
				ch <- prometheus.MustNewConstMetric(e.procMemory, prometheus.GaugeValue, parseFloat(proc.RealMemory), sg.Name, strconv.Itoa(bucketID))
				ch <- prometheus.MustNewConstMetric(e.requestsProcessed, prometheus.CounterValue, parseFloat(proc.RequestsProcessed), sg.Name, strconv.Itoa(bucketID))

				if startTime, err := strconv.Atoi(proc.SpawnStartTime); err == nil {
					ch <- prometheus.MustNewConstMetric(e.procStartTime, prometheus.GaugeValue, float64(startTime/nanosecondsPerSecond),
						sg.Name, strconv.Itoa(bucketID), proc.CodeRevision,
					)
				}
			}
		}
	}

}

func (e *Exporter) status() (*Info, error) {
	var (
		out bytes.Buffer
		cmd = exec.Command(e.cmd, e.args...)
	)
	cmd.Stdout = &out

	err := cmd.Start()
	if err != nil {
		return nil, err
	}

	errc := make(chan error, 1)
	go func(cmd *exec.Cmd, c chan<- error) {
		c <- cmd.Wait()
	}(cmd, errc)

	select {
	case err := <-errc:
		if err != nil {
			return nil, err
		}
	case <-time.After(e.timeout):
		return nil, timeoutErr
	}

	return parseOutput(&out)
}

func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- e.up
	ch <- e.version
	ch <- e.toplevelQueue
	ch <- e.maxProcessCount
	ch <- e.currentProcessCount
	ch <- e.appCount
	ch <- e.appQueue
	ch <- e.appGroupQueue
	ch <- e.appProcsSpawning
	ch <- e.requestsProcessed
	ch <- e.procStartTime
	ch <- e.procMemory
}

func parseOutput(r io.Reader) (*Info, error) {
	var info Info
	decoder := xml.NewDecoder(r)
	decoder.CharsetReader = charset.NewReaderLabel
	err := decoder.Decode(&info)
	if err != nil {
		return nil, err
	}
	return &info, nil
}

func parseFloat(val string) float64 {
	v, err := strconv.ParseFloat(val, 64)
	if err != nil {
		log.Errorf("failed to parse %s: %v", val, err)
		v = math.NaN()
	}
	return v
}

// updateProcesses updates the global map from process id:exporter id. Process
// TTLs cause new processes to be created on a user-defined cycle. When a new
// process replaces an old process, the new process's statistics will be
// bucketed with those of the process it replaced.
// Processes are restarted at an offset, user-defined interval. The
// restarted process is appended to the end of the status output.  For
// maintaining consistent process identifiers between process starts,
// pids are mapped to an identifier based on process count. When a new
// process/pid appears, it is mapped to either the first empty place
// within the global map storing process identifiers, or mapped to
// pid:id pair in the map.
func updateProcesses(old map[string]int, processes []Process) map[string]int {
	var (
		updated = make(map[string]int)
		found   = make([]string, len(old))
		missing []string
	)

	for _, p := range processes {
		if id, ok := old[p.PID]; ok {
			found[id] = p.PID
			// id also serves as an index.
			// By putting the pid at a certain index, we can loop
			// through the array to find the values that are the 0
			// value (empty string).
			// If index i has the empty value, then it was never
			// updated, so we slot the first of the missingPIDs
			// into that position. Passenger-status orders output
			// by pid, increasing. We can then assume that
			// unclaimed pid positions map in order to the missing
			// pids.
		} else {
			missing = append(missing, p.PID)
		}
	}

	j := 0
	for i, pid := range found {
		if pid == "" {
			if j >= len(missing) {
				continue
			}
			pid = missing[j]
			j++
		}
		updated[pid] = i
	}

	// If the number of elements in missing iterated through is less
	// than len(missing), there are new elements to be added to the map.
	// Unused pids from the last collection are not copied from old to
	// updated, thereby cleaning the return value of unused PIDs.
	if j < len(missing) {
		count := len(found)
		for i, pid := range missing[j:] {
			updated[pid] = count + i
		}
	}

	return updated
}

func main() {
	var (
		cmd           = flag.String("passenger.command", "passenger-status --show=xml", "Passenger command for querying passenger status.")
		timeout       = flag.Duration("passenger.command.timeout", 500*time.Millisecond, "Timeout for passenger.command.")
		pidFile       = flag.String("passenger.pid-file", "", "Optional path to a file containing the passenger/nginx PID for additional metrics.")
		metricsPath   = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
		listenAddress = flag.String("web.listen-address", ":9149", "Address to listen on for web interface and telemetry.")
	)
	flag.Parse()

	if *pidFile != "" {
		prometheus.MustRegister(prometheus.NewProcessCollectorPIDFn(
			func() (int, error) {
				content, err := ioutil.ReadFile(*pidFile)
				if err != nil {
					return 0, fmt.Errorf("error reading pidfile %q: %s", *pidFile, err)
				}
				value, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return 0, fmt.Errorf("error parsing pidfile %q: %s", *pidFile, err)
				}
				return value, nil
			},
			namespace),
		)
	}

	prometheus.MustRegister(NewExporter(*cmd, *timeout))

	http.Handle(*metricsPath, prometheus.Handler())

	log.Infoln("starting passenger_exporter_nginx", version.Info())
	log.Infoln("build context", version.BuildContext())
	log.Infoln("listening on", *listenAddress)
	log.Fatal(http.ListenAndServe(*listenAddress, nil))
}
<|endoftext|>


<commit_before>package main

import (
  "github.com/ant0ine/go-json-rest/rest"
  "github.com/PuerkitoBio/goquery"
  //"github.com/k0kubun/pp"
  "log"
  "fmt"
  "net/http"
  "sync"
  "strconv"
  "runtime"
)

type PostData struct {
  Url string
}

type List struct {
  Url []string
  User []User
}

type User struct {
  Name string
  Image string
  CancelCount int
  JoinCount int
}

func main() {
  api := rest.NewApi()
  api.Use(rest.DefaultDevStack...)
  router, err := rest.MakeRouter(
    rest.Post("/cancel", PostCancel),
  )

  if err != nil {
    log.Fatal(err)
  }

  api.SetApp(router)
  log.Fatal(http.ListenAndServe(":8080", api.MakeHandler()))
}

func PostCancel(w rest.ResponseWriter, r *rest.Request) {
  cpus := runtime.NumCPU()
  runtime.GOMAXPROCS(cpus)

  post_data := PostData{}
  err := r.DecodeJsonPayload(&post_data)
  if err != nil {
    rest.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  if post_data.Url == "" {
    rest.Error(w, "url required", 400)
  }

  list := List{}
  fmt.Println(post_data.Url)
  GetPageToConnpass(post_data.Url, &list)

  wg := new(sync.WaitGroup)
  for _, url := range list.Url {
    wg.Add(1)
    go GetUserPageToConnpass(&list, url, wg)
  }
  wg.Wait()

  w.WriteJson(list.User)
  // pp.Println(list.User)
}

func GetPageToConnpass(url string, list *List) {
  doc, _ := goquery.NewDocument(url + "participation/#participants")
  doc.Find(".user").Each(func(_ int, s *goquery.Selection) {
    s.Find(".image_link").Each(func(_ int, s *goquery.Selection) {
      url, _ := s.Attr("href")
      list.Url = append(list.Url, url)
    })
  })
}

func GetUserPageToConnpass(list *List, url string, wg *sync.WaitGroup) {
  // 退会ユーザーなどはURLが取れないため無視
  if url != "" {
    user := User{"", "", 0, 0}

    doc, _ := goquery.NewDocument(url)
    image_elm := doc.Find("#side_area > div.mb_20.text_center img")
    user.Name, _ = image_elm.Attr("title")
    user.Image, _ = image_elm.Attr("src")
    doc.Find("#main > div.event_area.mb_10 > div.event_list.vevent").Each(func(_ int, s *goquery.Selection) {
      join_status := s.Find("p.label_status_tag").Text()
      if join_status == "キャンセル" {
        user.CancelCount++
      } else {
        user.JoinCount++
      }
    })

    // ページ数が１以上ある場合
    if (doc.Find("#main > div.paging_area > ul > li").Length() - 1) > 1 {
      total_page := doc.Find("#main > div.paging_area > ul > li").Length() - 1

      for i := 2; i <= total_page; i++ {
        doc, _ := goquery.NewDocument(url + "?page=" + strconv.Itoa(i))
        doc.Find("#main > div.event_area.mb_10 > div.event_list.vevent").Each(func(_ int, s *goquery.Selection) {
          join_status := s.Find("p.label_status_tag").Text()
          if join_status == "キャンセル" {
            user.CancelCount++
          } else {
            user.JoinCount++
          }
        })
      }
    }

    list.User = append(list.User, user)
  }
  wg.Done()
}
<commit_msg>commit<commit_after>package main

import (
  "github.com/ant0ine/go-json-rest/rest"
  "github.com/PuerkitoBio/goquery"
  //"github.com/k0kubun/pp"
  "log"
  "fmt"
  "net/http"
  "sync"
  "strconv"
  "runtime"
)

type PostData struct {
  Url string
}

type List struct {
  Url []string
  User []User
}

type User struct {
  Name string
  Image string
  CancelCount int
  JoinCount int
}

func main() {
  api := rest.NewApi()
  api.Use(rest.DefaultDevStack...)
  router, err := rest.MakeRouter(
    rest.Post("/", PostCancel),
  )

  if err != nil {
    log.Fatal(err)
  }

  api.SetApp(router)
  log.Fatal(http.ListenAndServe(":8080", api.MakeHandler()))
}

func PostCancel(w rest.ResponseWriter, r *rest.Request) {
  cpus := runtime.NumCPU()
  runtime.GOMAXPROCS(cpus)

  post_data := PostData{}
  err := r.DecodeJsonPayload(&post_data)
  if err != nil {
    rest.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  if post_data.Url == "" {
    rest.Error(w, "url required", 400)
  }

  list := List{}
  fmt.Println(post_data.Url)
  GetPageToConnpass(post_data.Url, &list)

  wg := new(sync.WaitGroup)
  for _, url := range list.Url {
    wg.Add(1)
    go GetUserPageToConnpass(&list, url, wg)
  }
  wg.Wait()

  w.WriteJson(list.User)
  // pp.Println(list.User)
}

func GetPageToConnpass(url string, list *List) {
  doc, _ := goquery.NewDocument(url + "participation/#participants")
  doc.Find(".user").Each(func(_ int, s *goquery.Selection) {
    s.Find(".image_link").Each(func(_ int, s *goquery.Selection) {
      url, _ := s.Attr("href")
      list.Url = append(list.Url, url)
    })
  })
}

func GetUserPageToConnpass(list *List, url string, wg *sync.WaitGroup) {
  // 退会ユーザーなどはURLが取れないため無視
  if url != "" {
    user := User{"", "", 0, 0}

    doc, _ := goquery.NewDocument(url)
    image_elm := doc.Find("#side_area > div.mb_20.text_center img")
    user.Name, _ = image_elm.Attr("title")
    user.Image, _ = image_elm.Attr("src")
    doc.Find("#main > div.event_area.mb_10 > div.event_list.vevent").Each(func(_ int, s *goquery.Selection) {
      join_status := s.Find("p.label_status_tag").Text()
      if join_status == "キャンセル" {
        user.CancelCount++
      } else {
        user.JoinCount++
      }
    })

    // ページ数が１以上ある場合
    if (doc.Find("#main > div.paging_area > ul > li").Length() - 1) > 1 {
      total_page := doc.Find("#main > div.paging_area > ul > li").Length() - 1

      for i := 2; i <= total_page; i++ {
        doc, _ := goquery.NewDocument(url + "?page=" + strconv.Itoa(i))
        doc.Find("#main > div.event_area.mb_10 > div.event_list.vevent").Each(func(_ int, s *goquery.Selection) {
          join_status := s.Find("p.label_status_tag").Text()
          if join_status == "キャンセル" {
            user.CancelCount++
          } else {
            user.JoinCount++
          }
        })
      }
    }

    list.User = append(list.User, user)
  }
  wg.Done()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
	"database/sql"
	"github.com/coopernurse/gorp"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"time"
	"strconv"
	//"github.com/go-errors/errors"
)

type Article struct {
	Id int64 `db:"article_id"`
	Created int64
	Title string
	Content string
}

var dbmap = initDb()

func initDb() gorp.DbMap {
	db, err := sql.Open("sqlite3", "db.sqlite3")
	checkErr(err, "sql.Open faild")
	dbmap := gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
	dbmap.AddTableWithName(Article{}, "articles").SetKeys(true, "Id")
	err = dbmap.CreateTablesIfNotExists()
	checkErr(err, "Create tables failed")
	return dbmap
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)//.(*errors.Error).ErrorStack())
	}
}

func index (c *gin.Context) {
	content := gin.H{"Hello": "World"}
	c.JSON(200, content)
}

func ArticlesList(c *gin.Context) {
	var articles []Article
	_, err := dbmap.Select(&articles, "select * from articles order by article_id")
	checkErr(err, "Select failed")
	content := gin.H{"records": articles,}
	c.JSON(200, content)
}

func ArticlesDetail(c *gin.Context) {
	article_id := c.Params.ByName("id")
	a_id, _ := strconv.Atoi(article_id)
	article := getArticle(a_id)
	content := gin.H{"title": article.Title, "content": article.Content}
	c.JSON(200, content)
}

func ArticlePost(c *gin.Context) {
	var json Article

	c.Bind(&json)
	article := createArticle(json.Title, json.Content)
	if article.Title == json.Title {
		content := gin.H{
			"result": "Success",
			"title": article.Title,
			"content": article.Content,
		}
		c.JSON(201, content)
	} else {
		c.JSON(500, gin.H{"result": "An error occured"})
	}
}

func createArticle(title, body string) Article {
	article := Article{
		Created: time.Now().UnixNano(),
		Title: title,
		Content: body,
	}

	err := dbmap.Insert(&article)
	checkErr(err, "Insert failed")
	return article
}

func getArticle(article_id int) Article {
	article := Article{}
	err := dbmap.SelectOne(&article, "select * from articles where article_id=?", article_id)
	checkErr(err, "selectOne failed")
	return article
}

func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept=Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-with")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
		} else {
			c.Next()
		}
	}
}

func main() {
	defer dbmap.Db.Close()

	app := gin.Default()
	app.Use(CORSMiddleware())
	app.GET("/", index)
	app.GET("/articles", ArticlesList)
	app.POST("/articles", ArticlePost)
	app.GET("/articles/:id", ArticlesDetail)

	app.Run(":8000")
}<commit_msg>formating<commit_after>package main

import (
	"github.com/gin-gonic/gin"
	"database/sql"
	"github.com/coopernurse/gorp"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"time"
	"strconv"
)

type Article struct {
	Id int64 `db:"article_id"`
	Created int64
	Title string
	Content string
}

var dbmap = initDb()

func initDb() gorp.DbMap {
	db, err := sql.Open("sqlite3", "db.sqlite3")
	checkErr(err, "sql.Open faild")
	dbmap := gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
	dbmap.AddTableWithName(Article{}, "articles").SetKeys(true, "Id")
	err = dbmap.CreateTablesIfNotExists()
	checkErr(err, "Create tables failed")
	return dbmap
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)//.(*errors.Error).ErrorStack())
	}
}

func index (c *gin.Context) {
	content := gin.H{"Hello": "World"}
	c.JSON(200, content)
}

func ArticlesList(c *gin.Context) {
	var articles []Article
	_, err := dbmap.Select(&articles, "select * from articles order by article_id")
	checkErr(err, "Select failed")
	content := gin.H{"records": articles,}
	c.JSON(200, content)
}

func ArticlesDetail(c *gin.Context) {
	article_id := c.Params.ByName("id")
	a_id, _ := strconv.Atoi(article_id)
	article := getArticle(a_id)
	content := gin.H{"title": article.Title, "content": article.Content}
	c.JSON(200, content)
}

func ArticlePost(c *gin.Context) {
	var json Article

	c.Bind(&json)
	article := createArticle(json.Title, json.Content)
	if article.Title == json.Title {
		content := gin.H{
			"result": "Success",
			"title": article.Title,
			"content": article.Content,
		}
		c.JSON(201, content)
	} else {
		c.JSON(500, gin.H{"result": "An error occured"})
	}
}

func createArticle(title, body string) Article {
	article := Article{
		Created: time.Now().UnixNano(),
		Title: title,
		Content: body,
	}

	err := dbmap.Insert(&article)
	checkErr(err, "Insert failed")
	return article
}

func getArticle(article_id int) Article {
	article := Article{}
	err := dbmap.SelectOne(&article, "select * from articles where article_id=?", article_id)
	checkErr(err, "selectOne failed")
	return article
}

func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept=Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-with")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
		} else {
			c.Next()
		}
	}
}

func main() {
	defer dbmap.Db.Close()

	app := gin.Default()
	app.Use(CORSMiddleware())
	app.GET("/", index)
	app.GET("/articles", ArticlesList)
	app.POST("/articles", ArticlePost)
	app.GET("/articles/:id", ArticlesDetail)

	app.Run(":8000")
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"

	"./api"
	"./ui"

	"github.com/222Labs/common/go/logging"
	"github.com/codegangsta/cli"
	"github.com/gorilla/mux"
)

var (
	log = logging.GetLogger("kala")
	// TODO - fix
	staticDir = "/home/ajvb/Code/kala/ui/static"
)

func initServer() *mux.Router {
	r := mux.NewRouter()
	// API
	api.SetupApiRoutes(r)
	// UI
	r.HandleFunc("/", ui.HandleDashboard).Methods("GET")
	fileServer := http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))
	r.PathPrefix("/").Handler(fileServer)

	return r
}

func main() {
	app := cli.NewApp()
	app.Name = "Kala"
	app.Usage = "Modern job scheduler"
	app.Version = "0.1"
	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "run kala",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port, p",
					Value: 8000,
					Usage: "port for Kala to run on",
				},
				cli.BoolFlag{
					Name:  "debug, d",
					Usage: "debug logging",
				},
				cli.BoolFlag{
					Name:  "dont-persist",
					Usage: "turn off job persistance",
				},
			},
			Action: func(c *cli.Context) {
				var parsedPort string
				port := c.Int("port")
				if port != 0 {
					parsedPort = fmt.Sprintf(":%d", port)
				} else {
					parsedPort = ":8000"
				}

				// TODO set log level
				if c.Bool("debug") {
				}

				// TODO
				if c.Bool("dont-persist") {
				}

				r := initServer()

				log.Info("Starting server...")
				log.Fatal(http.ListenAndServe(parsedPort, r))
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>Removed dont persist flag from main.go<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"

	"./api"
	"./ui"

	"github.com/222Labs/common/go/logging"
	"github.com/codegangsta/cli"
	"github.com/gorilla/mux"
)

var (
	log = logging.GetLogger("kala")
	// TODO - fix
	staticDir = "/home/ajvb/Code/kala/ui/static"
)

func initServer() *mux.Router {
	r := mux.NewRouter()
	// API
	api.SetupApiRoutes(r)
	// UI
	r.HandleFunc("/", ui.HandleDashboard).Methods("GET")
	fileServer := http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))
	r.PathPrefix("/").Handler(fileServer)

	return r
}

func main() {
	app := cli.NewApp()
	app.Name = "Kala"
	app.Usage = "Modern job scheduler"
	app.Version = "0.1"
	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "run kala",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port, p",
					Value: 8000,
					Usage: "port for Kala to run on",
				},
				cli.BoolFlag{
					Name:  "debug, d",
					Usage: "debug logging",
				},
			},
			Action: func(c *cli.Context) {
				var parsedPort string
				port := c.Int("port")
				if port != 0 {
					parsedPort = fmt.Sprintf(":%d", port)
				} else {
					parsedPort = ":8000"
				}

				// TODO set log level
				if c.Bool("debug") {
				}

				r := initServer()

				log.Info("Starting server...")
				log.Fatal(http.ListenAndServe(parsedPort, r))
			},
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"

	"github.com/motain/s3downloader/cfg"
	"github.com/motain/s3downloader/s3loader"
)

var inArgs = cfg.InArgs{Regexp: ".*", LocalDir: "downloads-s3"}

func main() {
	if err := start(); err != nil {
		panic(err)
	}
}

func parseFlags() {
	flag.StringVar(&inArgs.Bucket, "bucket", inArgs.Bucket, "Download bucket")
	flag.StringVar(&inArgs.Prefix, "prefix", inArgs.Prefix, "Bucket download path")
	flag.StringVar(&inArgs.LocalDir, "dir", inArgs.LocalDir, "Target local dir")
	flag.StringVar(&inArgs.Regexp, "regexp", inArgs.Regexp, "Item name regular expression")
	flag.BoolVar(&inArgs.DryRun, "dry-run", inArgs.DryRun, "Find only flag - no download")
	flag.BoolVar(&inArgs.PrependName, "p", inArgs.PrependName, "Prepend downloaded file name with lastmodified timestamp")
	flag.Parse()
}

func start() error {
	parseFlags()

	if err := inArgs.Validate(); err != nil {
		return err
	}

	conf, err := cfg.GetCfg()
	if err != nil {
		return err
	}

	d, err := s3loader.NewDownloader(&inArgs, conf)
	if err != nil {
		return err
	}

	if err := d.Run(); err != nil {
		return err
	}

	return nil
}
<commit_msg>Added main documentation<commit_after>// s3downloader cmd is an aws go sdk wrapper
// which utilizes go concurrency patterns for efficient
// and fast AWS s3 data search and download
package main

import (
	"flag"

	"github.com/motain/s3downloader/cfg"
	"github.com/motain/s3downloader/s3loader"
)

var inArgs = cfg.InArgs{Regexp: ".*", LocalDir: "downloads-s3"}

func main() {
	if err := start(); err != nil {
		panic(err)
	}
}

func parseFlags() {
	flag.StringVar(&inArgs.Bucket, "bucket", inArgs.Bucket, "Download bucket")
	flag.StringVar(&inArgs.Prefix, "prefix", inArgs.Prefix, "Bucket download path")
	flag.StringVar(&inArgs.LocalDir, "dir", inArgs.LocalDir, "Target local dir")
	flag.StringVar(&inArgs.Regexp, "regexp", inArgs.Regexp, "Item name regular expression")
	flag.BoolVar(&inArgs.DryRun, "dry-run", inArgs.DryRun, "Find only flag - no download")
	flag.BoolVar(&inArgs.PrependName, "p", inArgs.PrependName, "Prepend downloaded file name with lastmodified timestamp")
	flag.Parse()
}

func start() error {
	parseFlags()

	if err := inArgs.Validate(); err != nil {
		return err
	}

	conf, err := cfg.GetCfg()
	if err != nil {
		return err
	}

	d, err := s3loader.NewDownloader(&inArgs, conf)
	if err != nil {
		return err
	}

	if err := d.Run(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>