<commit_before>package php

import (
	"fmt"
	"sort"
	"strconv"
)

type Item struct {
	typ ItemType
	pos Location
	val string
}

type Location struct {
	Pos  int
	Line int
	File string
}

type ItemType int

const (
	itemHTML ItemType = iota
	itemPHP
	itemPHPBegin
	itemPHPEnd
	itemPHPToken
	itemEOF
	itemError
	itemSpace
	itemFunction
	itemFunctionName
	itemTypeHint
	itemIdentifier
	itemBlockBegin
	itemBlockEnd
	itemGlobal

	itemComment

	itemIgnoreErrorOperator

	itemReturn
	itemFunctionCallBegin
	itemFunctionCallEnd
	itemArgumentType
	itemArgumentName
	itemArgumentSeparator
	itemStatementEnd
	itemEcho

	itemIf
	itemElse
	itemElseIf
	itemFor
	itemForeach
	itemAsOperator
	itemWhile
	itemContinue
	itemBreak
	itemDo
	itemOpenParen
	itemCloseParen
	itemSwitch
	itemCase
	itemDefault

	itemTry
	itemCatch
	itemFinally
	itemThrow

	itemClass
	itemPrivate
	itemPublic
	itemProtected
	itemInterface
	itemImplements
	itemExtends
	itemNewOperator

	itemStringLiteral
	itemNumberLiteral
	itemBooleanLiteral

	itemNonVariableIdentifier

	itemAssignmentOperator
	itemNegationOperator
	itemAdditionOperator
	itemSubtractionOperator
	itemMultOperator
	itemConcatenationOperator
	itemUnaryOperator
	itemComparisonOperator
	itemInstanceofOperator

	itemAndOperator
	itemOrOperator
	itemWrittenAndOperator
	itemWrittenXorOperator
	itemWrittenOrOperator

	itemObjectOperator
	itemScopeResolutionOperator

	itemCastOperator

	itemArray
	itemArrayKeyOperator
	itemArrayLookupOperatorLeft
	itemArrayLookupOperatorRight
	itemBitwiseShiftOperator
	itemEqualityOperator
	itemAmpersandOperator
	itemBitwiseXorOperator
	itemBitwiseOrOperator
	itemTernaryOperator1
	itemTernaryOperator2

	itemInclude
	itemExit
)

// itemTypeMap maps itemType to strings that may be used for debugging and error messages
var itemTypeMap = map[ItemType]string{
	itemHTML:         "HTML",
	itemPHP:          "PHP",
	itemPHPBegin:     "PHP Begin",
	itemPHPEnd:       "PHP End",
	itemPHPToken:     "PHP Token",
	itemEOF:          "EOF",
	itemError:        "Error",
	itemSpace:        "Space",
	itemFunction:     "Function",
	itemFunctionName: "Function Name",
	itemTypeHint:     "Function Type Hint",
	itemIdentifier:   "Identifier",
	itemBlockBegin:   "Block Begin",
	itemBlockEnd:     "Block End",

	itemGlobal:            "global",
	itemReturn:            "Return",
	itemFunctionCallBegin: "Function Call Begin",
	itemFunctionCallEnd:   "Function Call End",
	itemArgumentType:      "Function Argument Type",
	itemArgumentName:      "Function Argument Name",
	itemArgumentSeparator: "Function Argument Separator",
	itemStatementEnd:      "Statement End",
	itemEcho:              "Echo",

	itemIgnoreErrorOperator: "@",

	itemIf:         "If",
	itemElse:       "Else",
	itemElseIf:     "ElseIf",
	itemFor:        "for",
	itemForeach:    "foreach",
	itemSwitch:     "switch",
	itemCase:       "case",
	itemDefault:    "default",
	itemAsOperator: "as",
	itemWhile:      "while",
	itemDo:         "do",
	itemOpenParen:  "open-paren",
	itemCloseParen: "close-paren",
	itemContinue:   "continue",
	itemBreak:      "break",

	itemComment: "/* */",

	itemTry:     "try",
	itemCatch:   "catch",
	itemFinally: "finally",
	itemThrow:   "throw",

	itemClass:       "Class",
	itemPrivate:     "Private",
	itemProtected:   "Protected",
	itemPublic:      "Public",
	itemInterface:   "Interface",
	itemImplements:  "implements",
	itemExtends:     "extends",
	itemNewOperator: "new",

	itemStringLiteral:  "sting-literal",
	itemNumberLiteral:  "number-literal",
	itemBooleanLiteral: "bool-literal",

	itemNonVariableIdentifier: "non-variable-identifier",

	itemAssignmentOperator:      "=",
	itemNegationOperator:        "!",
	itemAdditionOperator:        "+",
	itemSubtractionOperator:     "-",
	itemMultOperator:            "*/%",
	itemConcatenationOperator:   ".",
	itemUnaryOperator:           "++|--",
	itemComparisonOperator:      "==<>",
	itemObjectOperator:          "->",
	itemScopeResolutionOperator: "::",
	itemInstanceofOperator:      "instanceof",

	itemAndOperator:        "&&",
	itemOrOperator:         "||",
	itemWrittenAndOperator: "logical-and",
	itemWrittenXorOperator: "logical-xor",
	itemWrittenOrOperator:  "logical-or",
	itemCastOperator:       "(type)",

	itemArray:                    "array",
	itemArrayKeyOperator:         "=>",
	itemArrayLookupOperatorLeft:  "[",
	itemArrayLookupOperatorRight: "]",
	itemBitwiseShiftOperator:     "<<>>",
	itemEqualityOperator:         "!===",
	itemAmpersandOperator:        "&",
	itemBitwiseXorOperator:       "^",
	itemBitwiseOrOperator:        "|",
	itemTernaryOperator1:         "?",
	itemTernaryOperator2:         ":",

	itemInclude: "include",
	itemExit:    "exit",
}

var tokenList []string

func init() {
	tokenList = make([]string, len(tokenMap))
	i := 0
	for token := range tokenMap {
		tokenList[i] = token
		i += 1
	}
	sort.Sort(sort.Reverse(sort.StringSlice(tokenList)))
}

// tokenMap maps source code string tokens to item types when strings can
// be represented directly. Not all item types will be represented here.
var tokenMap = map[string]ItemType{
	"class":          itemClass,
	"abstract class": itemClass,
	"interface":      itemInterface,
	"implements":     itemImplements,
	"extends":        itemExtends,
	"new":            itemNewOperator,
	"if":             itemIf,
	"else":           itemElse,
	"while":          itemWhile,
	"do":             itemDo,
	"for":            itemFor,
	"foreach":        itemForeach,
	"switch":         itemSwitch,
	"case":           itemCase,
	"break":          itemBreak,
	"continue":       itemContinue,
	"default":        itemDefault,
	"function":       itemFunction,
	"return":         itemReturn,
	"{":              itemBlockBegin,
	"}":              itemBlockEnd,
	";":              itemStatementEnd,
	"(":              itemOpenParen,
	")":              itemCloseParen,
	",":              itemArgumentSeparator,
	"echo":           itemEcho,
	"throw":          itemThrow,
	"try":            itemTry,
	"catch":          itemCatch,
	"finally":        itemFinally,
	"private":        itemPrivate,
	"public":         itemPublic,
	"protected":      itemProtected,
	"true":           itemBooleanLiteral,
	"false":          itemBooleanLiteral,
	"instanceof":     itemInstanceofOperator,
	"global":         itemGlobal,
	"array":          itemArray,
	"exit":           itemExit,
	"include":        itemInclude,
	"include_once":   itemInclude,
	"require":        itemInclude,
	"require_once":   itemInclude,
	"@":              itemIgnoreErrorOperator,

	"(int)":     itemCastOperator,
	"(integer)": itemCastOperator,
	"(bool)":    itemCastOperator,
	"(boolean)": itemCastOperator,
	"(float)":   itemCastOperator,
	"(double)":  itemCastOperator,
	"(real)":    itemCastOperator,
	"(string)":  itemCastOperator,
	"(array)":   itemCastOperator,
	"(object)":  itemCastOperator,
	"(unset)":   itemCastOperator,

	"/*": itemComment,
	"*/": itemComment,
	"//": itemComment,

	"->": itemObjectOperator,
	"::": itemScopeResolutionOperator,

	"+=":  itemAssignmentOperator,
	"-=":  itemAssignmentOperator,
	"*=":  itemAssignmentOperator,
	"/=":  itemAssignmentOperator,
	".=":  itemAssignmentOperator,
	"%=":  itemAssignmentOperator,
	"&=":  itemAssignmentOperator,
	"|=":  itemAssignmentOperator,
	"^=":  itemAssignmentOperator,
	"<<=": itemAssignmentOperator,
	">>=": itemAssignmentOperator,
	"=>":  itemArrayKeyOperator,

	"===": itemComparisonOperator,
	"==":  itemComparisonOperator,
	"=":   itemAssignmentOperator,
	"!==": itemComparisonOperator,
	"!=":  itemComparisonOperator,
	"<>":  itemComparisonOperator,
	"!":   itemNegationOperator,
	"++":  itemUnaryOperator,
	"--":  itemUnaryOperator,
	"+":   itemAdditionOperator,
	"-":   itemSubtractionOperator,
	"*":   itemMultOperator,
	"/":   itemMultOperator,
	">=":  itemComparisonOperator,
	">":   itemComparisonOperator,
	"<=":  itemComparisonOperator,
	"<":   itemComparisonOperator,
	"%":   itemMultOperator,
	".":   itemConcatenationOperator,

	"&&":  itemAndOperator,
	"||":  itemOrOperator,
	"&":   itemAmpersandOperator,
	"^":   itemBitwiseXorOperator,
	"|":   itemBitwiseOrOperator,
	"<<":  itemBitwiseShiftOperator,
	">>":  itemBitwiseShiftOperator,
	"?":   itemTernaryOperator1,
	":":   itemTernaryOperator2,
	"and": itemWrittenAndOperator,
	"xor": itemWrittenXorOperator,
	"or":  itemWrittenOrOperator,
	"as":  itemAsOperator,

	"[": itemArrayLookupOperatorLeft,
	"]": itemArrayLookupOperatorRight,
}

func (i ItemType) String() string {
	itemTypeName, ok := itemTypeMap[i]
	if !ok {
		return strconv.Itoa(int(i))
	}
	return itemTypeName
}

func (i Item) String() string {
	switch i.typ {
	case itemEOF:
		return "EOF"
	case itemError:
		return i.val
	}
	if len(i.val) > 10 {
		return fmt.Sprintf("%v:%.10q...", i.typ, i.val)
	}
	return fmt.Sprintf("%v:%q", i.typ, i.val)
}
<commit_msg>Supporting static functions<commit_after>package php

import (
	"fmt"
	"sort"
	"strconv"
)

type Item struct {
	typ ItemType
	pos Location
	val string
}

type Location struct {
	Pos  int
	Line int
	File string
}

type ItemType int

const (
	itemHTML ItemType = iota
	itemPHP
	itemPHPBegin
	itemPHPEnd
	itemPHPToken
	itemEOF
	itemError
	itemSpace
	itemFunction
	itemFunctionName
	itemTypeHint
	itemIdentifier
	itemBlockBegin
	itemBlockEnd
	itemGlobal

	itemComment

	itemIgnoreErrorOperator

	itemReturn
	itemFunctionCallBegin
	itemFunctionCallEnd
	itemArgumentType
	itemArgumentName
	itemArgumentSeparator
	itemStatementEnd
	itemEcho

	itemIf
	itemElse
	itemElseIf
	itemFor
	itemForeach
	itemAsOperator
	itemWhile
	itemContinue
	itemBreak
	itemDo
	itemOpenParen
	itemCloseParen
	itemSwitch
	itemCase
	itemDefault

	itemTry
	itemCatch
	itemFinally
	itemThrow

	itemClass
	itemPrivate
	itemPublic
	itemProtected
	itemInterface
	itemImplements
	itemExtends
	itemNewOperator

	itemStringLiteral
	itemNumberLiteral
	itemBooleanLiteral

	itemNonVariableIdentifier

	itemAssignmentOperator
	itemNegationOperator
	itemAdditionOperator
	itemSubtractionOperator
	itemMultOperator
	itemConcatenationOperator
	itemUnaryOperator
	itemComparisonOperator
	itemInstanceofOperator

	itemAndOperator
	itemOrOperator
	itemWrittenAndOperator
	itemWrittenXorOperator
	itemWrittenOrOperator

	itemObjectOperator
	itemScopeResolutionOperator

	itemCastOperator

	itemArray
	itemArrayKeyOperator
	itemArrayLookupOperatorLeft
	itemArrayLookupOperatorRight
	itemBitwiseShiftOperator
	itemEqualityOperator
	itemAmpersandOperator
	itemBitwiseXorOperator
	itemBitwiseOrOperator
	itemTernaryOperator1
	itemTernaryOperator2

	itemInclude
	itemExit
)

// itemTypeMap maps itemType to strings that may be used for debugging and error messages
var itemTypeMap = map[ItemType]string{
	itemHTML:         "HTML",
	itemPHP:          "PHP",
	itemPHPBegin:     "PHP Begin",
	itemPHPEnd:       "PHP End",
	itemPHPToken:     "PHP Token",
	itemEOF:          "EOF",
	itemError:        "Error",
	itemSpace:        "Space",
	itemFunction:     "Function",
	itemFunctionName: "Function Name",
	itemTypeHint:     "Function Type Hint",
	itemIdentifier:   "Identifier",
	itemBlockBegin:   "Block Begin",
	itemBlockEnd:     "Block End",

	itemGlobal:            "global",
	itemReturn:            "Return",
	itemFunctionCallBegin: "Function Call Begin",
	itemFunctionCallEnd:   "Function Call End",
	itemArgumentType:      "Function Argument Type",
	itemArgumentName:      "Function Argument Name",
	itemArgumentSeparator: "Function Argument Separator",
	itemStatementEnd:      "Statement End",
	itemEcho:              "Echo",

	itemIgnoreErrorOperator: "@",

	itemIf:         "If",
	itemElse:       "Else",
	itemElseIf:     "ElseIf",
	itemFor:        "for",
	itemForeach:    "foreach",
	itemSwitch:     "switch",
	itemCase:       "case",
	itemDefault:    "default",
	itemAsOperator: "as",
	itemWhile:      "while",
	itemDo:         "do",
	itemOpenParen:  "open-paren",
	itemCloseParen: "close-paren",
	itemContinue:   "continue",
	itemBreak:      "break",

	itemComment: "/* */",

	itemTry:     "try",
	itemCatch:   "catch",
	itemFinally: "finally",
	itemThrow:   "throw",

	itemClass:       "Class",
	itemPrivate:     "Private",
	itemProtected:   "Protected",
	itemPublic:      "Public",
	itemInterface:   "Interface",
	itemImplements:  "implements",
	itemExtends:     "extends",
	itemNewOperator: "new",

	itemStringLiteral:  "sting-literal",
	itemNumberLiteral:  "number-literal",
	itemBooleanLiteral: "bool-literal",

	itemNonVariableIdentifier: "non-variable-identifier",

	itemAssignmentOperator:      "=",
	itemNegationOperator:        "!",
	itemAdditionOperator:        "+",
	itemSubtractionOperator:     "-",
	itemMultOperator:            "*/%",
	itemConcatenationOperator:   ".",
	itemUnaryOperator:           "++|--",
	itemComparisonOperator:      "==<>",
	itemObjectOperator:          "->",
	itemScopeResolutionOperator: "::",
	itemInstanceofOperator:      "instanceof",

	itemAndOperator:        "&&",
	itemOrOperator:         "||",
	itemWrittenAndOperator: "logical-and",
	itemWrittenXorOperator: "logical-xor",
	itemWrittenOrOperator:  "logical-or",
	itemCastOperator:       "(type)",

	itemArray:                    "array",
	itemArrayKeyOperator:         "=>",
	itemArrayLookupOperatorLeft:  "[",
	itemArrayLookupOperatorRight: "]",
	itemBitwiseShiftOperator:     "<<>>",
	itemEqualityOperator:         "!===",
	itemAmpersandOperator:        "&",
	itemBitwiseXorOperator:       "^",
	itemBitwiseOrOperator:        "|",
	itemTernaryOperator1:         "?",
	itemTernaryOperator2:         ":",

	itemInclude: "include",
	itemExit:    "exit",
}

var tokenList []string

func init() {
	tokenList = make([]string, len(tokenMap))
	i := 0
	for token := range tokenMap {
		tokenList[i] = token
		i += 1
	}
	sort.Sort(sort.Reverse(sort.StringSlice(tokenList)))
}

// tokenMap maps source code string tokens to item types when strings can
// be represented directly. Not all item types will be represented here.
var tokenMap = map[string]ItemType{
	"class":           itemClass,
	"abstract class":  itemClass,
	"interface":       itemInterface,
	"implements":      itemImplements,
	"extends":         itemExtends,
	"new":             itemNewOperator,
	"if":              itemIf,
	"else":            itemElse,
	"while":           itemWhile,
	"do":              itemDo,
	"for":             itemFor,
	"foreach":         itemForeach,
	"switch":          itemSwitch,
	"case":            itemCase,
	"break":           itemBreak,
	"continue":        itemContinue,
	"default":         itemDefault,
	"function":        itemFunction,
	"static function": itemFunction,
	"return":          itemReturn,
	"{":               itemBlockBegin,
	"}":               itemBlockEnd,
	";":               itemStatementEnd,
	"(":               itemOpenParen,
	")":               itemCloseParen,
	",":               itemArgumentSeparator,
	"echo":            itemEcho,
	"throw":           itemThrow,
	"try":             itemTry,
	"catch":           itemCatch,
	"finally":         itemFinally,
	"private":         itemPrivate,
	"public":          itemPublic,
	"protected":       itemProtected,
	"true":            itemBooleanLiteral,
	"false":           itemBooleanLiteral,
	"instanceof":      itemInstanceofOperator,
	"global":          itemGlobal,
	"array":           itemArray,
	"exit":            itemExit,
	"include":         itemInclude,
	"include_once":    itemInclude,
	"require":         itemInclude,
	"require_once":    itemInclude,
	"@":               itemIgnoreErrorOperator,

	"(int)":     itemCastOperator,
	"(integer)": itemCastOperator,
	"(bool)":    itemCastOperator,
	"(boolean)": itemCastOperator,
	"(float)":   itemCastOperator,
	"(double)":  itemCastOperator,
	"(real)":    itemCastOperator,
	"(string)":  itemCastOperator,
	"(array)":   itemCastOperator,
	"(object)":  itemCastOperator,
	"(unset)":   itemCastOperator,

	"/*": itemComment,
	"*/": itemComment,
	"//": itemComment,

	"->": itemObjectOperator,
	"::": itemScopeResolutionOperator,

	"+=":  itemAssignmentOperator,
	"-=":  itemAssignmentOperator,
	"*=":  itemAssignmentOperator,
	"/=":  itemAssignmentOperator,
	".=":  itemAssignmentOperator,
	"%=":  itemAssignmentOperator,
	"&=":  itemAssignmentOperator,
	"|=":  itemAssignmentOperator,
	"^=":  itemAssignmentOperator,
	"<<=": itemAssignmentOperator,
	">>=": itemAssignmentOperator,
	"=>":  itemArrayKeyOperator,

	"===": itemComparisonOperator,
	"==":  itemComparisonOperator,
	"=":   itemAssignmentOperator,
	"!==": itemComparisonOperator,
	"!=":  itemComparisonOperator,
	"<>":  itemComparisonOperator,
	"!":   itemNegationOperator,
	"++":  itemUnaryOperator,
	"--":  itemUnaryOperator,
	"+":   itemAdditionOperator,
	"-":   itemSubtractionOperator,
	"*":   itemMultOperator,
	"/":   itemMultOperator,
	">=":  itemComparisonOperator,
	">":   itemComparisonOperator,
	"<=":  itemComparisonOperator,
	"<":   itemComparisonOperator,
	"%":   itemMultOperator,
	".":   itemConcatenationOperator,

	"&&":  itemAndOperator,
	"||":  itemOrOperator,
	"&":   itemAmpersandOperator,
	"^":   itemBitwiseXorOperator,
	"|":   itemBitwiseOrOperator,
	"<<":  itemBitwiseShiftOperator,
	">>":  itemBitwiseShiftOperator,
	"?":   itemTernaryOperator1,
	":":   itemTernaryOperator2,
	"and": itemWrittenAndOperator,
	"xor": itemWrittenXorOperator,
	"or":  itemWrittenOrOperator,
	"as":  itemAsOperator,

	"[": itemArrayLookupOperatorLeft,
	"]": itemArrayLookupOperatorRight,
}

func (i ItemType) String() string {
	itemTypeName, ok := itemTypeMap[i]
	if !ok {
		return strconv.Itoa(int(i))
	}
	return itemTypeName
}

func (i Item) String() string {
	switch i.typ {
	case itemEOF:
		return "EOF"
	case itemError:
		return i.val
	}
	if len(i.val) > 10 {
		return fmt.Sprintf("%v:%.10q...", i.typ, i.val)
	}
	return fmt.Sprintf("%v:%q", i.typ, i.val)
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/gojp/kana"
	"github.com/gojp/nihongo/app/models"
	"github.com/gojp/nihongo/app/routes"
	"github.com/jgraham909/revmgo"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"regexp"
	"strings"
)

type App struct {
	*revel.Controller
	revmgo.MongoController
}

type Gloss struct {
	English string
	Tags    []string
	Related []string
	Common  bool
}

type Highlight struct {
	Furigana string
	Japanese string
	Romaji   string
	English  []string
}

type Word struct {
	Romaji    string
	Common    bool
	Dialects  []string
	Fields    []string
	Glosses   []Gloss
	English   []string
	Furigana  string
	Japanese  string
	MainEntry string
	Tags      []string
	Pos       []string
}

// wrap a string in strong tags
func makeStrong(query string) string {
	return "" + query + ""
}

// convert the query to hiragana and katakana. if it's already in
// hiragana or katakana, it will just be the same.
func convertQueryToKana(query string) (hiragana, katakana string) {
	kana := kana.NewKana()
	h := kana.RomajiToHiragana(query)
	k := kana.RomajiToKatakana(query)
	return h, k
}

// Wrap the query in  tags so that we can highlight it in the results
func (w *Word) highlightQuery(query string) {
	// make regular expression that matches the original query
	re := regexp.MustCompile(`\b` + query + `\b`)
	// convert original query to kana
	h, k := convertQueryToKana(query)
	// wrap the query in strong tags
	queryHighlighted := makeStrong(query)
	hiraganaHighlighted := makeStrong(h)
	katakanaHighlighted := makeStrong(k)

	// if the original input is Japanese, then the original input converted
	// to hiragana and katakana will be equal, so just choose one
	// to highlight so that we only end up with one pair of strong tags
	if hiraganaHighlighted == katakanaHighlighted {
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
	} else {
		// The original input is romaji, so we convert it to hiragana and katakana
		// and highlight both.
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
		w.Japanese = strings.Replace(w.Japanese, k, katakanaHighlighted, -1)
	}

	// highlight the furigana too, same as above
	w.Furigana = strings.Replace(w.Furigana, h, hiraganaHighlighted, -1)
	w.Furigana = strings.Replace(w.Furigana, k, katakanaHighlighted, -1)
	// highlight the query inside the list of English definitions
	for i, e := range w.English {
		e = re.ReplaceAllString(e, queryHighlighted)
		w.English[i] = e
	}
}

func search(query string) []Word {
	fmt.Println("Searching for... ", query)
	api.Domain = "localhost"

	kana := kana.NewKana()

	isLatin := kana.IsLatin(query)
	isKana := kana.IsKana(query)
	isKanji := kana.IsKanji(query)
	fmt.Println(isLatin, isKana, isKanji)

	// convert to hiragana and katakana
	romaji := kana.KanaToRomaji(query)

	// handle different types of input differently:
	matches := []string{}
	if isKana {
		// add boost for exact-matching kana
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"furigana" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 5.0
				}
			}
		}`, query))

		// also look for romaji version in case
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"romaji" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 2.0
				}
			}
		}`, romaji))
	}
	if !isLatin {
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"japanese" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 10.0
				}
			}
		}`, query))
	} else {
		// add romaji search term
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"romaji" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 3.0
				}
			}
		}`, query))

		// add english search term
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"english" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 5.0
				}
			}
		}`, query))
	}

	searchJson := fmt.Sprintf(`
		{"query":
			{"bool":
				{
				"should":
					[` + strings.Join(matches, ",") + `],
				"minimum_should_match" : 0,
				"boost": 2.0
				}
			}
		}`)

	out, err := core.SearchRequest(true, "edict", "entry", searchJson, "", 0)
	if err != nil {
		log.Println(err)
	}

	hits := [][]byte{}
	for _, hit := range out.Hits.Hits {
		hits = append(hits, hit.Source)
	}

	wordList := []Word{}
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			log.Println(err)
		}
		w.MainEntry = w.Japanese
		w.highlightQuery(query)
		wordList = append(wordList, w)
	}
	return wordList
}

func (a App) Search(query string) revel.Result {
	if len(query) == 0 {
		return a.Redirect(routes.App.Index())
	}
	wordList := search(query)
	return a.Render(wordList)
}

func (c App) Details(query string) revel.Result {
	if len(query) == 0 {
		return c.Redirect(routes.App.Index())
	}
	if strings.Contains(query, " ") {
		return c.Redirect(routes.App.Details(strings.Replace(query, " ", "-", -1)))
	}
	// Copy the query so that we maintain the dashes
	// when inserting into MongoDB
	mongoTerm := query
	query = strings.Replace(query, "-", " ", -1)
	wordList := search(query)
	pageTitle := query + " in Japanese"

	// log this call in mongo
	collection := c.MongoSession.DB("greenbook").C("hits")
	_, err := collection.Upsert(bson.M{"term": mongoTerm}, bson.M{"$inc": bson.M{"count": 1}})
	if err != nil {
		log.Println("DEBUG: mongo failed to upsert count: " + err.Error())
		// mongo failed to log, but who cares
	}

	index := mgo.Index{
		Key:        []string{"count"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}
	collection.EnsureIndex(index)

	return c.Render(wordList, query, pageTitle)
}

func (c App) SearchGet() revel.Result {
	if query, ok := c.Params.Values["q"]; ok && len(query) > 0 {
		return c.Redirect(routes.App.Details(query[0]))
	}
	return c.Redirect(routes.App.Index())
}

func (c App) About() revel.Result {
	return c.Render()
}

func (c App) Index() revel.Result {

	// get the popular searches
	collection := c.MongoSession.DB("greenbook").C("hits")
	q := collection.Find(nil).Sort("-count")

	termList := []models.SearchTerm{}
	iter := q.Limit(10).Iter()
	iter.All(&termList)

	return c.Render(termList)
}
<commit_msg>remove Println<commit_after>package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/gojp/kana"
	"github.com/gojp/nihongo/app/models"
	"github.com/gojp/nihongo/app/routes"
	"github.com/jgraham909/revmgo"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"regexp"
	"strings"
)

type App struct {
	*revel.Controller
	revmgo.MongoController
}

type Gloss struct {
	English string
	Tags    []string
	Related []string
	Common  bool
}

type Highlight struct {
	Furigana string
	Japanese string
	Romaji   string
	English  []string
}

type Word struct {
	Romaji    string
	Common    bool
	Dialects  []string
	Fields    []string
	Glosses   []Gloss
	English   []string
	Furigana  string
	Japanese  string
	MainEntry string
	Tags      []string
	Pos       []string
}

// wrap a string in strong tags
func makeStrong(query string) string {
	return "" + query + ""
}

// convert the query to hiragana and katakana. if it's already in
// hiragana or katakana, it will just be the same.
func convertQueryToKana(query string) (hiragana, katakana string) {
	kana := kana.NewKana()
	h := kana.RomajiToHiragana(query)
	k := kana.RomajiToKatakana(query)
	return h, k
}

// Wrap the query in  tags so that we can highlight it in the results
func (w *Word) highlightQuery(query string) {
	// make regular expression that matches the original query
	re := regexp.MustCompile(`\b` + query + `\b`)
	// convert original query to kana
	h, k := convertQueryToKana(query)
	// wrap the query in strong tags
	queryHighlighted := makeStrong(query)
	hiraganaHighlighted := makeStrong(h)
	katakanaHighlighted := makeStrong(k)

	// if the original input is Japanese, then the original input converted
	// to hiragana and katakana will be equal, so just choose one
	// to highlight so that we only end up with one pair of strong tags
	if hiraganaHighlighted == katakanaHighlighted {
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
	} else {
		// The original input is romaji, so we convert it to hiragana and katakana
		// and highlight both.
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
		w.Japanese = strings.Replace(w.Japanese, k, katakanaHighlighted, -1)
	}

	// highlight the furigana too, same as above
	w.Furigana = strings.Replace(w.Furigana, h, hiraganaHighlighted, -1)
	w.Furigana = strings.Replace(w.Furigana, k, katakanaHighlighted, -1)
	// highlight the query inside the list of English definitions
	for i, e := range w.English {
		e = re.ReplaceAllString(e, queryHighlighted)
		w.English[i] = e
	}
}

func search(query string) []Word {
	fmt.Println("Searching for... ", query)
	api.Domain = "localhost"

	kana := kana.NewKana()

	isLatin := kana.IsLatin(query)
	isKana := kana.IsKana(query)
	isKanji := kana.IsKanji(query)

	// convert to hiragana and katakana
	romaji := kana.KanaToRomaji(query)

	// handle different types of input differently:
	matches := []string{}
	if isKana {
		// add boost for exact-matching kana
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"furigana" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 5.0
				}
			}
		}`, query))

		// also look for romaji version in case
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"romaji" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 2.0
				}
			}
		}`, romaji))
	}
	if !isLatin {
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"japanese" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 10.0
				}
			}
		}`, query))
	} else {
		// add romaji search term
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"romaji" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 3.0
				}
			}
		}`, query))

		// add english search term
		matches = append(matches, fmt.Sprintf(`
		{"match" :
			{
				"english" : {
					"query" : "%s",
					"type" : "phrase",
					"boost": 5.0
				}
			}
		}`, query))
	}

	searchJson := fmt.Sprintf(`
		{"query":
			{"bool":
				{
				"should":
					[` + strings.Join(matches, ",") + `],
				"minimum_should_match" : 0,
				"boost": 2.0
				}
			}
		}`)

	out, err := core.SearchRequest(true, "edict", "entry", searchJson, "", 0)
	if err != nil {
		log.Println(err)
	}

	hits := [][]byte{}
	for _, hit := range out.Hits.Hits {
		hits = append(hits, hit.Source)
	}

	wordList := []Word{}
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			log.Println(err)
		}
		w.MainEntry = w.Japanese
		w.highlightQuery(query)
		wordList = append(wordList, w)
	}
	return wordList
}

func (a App) Search(query string) revel.Result {
	if len(query) == 0 {
		return a.Redirect(routes.App.Index())
	}
	wordList := search(query)
	return a.Render(wordList)
}

func (c App) Details(query string) revel.Result {
	if len(query) == 0 {
		return c.Redirect(routes.App.Index())
	}
	if strings.Contains(query, " ") {
		return c.Redirect(routes.App.Details(strings.Replace(query, " ", "-", -1)))
	}
	// Copy the query so that we maintain the dashes
	// when inserting into MongoDB
	mongoTerm := query
	query = strings.Replace(query, "-", " ", -1)
	wordList := search(query)
	pageTitle := query + " in Japanese"

	// log this call in mongo
	collection := c.MongoSession.DB("greenbook").C("hits")
	_, err := collection.Upsert(bson.M{"term": mongoTerm}, bson.M{"$inc": bson.M{"count": 1}})
	if err != nil {
		log.Println("DEBUG: mongo failed to upsert count: " + err.Error())
		// mongo failed to log, but who cares
	}

	index := mgo.Index{
		Key:        []string{"count"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}
	collection.EnsureIndex(index)

	return c.Render(wordList, query, pageTitle)
}

func (c App) SearchGet() revel.Result {
	if query, ok := c.Params.Values["q"]; ok && len(query) > 0 {
		return c.Redirect(routes.App.Details(query[0]))
	}
	return c.Redirect(routes.App.Index())
}

func (c App) About() revel.Result {
	return c.Render()
}

func (c App) Index() revel.Result {

	// get the popular searches
	collection := c.MongoSession.DB("greenbook").C("hits")
	q := collection.Find(nil).Sort("-count")

	termList := []models.SearchTerm{}
	iter := q.Limit(10).Iter()
	iter.All(&termList)

	return c.Render(termList)
}
<|endoftext|>


<commit_before>package controllers

import "github.com/revel/revel"
import  "time"
import (
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	"os"
	"strings"

)

const KKDEV_DEV_MODE = true

type App struct {
	*revel.Controller
}

func (c App) Index() revel.Result {
	return c.Render()
}

type CommentItem struct{
	Id string  `bson:"_id,omitempty"`
	Dt string  `bson:"Dt,omitempty"`
	Email string `bson:"Email,omitempty"`
	Time int64 `bson:"Time,omitempty"`
	Ip string `bson:"Ip,omitempty"`
	CmChunk string `bson:"CmChunk,omitempty"`
	Name string `bson:"Name,omitempty"`

}

func (c App) CommentBasic(chunk string) revel.Result {

	if len(c.Params.Form["Name"])==1&&len(c.Params.Form["Email"])==1&&len(c.Params.Form["Dt"])==1{

		ret:=genComment(c.Params.Form["Dt"][0],c.Params.Form["Email"][0],getIp(c),c.Params.Form["Name"][0])
		ret.CmChunk=chunk
		postComment(ret,KKDEV_DEV_MODE)

	}

	CommentAr:=listCommentByChunk(chunk,KKDEV_DEV_MODE)
	return c.Render(CommentAr)

}

func getIp(c App) string{

	var uip string

	if ip := c.Request.Header.Get("X-Forwarded-For"); ip != "" {
	ips := strings.Split(ip, ",")
	if len(ips) > 0 && ips[0] != "" {
		rip := strings.Split(ips[0], ":")
		uip		= rip[0]
	}
} else {
	ip := strings.Split(c.Request.RemoteAddr, ":")
	if len(ip) > 0 {
		if ip[0] != "[" {
			uip	 = ip[0]
		}
	}
}
return uip
}

func getMongoDbUrl() string {

  mongodburl := ""

  if os.Getenv("KKDEV_MONGO_DB_URL") == "" {

		if os.Getenv("MONGO_PORT_27017_TCP_ADDR")!=""{
			//Running inside docker, we will construct mongodburl ourself
			mongodburl = os.Getenv("MONGO_PORT_27017_TCP_ADDR") +
			":" + os.Getenv("MONGO_PORT_27017_TCP_PORT") +
			"/" + os.Getenv("KKDEV_MONGO_DB_DBNAME") // not required if KKDEV_MONGO_DB_URL defined
		}else{
			//under development
			if os.Getenv("KKDEV_MONGO_DB_DBNAME")!=""{
				mongodburl="127.0.0.1:27017/"+os.Getenv("KKDEV_MONGO_DB_DBNAME")
			}else{
				mongodburl="127.0.0.1:27017/kkdev_kkcommentboxtest"
			}

		}

  } else {
    mongodburl = os.Getenv("KKDEV_MONGO_DB_URL")
  }

	return mongodburl

}

func getCommentbyid(id string, extout bool) CommentItem{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	var CommentItemId CommentItem

	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").FindId(id).Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}

	queryerr:=db.C("Comments").FindId(id).One(CommentItemId)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return CommentItemId

}

func postComment(target CommentItem, extout bool) string{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	/*
	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").Insert(target).Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}
*/
	queryerr:=db.C("Comments").Insert(target)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return target.Id

}

func listCommentByChunk(target string, extout bool)[]CommentItem{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	var CommentItemIds []CommentItem

	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").Find(bson.M{"CmChunk": target}).Sort("-Time").Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}

	queryerr:=db.C("Comments").Find(bson.M{"CmChunk": target}).Sort("-Time").All(&CommentItemIds)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return CommentItemIds

}

func genComment(Dt,Email,Ip,Name string)CommentItem{
	var CommentItema CommentItem
	CommentItema.Dt=Dt
	CommentItema.Email=Email
	CommentItema.Ip=Ip
	CommentItema.Name=Name
	CommentItema.Time=time.Now().UTC().Unix()
	return CommentItema

}
<commit_msg>use string as Id<commit_after>package controllers

import "github.com/revel/revel"
import  "time"
import (
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	"os"
	"strings"
	"github.com/nu7hatch/gouuid"

)

const KKDEV_DEV_MODE = true

type App struct {
	*revel.Controller
}

func (c App) Index() revel.Result {
	return c.Render()
}

type CommentItem struct{
	Id string  `bson:"_id,omitempty"`
	Dt string  `bson:"Dt,omitempty"`
	Email string `bson:"Email,omitempty"`
	Time int64 `bson:"Time,omitempty"`
	Ip string `bson:"Ip,omitempty"`
	CmChunk string `bson:"CmChunk,omitempty"`
	Name string `bson:"Name,omitempty"`

}

func (c App) CommentBasic(chunk string) revel.Result {

	if len(c.Params.Form["Name"])==1&&len(c.Params.Form["Email"])==1&&len(c.Params.Form["Dt"])==1{

		ret:=genComment(c.Params.Form["Dt"][0],c.Params.Form["Email"][0],getIp(c),c.Params.Form["Name"][0])
		ret.CmChunk=chunk
		postComment(ret,KKDEV_DEV_MODE)

	}

	CommentAr:=listCommentByChunk(chunk,KKDEV_DEV_MODE)
	return c.Render(CommentAr)

}

func getIp(c App) string{

	var uip string

	if ip := c.Request.Header.Get("X-Forwarded-For"); ip != "" {
	ips := strings.Split(ip, ",")
	if len(ips) > 0 && ips[0] != "" {
		rip := strings.Split(ips[0], ":")
		uip		= rip[0]
	}
} else {
	ip := strings.Split(c.Request.RemoteAddr, ":")
	if len(ip) > 0 {
		if ip[0] != "[" {
			uip	 = ip[0]
		}
	}
}
return uip
}

func getMongoDbUrl() string {

  mongodburl := ""

  if os.Getenv("KKDEV_MONGO_DB_URL") == "" {

		if os.Getenv("MONGO_PORT_27017_TCP_ADDR")!=""{
			//Running inside docker, we will construct mongodburl ourself
			mongodburl = os.Getenv("MONGO_PORT_27017_TCP_ADDR") +
			":" + os.Getenv("MONGO_PORT_27017_TCP_PORT") +
			"/" + os.Getenv("KKDEV_MONGO_DB_DBNAME") // not required if KKDEV_MONGO_DB_URL defined
		}else{
			//under development
			if os.Getenv("KKDEV_MONGO_DB_DBNAME")!=""{
				mongodburl="127.0.0.1:27017/"+os.Getenv("KKDEV_MONGO_DB_DBNAME")
			}else{
				mongodburl="127.0.0.1:27017/kkdev_kkcommentboxtest"
			}

		}

  } else {
    mongodburl = os.Getenv("KKDEV_MONGO_DB_URL")
  }

	return mongodburl

}

func getCommentbyid(id string, extout bool) CommentItem{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	var CommentItemId CommentItem

	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").FindId(id).Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}

	queryerr:=db.C("Comments").FindId(id).One(CommentItemId)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return CommentItemId

}

func postComment(target CommentItem, extout bool) string{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	/*
	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").Insert(target).Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}
*/
	queryerr:=db.C("Comments").Insert(target)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return target.Id

}

func listCommentByChunk(target string, extout bool)[]CommentItem{

	mongodburl:=getMongoDbUrl()

	session,dialerr:=mgo.Dial(mongodburl)

	if dialerr!=nil{
		log.Println(dialerr)
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	db:=session.DB("")

	var CommentItemIds []CommentItem

	if (extout){
		m := bson.M{}
		prequeryerr:=db.C("Comments").Find(bson.M{"CmChunk": target}).Sort("-Time").Explain(m)

		log.Println("Explain: %#v\n", m)

		if prequeryerr!=nil{
			log.Println(prequeryerr)
		}

	}

	queryerr:=db.C("Comments").Find(bson.M{"CmChunk": target}).Sort("-Time").All(&CommentItemIds)

	if queryerr!=nil{
		log.Println(queryerr)
	}

	return CommentItemIds

}

func genComment(Dt,Email,Ip,Name string)CommentItem{
	var CommentItema CommentItem
	id,_=uuid.NewV4()
	CommentItema.Id=id.String()
	CommentItema.Dt=Dt
	CommentItema.Email=Email
	CommentItema.Ip=Ip
	CommentItema.Name=Name
	CommentItema.Time=time.Now().UTC().Unix()
	return CommentItema

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/ferki/poker-player-go/player"
)

func main() {
	port, err := strconv.Atoi(os.Getenv("PORT"))
	if err != nil {
		port = 4711
	}

	http.HandleFunc("/", handleRequest)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
		log.Fatal(err)
	}
}

func handleRequest(w http.ResponseWriter, request *http.Request) {
	if err := request.ParseForm(); err != nil {
		log.Printf("Error parsing form data: %s", err)
		http.Error(w, "Internal Server Error", 500)
		return
	}

	action := request.FormValue("action")
	log.Printf("Request method=%s url=%s action=%s from client=%s\n", request.Method, request.URL, action, request.RemoteAddr)
	switch action {
	case "check":
		fmt.Fprint(w, "")
		return
	case "bet_request":
		gameState, err := parseGameState(request.FormValue("game_state"))
		if err != nil {
			http.Error(w, "Internal Server Error", 500)
			return
		}
		result := player.BetRequest(gameState)
		fmt.Fprintf(w, "%d", result)
		return
	case "showdown":
		gameState, err := parseGameState(request.FormValue("game_state"))
		if err != nil {
			http.Error(w, "Internal Server Error", 500)
			return
		}
		player.Showdown(gameState)
		fmt.Fprint(w, "")
		return
	case "version":
		fmt.Fprint(w, player.Version())
		return
	default:
		http.Error(w, "Invalid action", 400)
	}
}

func parseGameState(stateStr string) (gameState *player.GameState, err error) {
	if err = json.Unmarshal([]byte(stateStr), gameState); err != nil {
		log.Printf("Error parsing game state: %s", err)
		return nil, err
	}

	return gameState, nil
}
<commit_msg>Remove excessive returns<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/ferki/poker-player-go/player"
)

func main() {
	port, err := strconv.Atoi(os.Getenv("PORT"))
	if err != nil {
		port = 4711
	}

	http.HandleFunc("/", handleRequest)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
		log.Fatal(err)
	}
}

func handleRequest(w http.ResponseWriter, request *http.Request) {
	if err := request.ParseForm(); err != nil {
		log.Printf("Error parsing form data: %s", err)
		http.Error(w, "Internal Server Error", 500)
		return
	}

	action := request.FormValue("action")
	log.Printf("Request method=%s url=%s action=%s from client=%s\n", request.Method, request.URL, action, request.RemoteAddr)
	switch action {
	case "check":
		fmt.Fprint(w, "")
	case "bet_request":
		gameState, err := parseGameState(request.FormValue("game_state"))
		if err != nil {
			http.Error(w, "Internal Server Error", 500)
			return
		}

		result := player.BetRequest(gameState)
		fmt.Fprintf(w, "%d", result)
	case "showdown":
		gameState, err := parseGameState(request.FormValue("game_state"))
		if err != nil {
			http.Error(w, "Internal Server Error", 500)
			return
		}

		player.Showdown(gameState)
		fmt.Fprint(w, "")
	case "version":
		fmt.Fprint(w, player.Version())
	default:
		http.Error(w, "Invalid action", 400)
	}
}

func parseGameState(stateStr string) (gameState *player.GameState, err error) {
	if err = json.Unmarshal([]byte(stateStr), gameState); err != nil {
		log.Printf("Error parsing game state: %s", err)
		return nil, err
	}

	return gameState, nil
}
<|endoftext|>


<commit_before>package pickjson

import (
	"encoding/json"
	"io"
)

func processToken(reader io.Reader, key string, hook func(*json.Decoder) bool) {
	decoder := json.NewDecoder(reader)

	isKey := true

	for {
		token, err := decoder.Token()

		// return when done
		if err == io.EOF {
			break
		}

		// stop on error
		if err != nil {
			break
		}

		// start process the tokens
		switch token.(type) {
		case json.Delim: // { } [ ]
			isKey = true

		case string: // key or value
			if isKey && key == token {
				stop := hook(decoder)

				if stop {
					return
				}
			}
			isKey = !isKey

		default:
			isKey = !isKey
		}
	}
	return
}

func PickString(reader io.Reader, key string, limit int) (res []string) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(string); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

func PickBool(reader io.Reader, key string, limit int) (res []bool) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(bool); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

func PickNumber(reader io.Reader, key string, limit int) (res []float64) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(float64); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

// there is no limit for PickObject yet :(
func PickObject(reader io.Reader, key string, object interface{}) (err error) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		err = decoder.Decode(object)
		return true
	})

	return
}
<commit_msg>add godoc<commit_after>package pickjson

import (
	"encoding/json"
	"io"
)

func processToken(reader io.Reader, key string, hook func(*json.Decoder) bool) {
	decoder := json.NewDecoder(reader)

	isKey := true

	for {
		token, err := decoder.Token()

		// return when done
		if err == io.EOF {
			break
		}

		// stop on error
		if err != nil {
			break
		}

		// start process the tokens
		switch token.(type) {
		case json.Delim: // { } [ ]
			isKey = true

		case string: // key or value
			if isKey && key == token {
				stop := hook(decoder)

				if stop {
					return
				}
			}
			isKey = !isKey

		default:
			isKey = !isKey
		}
	}
	return
}

// PickString pick String by key, return empty array if there is no matching key or error
func PickString(reader io.Reader, key string, limit int) (res []string) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(string); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

// PickBool pick Bool by key, return empty array if there is no matching key or error
func PickBool(reader io.Reader, key string, limit int) (res []bool) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(bool); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

// PickNumber pick Float64 by key, return empty array if there is no matching key or error
func PickNumber(reader io.Reader, key string, limit int) (res []float64) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		// matched token
		token, err := decoder.Token()

		// skip the error token
		if err != nil {
			return false
		}

		if tokenStr, ok := token.(float64); ok {
			res = append(res, tokenStr)

			if limit > 0 && len(res) >= limit {
				return true
			}
		}

		return false
	})
	return
}

// PickObject pick struct by key
// there is no limit for PickObject yet :(
func PickObject(reader io.Reader, key string, object interface{}) (err error) {
	processToken(reader, key, func(decoder *json.Decoder) bool {
		err = decoder.Decode(object)
		return true
	})

	return
}
<|endoftext|>


<commit_before>package libkb

import (
	"fmt"
)

type Pinentry struct {
	path string
}

func NewPinentry() *Pinentry {
	return &Pinentry{path: ""}
}

func (pe *Pinentry) Init() error {
	prog := G.Env.GetPinentry()
	var err error
	if len(prog) > 0 {
		if err := canExec(prog); err == nil {
			pe.path = prog
		} else {
			err = fmt.Errorf("Can't execute given pinentry program '%s': %s",
				prog, err.Error())
		}
	} else if prog, err = FindPinentry(); err == nil {
		pe.path = prog
	}
	return err
}
<commit_msg>get the pinentry stuff to compile<commit_after>package libkb

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

type Pinentry struct {
	initRes *error
	path    string
	term    string
	tty     string
}

func NewPinentry() *Pinentry {
	return &Pinentry{path: ""}
}

func (pe *Pinentry) Init() error {
	if pe.initRes != nil {
		return *pe.initRes
	}
	err := pe.FindProgram()
	if err == nil {
		err = pe.GetTerminalName()
	}
	pe.initRes = &err
	return err
}

func (pe *Pinentry) SetInitError(e error) {
	pe.initRes = &e
}

func (pe *Pinentry) FindProgram() error {
	prog := G.Env.GetPinentry()
	var err error
	if len(prog) > 0 {
		if err := canExec(prog); err == nil {
			pe.path = prog
		} else {
			err = fmt.Errorf("Can't execute given pinentry program '%s': %s",
				prog, err.Error())
		}
	} else if prog, err = FindPinentry(); err == nil {
		pe.path = prog
	}
	return err
}

func (pe *Pinentry) GetTerminalName() error {
	out, err := exec.Command("tty").Output()
	if err != nil {
		return err
	} else if s := string(out); len(s) == 0 {
		return fmt.Errorf("No feasible TTY returned by tty")
	} else {
		pe.tty = s
	}
	return nil
}

type PinentryArg struct {
	Desc   string
	Prompt string
	Error  string
	Cancel string
	OK     string
}

// Eventually we'll learn how to set checkboxes like GPG2 does on
// OSX. But for now, just the string...
type PinentryRes struct {
	Text     string
	Canceled bool
}

func (pe *Pinentry) Get(arg *PinentryArg) (res *PinentryRes, err error) {

	// Do a lazy initialization
	if err = pe.Init(); err != nil {
		return
	}

	inst := pinentryInstance{parent: pe}
	defer inst.Close()

	if err = inst.Init(); err != nil {
		// We probably shouldn't try to use this thing again if we failed
		// to set it up.
		pe.SetInitError(err)
		return
	}
	res, err = inst.Run(arg)
	return
}

func (pi *pinentryInstance) Close() {
	pi.cmd.Wait()
	pi.stdin.Close()
}

type pinentryInstance struct {
	parent *Pinentry
	cmd    *exec.Cmd
	stdout io.ReadCloser
	stdin  io.WriteCloser
	br     *bufio.Reader
}

func (pi *pinentryInstance) Set(cmd, val string, errp *error) {
	if val == "" {
		return
	}
	fmt.Fprintf(pi.stdin, "%s %s\n", cmd, val)
	line, _, err := pi.br.ReadLine()
	if err != nil {
		*errp = err
		return
	}
	if string(line) != "OK" {
		*errp = fmt.Errorf("Response to " + cmd + " was " + string(line))
	}
	return
}

func (pi *pinentryInstance) Init() (err error) {

	parent := pi.parent

	pi.cmd = exec.Command(parent.path)
	pi.stdin, _ = pi.cmd.StdinPipe()
	pi.stdout, _ = pi.cmd.StdoutPipe()

	if err = pi.cmd.Start(); err != nil {
		G.Log.Error("unexpected error running pinentry: %s", err.Error())
		return
	}

	pi.br = bufio.NewReader(pi.stdout)
	lineb, _, err := pi.br.ReadLine()

	if err != nil {
		err = fmt.Errorf("Failed to get getpin greeting: %s", err.Error())
		return
	}

	line := string(lineb)
	if !strings.HasPrefix(line, "OK") {
		err = fmt.Errorf("getpin greeting didn't say 'OK', said: %q", line)
		return
	}

	pi.Set("OPTION", "ttyname="+parent.tty, &err)
	pi.Set("OPTION", "ttytype="+parent.term, &err)

	return
}

func descEncode(s string) string {
	s = strings.Replace(s, "%", "%%", -1)
	s = strings.Replace(s, "\n", "%0A", -1)
	return s
}

func (pi *pinentryInstance) Run(arg *PinentryArg) (res *PinentryRes, err error) {

	pi.Set("SETPROMPT", arg.Prompt, &err)
	pi.Set("SETDESC", descEncode(arg.Desc), &err)
	pi.Set("SETOK", arg.OK, &err)
	pi.Set("SETCANCEL", arg.Cancel, &err)
	pi.Set("SETERROR", arg.Error, &err)

	if err != nil {
		return
	}

	fmt.Fprintf(pi.stdin, "GETPIN\n")
	var lineb []byte
	lineb, _, err = pi.br.ReadLine()
	if err != nil {
		err = fmt.Errorf("Failed to read line after GETPIN: %v", err)
		return
	}
	line := string(lineb)
	if strings.HasPrefix(line, "D ") {
		res = &PinentryRes{Text: line[2:]}
	} else if strings.HasPrefix(line, "ERR 83886179 canceled") {
		res = &PinentryRes{Canceled: true}
	} else {
		err = fmt.Errorf("GETPIN response didn't start with D; got %q", line)
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	// "github.com/davecgh/go-spew/spew"
	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"github.com/elastic/libbeat/publisher"
	"github.com/tatsushid/go-fastping"
	"net"
	"os"
	"time"
)

// Pingbeat struct contains all options and
// hosts to ping
type Pingbeat struct {
	isAlive     bool
	useIPv4     bool
	useIPv6     bool
	period      time.Duration
	timeout     time.Duration
	pingType    string
	ipv4targets map[string][2]string
	ipv6targets map[string][2]string
	config      ConfigSettings
	events      publisher.Client
	done        chan struct{}
}

// Function to convert s to ms
// Not sure why this isn't provided in time...
func milliSeconds(d time.Duration) float64 {
	msec := d / time.Millisecond
	nsec := d % time.Millisecond
	return float64(msec) + float64(nsec)*1e-6
}

// Simple struct that is filled with ICMP response
// and passed through channels
type response struct {
	name string
	addr *net.IPAddr
	rtt  time.Duration
	tag  string
}

func (p *Pingbeat) AddTarget(target string, tag string) {
	addr := net.ParseIP(target)
	if addr != nil {
		if addr.To4() != nil {
			logp.Debug("pingbeat", "IPv4: %s\n", addr.String())
			p.ipv4targets[addr.String()] = [2]string{target, tag}
		} else {
			logp.Debug("pingbeat", "IPv6: %s\n", addr.String())
			p.ipv6targets[addr.String()] = [2]string{target, tag}
		}
	} else {
		logp.Debug("pingbeat", "Getting IP addresses for %s:\n", target)
		addrs, err := net.LookupIP(target)
		if err != nil {
			logp.Warn("Failed to resolve %s to IP address, ignoring this target.\n", target)
		} else {
			for j := 0; j < len(addrs); j++ {
				if addrs[j].To4() != nil {
					logp.Debug("pingbeat", "IPv4: %s\n", addrs[j].String())
					p.ipv4targets[addrs[j].String()] = [2]string{target, tag}
				} else {
					logp.Debug("pingbeat", "IPv6: %s\n", addrs[j].String())
					p.ipv6targets[addrs[j].String()] = [2]string{target, tag}
				}
			}
		}
	}
}

func (p *Pingbeat) Addr2Name(addr *net.IPAddr) (string, string) {
	var name, tag string
	if _, found := p.ipv4targets[addr.String()]; found {
		name = p.ipv4targets[addr.String()][0]
		tag = p.ipv4targets[addr.String()][1]
	} else if _, found := p.ipv6targets[addr.String()]; found {
		name = p.ipv6targets[addr.String()][0]
		tag = p.ipv6targets[addr.String()][1]
	} else {
		logp.Err("Error: %s not found in Pingbeat targets!", addr.String())
		name = "err"
		tag = "err"
	}
	return name, tag
}

func (p *Pingbeat) Config(b *beat.Beat) error {
	// Read in provided config file, bail if problem
	err := cfgfile.Read(&p.config, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	// Use period provided in config or default to 5s
	if p.config.Input.Period != nil {
		p.period = time.Duration(*p.config.Input.Period) * time.Second
	} else {
		p.period = 5 * time.Second
	}
	logp.Debug("pingbeat", "Period %v\n", p.period)

	// Check if we can use privileged (i.e. raw socket) ping,
	// else use a UDP ping
	if *p.config.Input.Privileged {
		p.pingType = "ip"
	} else {
		p.pingType = "udp"
	}
	logp.Debug("pingbeat", "Using %v for pings\n", p.pingType)

	// Check whether IPv4/IPv6 pings are requested in config
	// Default to just IPv4 pings
	if &p.config.Input.UseIPv4 != nil {
		p.useIPv4 = *p.config.Input.UseIPv4
	} else {
		p.useIPv4 = true
	}
	if &p.config.Input.UseIPv6 != nil {
		p.useIPv6 = *p.config.Input.UseIPv6
	} else {
		p.useIPv6 = false
	}
	logp.Debug("pingbeat", "IPv4: %v, IPv6: %v\n", p.useIPv4, p.useIPv6)

	// Fill the IPv4/IPv6 targets maps
	p.ipv4targets = make(map[string][2]string)
	p.ipv6targets = make(map[string][2]string)
	if p.config.Input.Targets != nil {
		for tag, targets := range *p.config.Input.Targets {
			for i := 0; i < len(targets); i++ {
				p.AddTarget(targets[i], tag)
			}
		}
	} else {
		logp.Critical("Error: no targets specified, cannot continue!")
		os.Exit(1)
	}

	return nil
}

func (p *Pingbeat) Setup(b *beat.Beat) error {
	p.events = b.Events
	p.done = make(chan struct{})
	return nil
}

func (p *Pingbeat) Run(b *beat.Beat) error {

	fp := fastping.NewPinger()

	// Set the MaxRTT, i.e., the interval between pinging a target
	fp.MaxRTT = p.period

	errInput, err := fp.Network(p.pingType)
	results := make(map[string]*response)
	if err != nil {
		logp.Critical("Error: %v (input %v)", err, errInput)
		os.Exit(1)
	}

	if p.useIPv4 {
		for addr, details := range p.ipv4targets {
			logp.Debug("pingbeat", "Adding target IP: %s, Name: %s, Tag: %s\n", addr, details[0], details[1])
			fp.AddIP(addr)
			results[addr] = nil
		}
	}
	if p.useIPv6 {
		for addr, details := range p.ipv6targets {
			logp.Debug("pingbeat", "Adding target IP: %s, Name: %s, Tag: %s\n", addr, details[0], details[1])
			fp.AddIP(addr)
			results[addr] = nil
		}
	}

	onRecv, onIdle := make(chan *response), make(chan bool)
	fp.OnRecv = func(addr *net.IPAddr, t time.Duration) {
		// Find the name and tag associated with this address
		name, tag := p.Addr2Name(addr)
		// Send the name, addr, rtt and tag as a struct through the onRecv channel
		onRecv <- &response{name: name, addr: addr, rtt: t, tag: tag}
	}
	fp.OnIdle = func() {
		onIdle <- true
	}

	fp.RunLoop()

	for {
		select {
		case <-p.done:
			logp.Debug("pingbeat", "Got interrupted, shutting down\n")
			fp.Stop()
			return nil
		case res := <-onRecv:
			results[res.addr.String()] = res
		case <-onIdle:
			for target, r := range results {
				if r == nil {
					var name, tag string
					if _, found := p.ipv4targets[target]; found {
						name = p.ipv4targets[target][0]
						tag = p.ipv4targets[target][1]
					} else if _, found := p.ipv6targets[target]; found {
						name = p.ipv6targets[target][0]
						tag = p.ipv6targets[target][1]
					} else {
						logp.Warn("Error: Unexpected target returned: %s", target)
						break
					}
					// Packet loss
					event := common.MapStr{
						"@timestamp":  common.Time(time.Now()),
						"type":        "pingbeat",
						"target_name": name,
						"target_addr": target,
						"tag":         tag,
						"loss":        true,
					}
					p.events.PublishEvent(event)
				} else {
					// Success, ping received
					event := common.MapStr{
						"@timestamp":  common.Time(time.Now()),
						"type":        "pingbeat",
						"target_name": r.name,
						"target_addr": target,
						"tag":         r.tag,
						"rtt":         milliSeconds(r.rtt),
					}
					p.events.PublishEvent(event)
				}
				results[target] = nil
			}
		case <-fp.Done():
			if err = fp.Err(); err != nil {
				logp.Critical("Error: %Ping failed v", err)
			}
			break
		}
	}
	fp.Stop()
	return nil
}

func (p *Pingbeat) Cleanup(b *beat.Beat) error {
	return nil
}

func (p *Pingbeat) Stop() {
	close(p.done)
}
<commit_msg>Minor adjustment to checking/adding new target.<commit_after>package main

import (
	// "github.com/davecgh/go-spew/spew"
	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"github.com/elastic/libbeat/publisher"
	"github.com/tatsushid/go-fastping"
	"net"
	"os"
	"time"
)

// Pingbeat struct contains all options and
// hosts to ping
type Pingbeat struct {
	isAlive     bool
	useIPv4     bool
	useIPv6     bool
	period      time.Duration
	timeout     time.Duration
	pingType    string
	ipv4targets map[string][2]string
	ipv6targets map[string][2]string
	config      ConfigSettings
	events      publisher.Client
	done        chan struct{}
}

// Function to convert s to ms
// Not sure why this isn't provided in time...
func milliSeconds(d time.Duration) float64 {
	msec := d / time.Millisecond
	nsec := d % time.Millisecond
	return float64(msec) + float64(nsec)*1e-6
}

// Simple struct that is filled with ICMP response
// and passed through channels
type response struct {
	name string
	addr *net.IPAddr
	rtt  time.Duration
	tag  string
}

func (p *Pingbeat) AddTarget(target string, tag string) {
	if addr := net.ParseIP(target); addr.String() != "" {
		if addr.To4() != nil {
			logp.Debug("pingbeat", "IPv4: %s\n", addr.String())
			p.ipv4targets[addr.String()] = [2]string{target, tag}
		} else {
			logp.Debug("pingbeat", "IPv6: %s\n", addr.String())
			p.ipv6targets[addr.String()] = [2]string{target, tag}
		}
	} else {
		logp.Debug("pingbeat", "Getting IP addresses for %s:\n", target)
		addrs, err := net.LookupIP(target)
		if err != nil {
			logp.Warn("Failed to resolve %s to IP address, ignoring this target.\n", target)
		} else {
			for j := 0; j < len(addrs); j++ {
				if addrs[j].To4() != nil {
					logp.Debug("pingbeat", "IPv4: %s\n", addrs[j].String())
					p.ipv4targets[addrs[j].String()] = [2]string{target, tag}
				} else {
					logp.Debug("pingbeat", "IPv6: %s\n", addrs[j].String())
					p.ipv6targets[addrs[j].String()] = [2]string{target, tag}
				}
			}
		}
	}
}

func (p *Pingbeat) Addr2Name(addr *net.IPAddr) (string, string) {
	var name, tag string
	if _, found := p.ipv4targets[addr.String()]; found {
		name = p.ipv4targets[addr.String()][0]
		tag = p.ipv4targets[addr.String()][1]
	} else if _, found := p.ipv6targets[addr.String()]; found {
		name = p.ipv6targets[addr.String()][0]
		tag = p.ipv6targets[addr.String()][1]
	} else {
		logp.Err("Error: %s not found in Pingbeat targets!", addr.String())
		name = "err"
		tag = "err"
	}
	return name, tag
}

func (p *Pingbeat) Config(b *beat.Beat) error {
	// Read in provided config file, bail if problem
	err := cfgfile.Read(&p.config, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	// Use period provided in config or default to 5s
	if p.config.Input.Period != nil {
		p.period = time.Duration(*p.config.Input.Period) * time.Second
	} else {
		p.period = 5 * time.Second
	}
	logp.Debug("pingbeat", "Period %v\n", p.period)

	// Check if we can use privileged (i.e. raw socket) ping,
	// else use a UDP ping
	if *p.config.Input.Privileged {
		p.pingType = "ip"
	} else {
		p.pingType = "udp"
	}
	logp.Debug("pingbeat", "Using %v for pings\n", p.pingType)

	// Check whether IPv4/IPv6 pings are requested in config
	// Default to just IPv4 pings
	if &p.config.Input.UseIPv4 != nil {
		p.useIPv4 = *p.config.Input.UseIPv4
	} else {
		p.useIPv4 = true
	}
	if &p.config.Input.UseIPv6 != nil {
		p.useIPv6 = *p.config.Input.UseIPv6
	} else {
		p.useIPv6 = false
	}
	logp.Debug("pingbeat", "IPv4: %v, IPv6: %v\n", p.useIPv4, p.useIPv6)

	// Fill the IPv4/IPv6 targets maps
	p.ipv4targets = make(map[string][2]string)
	p.ipv6targets = make(map[string][2]string)
	if p.config.Input.Targets != nil {
		for tag, targets := range *p.config.Input.Targets {
			for i := 0; i < len(targets); i++ {
				p.AddTarget(targets[i], tag)
			}
		}
	} else {
		logp.Critical("Error: no targets specified, cannot continue!")
		os.Exit(1)
	}

	return nil
}

func (p *Pingbeat) Setup(b *beat.Beat) error {
	p.events = b.Events
	p.done = make(chan struct{})
	return nil
}

func (p *Pingbeat) Run(b *beat.Beat) error {

	fp := fastping.NewPinger()

	// Set the MaxRTT, i.e., the interval between pinging a target
	fp.MaxRTT = p.period

	errInput, err := fp.Network(p.pingType)
	results := make(map[string]*response)
	if err != nil {
		logp.Critical("Error: %v (input %v)", err, errInput)
		os.Exit(1)
	}

	if p.useIPv4 {
		for addr, details := range p.ipv4targets {
			logp.Debug("pingbeat", "Adding target IP: %s, Name: %s, Tag: %s\n", addr, details[0], details[1])
			fp.AddIP(addr)
			results[addr] = nil
		}
	}
	if p.useIPv6 {
		for addr, details := range p.ipv6targets {
			logp.Debug("pingbeat", "Adding target IP: %s, Name: %s, Tag: %s\n", addr, details[0], details[1])
			fp.AddIP(addr)
			results[addr] = nil
		}
	}

	onRecv, onIdle := make(chan *response), make(chan bool)
	fp.OnRecv = func(addr *net.IPAddr, t time.Duration) {
		// Find the name and tag associated with this address
		name, tag := p.Addr2Name(addr)
		// Send the name, addr, rtt and tag as a struct through the onRecv channel
		onRecv <- &response{name: name, addr: addr, rtt: t, tag: tag}
	}
	fp.OnIdle = func() {
		onIdle <- true
	}

	fp.RunLoop()

	for {
		select {
		case <-p.done:
			logp.Debug("pingbeat", "Got interrupted, shutting down\n")
			fp.Stop()
			return nil
		case res := <-onRecv:
			results[res.addr.String()] = res
		case <-onIdle:
			for target, r := range results {
				if r == nil {
					var name, tag string
					if _, found := p.ipv4targets[target]; found {
						name = p.ipv4targets[target][0]
						tag = p.ipv4targets[target][1]
					} else if _, found := p.ipv6targets[target]; found {
						name = p.ipv6targets[target][0]
						tag = p.ipv6targets[target][1]
					} else {
						logp.Warn("Error: Unexpected target returned: %s", target)
						break
					}
					// Packet loss
					event := common.MapStr{
						"@timestamp":  common.Time(time.Now()),
						"type":        "pingbeat",
						"target_name": name,
						"target_addr": target,
						"tag":         tag,
						"loss":        true,
					}
					p.events.PublishEvent(event)
				} else {
					// Success, ping received
					event := common.MapStr{
						"@timestamp":  common.Time(time.Now()),
						"type":        "pingbeat",
						"target_name": r.name,
						"target_addr": target,
						"tag":         r.tag,
						"rtt":         milliSeconds(r.rtt),
					}
					p.events.PublishEvent(event)
				}
				results[target] = nil
			}
		case <-fp.Done():
			if err = fp.Err(); err != nil {
				logp.Critical("Error: %Ping failed v", err)
			}
			break
		}
	}
	fp.Stop()
	return nil
}

func (p *Pingbeat) Cleanup(b *beat.Beat) error {
	return nil
}

func (p *Pingbeat) Stop() {
	close(p.done)
}
<|endoftext|>


<commit_before>package blob

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
)

const (
	TemplateFiles = "templates"
	StaticFiles   = "static"
)

var mimeMap = map[string]string{
	"css":        "text/css",
	"js":         "text/javascript",
	"descriptor": "application/vnd.google.protobuf;proto=google.protobuf.FileDescriptorSet",
}

func GetFile(bucket string, name string) ([]byte, error) {
	blob, ok := files[bucket][name]
	if !ok {
		return nil, fmt.Errorf("Could not find %s/%s. Missing/updated files.go?", bucket, name)
	}
	reader := bytes.NewReader(blob)
	gz, err := gzip.NewReader(reader)
	if err != nil {
		return nil, err
	}

	var b bytes.Buffer
	io.Copy(&b, gz)
	gz.Close()

	return b.Bytes(), nil
}

type Handler struct{}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Path
	if name == "" {
		name = "index.html"
	}

	file, err := GetFile(StaticFiles, name)
	if err != nil {
		if err != io.EOF {
			log.Printf("Could not get file: %s", err)
		}
		w.WriteHeader(http.StatusNotFound)
		return
	}
	contentType := http.DetectContentType(file)
	if strings.Contains(contentType, "text/plain") || strings.Contains(contentType, "application/octet-stream") {
		parts := strings.Split(name, ".")
		contentType = mimeMap[parts[len(parts)-1]]
	}
	w.Header().Set("Content-Type", contentType)
	w.Write(file)
}
<commit_msg>Add caching to static assets when served from blob handler.<commit_after>package blob

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
)

const (
	TemplateFiles = "templates"
	StaticFiles   = "static"
)

var mimeMap = map[string]string{
	"css":        "text/css",
	"js":         "text/javascript",
	"descriptor": "application/vnd.google.protobuf;proto=google.protobuf.FileDescriptorSet",
}

func GetFile(bucket string, name string) ([]byte, error) {
	blob, ok := files[bucket][name]
	if !ok {
		return nil, fmt.Errorf("Could not find %s/%s. Missing/updated files.go?", bucket, name)
	}
	reader := bytes.NewReader(blob)
	gz, err := gzip.NewReader(reader)
	if err != nil {
		return nil, err
	}

	var b bytes.Buffer
	io.Copy(&b, gz)
	gz.Close()

	return b.Bytes(), nil
}

type Handler struct{}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Path
	if name == "" {
		name = "index.html"
	}

	file, err := GetFile(StaticFiles, name)
	if err != nil {
		if err != io.EOF {
			log.Printf("Could not get file: %s", err)
		}
		w.WriteHeader(http.StatusNotFound)
		return
	}
	contentType := http.DetectContentType(file)
	if strings.Contains(contentType, "text/plain") || strings.Contains(contentType, "application/octet-stream") {
		parts := strings.Split(name, ".")
		contentType = mimeMap[parts[len(parts)-1]]
	}
	w.Header().Set("Content-Type", contentType)
	w.Header().Set("Cache-Control", "public, max-age=259200")
	w.Write(file)
}
<|endoftext|>


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

package goga

import (
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/plt"
	"github.com/cpmech/gosl/utl"
)

// ContourParams holds parameters to plot contours
type ContourParams struct {
	Npts    int       // number of points for contour
	CmapIdx int       // colormap index
	Csimple bool      // simple contour
	AxEqual bool      // axes-equal
	Lwg     float64   // linewidth for g functions
	Lwh     float64   // linewidth for h functions
	Args    string    // extra arguments for plot
	Extra   func()    // extra function
	Xrange  []float64 // to override x-range
	Yrange  []float64 // to override y-range
}

// PlotContour plots contour
func (o *Optimiser) PlotContour(iFlt, jFlt, iOva int, prms ContourParams) {

	// fix parameters
	if prms.Npts < 3 {
		prms.Npts = 41
	}
	if prms.Lwg < 0.1 {
		prms.Lwg = 1.5
	}
	if prms.Lwh < 0.1 {
		prms.Lwh = 1.5
	}

	// limits and meshgrid
	xmin, xmax := o.FltMin[iFlt], o.FltMax[iFlt]
	ymin, ymax := o.FltMin[jFlt], o.FltMax[jFlt]
	if prms.Xrange != nil {
		xmin, xmax = prms.Xrange[0], prms.Xrange[1]
	}
	if prms.Yrange != nil {
		ymin, ymax = prms.Yrange[0], prms.Yrange[1]
	}

	// auxiliary variables
	X, Y := utl.MeshGrid2D(xmin, xmax, ymin, ymax, prms.Npts, prms.Npts)
	Zf := utl.DblsAlloc(prms.Npts, prms.Npts)
	var Zg [][][]float64
	var Zh [][][]float64
	if o.Ng > 0 {
		Zg = utl.Deep3alloc(o.Ng, prms.Npts, prms.Npts)
	}
	if o.Nh > 0 {
		Zh = utl.Deep3alloc(o.Nh, prms.Npts, prms.Npts)
	}

	// compute values
	x := make([]float64, 2)
	grp := 0
	for i := 0; i < prms.Npts; i++ {
		for j := 0; j < prms.Npts; j++ {
			x[0], x[1] = X[i][j], Y[i][j]
			o.MinProb(o.F[grp], o.G[grp], o.H[grp], x, nil, grp)
			Zf[i][j] = o.F[grp][iOva]
			for k, g := range o.G[grp] {
				Zg[k][i][j] = g
			}
			for k, h := range o.H[grp] {
				Zh[k][i][j] = h
			}
		}
	}

	// plot f
	if prms.Csimple {
		plt.ContourSimple(X, Y, Zf, true, 7, "colors=['k'], fsz=7, "+prms.Args)
	} else {
		plt.Contour(X, Y, Zf, io.Sf("fsz=7, cmapidx=%d, "+prms.Args, prms.CmapIdx))
	}

	// plot g
	clr := "yellow"
	if prms.Csimple {
		clr = "blue"
	}
	for _, g := range Zg {
		plt.ContourSimple(X, Y, g, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, prms.Lwg))
	}

	// plot h
	clr = "yellow"
	if prms.Csimple {
		clr = "blue"
	}
	for _, h := range Zh {
		plt.ContourSimple(X, Y, h, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, prms.Lwh))
	}
}

// PlotAddFltFlt adds flt-flt points to existent plot
func (o *Optimiser) PlotAddFltFlt(iFlt, jFlt int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Flt[iFlt], sol.Flt[jFlt]
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddFltOva adds flt-ova points to existent plot
func (o *Optimiser) PlotAddFltOva(iFlt, iOva int, sols []*Solution, ovaMult float64, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Flt[iFlt], sol.Ova[iOva]*ovaMult
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddOvaOva adds ova-ova points to existent plot
func (o *Optimiser) PlotAddOvaOva(iOva, jOva int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Ova[iOva], sol.Ova[jOva]
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddParetoFront highlights Pareto front
func (o *Optimiser) PlotAddParetoFront(iOva, jOva int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	x, y, _ := GetParetoFront(iOva, jOva, sols, false)
	plt.Plot(x, y, args)
}

// PlotFltOva plots flt-ova points
func PlotFltOva(fnkey string, opt *Optimiser, sols0 []*Solution, iFlt, iOva, np int, ovaMult float64, fcn func(x float64) float64, extra func(), equalAxes bool) {
	if fcn != nil {
		X := utl.LinSpace(opt.FltMin[0], opt.FltMax[0], np)
		Y := make([]float64, np)
		for i := 0; i < np; i++ {
			Y[i] = fcn(X[i])
		}
		plt.Plot(X, Y, "'b-'")
	}
	if sols0 != nil {
		opt.PlotAddFltOva(iFlt, iOva, sols0, ovaMult, plt.Fmt{L: "initial", M: "o", C: "k", Ls: "none", Ms: 3}, false)
	}
	SortByOva(opt.Solutions, iOva)
	best := opt.Solutions[0]
	opt.PlotAddFltOva(iFlt, iOva, opt.Solutions, ovaMult, plt.Fmt{L: "final", M: "o", C: "r", Ls: "none", Ms: 6}, true)
	plt.PlotOne(best.Flt[iFlt], best.Ova[iOva]*ovaMult, "'g*', markeredgecolor='g', label='best', clip_on=0, zorder=20")
	if extra != nil {
		extra()
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$x_%d$", iFlt), io.Sf("$f_%d$", iOva), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}

// PlotFltFlt plots flt-flt contour
func PlotFltFltContour(fnkey string, opt *Optimiser, sols0 []*Solution, iFlt, jFlt, iOva int, cprms ContourParams, extra func(), equalAxes bool) {
	clr1 := "green"
	clr2 := "black"
	if cprms.Csimple {
		clr1 = "red"
		clr2 = "green"
	}
	opt.PlotContour(iFlt, jFlt, iOva, cprms)
	if sols0 != nil {
		opt.PlotAddFltFlt(iFlt, jFlt, sols0, plt.Fmt{L: "initial", M: "o", C: "k", Ls: "none", Ms: 3}, false)
	}
	SortByOva(opt.Solutions, iOva)
	best := opt.Solutions[0]
	opt.PlotAddFltFlt(iFlt, jFlt, opt.Solutions, plt.Fmt{L: "final", M: "o", C: clr2, Ls: "none", Ms: 6}, true)
	plt.PlotOne(best.Flt[iFlt], best.Flt[jFlt], io.Sf("'k*', color='%s', markeredgecolor='%s', label='best', clip_on=0, zorder=20", clr1, clr1))
	if extra != nil {
		extra()
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$x_%d$", iFlt), io.Sf("$x_%d$", jFlt), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}

// PlotOvaOvaPareto plots ova-ova Pareto values
func PlotOvaOvaPareto(fnkey string, opt *Optimiser, sols0 []*Solution, iOva, jOva int, extra func(), lims []float64, equalAxes bool) {
	if sols0 != nil {
		opt.PlotAddOvaOva(iOva, jOva, sols0, plt.Fmt{L: "initial", M: "+", C: "g", Ls: "none", Ms: 4}, false)
	}
	opt.PlotAddOvaOva(iOva, jOva, opt.Solutions, plt.Fmt{L: "final", M: ".", C: "r", Ls: "none", Ms: 5}, false)
	opt.PlotAddParetoFront(iOva, jOva, opt.Solutions, plt.Fmt{M: "o", C: "k", Ls: "none", Ms: 6}, true)
	if extra != nil {
		extra()
	}
	if lims != nil {
		plt.AxisLims(lims)
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$f_%d$", iOva), io.Sf("$f_%d$", jOva), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}
<commit_msg>plotting improved a little: colours for markers<commit_after>// Copyright 2015 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goga

import (
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/plt"
	"github.com/cpmech/gosl/utl"
)

// ContourParams holds parameters to plot contours
type ContourParams struct {
	Npts    int       // number of points for contour
	CmapIdx int       // colormap index
	Csimple bool      // simple contour
	AxEqual bool      // axes-equal
	Lwg     float64   // linewidth for g functions
	Lwh     float64   // linewidth for h functions
	Args    string    // extra arguments for plot
	Extra   func()    // extra function
	Xrange  []float64 // to override x-range
	Yrange  []float64 // to override y-range
}

// PlotContour plots contour
func (o *Optimiser) PlotContour(iFlt, jFlt, iOva int, prms ContourParams) {

	// fix parameters
	if prms.Npts < 3 {
		prms.Npts = 41
	}
	if prms.Lwg < 0.1 {
		prms.Lwg = 1.5
	}
	if prms.Lwh < 0.1 {
		prms.Lwh = 1.5
	}

	// limits and meshgrid
	xmin, xmax := o.FltMin[iFlt], o.FltMax[iFlt]
	ymin, ymax := o.FltMin[jFlt], o.FltMax[jFlt]
	if prms.Xrange != nil {
		xmin, xmax = prms.Xrange[0], prms.Xrange[1]
	}
	if prms.Yrange != nil {
		ymin, ymax = prms.Yrange[0], prms.Yrange[1]
	}

	// auxiliary variables
	X, Y := utl.MeshGrid2D(xmin, xmax, ymin, ymax, prms.Npts, prms.Npts)
	Zf := utl.DblsAlloc(prms.Npts, prms.Npts)
	var Zg [][][]float64
	var Zh [][][]float64
	if o.Ng > 0 {
		Zg = utl.Deep3alloc(o.Ng, prms.Npts, prms.Npts)
	}
	if o.Nh > 0 {
		Zh = utl.Deep3alloc(o.Nh, prms.Npts, prms.Npts)
	}

	// compute values
	x := make([]float64, 2)
	grp := 0
	for i := 0; i < prms.Npts; i++ {
		for j := 0; j < prms.Npts; j++ {
			x[0], x[1] = X[i][j], Y[i][j]
			o.MinProb(o.F[grp], o.G[grp], o.H[grp], x, nil, grp)
			Zf[i][j] = o.F[grp][iOva]
			for k, g := range o.G[grp] {
				Zg[k][i][j] = g
			}
			for k, h := range o.H[grp] {
				Zh[k][i][j] = h
			}
		}
	}

	// plot f
	if prms.Csimple {
		plt.ContourSimple(X, Y, Zf, true, 7, "colors=['k'], fsz=7, "+prms.Args)
	} else {
		plt.Contour(X, Y, Zf, io.Sf("fsz=7, cmapidx=%d, "+prms.Args, prms.CmapIdx))
	}

	// plot g
	clr := "yellow"
	if prms.Csimple {
		clr = "blue"
	}
	for _, g := range Zg {
		plt.ContourSimple(X, Y, g, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, prms.Lwg))
	}

	// plot h
	clr = "yellow"
	if prms.Csimple {
		clr = "blue"
	}
	for _, h := range Zh {
		plt.ContourSimple(X, Y, h, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, prms.Lwh))
	}
}

// PlotAddFltFlt adds flt-flt points to existent plot
func (o *Optimiser) PlotAddFltFlt(iFlt, jFlt int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Flt[iFlt], sol.Flt[jFlt]
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddFltOva adds flt-ova points to existent plot
func (o *Optimiser) PlotAddFltOva(iFlt, iOva int, sols []*Solution, ovaMult float64, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Flt[iFlt], sol.Ova[iOva]*ovaMult
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddOvaOva adds ova-ova points to existent plot
func (o *Optimiser) PlotAddOvaOva(iOva, jOva int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	nsol := len(sols)
	x, y := make([]float64, nsol), make([]float64, nsol)
	for i, sol := range sols {
		x[i], y[i] = sol.Ova[iOva], sol.Ova[jOva]
	}
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	plt.Plot(x, y, args)
}

// PlotAddParetoFront highlights Pareto front
func (o *Optimiser) PlotAddParetoFront(iOva, jOva int, sols []*Solution, fmt plt.Fmt, emptyMarker bool) {
	args := fmt.GetArgs("") + ",clip_on=0,zorder=10"
	if emptyMarker {
		args += io.Sf(",markeredgecolor='%s',markerfacecolor='none'", fmt.C)
	}
	x, y, _ := GetParetoFront(iOva, jOva, sols, false)
	plt.Plot(x, y, args)
}

// PlotFltOva plots flt-ova points
func PlotFltOva(fnkey string, opt *Optimiser, sols0 []*Solution, iFlt, iOva, np int, ovaMult float64, fcn func(x float64) float64, extra func(), equalAxes bool) {
	if fcn != nil {
		X := utl.LinSpace(opt.FltMin[0], opt.FltMax[0], np)
		Y := make([]float64, np)
		for i := 0; i < np; i++ {
			Y[i] = fcn(X[i])
		}
		plt.Plot(X, Y, "'b-'")
	}
	if sols0 != nil {
		opt.PlotAddFltOva(iFlt, iOva, sols0, ovaMult, plt.Fmt{L: "initial", M: "o", C: "k", Ls: "none", Ms: 3}, false)
	}
	SortByOva(opt.Solutions, iOva)
	best := opt.Solutions[0]
	opt.PlotAddFltOva(iFlt, iOva, opt.Solutions, ovaMult, plt.Fmt{L: "final", M: "o", C: "r", Ls: "none", Ms: 6}, true)
	plt.PlotOne(best.Flt[iFlt], best.Ova[iOva]*ovaMult, "'g*', markeredgecolor='g', label='best', clip_on=0, zorder=20")
	if extra != nil {
		extra()
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$x_%d$", iFlt), io.Sf("$f_%d$", iOva), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}

// PlotFltFlt plots flt-flt contour
func PlotFltFltContour(fnkey string, opt *Optimiser, sols0 []*Solution, iFlt, jFlt, iOva int, cprms ContourParams, extra func(), equalAxes bool) {
	clr1 := "green"
	clr2 := "magenta"
	if cprms.Csimple {
		clr1 = "red"
		clr2 = "green"
	}
	opt.PlotContour(iFlt, jFlt, iOva, cprms)
	if sols0 != nil {
		opt.PlotAddFltFlt(iFlt, jFlt, sols0, plt.Fmt{L: "initial", M: "o", C: "k", Ls: "none", Ms: 3}, false)
	}
	SortByOva(opt.Solutions, iOva)
	best := opt.Solutions[0]
	opt.PlotAddFltFlt(iFlt, jFlt, opt.Solutions, plt.Fmt{L: "final", M: "o", C: clr2, Ls: "none", Ms: 7}, true)
	plt.PlotOne(best.Flt[iFlt], best.Flt[jFlt], io.Sf("'k*', markersize=6, color='%s', markeredgecolor='%s', label='best', clip_on=0, zorder=20", clr1, clr1))
	if extra != nil {
		extra()
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$x_%d$", iFlt), io.Sf("$x_%d$", jFlt), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}

// PlotOvaOvaPareto plots ova-ova Pareto values
func PlotOvaOvaPareto(fnkey string, opt *Optimiser, sols0 []*Solution, iOva, jOva int, extra func(), lims []float64, equalAxes bool) {
	if sols0 != nil {
		opt.PlotAddOvaOva(iOva, jOva, sols0, plt.Fmt{L: "initial", M: "+", C: "g", Ls: "none", Ms: 4}, false)
	}
	opt.PlotAddOvaOva(iOva, jOva, opt.Solutions, plt.Fmt{L: "final", M: ".", C: "r", Ls: "none", Ms: 5}, false)
	opt.PlotAddParetoFront(iOva, jOva, opt.Solutions, plt.Fmt{M: "o", C: "k", Ls: "none", Ms: 6}, true)
	if extra != nil {
		extra()
	}
	if lims != nil {
		plt.AxisLims(lims)
	}
	if equalAxes {
		plt.Equal()
	}
	plt.Gll(io.Sf("$f_%d$", iOva), io.Sf("$f_%d$", jOva), "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD("/tmp/goga", fnkey+".eps")
}
<|endoftext|>


<commit_before>package postailer

import (
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func init() {
	var _ readSeekCloser = &Postailer{}
}

func fileAndPos(dir string) (string, string) {
	fname := filepath.Join(dir, "log.log")
	posfile := fname + ".json"
	return fname, posfile
}

var readTests = []struct {
	Name    string
	Prepare func() (string, error)
	Output1 []byte
	N1      int
	Error1  error
	Output2 []byte
	N2      int
	Error2  error
	NextPos int64
}{
	{
		Name: "New",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, _ := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
	{
		Name: "Simple",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcdf13579"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 14,
	},
	{
		Name: "EOF",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, _ := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcd"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 0},
		N1:      4,
		Error1:  nil,
		Output2: []byte{0, 0, 0},
		N2:      0,
		Error2:  io.EOF,
		NextPos: 4,
	},
	{
		Name: "Roteted",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcd"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			os.Rename(fname, fname+".bak")
			ioutil.WriteFile(fname, []byte("f135999"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 4,
	},
	{
		Name: "Just Roteted",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcdf"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			os.Rename(fname, fname+".bak")
			ioutil.WriteFile(fname, []byte("135999"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 3,
	},
	{
		Name: "Roteted but missing",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			savePos(posfile, &position{
				Inode: ^uint(0) - 10,
				Pos:   6,
			})
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
	{
		Name: "Same inode, but Truncated",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   10000,
			})
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
}

func TestReadClose(t *testing.T) {
	for _, tt := range readTests {
		func() {
			tmpd, err := tt.Prepare()
			if tmpd != "" {
				defer os.RemoveAll(tmpd)
			}
			if err != nil {
				t.Fatalf("error occured while preparing test: %s, %+v", tt.Name, err)
			}
			fname, posfile := fileAndPos(tmpd)
			pt, err := Open(fname, posfile)
			if err != nil {
				t.Fatalf("error should be nil but: %+v", err)
			}

			p1 := make([]byte, 5)
			n1, err1 := pt.Read(p1)
			if !reflect.DeepEqual(p1, tt.Output1) {
				t.Errorf("%s(output1): out=%q want %q", tt.Name, p1, tt.Output1)
			}
			if n1 != tt.N1 {
				t.Errorf("%s(n1): out=%d want %d", tt.Name, n1, tt.N1)
			}
			if err1 != tt.Error1 {
				t.Errorf("%s(err1): out=%+v want %+v", tt.Name, err1, tt.Error1)
			}

			p2 := make([]byte, 3)
			n2, err2 := pt.Read(p2)
			if !reflect.DeepEqual(p2, tt.Output2) {
				t.Errorf("%s(output2): out=%q want %q", tt.Name, p2, tt.Output2)
			}
			if n2 != tt.N2 {
				t.Errorf("%s(n2): out=%d want %d", tt.Name, n2, tt.N2)
			}
			if err2 != tt.Error2 {
				t.Errorf("%s(err2): out=%+v want %+v", tt.Name, err2, tt.Error2)
			}

			pt.Close()
			pos, _ := loadPos(posfile)
			fi, _ := os.Stat(fname)
			expect := &position{
				Inode: detectInode(fi),
				Pos:   tt.NextPos,
			}
			if !reflect.DeepEqual(pos, expect) {
				t.Errorf("%s(nextPos): out=%+v want %+v", tt.Name, pos, expect)
			}
		}()
	}
}
<commit_msg>There are no inode on windows<commit_after>package postailer

import (
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
)

func init() {
	// check the Postailer satisfied readSeekCloser interface
	var _ readSeekCloser = &Postailer{}
	if runtime.GOOS != "windows" {
		readTests = append(readTests, readRotateTests...)
	}
}

func fileAndPos(dir string) (string, string) {
	fname := filepath.Join(dir, "log.log")
	posfile := fname + ".json"
	return fname, posfile
}

type testReadTest struct {
	Name    string
	Prepare func() (string, error)
	Output1 []byte
	N1      int
	Error1  error
	Output2 []byte
	N2      int
	Error2  error
	NextPos int64
}

var readTests = []testReadTest{
	{
		Name: "New",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, _ := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
	{
		Name: "Simple",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcdf13579"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 14,
	},
	{
		Name: "EOF",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, _ := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcd"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 0},
		N1:      4,
		Error1:  nil,
		Output2: []byte{0, 0, 0},
		N2:      0,
		Error2:  io.EOF,
		NextPos: 4,
	},
	{
		Name: "Roteted but missing",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			savePos(posfile, &position{
				Inode: ^uint(0) - 10,
				Pos:   6,
			})
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
	{
		Name: "Same inode, but Truncated",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("abcdf13579"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   10000,
			})
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 8,
	},
}

var readRotateTests = []testReadTest{
	{
		Name: "Roteted",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcd"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			os.Rename(fname, fname+".bak")
			ioutil.WriteFile(fname, []byte("f135999"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 4,
	},
	{
		Name: "Just Roteted",
		Prepare: func() (string, error) {
			tmpd, err := ioutil.TempDir("", "")
			if err != nil {
				return "", err
			}
			fname, posfile := fileAndPos(tmpd)
			ioutil.WriteFile(fname, []byte("-skip-abcdf"), 0644)
			fi, _ := os.Stat(fname)
			savePos(posfile, &position{
				Inode: detectInode(fi),
				Pos:   6,
			})
			os.Rename(fname, fname+".bak")
			ioutil.WriteFile(fname, []byte("135999"), 0644)
			return tmpd, nil
		},
		Output1: []byte{'a', 'b', 'c', 'd', 'f'},
		N1:      5,
		Error1:  nil,
		Output2: []byte{'1', '3', '5'},
		N2:      3,
		Error2:  nil,
		NextPos: 3,
	},
}

func TestReadClose(t *testing.T) {
	for _, tt := range readTests {
		func() {
			tmpd, err := tt.Prepare()
			if tmpd != "" {
				defer os.RemoveAll(tmpd)
			}
			if err != nil {
				t.Fatalf("error occured while preparing test: %s, %+v", tt.Name, err)
			}
			fname, posfile := fileAndPos(tmpd)
			pt, err := Open(fname, posfile)
			if err != nil {
				t.Fatalf("error should be nil but: %+v", err)
			}

			p1 := make([]byte, 5)
			n1, err1 := pt.Read(p1)
			if !reflect.DeepEqual(p1, tt.Output1) {
				t.Errorf("%s(output1): out=%q want %q", tt.Name, p1, tt.Output1)
			}
			if n1 != tt.N1 {
				t.Errorf("%s(n1): out=%d want %d", tt.Name, n1, tt.N1)
			}
			if err1 != tt.Error1 {
				t.Errorf("%s(err1): out=%+v want %+v", tt.Name, err1, tt.Error1)
			}

			p2 := make([]byte, 3)
			n2, err2 := pt.Read(p2)
			if !reflect.DeepEqual(p2, tt.Output2) {
				t.Errorf("%s(output2): out=%q want %q", tt.Name, p2, tt.Output2)
			}
			if n2 != tt.N2 {
				t.Errorf("%s(n2): out=%d want %d", tt.Name, n2, tt.N2)
			}
			if err2 != tt.Error2 {
				t.Errorf("%s(err2): out=%+v want %+v", tt.Name, err2, tt.Error2)
			}

			pt.Close()
			pos, _ := loadPos(posfile)
			fi, _ := os.Stat(fname)
			expect := &position{
				Inode: detectInode(fi),
				Pos:   tt.NextPos,
			}
			if !reflect.DeepEqual(pos, expect) {
				t.Errorf("%s(nextPos): out=%+v want %+v", tt.Name, pos, expect)
			}
		}()
	}
}
<|endoftext|>