<commit_before>package jmespath

import (
	"errors"
	"reflect"
)

// IsFalse determines if an object is false based on the JMESPath spec.
// JMESPath defines false values to be any of:
// - An empty string array, or hash.
// - The boolean value false.
// - nil
func isFalse(value interface{}) bool {
	switch v := value.(type) {
	case bool:
		return !v
	case []interface{}:
		return len(v) == 0
	case map[string]interface{}:
		return len(v) == 0
	case string:
		return len(v) == 0
	case nil:
		return true
	}
	// Try the reflection cases before returning false.
	v := reflect.ValueOf(value)
	vType := v.Type().Kind()
	if vType == reflect.Struct {
		// A struct type will never be false, even if
		// all of its values are the zero type.
		return false
	} else if vType == reflect.Slice || vType == reflect.Map {
		if v.Len() == 0 {
			return true
		}
		return false
	} else if vType == reflect.Ptr {
		if v.IsNil() {
			return true
		}
		// If it's a pointer type, we'll try to deref the pointer
		// and evaluate the pointer value for isFalse.
		element := v.Elem()
		return isFalse(element.Interface())
	}
	return false
}

// ObjsEqual is a generic object equality check.
// It will take two arbitrary objects and recursively determine
// if they are equal.
func objsEqual(left interface{}, right interface{}) bool {
	return reflect.DeepEqual(left, right)
}

// SliceParam refers to a single part of a slice.
// A slice consists of a start, a stop, and a step, similar to
// python slices.
type sliceParam struct {
	N         int
	Specified bool
}

// Slice supports [start:stop:step] style slicing that's supported in JMESPath.
func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) {
	computed, err := computeSliceParams(len(slice), parts)
	if err != nil {
		return nil, err
	}
	start, stop, step := computed[0], computed[1], computed[2]
	result := make([]interface{}, 0, 0)
	if step > 0 {
		for i := start; i < stop; i += step {
			result = append(result, slice[i])
		}
	} else {
		for i := start; i > stop; i += step {
			result = append(result, slice[i])
		}
	}
	return result, nil
}

func computeSliceParams(length int, parts []sliceParam) ([]int, error) {
	var start, stop, step int
	if !parts[2].Specified {
		step = 1
	} else if parts[2].N == 0 {
		return nil, errors.New("Invalid slice, step cannot be 0")
	} else {
		step = parts[2].N
	}
	var stepValueNegative bool
	if step < 0 {
		stepValueNegative = true
	} else {
		stepValueNegative = false
	}

	if !parts[0].Specified {
		if stepValueNegative {
			start = length - 1
		} else {
			start = 0
		}
	} else {
		start = capSlice(length, parts[0].N, step)
	}

	if !parts[1].Specified {
		if stepValueNegative {
			stop = -1
		} else {
			stop = length
		}
	} else {
		stop = capSlice(length, parts[1].N, step)
	}
	return []int{start, stop, step}, nil
}

func capSlice(length int, actual int, step int) int {
	if actual < 0 {
		actual += length
		if actual < 0 {
			if step < 0 {
				actual = -1
			} else {
				actual = 0
			}
		}
	} else if actual >= length {
		if step < 0 {
			actual = length - 1
		} else {
			actual = length
		}
	}
	return actual
}

// ToArrayNum converts an empty interface type to a slice of float64.
// If any element in the array cannot be converted, then nil is returned
// along with a second value of false.
func toArrayNum(data interface{}) ([]float64, bool) {
	// Is there a better way to do this with reflect?
	if d, ok := data.([]interface{}); ok {
		result := make([]float64, len(d))
		for i, el := range d {
			item, ok := el.(float64)
			if !ok {
				return nil, false
			}
			result[i] = item
		}
		return result, true
	}
	return nil, false
}

// ToArrayStr converts an empty interface type to a slice of strings.
// If any element in the array cannot be converted, then nil is returned
// along with a second value of false.  If the input data could be entirely
// converted, then the converted data, along with a second value of true,
// will be returned.
func toArrayStr(data interface{}) ([]string, bool) {
	// Is there a better way to do this with reflect?
	if d, ok := data.([]interface{}); ok {
		result := make([]string, len(d))
		for i, el := range d {
			item, ok := el.(string)
			if !ok {
				return nil, false
			}
			result[i] = item
		}
		return result, true
	}
	return nil, false
}

func isSliceType(v interface{}) bool {
	if v == nil {
		return false
	}
	return reflect.TypeOf(v).Kind() == reflect.Slice
}
<commit_msg>Use switch statement instead of ifelse chain<commit_after>package jmespath

import (
	"errors"
	"reflect"
)

// IsFalse determines if an object is false based on the JMESPath spec.
// JMESPath defines false values to be any of:
// - An empty string array, or hash.
// - The boolean value false.
// - nil
func isFalse(value interface{}) bool {
	switch v := value.(type) {
	case bool:
		return !v
	case []interface{}:
		return len(v) == 0
	case map[string]interface{}:
		return len(v) == 0
	case string:
		return len(v) == 0
	case nil:
		return true
	}
	// Try the reflection cases before returning false.
	rv := reflect.ValueOf(value)
	switch rv.Kind() {
	case reflect.Struct:
		// A struct type will never be false, even if
		// all of its values are the zero type.
		return false
	case reflect.Slice, reflect.Map:
		return rv.Len() == 0
	case reflect.Ptr:
		if rv.IsNil() {
			return true
		}
		// If it's a pointer type, we'll try to deref the pointer
		// and evaluate the pointer value for isFalse.
		element := rv.Elem()
		return isFalse(element.Interface())
	}
	return false
}

// ObjsEqual is a generic object equality check.
// It will take two arbitrary objects and recursively determine
// if they are equal.
func objsEqual(left interface{}, right interface{}) bool {
	return reflect.DeepEqual(left, right)
}

// SliceParam refers to a single part of a slice.
// A slice consists of a start, a stop, and a step, similar to
// python slices.
type sliceParam struct {
	N         int
	Specified bool
}

// Slice supports [start:stop:step] style slicing that's supported in JMESPath.
func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) {
	computed, err := computeSliceParams(len(slice), parts)
	if err != nil {
		return nil, err
	}
	start, stop, step := computed[0], computed[1], computed[2]
	result := make([]interface{}, 0, 0)
	if step > 0 {
		for i := start; i < stop; i += step {
			result = append(result, slice[i])
		}
	} else {
		for i := start; i > stop; i += step {
			result = append(result, slice[i])
		}
	}
	return result, nil
}

func computeSliceParams(length int, parts []sliceParam) ([]int, error) {
	var start, stop, step int
	if !parts[2].Specified {
		step = 1
	} else if parts[2].N == 0 {
		return nil, errors.New("Invalid slice, step cannot be 0")
	} else {
		step = parts[2].N
	}
	var stepValueNegative bool
	if step < 0 {
		stepValueNegative = true
	} else {
		stepValueNegative = false
	}

	if !parts[0].Specified {
		if stepValueNegative {
			start = length - 1
		} else {
			start = 0
		}
	} else {
		start = capSlice(length, parts[0].N, step)
	}

	if !parts[1].Specified {
		if stepValueNegative {
			stop = -1
		} else {
			stop = length
		}
	} else {
		stop = capSlice(length, parts[1].N, step)
	}
	return []int{start, stop, step}, nil
}

func capSlice(length int, actual int, step int) int {
	if actual < 0 {
		actual += length
		if actual < 0 {
			if step < 0 {
				actual = -1
			} else {
				actual = 0
			}
		}
	} else if actual >= length {
		if step < 0 {
			actual = length - 1
		} else {
			actual = length
		}
	}
	return actual
}

// ToArrayNum converts an empty interface type to a slice of float64.
// If any element in the array cannot be converted, then nil is returned
// along with a second value of false.
func toArrayNum(data interface{}) ([]float64, bool) {
	// Is there a better way to do this with reflect?
	if d, ok := data.([]interface{}); ok {
		result := make([]float64, len(d))
		for i, el := range d {
			item, ok := el.(float64)
			if !ok {
				return nil, false
			}
			result[i] = item
		}
		return result, true
	}
	return nil, false
}

// ToArrayStr converts an empty interface type to a slice of strings.
// If any element in the array cannot be converted, then nil is returned
// along with a second value of false.  If the input data could be entirely
// converted, then the converted data, along with a second value of true,
// will be returned.
func toArrayStr(data interface{}) ([]string, bool) {
	// Is there a better way to do this with reflect?
	if d, ok := data.([]interface{}); ok {
		result := make([]string, len(d))
		for i, el := range d {
			item, ok := el.(string)
			if !ok {
				return nil, false
			}
			result[i] = item
		}
		return result, true
	}
	return nil, false
}

func isSliceType(v interface{}) bool {
	if v == nil {
		return false
	}
	return reflect.TypeOf(v).Kind() == reflect.Slice
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gnewton/gomesh"
	"log"
	"sort"
	"strings"
)

const DESCRIPTOR = "descriptor"
const QUALIFIER = "qualifier"
const SUPPLEMENTAL = "supplemental"
const PHARMACOLOGICAL = "pharmacological"
const TREE = "tree"

var NOUNS = []string{
	DESCRIPTOR,
	QUALIFIER,
	SUPPLEMENTAL,
	TREE,
	PHARMACOLOGICAL,
}
var allNouns []gomesh.IdEntry

var descMap map[string]*gomesh.DescriptorRecord
var descMap2 map[string]*LocalDesc
var descSlice []*gomesh.IdEntry

var suppMap map[string]*gomesh.SupplementalRecord
var suppSlice []*gomesh.IdEntry

var qualMap map[string]*gomesh.QualifierRecord
var qualSlice []*gomesh.IdEntry

var pharmMap map[string]*gomesh.PharmacologicalAction
var pharmSlice []*gomesh.IdEntry

var root *gomesh.Node
var treeMap map[string]*gomesh.Node

type LocalDesc gomesh.DescriptorRecord

type Paging struct {
	Limit            int    `json:"limit"`
	Offset           int    `json:"offset"`
	Count            int    `json:"count"`
	NextPageUrl      string `json:"nextPageUrl,omitempty"`
	PrevioustPageUrl string `json:"previousPageUrl,omitempty"`
}

func (desc *LocalDesc) setQualifierUrls(baseUrl string) {
	if desc.AllowableQualifiersList.AllowableQualifier != nil {
		for i := 0; i < len(desc.AllowableQualifiersList.AllowableQualifier); i++ {
			qualifierReferredTo := desc.AllowableQualifiersList.AllowableQualifier[i].QualifierReferredTo
			qualifierReferredTo.Url = baseUrl + "/" + QUALIFIER + "/" + qualifierReferredTo.QualifierUI
		}
	}
}

func (desc *LocalDesc) setTreeNumberUrls(baseUrl string) {
	if desc.TreeNumberList.TreeNumber != nil {
		for i := 0; i < len(desc.TreeNumberList.TreeNumber); i++ {
			tn := &(desc.TreeNumberList.TreeNumber[i])
			tn.Url = baseUrl + "/" + TREE + "/" + tn.TreeNumber
		}
	}
}

func (desc *LocalDesc) setDescUrls(baseUrl string) {
	if desc.PharmacologicalActionList.PharmacologicalAction != nil {
		for i := 0; i < len(desc.PharmacologicalActionList.PharmacologicalAction); i++ {
			ref := &(desc.PharmacologicalActionList.PharmacologicalAction[i])
			ref.DescriptorReferredTo.Url = baseUrl + "/" + DESCRIPTOR + "/" + ref.DescriptorReferredTo.DescriptorUI
		}
	}

	if desc.SeeRelatedList.SeeRelatedDescriptor != nil {
		for i := 0; i < len(desc.SeeRelatedList.SeeRelatedDescriptor); i++ {
			ref := &(desc.SeeRelatedList.SeeRelatedDescriptor[i])
			ref.DescriptorReferredTo.Url = baseUrl + "/" + DESCRIPTOR + "/" + ref.DescriptorReferredTo.DescriptorUI
		}
	}
}

func loadData() error {
	treeMap = make(map[string]*gomesh.Node)
	var err error
	log.Println("Start Loading MeSH XML...")

	////////////////
	log.Println("\tLoading Supplemental MeSH XML from file: ", *SUPPLEMENTAL_XML_FILE)
	suppMap, err = gomesh.SupplementalMapFromFile(*SUPPLEMENTAL_XML_FILE)
	if err != nil {
		return err
	}
	index := 0
	suppSlice = make([]*gomesh.IdEntry, len(suppMap))
	for _, supp := range suppMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = supp.SupplementalRecordUI
		//newEntry.Url = BASE_URL + "/" + SUPPLEMENTAL + "/" + newEntry.Id
		newEntry.Url = SUPPLEMENTAL + "/" + newEntry.Id
		suppSlice[index] = newEntry
		index += 1

		for i := 0; i < len(supp.HeadingMappedToList.HeadingMappedTo); i++ {
			descriptorReferredTo := supp.HeadingMappedToList.HeadingMappedTo[i].DescriptorReferredTo
			descriptorReferredTo.Url = BASE_URL + "/" + DESCRIPTOR + "/" + strings.TrimLeft(descriptorReferredTo.DescriptorUI, "*")
		}
	}

	////////////////
	log.Println("\tLoading Pharmacological Action MeSH XML from file: ", *PHARMACOLOGICAL_XML_FILE)
	pharmMap, err = gomesh.PharmacologicalMapFromFile(*PHARMACOLOGICAL_XML_FILE)
	if err != nil {
		return err
	}
	index = 0
	pharmSlice = make([]*gomesh.IdEntry, len(pharmMap))
	for pharm := range pharmMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = pharmMap[pharm].DescriptorReferredTo.DescriptorUI
		newEntry.Url = BASE_URL + "/" + PHARMACOLOGICAL + "/" + newEntry.Id
		pharmSlice[index] = newEntry
		index += 1

		pharmMap[pharm].DescriptorReferredTo.Url = BASE_URL + "/" + DESCRIPTOR + "/" + pharm
		//if pharmMap[pharm].PharmacologicalActionSubstanceList.Substance != nil
		{
			for i := 0; i < len(pharmMap[pharm].PharmacologicalActionSubstanceList.Substance); i++ {
				//for _, substance := range pharmMap[pharm].PharmacologicalActionSubstanceList.Substance{
				substance := &pharmMap[pharm].PharmacologicalActionSubstanceList.Substance[i]
				if strings.Index(substance.RecordUI, "C") == 0 {
					substance.SupplementalUrl = BASE_URL + "/" + SUPPLEMENTAL + "/" + substance.RecordUI
				} else {
					substance.DescriptorUrl = BASE_URL + "/" + DESCRIPTOR + "/" + substance.RecordUI

				}
			}
		}
	}

	////////////////
	log.Println("\tLoading Qualifier MeSH XML from file:", *QUALIFIER_XML_FILE)
	qualMap, err = gomesh.QualifierMapFromFile(*QUALIFIER_XML_FILE)
	if err != nil {
		return err
	}
	qualSlice = make([]*gomesh.IdEntry, len(qualMap))
	index = 0
	for _, qual := range qualMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = qual.QualifierUI
		newEntry.Url = BASE_URL + "/" + QUALIFIER + "/" + newEntry.Id
		qualSlice[index] = newEntry
		index += 1
	}

	////////////////
	log.Println("\tLoading Descriptor MeSH XML from file: ", *DESCRIPTOR_XML_FILE)
	descMap, err = gomesh.DescriptorMapFromFile(*DESCRIPTOR_XML_FILE)
	if err != nil {
		return err
	}
	log.Println("\tBuilding name map")
	_ = gomesh.MeshDescriptorNameMap(descMap)

	descSlice = make([]*gomesh.IdEntry, len(descMap))
	index = 0
	descMap2 = make(map[string]*LocalDesc)

	for _, desc := range descMap {
		newEntry := new(gomesh.IdEntry)
		descriptorRecord := desc
		var localDesc = (*LocalDesc)(descriptorRecord)
		localDesc.setDescUrls(BASE_URL)
		localDesc.setTreeNumberUrls(BASE_URL)
		localDesc.setQualifierUrls(BASE_URL)

		descMap2[desc.DescriptorUI] = localDesc
		newEntry.Id = desc.DescriptorUI
		newEntry.Url = BASE_URL + "/" + DESCRIPTOR + "/" + newEntry.Id
		descSlice[index] = newEntry
		index += 1
	}

	sort.Sort(ById(descSlice))
	sort.Sort(ById(qualSlice))
	sort.Sort(ById(suppSlice))
	sort.Sort(ById(pharmSlice))

	root = gomesh.MakeTree(descMap)
	root.Traverse(0, AddUrlInfo)
	sort.Sort(ByIdX(root.Children))

	log.Println("Done Loading MeSH XML...")

	allNouns = make([]gomesh.IdEntry, len(NOUNS))
	for i, noun := range NOUNS {
		allNouns[i].Id = "/" + noun
		allNouns[i].Url = BASE_URL + "/" + noun
	}

	descMap = nil
	return nil
}

func AddUrlInfo(node *gomesh.Node) {
	//fmt.Println("AddUrlInfo", node.TreeNumber)
	treeMap[node.TreeNumber] = node
	if node.Children == nil {
		node.Children = make([]gomesh.IdEntry, len(node.ChildrenMap))
		if node.Descriptor != nil {
			node.DescriptorUrl = BASE_URL + "/" + DESCRIPTOR + "/" + node.Descriptor.DescriptorUI
		}
	}
	i := 0
	for _, childNode := range node.ChildrenMap {
		node.Children[i].Id = childNode.TreeNumber
		node.Children[i].Url = BASE_URL + "/" + TREE + "/" + childNode.TreeNumber
		node.Children[i].Label = childNode.Name
		i++
	}
}

//sort slices

type ByIdX []gomesh.IdEntry

type ById []*gomesh.IdEntry

func (a ById) Len() int            { return len(a) }
func (a ByIdX) Len() int           { return len(a) }
func (a ById) Swap(i, j int)       { a[i], a[j] = a[j], a[i] }
func (a ByIdX) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ById) Less(i, j int) bool  { return a[i].Id < a[j].Id }
func (a ByIdX) Less(i, j int) bool { return a[i].Id < a[j].Id }
<commit_msg>Cleaned up<commit_after>package main

import (
	"github.com/gnewton/gomesh"
	"log"
	"sort"
	"strings"
)

const DESCRIPTOR = "descriptor"
const QUALIFIER = "qualifier"
const SUPPLEMENTAL = "supplemental"
const PHARMACOLOGICAL = "pharmacological"
const TREE = "tree"

var NOUNS = []string{
	DESCRIPTOR,
	QUALIFIER,
	SUPPLEMENTAL,
	TREE,
	PHARMACOLOGICAL,
}
var allNouns []gomesh.IdEntry

var descMap map[string]*gomesh.DescriptorRecord
var descMap2 map[string]*LocalDesc
var descSlice []*gomesh.IdEntry

var suppMap map[string]*gomesh.SupplementalRecord
var suppSlice []*gomesh.IdEntry

var qualMap map[string]*gomesh.QualifierRecord
var qualSlice []*gomesh.IdEntry

var pharmMap map[string]*gomesh.PharmacologicalAction
var pharmSlice []*gomesh.IdEntry

var root *gomesh.Node
var treeMap map[string]*gomesh.Node

type LocalDesc gomesh.DescriptorRecord

type Paging struct {
	Limit            int    `json:"limit"`
	Offset           int    `json:"offset"`
	Count            int    `json:"count"`
	NextPageUrl      string `json:"nextPageUrl,omitempty"`
	PrevioustPageUrl string `json:"previousPageUrl,omitempty"`
}

func (desc *LocalDesc) setQualifierUrls(baseUrl string) {
	if desc.AllowableQualifiersList.AllowableQualifier != nil {
		for i := 0; i < len(desc.AllowableQualifiersList.AllowableQualifier); i++ {
			qualifierReferredTo := desc.AllowableQualifiersList.AllowableQualifier[i].QualifierReferredTo
			qualifierReferredTo.Url = baseUrl + "/" + QUALIFIER + "/" + qualifierReferredTo.QualifierUI
		}
	}
}

func (desc *LocalDesc) setTreeNumberUrls(baseUrl string) {
	if desc.TreeNumberList.TreeNumber != nil {
		for i := 0; i < len(desc.TreeNumberList.TreeNumber); i++ {
			tn := &(desc.TreeNumberList.TreeNumber[i])
			tn.Url = baseUrl + "/" + TREE + "/" + tn.TreeNumber
		}
	}
}

func (desc *LocalDesc) setDescUrls(baseUrl string) {
	if desc.PharmacologicalActionList.PharmacologicalAction != nil {
		for i := 0; i < len(desc.PharmacologicalActionList.PharmacologicalAction); i++ {
			ref := &(desc.PharmacologicalActionList.PharmacologicalAction[i])
			ref.DescriptorReferredTo.Url = baseUrl + "/" + DESCRIPTOR + "/" + ref.DescriptorReferredTo.DescriptorUI
		}
	}

	if desc.SeeRelatedList.SeeRelatedDescriptor != nil {
		for i := 0; i < len(desc.SeeRelatedList.SeeRelatedDescriptor); i++ {
			ref := &(desc.SeeRelatedList.SeeRelatedDescriptor[i])
			ref.DescriptorReferredTo.Url = baseUrl + "/" + DESCRIPTOR + "/" + ref.DescriptorReferredTo.DescriptorUI
		}
	}
}

func loadData() error {
	treeMap = make(map[string]*gomesh.Node)
	var err error
	log.Println("Start Loading MeSH XML...")

	////////////////
	log.Println("\tLoading Supplemental MeSH XML from file: ", *SUPPLEMENTAL_XML_FILE)
	suppMap, err = gomesh.SupplementalMapFromFile(*SUPPLEMENTAL_XML_FILE)
	if err != nil {
		return err
	}
	index := 0
	suppSlice = make([]*gomesh.IdEntry, len(suppMap))
	for _, supp := range suppMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = supp.SupplementalRecordUI
		newEntry.Url = BASE_URL + "/" + SUPPLEMENTAL + "/" + newEntry.Id
		//newEntry.Url = SUPPLEMENTAL + "/" + newEntry.Id
		suppSlice[index] = newEntry
		index += 1

		for i := 0; i < len(supp.HeadingMappedToList.HeadingMappedTo); i++ {
			descriptorReferredTo := supp.HeadingMappedToList.HeadingMappedTo[i].DescriptorReferredTo
			descriptorReferredTo.Url = BASE_URL + "/" + DESCRIPTOR + "/" + strings.TrimLeft(descriptorReferredTo.DescriptorUI, "*")
		}
	}

	////////////////
	log.Println("\tLoading Pharmacological Action MeSH XML from file: ", *PHARMACOLOGICAL_XML_FILE)
	pharmMap, err = gomesh.PharmacologicalMapFromFile(*PHARMACOLOGICAL_XML_FILE)
	if err != nil {
		return err
	}
	index = 0
	pharmSlice = make([]*gomesh.IdEntry, len(pharmMap))
	for pharm := range pharmMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = pharmMap[pharm].DescriptorReferredTo.DescriptorUI
		newEntry.Url = BASE_URL + "/" + PHARMACOLOGICAL + "/" + newEntry.Id
		pharmSlice[index] = newEntry
		index += 1

		pharmMap[pharm].DescriptorReferredTo.Url = BASE_URL + "/" + DESCRIPTOR + "/" + pharm
		//if pharmMap[pharm].PharmacologicalActionSubstanceList.Substance != nil
		{
			for i := 0; i < len(pharmMap[pharm].PharmacologicalActionSubstanceList.Substance); i++ {
				//for _, substance := range pharmMap[pharm].PharmacologicalActionSubstanceList.Substance{
				substance := &pharmMap[pharm].PharmacologicalActionSubstanceList.Substance[i]
				if strings.Index(substance.RecordUI, "C") == 0 {
					substance.SupplementalUrl = BASE_URL + "/" + SUPPLEMENTAL + "/" + substance.RecordUI
				} else {
					substance.DescriptorUrl = BASE_URL + "/" + DESCRIPTOR + "/" + substance.RecordUI

				}
			}
		}
	}

	////////////////
	log.Println("\tLoading Qualifier MeSH XML from file:", *QUALIFIER_XML_FILE)
	qualMap, err = gomesh.QualifierMapFromFile(*QUALIFIER_XML_FILE)
	if err != nil {
		return err
	}
	qualSlice = make([]*gomesh.IdEntry, len(qualMap))
	index = 0
	for _, qual := range qualMap {
		newEntry := new(gomesh.IdEntry)
		newEntry.Id = qual.QualifierUI
		newEntry.Url = BASE_URL + "/" + QUALIFIER + "/" + newEntry.Id
		qualSlice[index] = newEntry
		index += 1
	}

	////////////////
	log.Println("\tLoading Descriptor MeSH XML from file: ", *DESCRIPTOR_XML_FILE)
	descMap, err = gomesh.DescriptorMapFromFile(*DESCRIPTOR_XML_FILE)
	if err != nil {
		return err
	}
	log.Println("\tBuilding name map")
	_ = gomesh.MeshDescriptorNameMap(descMap)

	descSlice = make([]*gomesh.IdEntry, len(descMap))
	index = 0
	descMap2 = make(map[string]*LocalDesc)

	for _, desc := range descMap {
		newEntry := new(gomesh.IdEntry)
		descriptorRecord := desc
		var localDesc = (*LocalDesc)(descriptorRecord)
		localDesc.setDescUrls(BASE_URL)
		localDesc.setTreeNumberUrls(BASE_URL)
		localDesc.setQualifierUrls(BASE_URL)

		descMap2[desc.DescriptorUI] = localDesc
		newEntry.Id = desc.DescriptorUI
		newEntry.Url = BASE_URL + "/" + DESCRIPTOR + "/" + newEntry.Id
		descSlice[index] = newEntry
		index += 1
	}

	sort.Sort(ById(descSlice))
	sort.Sort(ById(qualSlice))
	sort.Sort(ById(suppSlice))
	sort.Sort(ById(pharmSlice))

	root = gomesh.MakeTree(descMap)
	root.Traverse(0, AddUrlInfo)
	sort.Sort(ByIdX(root.Children))

	log.Println("Done Loading MeSH XML...")

	allNouns = make([]gomesh.IdEntry, len(NOUNS))
	for i, noun := range NOUNS {
		allNouns[i].Id = "/" + noun
		allNouns[i].Url = BASE_URL + "/" + noun
	}

	descMap = nil
	return nil
}

func AddUrlInfo(node *gomesh.Node) {
	//fmt.Println("AddUrlInfo", node.TreeNumber)
	treeMap[node.TreeNumber] = node
	if node.Children == nil {
		node.Children = make([]gomesh.IdEntry, len(node.ChildrenMap))
		if node.Descriptor != nil {
			node.DescriptorUrl = BASE_URL + "/" + DESCRIPTOR + "/" + node.Descriptor.DescriptorUI
		}
	}
	i := 0
	for _, childNode := range node.ChildrenMap {
		node.Children[i].Id = childNode.TreeNumber
		node.Children[i].Url = BASE_URL + "/" + TREE + "/" + childNode.TreeNumber
		node.Children[i].Label = childNode.Name
		i++
	}
}

//sort slices

type ByIdX []gomesh.IdEntry

type ById []*gomesh.IdEntry

func (a ById) Len() int            { return len(a) }
func (a ByIdX) Len() int           { return len(a) }
func (a ById) Swap(i, j int)       { a[i], a[j] = a[j], a[i] }
func (a ByIdX) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ById) Less(i, j int) bool  { return a[i].Id < a[j].Id }
func (a ByIdX) Less(i, j int) bool { return a[i].Id < a[j].Id }
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

var (
	parseSizeRegex *regexp.Regexp
)

// Utility method to determine if a file/dir exists
func FileOrDirExists(path string) (exists bool, isDir bool) {
	fi, err := os.Stat(path)
	if err != nil {
		return false, false
	} else {
		return true, fi.IsDir()
	}
}

// Utility method to determine if a file/dir exists and is of a specific size
func FileExistsAndIsOfSize(path string, sz int64) bool {
	fi, err := os.Stat(path)

	if err != nil && os.IsNotExist(err) {
		return false
	}

	return fi.Size() == sz
}

// Parse a string representing a size into a number of bytes
// supports m/mb = megabytes, g/gb = gigabytes etc (case insensitive)
func ParseSize(str string) (int64, error) {
	if parseSizeRegex == nil {
		parseSizeRegex = regexp.MustCompile(`(?i)^\s*([\d\.]+)\s*([KMGTP]?B?)\s*$`)
	}

	if match := parseSizeRegex.FindStringSubmatch(str); match != nil {
		value, err := strconv.ParseFloat(match[1], 32)
		if err != nil {
			return 0, err
		}
		strUnits := strings.ToUpper(match[2])
		switch strUnits {
		case "KB", "K":
			return int64(value * (1 << 10)), nil
		case "MB", "M":
			return int64(value * (1 << 20)), nil
		case "GB", "G":
			return int64(value * (1 << 30)), nil
		case "TB", "T":
			return int64(value * (1 << 40)), nil
		case "PB", "P":
			return int64(value * (1 << 50)), nil
		default:
			return int64(value), nil

		}

	} else {
		return 0, errors.New(fmt.Sprintf("Invalid size: %v", str))
	}

}

// Format a number of bytes into a display format
func FormatSize(sz int64) string {

	switch {
	case sz >= (1 << 50):
		return fmt.Sprintf("%.3gPB", float32(sz)/float32(1<<50))
	case sz >= (1 << 40):
		return fmt.Sprintf("%.3gTB", float32(sz)/float32(1<<40))
	case sz >= (1 << 30):
		return fmt.Sprintf("%.3gGB", float32(sz)/float32(1<<30))
	case sz >= (1 << 20):
		return fmt.Sprintf("%.3gMB", float32(sz)/float32(1<<20))
	case sz >= (1 << 10):
		return fmt.Sprintf("%.3gKB", float32(sz)/float32(1<<10))
	default:
		return fmt.Sprintf("%d", sz)
	}
}

// Search a sorted slice of strings for a specific string
// Returns boolean for if found, and either location or insertion point
func StringBinarySearch(sortedSlice []string, searchTerm string) (bool, int) {
	// Convenience method to easily provide boolean of whether to insert or not
	idx := sort.SearchStrings(sortedSlice, searchTerm)
	found := idx < len(sortedSlice) && sortedSlice[idx] == searchTerm
	return found, idx
}
<commit_msg>Split utility function for FileExists and DirExists for convenience & brevity<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

var (
	parseSizeRegex *regexp.Regexp
)

// Utility method to determine if a file/dir exists
func FileOrDirExists(path string) (exists bool, isDir bool) {
	fi, err := os.Stat(path)
	if err != nil {
		return false, false
	} else {
		return true, fi.IsDir()
	}
}

// Utility method to determine if a file (NOT dir) exists
func FileExists(path string) bool {
	ret, isDir := FileOrDirExists(path)
	return ret && !isDir
}

// Utility method to determine if a dir (NOT file) exists
func DirExists(path string) bool {
	ret, isDir := FileOrDirExists(path)
	return ret && isDir
}

// Utility method to determine if a file/dir exists and is of a specific size
func FileExistsAndIsOfSize(path string, sz int64) bool {
	fi, err := os.Stat(path)

	if err != nil && os.IsNotExist(err) {
		return false
	}

	return fi.Size() == sz
}

// Parse a string representing a size into a number of bytes
// supports m/mb = megabytes, g/gb = gigabytes etc (case insensitive)
func ParseSize(str string) (int64, error) {
	if parseSizeRegex == nil {
		parseSizeRegex = regexp.MustCompile(`(?i)^\s*([\d\.]+)\s*([KMGTP]?B?)\s*$`)
	}

	if match := parseSizeRegex.FindStringSubmatch(str); match != nil {
		value, err := strconv.ParseFloat(match[1], 32)
		if err != nil {
			return 0, err
		}
		strUnits := strings.ToUpper(match[2])
		switch strUnits {
		case "KB", "K":
			return int64(value * (1 << 10)), nil
		case "MB", "M":
			return int64(value * (1 << 20)), nil
		case "GB", "G":
			return int64(value * (1 << 30)), nil
		case "TB", "T":
			return int64(value * (1 << 40)), nil
		case "PB", "P":
			return int64(value * (1 << 50)), nil
		default:
			return int64(value), nil

		}

	} else {
		return 0, errors.New(fmt.Sprintf("Invalid size: %v", str))
	}

}

// Format a number of bytes into a display format
func FormatSize(sz int64) string {

	switch {
	case sz >= (1 << 50):
		return fmt.Sprintf("%.3gPB", float32(sz)/float32(1<<50))
	case sz >= (1 << 40):
		return fmt.Sprintf("%.3gTB", float32(sz)/float32(1<<40))
	case sz >= (1 << 30):
		return fmt.Sprintf("%.3gGB", float32(sz)/float32(1<<30))
	case sz >= (1 << 20):
		return fmt.Sprintf("%.3gMB", float32(sz)/float32(1<<20))
	case sz >= (1 << 10):
		return fmt.Sprintf("%.3gKB", float32(sz)/float32(1<<10))
	default:
		return fmt.Sprintf("%d", sz)
	}
}

// Search a sorted slice of strings for a specific string
// Returns boolean for if found, and either location or insertion point
func StringBinarySearch(sortedSlice []string, searchTerm string) (bool, int) {
	// Convenience method to easily provide boolean of whether to insert or not
	idx := sort.SearchStrings(sortedSlice, searchTerm)
	found := idx < len(sortedSlice) && sortedSlice[idx] == searchTerm
	return found, idx
}
<|endoftext|>


<commit_before>package stats

import (
	"time"

	"github.com/gempir/go-twitch-irc/v2"
	"github.com/gempir/spamchamp/bot/api"
	"github.com/paulbellamy/ratecounter"
	log "github.com/sirupsen/logrus"
)

var (
	stats          = map[string]stat{}
	activeChannels = map[string]bool{}
)

type Broadcaster struct {
	messageQueue   chan twitch.PrivateMessage
	broadcastQueue chan api.BroadcastMessage
}

func NewBroadcaster(messageQueue chan twitch.PrivateMessage, broadcastQueue chan api.BroadcastMessage) Broadcaster {
	return Broadcaster{
		messageQueue:   messageQueue,
		broadcastQueue: broadcastQueue,
	}
}

func (b *Broadcaster) Start() {
	log.Info("[stats] starting stats collector")

	go b.startTicker()

	for message := range b.messageQueue {
		if _, ok := stats[message.RoomID]; !ok {
			stats[message.RoomID] = newStat(message.Channel)
		}

		stats[message.RoomID].messages.Incr(1)
	}
}

func (b *Broadcaster) startTicker() {
	ticker := time.NewTicker(1 * time.Second)

	for range ticker.C {
		message := api.BroadcastMessage{
			ChannelStats: []api.ChannelStat{},
		}

		for channelID, stat := range stats {
			rate := stat.messages.Rate() / 5
			if rate == 0 {
				continue
			}
			activeChannels[channelID] = true

			message.ChannelStats = append(message.ChannelStats, api.ChannelStat{
				ID:    channelID,
				Msgps: rate,
			})
		}

		message.ActiveChannels = len(activeChannels)

		if len(stats) > 0 {
			b.broadcastQueue <- message
		}
	}
}

type stat struct {
	channelName  string
	messages     *ratecounter.RateCounter
	messageCount int
}

func newStat(channelName string) stat {
	return stat{
		channelName: channelName,
		messages:    ratecounter.NewRateCounter(time.Second * 5),
	}
}
<commit_msg>average over 3 secs<commit_after>package stats

import (
	"time"

	"github.com/gempir/go-twitch-irc/v2"
	"github.com/gempir/spamchamp/bot/api"
	"github.com/paulbellamy/ratecounter"
	log "github.com/sirupsen/logrus"
)

var (
	stats          = map[string]stat{}
	activeChannels = map[string]bool{}
)

type Broadcaster struct {
	messageQueue   chan twitch.PrivateMessage
	broadcastQueue chan api.BroadcastMessage
}

func NewBroadcaster(messageQueue chan twitch.PrivateMessage, broadcastQueue chan api.BroadcastMessage) Broadcaster {
	return Broadcaster{
		messageQueue:   messageQueue,
		broadcastQueue: broadcastQueue,
	}
}

func (b *Broadcaster) Start() {
	log.Info("[stats] starting stats collector")

	go b.startTicker()

	for message := range b.messageQueue {
		if _, ok := stats[message.RoomID]; !ok {
			stats[message.RoomID] = newStat(message.Channel)
		}

		stats[message.RoomID].messages.Incr(1)
	}
}

func (b *Broadcaster) startTicker() {
	ticker := time.NewTicker(1 * time.Second)

	for range ticker.C {
		message := api.BroadcastMessage{
			ChannelStats: []api.ChannelStat{},
		}

		for channelID, stat := range stats {
			rate := stat.messages.Rate() / 3
			if rate == 0 {
				continue
			}
			activeChannels[channelID] = true

			message.ChannelStats = append(message.ChannelStats, api.ChannelStat{
				ID:    channelID,
				Msgps: rate,
			})
		}

		message.ActiveChannels = len(activeChannels)

		if len(stats) > 0 {
			b.broadcastQueue <- message
		}
	}
}

type stat struct {
	channelName  string
	messages     *ratecounter.RateCounter
	messageCount int
}

func newStat(channelName string) stat {
	return stat{
		channelName: channelName,
		messages:    ratecounter.NewRateCounter(time.Second * 3),
	}
}
<|endoftext|>


<commit_before>package filter
import (
	"encoding/json"
	"strings"
)

type FilterConfig struct {
	Ignore []string `json:"ignore"`
}

func GetFilterConfig(fileName string) (FilterConfig, error) {
	/* Takes a json file name as a string. Reads the file, unmarshals json.
	Returns the unmarshalled FilterConfig object
	See configurator.ReadConfig for an example
	In detail:
	1. Read all of the file with ioutil.ReadFile
	2. Instantiate an empty config object.
	3. Unmarshal the byte array which is the file's contents as json into the
	new config object using jsom.Unmarshal.
	4. Return the config object.
	If there is an error, return it.
	*/
	// Dummy implementation for testing. Remove later
	newFilterConf := FilterConfig{Ignore: []string{"/dev/"}}
	return newFilterConf, nil
}

type Filter interface {
	Start(c FilterConfig, sending chan<- []byte, receiving <-chan []byte)
}

type FSFilter struct { }

type NOP struct { }

type ZachsInotifyData struct {
	Date	 string `json:"DATE"`
	Event	 string `json:"EVENT"`
	FilePath string `json:"PATH"`
	Type	 string `json:"TYPE"`
}

func StartFilterStream(sending chan<- []byte, receiving <-chan []byte) {
	fsFilter := FSFilter{}
	nopFilter := NOP{}
	conf := FilterConfig{Ignore: []string{"/dev/"}}
	link := make(chan []byte)
	go fsFilter.Start(conf, link, receiving)
	go nopFilter.Start(conf, sending, link)
}

func (f FSFilter) Start (c FilterConfig, sending chan<- []byte, receiving <-chan []byte){
	for {
		message := <-receiving
		zid := ZachsInotifyData{}
		err := json.Unmarshal(message, &zid)
		if err != nil {
			panic(err)
		}
		notblacklisted := true
		for _, i := range c.Ignore {
			if strings.HasPrefix(zid.FilePath,i) {
				notblacklisted = false
				break
			}
		}
		if notblacklisted {
			sending <- message
		}
	}

}

func (N NOP) Start( c FilterConfig, sending chan<- []byte, receiving <-chan []byte){
	for {
		message := <- receiving
		sending <- message
	}

}
<commit_msg>Refactor nop filter struct name<commit_after>package filter
import (
	"encoding/json"
	"strings"
)

type FilterConfig struct {
	Ignore []string `json:"ignore"`
}

func GetFilterConfig(fileName string) (FilterConfig, error) {
	/* Takes a json file name as a string. Reads the file, unmarshals json.
	Returns the unmarshalled FilterConfig object
	See configurator.ReadConfig for an example
	In detail:
	1. Read all of the file with ioutil.ReadFile
	2. Instantiate an empty config object.
	3. Unmarshal the byte array which is the file's contents as json into the
	new config object using jsom.Unmarshal.
	4. Return the config object.
	If there is an error, return it.
	*/
	// Dummy implementation for testing. Remove later
	newFilterConf := FilterConfig{Ignore: []string{"/dev/"}}
	return newFilterConf, nil
}

type Filter interface {
	Start(c FilterConfig, sending chan<- []byte, receiving <-chan []byte)
}

type FSFilter struct { }

type NOPFilter struct { }

type ZachsInotifyData struct {
	Date	 string `json:"DATE"`
	Event	 string `json:"EVENT"`
	FilePath string `json:"PATH"`
	Type	 string `json:"TYPE"`
}

func StartFilterStream(sending chan<- []byte, receiving <-chan []byte) {
	fsFilter := FSFilter{}
	nopFilter := NOPFilter{}
	conf := FilterConfig{Ignore: []string{"/dev/"}}
	link := make(chan []byte)
	go fsFilter.Start(conf, link, receiving)
	go nopFilter.Start(conf, sending, link)
}

func (f FSFilter) Start (c FilterConfig, sending chan<- []byte, receiving <-chan []byte){
	for {
		message := <-receiving
		zid := ZachsInotifyData{}
		err := json.Unmarshal(message, &zid)
		if err != nil {
			panic(err)
		}
		notblacklisted := true
		for _, i := range c.Ignore {
			if strings.HasPrefix(zid.FilePath,i) {
				notblacklisted = false
				break
			}
		}
		if notblacklisted {
			sending <- message
		}
	}

}

func (N NOPFilter) Start( c FilterConfig, sending chan<- []byte, receiving <-chan []byte){
	for {
		message := <- receiving
		sending <- message
	}

}
<|endoftext|>


<commit_before>// Copyright 2016 conntrack-prometheus authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"log"
	"regexp"
	"strings"
	"sync"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/prometheus/client_golang/prometheus"
)

var additionalLabels = []string{"state", "protocol", "destination"}

type ConntrackCollector struct {
	containerLister func() ([]*docker.Container, error)
	conntrack       func() ([]conn, error)
	sync.Mutex
	connCount  map[string]map[string]int
	containers map[string]*docker.Container
}

func (c *ConntrackCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- prometheus.NewDesc("container_connections", "Number of outbound connections by destionation and state", []string{"id", "name"}, nil)
}

func (c *ConntrackCollector) Collect(ch chan<- prometheus.Metric) {
	counts, currContainers := c.getState()
	containers, err := c.containerLister()
	if err != nil {
		log.Print(err)
		return
	}
	conns, err := c.conntrack()
	if err != nil {
		log.Print(err)
		return
	}
	for _, container := range containers {
		for _, conn := range conns {
			value := ""
			switch container.NetworkSettings.IPAddress {
			case conn.SourceIP:
				value = conn.DestinationIP + ":" + conn.DestinationPort
			case conn.DestinationIP:
				value = conn.SourceIP + ":" + conn.SourcePort
			}
			if value != "" {
				key := conn.State + "-" + conn.Protocol + "-" + value
				if counts[container.ID] == nil {
					counts[container.ID] = make(map[string]int)
				}
				counts[container.ID][key] = counts[container.ID][key] + 1
			}
			currContainers[container.ID] = *container
		}
	}
	log.Print(counts)
	c.setState(counts, currContainers)
	sendMetrics(counts, currContainers, ch)
}

func (c *ConntrackCollector) getState() (map[string]map[string]int, map[string]docker.Container) {
	c.Lock()
	defer c.Unlock()
	copyCont := make(map[string]docker.Container)
	for _, cont := range c.containers {
		copyCont[cont.ID] = *cont
	}
	copy := make(map[string]map[string]int)
	for k, v := range c.connCount {
		innerCopy := make(map[string]int)
		for ik, iv := range v {
			if iv == 0 {
				continue
			}
			innerCopy[ik] = 0
		}
		if len(innerCopy) == 0 {
			delete(copyCont, k)
			continue
		}
		copy[k] = innerCopy
	}
	return copy, copyCont
}

func (c *ConntrackCollector) setState(count map[string]map[string]int, containers map[string]docker.Container) {
	c.Lock()
	defer c.Unlock()
	c.connCount = count
	for k, v := range containers {
		c.containers[k] = &v
	}
}

func sendMetrics(metrics map[string]map[string]int, containers map[string]docker.Container, ch chan<- prometheus.Metric) {
	for contID, count := range metrics {
		labelsMap := containerLabels(containers[contID])
		labels := make([]string, len(labelsMap)+len(additionalLabels))
		values := make([]string, len(labelsMap)+len(additionalLabels))
		i := 0
		for k, v := range labelsMap {
			labels[i] = sanitizeLabelName(k)
			values[i] = v
			i++
		}
		for _, l := range additionalLabels {
			labels[i] = l
			i++
		}
		i = i - len(additionalLabels)
		desc := prometheus.NewDesc("container_connections", "Number of outbound connections by destionation and state", labels, nil)
		for k, v := range count {
			keys := strings.SplitN(k, "-", 3)
			values[i] = keys[0]
			values[i+1] = keys[1]
			values[i+2] = keys[2]
			ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(v), values...)
		}
	}
}

func containerLabels(container docker.Container) map[string]string {
	labels := map[string]string{
		"id":    container.ID,
		"name":  container.Name,
		"image": container.Config.Image,
	}
	for k, v := range container.Config.Labels {
		labels["container_label_"+k] = v
	}
	return labels
}

var invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)

func sanitizeLabelName(name string) string {
	return invalidLabelCharRE.ReplaceAllString(name, "_")
}
<commit_msg>remove lost print<commit_after>// Copyright 2016 conntrack-prometheus authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"log"
	"regexp"
	"strings"
	"sync"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/prometheus/client_golang/prometheus"
)

var additionalLabels = []string{"state", "protocol", "destination"}

type ConntrackCollector struct {
	containerLister func() ([]*docker.Container, error)
	conntrack       func() ([]conn, error)
	sync.Mutex
	connCount  map[string]map[string]int
	containers map[string]*docker.Container
}

func (c *ConntrackCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- prometheus.NewDesc("container_connections", "Number of outbound connections by destionation and state", []string{"id", "name"}, nil)
}

func (c *ConntrackCollector) Collect(ch chan<- prometheus.Metric) {
	counts, currContainers := c.getState()
	containers, err := c.containerLister()
	if err != nil {
		log.Print(err)
		return
	}
	conns, err := c.conntrack()
	if err != nil {
		log.Print(err)
		return
	}
	for _, container := range containers {
		for _, conn := range conns {
			value := ""
			switch container.NetworkSettings.IPAddress {
			case conn.SourceIP:
				value = conn.DestinationIP + ":" + conn.DestinationPort
			case conn.DestinationIP:
				value = conn.SourceIP + ":" + conn.SourcePort
			}
			if value != "" {
				key := conn.State + "-" + conn.Protocol + "-" + value
				if counts[container.ID] == nil {
					counts[container.ID] = make(map[string]int)
				}
				counts[container.ID][key] = counts[container.ID][key] + 1
			}
			currContainers[container.ID] = *container
		}
	}
	c.setState(counts, currContainers)
	sendMetrics(counts, currContainers, ch)
}

func (c *ConntrackCollector) getState() (map[string]map[string]int, map[string]docker.Container) {
	c.Lock()
	defer c.Unlock()
	copyCont := make(map[string]docker.Container)
	for _, cont := range c.containers {
		copyCont[cont.ID] = *cont
	}
	copy := make(map[string]map[string]int)
	for k, v := range c.connCount {
		innerCopy := make(map[string]int)
		for ik, iv := range v {
			if iv == 0 {
				continue
			}
			innerCopy[ik] = 0
		}
		if len(innerCopy) == 0 {
			delete(copyCont, k)
			continue
		}
		copy[k] = innerCopy
	}
	return copy, copyCont
}

func (c *ConntrackCollector) setState(count map[string]map[string]int, containers map[string]docker.Container) {
	c.Lock()
	defer c.Unlock()
	c.connCount = count
	for k, v := range containers {
		c.containers[k] = &v
	}
}

func sendMetrics(metrics map[string]map[string]int, containers map[string]docker.Container, ch chan<- prometheus.Metric) {
	for contID, count := range metrics {
		labelsMap := containerLabels(containers[contID])
		labels := make([]string, len(labelsMap)+len(additionalLabels))
		values := make([]string, len(labelsMap)+len(additionalLabels))
		i := 0
		for k, v := range labelsMap {
			labels[i] = sanitizeLabelName(k)
			values[i] = v
			i++
		}
		for _, l := range additionalLabels {
			labels[i] = l
			i++
		}
		i = i - len(additionalLabels)
		desc := prometheus.NewDesc("container_connections", "Number of outbound connections by destionation and state", labels, nil)
		for k, v := range count {
			keys := strings.SplitN(k, "-", 3)
			values[i] = keys[0]
			values[i+1] = keys[1]
			values[i+2] = keys[2]
			ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(v), values...)
		}
	}
}

func containerLabels(container docker.Container) map[string]string {
	labels := map[string]string{
		"id":    container.ID,
		"name":  container.Name,
		"image": container.Config.Image,
	}
	for k, v := range container.Config.Labels {
		labels["container_label_"+k] = v
	}
	return labels
}

var invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)

func sanitizeLabelName(name string) string {
	return invalidLabelCharRE.ReplaceAllString(name, "_")
}
<|endoftext|>


<commit_before>// +build experimental

package client

import (
	"fmt"

	"github.com/docker/docker/api/types"
	Cli "github.com/docker/docker/cli"
	flag "github.com/docker/docker/pkg/mflag"
)

// CmdCheckpoint checkpoints the process running in a container
//
// Usage: docker checkpoint CONTAINER
func (cli *DockerCli) CmdCheckpoint(args ...string) error {
	cmd := Cli.Subcmd("checkpoint", []string{"CONTAINER"}, Cli.DockerCommands["checkpoint"].Description, true)
	cmd.Require(flag.Min, 1)

	var (
		flImgDir       = cmd.String([]string{"-image-dir"}, "", "directory for storing checkpoint image files")
		flWorkDir      = cmd.String([]string{"-work-dir"}, "", "directory for storing log file")
		flLeaveRunning = cmd.Bool([]string{"-leave-running"}, false, "leave the container running after checkpoint")
	)

	if err := cmd.ParseFlags(args, true); err != nil {
		return err
	}

	if cmd.NArg() < 1 {
		cmd.Usage()
		return nil
	}

	criuOpts := types.CriuConfig{
		ImagesDirectory: *flImgDir,
		WorkDirectory:   *flWorkDir,
		LeaveRunning:    *flLeaveRunning,
	}

	var encounteredError error
	for _, name := range cmd.Args() {
		err := cli.client.ContainerCheckpoint(name, criuOpts)
		if err != nil {
			fmt.Fprintf(cli.err, "%s\n", err)
			encounteredError = fmt.Errorf("Error: failed to checkpoint one or more containers")
		} else {
			fmt.Fprintf(cli.out, "%s\n", name)
		}
	}
	return encounteredError
}
<commit_msg>pre-dump in docker<commit_after>// +build experimental
// ./docker/api/client/checkpoint.go     //peter
package client

import (
	"fmt"

	"github.com/docker/docker/api/types"
	Cli "github.com/docker/docker/cli"
	flag "github.com/docker/docker/pkg/mflag"
)

// CmdCheckpoint checkpoints the process running in a container
//
// Usage: docker checkpoint CONTAINER
func (cli *DockerCli) CmdCheckpoint(args ...string) error {
	cmd := Cli.Subcmd("checkpoint", []string{"CONTAINER"}, Cli.DockerCommands["checkpoint"].Description, true)
	cmd.Require(flag.Min, 1)

	var (
		flImgDir       = cmd.String([]string{"-image-dir"}, "", "directory for storing checkpoint image files")
		flWorkDir      = cmd.String([]string{"-work-dir"}, "", "directory for storing log file")
		flLeaveRunning = cmd.Bool([]string{"-leave-running"}, false, "leave the container running after checkpoint")
                flPrevImgDir      = cmd.String([]string{"-prev-image-dir"}, "", "previous Image directory")  //peter
		flTrackMem = cmd.Bool([]string{"-track-mem"}, false, "track memory flag")   // peter
                flEnablePreDump = cmd.Bool([]string{"-predump"}, false, "predump flag")   // peter
                flAutoDedup = cmd.Bool([]string{"-auto-dedup"}, false, "auto-dedup flag")   // peter
	)

	if err := cmd.ParseFlags(args, true); err != nil {
		return err
	}

	if cmd.NArg() < 1 {
		cmd.Usage()
		return nil
	}

	criuOpts := types.CriuConfig{
		ImagesDirectory: *flImgDir,
		WorkDirectory:   *flWorkDir,
		LeaveRunning:    *flLeaveRunning,
                PrevImagesDirectory:  *flPrevImgDir,  //peter
                TrackMemory:  *flTrackMem,  //peter
                EnablePreDump:  *flEnablePreDump, //peter
                AutoDedup:      *flAutoDedup,     //peter
	}

	var encounteredError error
	for _, name := range cmd.Args() {
		err := cli.client.ContainerCheckpoint(name, criuOpts)
		if err != nil {
			fmt.Fprintf(cli.err, "%s\n", err)
			encounteredError = fmt.Errorf("Error: failed to checkpoint one or more containers")
		} else {
			fmt.Fprintf(cli.out, "%s\n", name)
		}
	}
	return encounteredError
}
<|endoftext|>


<commit_before>package handler

import (
	"context"
	"encoding/base64"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
)

// Base64ToWave converts audio encoded in base64 into wave.
func Base64ToWave(ctx context.Context, content string) ([]byte, error) {
	audio, err := base64.StdEncoding.DecodeString(content)
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusBadRequest,
			"invalid encoded audio",
			"failed to decode base64: %w", err)
	}

	dir, err := ioutil.TempDir("", "clouddemo")
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to create tempdir: %w", err)
	}
	defer os.RemoveAll(dir)

	srcFile := filepath.Join(dir, "src.ogg")
	dstFile := filepath.Join(dir, "dst.wav")

	if err := ioutil.WriteFile(srcFile, audio, 0644); err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to write file: %s: %w", srcFile, err)
	}

	if err := exec.Command("ffmpeg", "-i", srcFile, dstFile).Run(); err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to exec ffmpeg: %w", err)
	}

	wav, err := ioutil.ReadFile(dstFile)
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to read wav file: %s: %w", dstFile, err)
	}

	return wav, nil
}
<commit_msg>[api] Reduce permissions for tmpfile<commit_after>package handler

import (
	"context"
	"encoding/base64"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
)

// Base64ToWave converts audio encoded in base64 into wave.
func Base64ToWave(ctx context.Context, content string) ([]byte, error) {
	audio, err := base64.StdEncoding.DecodeString(content)
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusBadRequest,
			"invalid encoded audio",
			"failed to decode base64: %w", err)
	}

	dir, err := ioutil.TempDir("", "clouddemo")
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to create tempdir: %w", err)
	}
	defer os.RemoveAll(dir)

	srcFile := filepath.Join(dir, "src.ogg")
	dstFile := filepath.Join(dir, "dst.wav")

	if err := ioutil.WriteFile(srcFile, audio, 0600); err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to write file: %s: %w", srcFile, err)
	}

	if err := exec.Command("ffmpeg", "-i", srcFile, dstFile).Run(); err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to exec ffmpeg: %w", err)
	}

	wav, err := ioutil.ReadFile(dstFile)
	if err != nil {
		return nil, Errorf(ctx,
			http.StatusInternalServerError,
			http.StatusText(http.StatusInternalServerError),
			"failed to read wav file: %s: %w", dstFile, err)
	}

	return wav, nil
}
<|endoftext|>


<commit_before>package lxc

import (
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"fmt"
	"time"
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	TemplateConfig      `mapstructure:",squash"`
	ConfigFile          string            `mapstructure:"config_file"`
	OutputDir           string            `mapstructure:"output_directory"`
	ContainerName       string            `mapstructure:"container_name"`
	CommandWrapper      string            `mapstructure:"command_wrapper"`
	RawInitTimeout      string            `mapstructure:"init_timeout"`
	InitTimeout         time.Duration

	tpl *packer.ConfigTemplate
}

func NewConfig(raws ...interface{}) (*Config, error) {
	c := new(Config)
	md, err := common.DecodeConfig(c, raws...)
	if err != nil {
		return nil, err
	}

	c.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return nil, err
	}
	c.tpl.UserVars = c.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)
	errs = packer.MultiErrorAppend(errs, c.TemplateConfig.Prepare(c.tpl)...)

	if c.OutputDir == "" {
		c.OutputDir = fmt.Sprintf("output-%s", c.PackerBuildName)
	}

	if c.ContainerName == "" {
		c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName)
	}

	if c.CommandWrapper == "" {
		c.CommandWrapper = "{{.Command}}"
	}

	if c.RawInitTimeout == "" {
		c.RawInitTimeout = "20s"
	}

	templates := map[string]*string{
		"config_file":      &c.ConfigFile,
		"output_directory": &c.OutputDir,
		"container_name":   &c.ContainerName,
		"command_wrapper":  &c.CommandWrapper,
		"init_timeout":     &c.RawInitTimeout,
		"template_name":    &c.Name,
		//"target_runlevel": &c.TargetRunlevel,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = c.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}
	for i, param := range c.Parameters {
		var err error
		c.Parameters[i], err = c.tpl.Process(param, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing template_parameters[%d]: %s", i, err))
		}
	}
	for i, evar := range c.EnvVars {
		var err error
		c.EnvVars[i], err = c.tpl.Process(evar, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing template_environment_vars[%d]: %s", i, err))
		}
	}

	c.InitTimeout, err = time.ParseDuration(c.RawInitTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing init_timeout: %s", err))
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, errs
	}

	return c, nil
}<commit_msg>Don't expand command_wrapper too early.<commit_after>package lxc

import (
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"fmt"
	"time"
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	TemplateConfig      `mapstructure:",squash"`
	ConfigFile          string            `mapstructure:"config_file"`
	OutputDir           string            `mapstructure:"output_directory"`
	ContainerName       string            `mapstructure:"container_name"`
	CommandWrapper      string            `mapstructure:"command_wrapper"`
	RawInitTimeout      string            `mapstructure:"init_timeout"`
	InitTimeout         time.Duration

	tpl *packer.ConfigTemplate
}

func NewConfig(raws ...interface{}) (*Config, error) {
	c := new(Config)
	md, err := common.DecodeConfig(c, raws...)
	if err != nil {
		return nil, err
	}

	c.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return nil, err
	}
	c.tpl.UserVars = c.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)
	errs = packer.MultiErrorAppend(errs, c.TemplateConfig.Prepare(c.tpl)...)

	if c.OutputDir == "" {
		c.OutputDir = fmt.Sprintf("output-%s", c.PackerBuildName)
	}

	if c.ContainerName == "" {
		c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName)
	}

	if c.CommandWrapper == "" {
		c.CommandWrapper = "{{.Command}}"
	}

	if c.RawInitTimeout == "" {
		c.RawInitTimeout = "20s"
	}

	templates := map[string]*string{
		"config_file":      &c.ConfigFile,
		"output_directory": &c.OutputDir,
		"container_name":   &c.ContainerName,
		//"command_wrapper":  &c.CommandWrapper, It's expanded later, when command is run.
		"init_timeout":     &c.RawInitTimeout,
		"template_name":    &c.Name,
		//"target_runlevel": &c.TargetRunlevel,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = c.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}
	for i, param := range c.Parameters {
		var err error
		c.Parameters[i], err = c.tpl.Process(param, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing template_parameters[%d]: %s", i, err))
		}
	}
	for i, evar := range c.EnvVars {
		var err error
		c.EnvVars[i], err = c.tpl.Process(evar, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing template_environment_vars[%d]: %s", i, err))
		}
	}

	c.InitTimeout, err = time.ParseDuration(c.RawInitTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing init_timeout: %s", err))
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, errs
	}

	return c, nil
}<|endoftext|>


<commit_before>package buildpacks

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"runtime"
	"strings"

	pack "github.com/buildpacks/pack/pkg/client"
	"github.com/buildpacks/pack/pkg/logging"
	"github.com/docker/docker/client"
	"github.com/heroku/color"

	fn "knative.dev/func"
	"knative.dev/func/builders"
	"knative.dev/func/docker"
)

// DefaultName when no WithName option is provided to NewBuilder
const DefaultName = builders.Pack

var (
	DefaultBuilderImages = map[string]string{
		"node":       "gcr.io/paketo-buildpacks/builder:base",
		"nodejs":     "gcr.io/paketo-buildpacks/builder:base",
		"typescript": "gcr.io/paketo-buildpacks/builder:base",
		"go":         "gcr.io/paketo-buildpacks/builder:base",
		"python":     "gcr.io/paketo-buildpacks/builder:base",
		"quarkus":    "gcr.io/paketo-buildpacks/builder:base",
		"rust":       "gcr.io/paketo-buildpacks/builder:base",
		"springboot": "gcr.io/paketo-buildpacks/builder:base",
	}

	// Ensure that all entries in this list are terminated with a trailing "/"
	// See GHSA-5336-2g3f-9g3m for details
	trustedBuilderImagePrefixes = []string{
		"quay.io/boson/",
		"gcr.io/paketo-buildpacks/",
		"docker.io/paketobuildpacks/",
		"ghcr.io/vmware-tanzu/function-buildpacks-for-knative/",
	}
)

// Builder will build Function using Pack.
type Builder struct {
	name    string
	verbose bool
	// in non-verbose mode contains std[err,out], so it can be printed on error
	outBuff bytes.Buffer
	logger  logging.Logger
	impl    Impl
}

// Impl allows for the underlying implementation to be mocked for tests.
type Impl interface {
	Build(context.Context, pack.BuildOptions) error
}

// NewBuilder instantiates a Buildpack-based Builder
func NewBuilder(options ...Option) *Builder {
	b := &Builder{name: DefaultName}
	for _, o := range options {
		o(b)
	}

	// Stream logs to stdout or buffer only for display on error.
	if b.verbose {
		b.logger = logging.NewLogWithWriters(color.Stdout(), color.Stderr(), logging.WithVerbose())
	} else {
		b.logger = logging.NewSimpleLogger(&b.outBuff)
	}

	return b
}

type Option func(*Builder)

func WithName(n string) Option {
	return func(b *Builder) {
		b.name = n
	}
}

func WithVerbose(v bool) Option {
	return func(b *Builder) {
		b.verbose = v
	}
}

func WithImpl(i Impl) Option {
	return func(b *Builder) {
		b.impl = i
	}
}

var DefaultLifecycleImage = "quay.io/boson/lifecycle@sha256:79dac4658ea5e9b42c3aece456f8a9c20f9e1a91d9d4648717967d88eaa7d9ef"

// Build the Function at path.
func (b *Builder) Build(ctx context.Context, f fn.Function) (err error) {
	// Builder image from the function if defined, default otherwise.
	image, err := BuilderImage(f, b.name)
	if err != nil {
		return
	}

	// Pack build options
	opts := pack.BuildOptions{
		AppPath:        f.Root,
		Image:          f.Image,
		LifecycleImage: DefaultLifecycleImage,
		Builder:        image,
		Buildpacks:     f.Build.Buildpacks,
		ContainerConfig: struct {
			Network string
			Volumes []string
		}{Network: "", Volumes: nil},
	}
	if opts.Env, err = fn.Interpolate(f.Build.BuildEnvs); err != nil {
		return err
	}
	if runtime.GOOS == "linux" {
		opts.ContainerConfig.Network = "host"
	}

	// only trust our known builders
	opts.TrustBuilder = TrustBuilder

	var impl = b.impl
	// Instantiate the pack build client implementation
	// (and update build opts as necessary)
	if impl == nil {
		var (
			cli        client.CommonAPIClient
			dockerHost string
		)

		cli, dockerHost, err = docker.NewClient(client.DefaultDockerHost)
		if err != nil {
			return fmt.Errorf("cannot create docker client: %w", err)
		}
		defer cli.Close()
		opts.DockerHost = dockerHost

		// Client with a logger which is enabled if in Verbose mode and a dockerClient that supports SSH docker daemon connection.
		if impl, err = pack.NewClient(pack.WithLogger(b.logger), pack.WithDockerClient(cli)); err != nil {
			return fmt.Errorf("cannot create pack client: %w", err)
		}
	}

	// Perform the build
	if err = impl.Build(ctx, opts); err != nil {
		if ctx.Err() != nil {
			return // SIGINT
		} else if !b.verbose {
			err = fmt.Errorf("failed to build the function: %w", err)
			fmt.Fprintln(color.Stderr(), "")
			_, _ = io.Copy(color.Stderr(), &b.outBuff)
			fmt.Fprintln(color.Stderr(), "")
		}
	}
	return
}

// TrustBuilder determines whether the builder image should be trusted
// based on a set of trusted builder image registry prefixes.
func TrustBuilder(b string) bool {
	for _, v := range trustedBuilderImagePrefixes {
		// Ensure that all entries in this list are terminated with a trailing "/"
		if !strings.HasSuffix(v, "/") {
			v = v + "/"
		}
		if strings.HasPrefix(b, v) {
			return true
		}
	}
	return false
}

// Builder Image chooses the correct builder image or defaults.
func BuilderImage(f fn.Function, builderName string) (string, error) {
	return builders.Image(f, builderName, DefaultBuilderImages)
}

// Errors

type ErrRuntimeRequired struct{}

func (e ErrRuntimeRequired) Error() string {
	return "Pack requires the Function define a language runtime"
}

type ErrRuntimeNotSupported struct {
	Runtime string
}

func (e ErrRuntimeNotSupported) Error() string {
	return fmt.Sprintf("Pack builder has no default builder image for the '%v' language runtime.  Please provide one.", e.Runtime)
}
<commit_msg>Add Google Cloud Function Buildpacks to trusted builder prefixes (#1438)<commit_after>package buildpacks

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"runtime"
	"strings"

	pack "github.com/buildpacks/pack/pkg/client"
	"github.com/buildpacks/pack/pkg/logging"
	"github.com/docker/docker/client"
	"github.com/heroku/color"

	fn "knative.dev/func"
	"knative.dev/func/builders"
	"knative.dev/func/docker"
)

// DefaultName when no WithName option is provided to NewBuilder
const DefaultName = builders.Pack

var (
	DefaultBuilderImages = map[string]string{
		"node":       "gcr.io/paketo-buildpacks/builder:base",
		"nodejs":     "gcr.io/paketo-buildpacks/builder:base",
		"typescript": "gcr.io/paketo-buildpacks/builder:base",
		"go":         "gcr.io/paketo-buildpacks/builder:base",
		"python":     "gcr.io/paketo-buildpacks/builder:base",
		"quarkus":    "gcr.io/paketo-buildpacks/builder:base",
		"rust":       "gcr.io/paketo-buildpacks/builder:base",
		"springboot": "gcr.io/paketo-buildpacks/builder:base",
	}

	// Ensure that all entries in this list are terminated with a trailing "/"
	// See GHSA-5336-2g3f-9g3m for details
	trustedBuilderImagePrefixes = []string{
		"quay.io/boson/",
		"gcr.io/paketo-buildpacks/",
		"docker.io/paketobuildpacks/",
		"ghcr.io/vmware-tanzu/function-buildpacks-for-knative/",
		"gcr.io/buildpacks/",
	}
)

// Builder will build Function using Pack.
type Builder struct {
	name    string
	verbose bool
	// in non-verbose mode contains std[err,out], so it can be printed on error
	outBuff bytes.Buffer
	logger  logging.Logger
	impl    Impl
}

// Impl allows for the underlying implementation to be mocked for tests.
type Impl interface {
	Build(context.Context, pack.BuildOptions) error
}

// NewBuilder instantiates a Buildpack-based Builder
func NewBuilder(options ...Option) *Builder {
	b := &Builder{name: DefaultName}
	for _, o := range options {
		o(b)
	}

	// Stream logs to stdout or buffer only for display on error.
	if b.verbose {
		b.logger = logging.NewLogWithWriters(color.Stdout(), color.Stderr(), logging.WithVerbose())
	} else {
		b.logger = logging.NewSimpleLogger(&b.outBuff)
	}

	return b
}

type Option func(*Builder)

func WithName(n string) Option {
	return func(b *Builder) {
		b.name = n
	}
}

func WithVerbose(v bool) Option {
	return func(b *Builder) {
		b.verbose = v
	}
}

func WithImpl(i Impl) Option {
	return func(b *Builder) {
		b.impl = i
	}
}

var DefaultLifecycleImage = "quay.io/boson/lifecycle@sha256:79dac4658ea5e9b42c3aece456f8a9c20f9e1a91d9d4648717967d88eaa7d9ef"

// Build the Function at path.
func (b *Builder) Build(ctx context.Context, f fn.Function) (err error) {
	// Builder image from the function if defined, default otherwise.
	image, err := BuilderImage(f, b.name)
	if err != nil {
		return
	}

	// Pack build options
	opts := pack.BuildOptions{
		AppPath:        f.Root,
		Image:          f.Image,
		LifecycleImage: DefaultLifecycleImage,
		Builder:        image,
		Buildpacks:     f.Build.Buildpacks,
		ContainerConfig: struct {
			Network string
			Volumes []string
		}{Network: "", Volumes: nil},
	}
	if opts.Env, err = fn.Interpolate(f.Build.BuildEnvs); err != nil {
		return err
	}
	if runtime.GOOS == "linux" {
		opts.ContainerConfig.Network = "host"
	}

	// only trust our known builders
	opts.TrustBuilder = TrustBuilder

	var impl = b.impl
	// Instantiate the pack build client implementation
	// (and update build opts as necessary)
	if impl == nil {
		var (
			cli        client.CommonAPIClient
			dockerHost string
		)

		cli, dockerHost, err = docker.NewClient(client.DefaultDockerHost)
		if err != nil {
			return fmt.Errorf("cannot create docker client: %w", err)
		}
		defer cli.Close()
		opts.DockerHost = dockerHost

		// Client with a logger which is enabled if in Verbose mode and a dockerClient that supports SSH docker daemon connection.
		if impl, err = pack.NewClient(pack.WithLogger(b.logger), pack.WithDockerClient(cli)); err != nil {
			return fmt.Errorf("cannot create pack client: %w", err)
		}
	}

	// Perform the build
	if err = impl.Build(ctx, opts); err != nil {
		if ctx.Err() != nil {
			return // SIGINT
		} else if !b.verbose {
			err = fmt.Errorf("failed to build the function: %w", err)
			fmt.Fprintln(color.Stderr(), "")
			_, _ = io.Copy(color.Stderr(), &b.outBuff)
			fmt.Fprintln(color.Stderr(), "")
		}
	}
	return
}

// TrustBuilder determines whether the builder image should be trusted
// based on a set of trusted builder image registry prefixes.
func TrustBuilder(b string) bool {
	for _, v := range trustedBuilderImagePrefixes {
		// Ensure that all entries in this list are terminated with a trailing "/"
		if !strings.HasSuffix(v, "/") {
			v = v + "/"
		}
		if strings.HasPrefix(b, v) {
			return true
		}
	}
	return false
}

// Builder Image chooses the correct builder image or defaults.
func BuilderImage(f fn.Function, builderName string) (string, error) {
	return builders.Image(f, builderName, DefaultBuilderImages)
}

// Errors

type ErrRuntimeRequired struct{}

func (e ErrRuntimeRequired) Error() string {
	return "Pack requires the Function define a language runtime"
}

type ErrRuntimeNotSupported struct {
	Runtime string
}

func (e ErrRuntimeNotSupported) Error() string {
	return fmt.Sprintf("Pack builder has no default builder image for the '%v' language runtime.  Please provide one.", e.Runtime)
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"io"
	"strings"
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte

// A Version represents a UUIDs version.
type Version byte

// A Variant represents a UUIDs variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

var rander = rand.Reader // random function

// New returns a new random (version 4) UUID as a string.  It is a convenience
// function for NewRandom().String().
func New() string {
	return NewRandom().String()
}

// Parse decodes s into a UUID or returns nil.  Both the UUID form of
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
	if len(s) == 36+9 {
		if strings.ToLower(s[:9]) != "urn:uuid:" {
			return nil
		}
		s = s[9:]
	} else if len(s) != 36 {
		return nil
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return nil
	}
	uuid := make([]byte, 16)
	for i, x := range []int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		if v, ok := xtob(s[x:]); !ok {
			return nil
		} else {
			uuid[i] = v
		}
	}
	return uuid
}

// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
	return bytes.Equal(uuid1, uuid2)
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	b := []byte(uuid)
	return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
		b[:4], b[4:6], b[6:8], b[8:10], b[10:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func (uuid UUID) URN() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	b := []byte(uuid)
	return fmt.Sprintf("urn:uuid:%08x-%04x-%04x-%04x-%012x",
		b[:4], b[4:6], b[6:8], b[8:10], b[10:])
}

// Variant returns the variant encoded in uuid.  It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
	if len(uuid) != 16 {
		return Invalid
	}
	switch {
	case (uuid[8] & 0xc0) == 0x80:
		return RFC4122
	case (uuid[8] & 0xe0) == 0xc0:
		return Microsoft
	case (uuid[8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
	panic("unreachable")
}

// Version returns the verison of uuid.  It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return Version(uuid[6] >> 4), true
}

func (v Version) String() string {
	if v > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", v)
	}
	return fmt.Sprintf("VERSION_%d", v)
}

func (v Variant) String() string {
	switch v {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int(v))
}

// SetRand sets the random number generator to r, which implents io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
	if r == nil {
		rander = rand.Reader
		return
	}
	rander = r
}
<commit_msg>symbolic exports of UUID4 and UUID1 made visible<commit_after>// Copyright 2011 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"io"
	"strings"
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte

// A Version represents a UUIDs version.
type Version byte

// A Variant represents a UUIDs variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

var rander = rand.Reader // random function

var UUID1 = NewUUID
var UUID4 = NewRandom

// New returns a new random (version 4) UUID as a string.  It is a convenience
// function for NewRandom().String().
func New() string {
	return UUID4().String()
}

// Parse decodes s into a UUID or returns nil.  Both the UUID form of
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
	if len(s) == 36+9 {
		if strings.ToLower(s[:9]) != "urn:uuid:" {
			return nil
		}
		s = s[9:]
	} else if len(s) != 36 {
		return nil
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return nil
	}
	uuid := make([]byte, 16)
	for i, x := range []int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		if v, ok := xtob(s[x:]); !ok {
			return nil
		} else {
			uuid[i] = v
		}
	}
	return uuid
}

// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
	return bytes.Equal(uuid1, uuid2)
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	b := []byte(uuid)
	return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
		b[:4], b[4:6], b[6:8], b[8:10], b[10:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func (uuid UUID) URN() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	b := []byte(uuid)
	return fmt.Sprintf("urn:uuid:%08x-%04x-%04x-%04x-%012x",
		b[:4], b[4:6], b[6:8], b[8:10], b[10:])
}

// Variant returns the variant encoded in uuid.  It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
	if len(uuid) != 16 {
		return Invalid
	}
	switch {
	case (uuid[8] & 0xc0) == 0x80:
		return RFC4122
	case (uuid[8] & 0xe0) == 0xc0:
		return Microsoft
	case (uuid[8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
	panic("unreachable")
}

// Version returns the verison of uuid.  It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return Version(uuid[6] >> 4), true
}

func (v Version) String() string {
	if v > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", v)
	}
	return fmt.Sprintf("VERSION_%d", v)
}

func (v Variant) String() string {
	switch v {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int(v))
}

// SetRand sets the random number generator to r, which implents io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
	if r == nil {
		rander = rand.Reader
		return
	}
	rander = r
}
<|endoftext|>


<commit_before>package core

import (
    "C"
    "fmt"
    "unsafe"
    "time"
    "strings"

    "github.com/looplab/fsm"
    st "./settings"
    api "./capi"
    "./audio"
    "./notify"
    "./webserver"
    "./xprint"
)

const (
    DoubleClick = 2
    SingleClick = 3
)

var (
    isWork bool
    watcher *Watcher
    settings *st.Settings
    systray api.SystemTray
    player *audio.Player
    window api.MainWindow
)

type Watcher struct {
    FSM *fsm.FSM
}

func (w *Watcher) enterPause(e *fsm.Event) {
    systray.SetIcon("static_source/images/icons/watch-grey.png")
    settings.Paused = true
}

func (w *Watcher) leavePause(e *fsm.Event) {
    systray.SetIcon("static_source/images/icons/watch-blue.png")
    settings.Paused = false
    settings.Work = 0
}

func (w *Watcher) enterWork(e *fsm.Event) {
    settings.Work = 0
    systray.SetIcon("static_source/images/icons/watch-blue.png")
}

func (w *Watcher) enterWorkLock(e *fsm.Event) {
    systray.SetIcon("static_source/images/icons/watch-red.png")
    showNotify()
}

func (w *Watcher) enterWorkWarningLock(e *fsm.Event) {
    systray.SetIcon("static_source/images/icons/watch-red.png")
    showNotify()
}

func (w *Watcher) enterState(e *fsm.Event) {
    fmt.Printf("Enter state %s\n", e.Dst)
}

func (w *Watcher) enterLock(e *fsm.Event) {
    window.FullScreen()
    systray.SetIcon("static_source/images/icons/watch-red.png")
}

func (w *Watcher) leaveLock(e *fsm.Event) {
    window.Hidde()
    settings.Lock = 0
    settings.Work = 0
}

func Run() {

    // init settings
    settings = st.SettingsPtr()
    settings.Init()
    settings.Load()

    systrayInit()
    playerInit()
    webserverInit()
    windowInit()
    fsmInit()
    loopInit()
}

func loop() {
    isWork = settings.Idle < time.Second
//    protected := settings.Idle < settings.Protect

    if settings.Paused {
        return
    }

    settings.Work += settings.Tick
    settings.TotalWork += settings.Tick

    switch watcher.FSM.Current() {
        case "worked":
            if isWork {
                if settings.Work >= (settings.WorkConst - 5 * time.Minute) {
                    watcher.FSM.Event("work_lock")
                } else if settings.Work >= (settings.WorkConst - 1 * time.Minute) {
                    watcher.FSM.Event("work_warning_lock")
                }
            }

        case "work_locked":
            if settings.Work < (settings.WorkConst - 5 * time.Minute) {
                watcher.FSM.Event("work")
            } else if settings.Work >= (settings.WorkConst - 1 * time.Minute) {
                watcher.FSM.Event("work_warning_lock")
            }

        case "work_warning_locked":
            if settings.Work <= (settings.WorkConst - 1 * time.Minute) {
                watcher.FSM.Event("work_locked")
            } else if settings.Work >= (settings.WorkConst) {
                watcher.FSM.Event("lock")
            }

        case "paused":

        case "locked":
            settings.Lock += settings.Tick
            settings.TotalIdle += settings.Tick

            if settings.Lock >= settings.LockConst {
                watcher.FSM.Event("work")
            }

    }
}

func systrayInit() {

    seconds := func(d time.Duration) int {
        ns := d.Nanoseconds()
        return int(ns / 1000000000)
    }

    thread := api.ApplicationThread()
    systray = api.GetSystemTray()
    systray.MoveToThread(thread)
    systray.SetIcon("static_source/images/icons/watch-grey.png")
    systray.SetToolTip("Watcher")

    var TimeCallbackFunc = TimeCallback
    var DTimeCallbackFunc = DTimeCallback
    var IconActivatedCallbackFunc = IconActivatedCallback
    var RunAtStartupCallbackFunc = RunAtStartupCallback
    var AlarmCallbackFunc = AlarmCallback

    systray.SetTimeCallback(unsafe.Pointer(&TimeCallbackFunc))
    systray.SetDTimeCallback(unsafe.Pointer(&DTimeCallbackFunc))
    systray.SetIconActivatedCallback(unsafe.Pointer(&IconActivatedCallbackFunc))
    systray.SetRunAtStartupCallback(unsafe.Pointer(&RunAtStartupCallbackFunc))
    systray.SetAlarmCallback(unsafe.Pointer(&AlarmCallbackFunc))

    systray.SetVisible(true)

    // set value
    if settings != nil && settings.Default_timer != 0 {
        systray.SetDTime( seconds(settings.Default_timer) )
        systray.SetTime( seconds(settings.Default_timer) )
    }

    if settings.RunAtStartup {
        systray.SetRunAtStartup(1)
    } else {
        systray.SetRunAtStartup(0)
    }

    if settings.SoundEnabled {
        systray.SetAlarm(1)
        systray.SetAlarmInfo("Alarm is on")
    } else {
        systray.SetAlarm(3)
        systray.SetAlarmInfo("Alarm is off")
    }
}

func playerInit() {

    player = audio.PlayerPtr()
    if settings.Alarm_file != "" {
        player.File("static_source/audio/" + settings.Alarm_file)
    }
}

func loopInit() {

    go func() {
        ticker := time.Tick(settings.Tick)
        for {
            select {
            case <-ticker:
                settings.UpTime = time.Now().Sub(settings.StartTime)
                go xprint.Update()
                loop()
            }
        }
    }()
}

func webserverInit() {
    webserver.Run(settings.Webserver_address)
}

// systray callbacks
func TimeCallback(x C.int) {
    settings.WorkConst = time.Duration(x) * time.Second
    settings.Work = 0
}

func DTimeCallback(x C.int) {

    settings.Default_timer = time.Duration(x) * time.Second
    settings.Save()
}

func IconActivatedCallback(x C.int) {

    switch int(x) {
        case DoubleClick:
            if watcher.FSM.Current() != "paused" {
                watcher.FSM.Event("pause")
            } else {
                watcher.FSM.Event("work")
            }

        case SingleClick:

    }
}

func RunAtStartupCallback(x C.int) {
    if int(x) == 1 {
        settings.RunAtStartup = true
    } else {
        settings.RunAtStartup = false
    }

    settings.Save()
}

func AlarmCallback(x C.int) {

    if int(x) == 1 {
        settings.SoundEnabled = true
        systray.SetAlarmInfo("Alarm is on")
    } else {
        settings.SoundEnabled = false
        systray.SetAlarmInfo("Alarm is off")
    }

    settings.Save()
}

func strConverter(in string) (out string) {

    out = strings.Replace(in, "{idle_time}", fmt.Sprintf("%v", settings.Idle), -1)
    out = strings.Replace(out, "{work_time}", fmt.Sprintf("%v", settings.Work), -1)
    out = strings.Replace(out, "{lock}", fmt.Sprintf("%v", settings.LockConst), -1)
    out = strings.Replace(out, "{time_to_lock}", fmt.Sprintf("%v", settings.WorkConst - settings.Work), -1)
    return
}

func showNotify() {

    if settings.Work <= ( 3 * time.Minute) {
        systray.ShowMessage(strConverter(settings.Message_title), strConverter(settings.Message_body), 1)
        return
    }

    if settings.SoundEnabled {
        player.Play()
    }

    go notify.Show(strConverter(settings.Message_title), strConverter(settings.Message_body), settings.Message_image)
}

func fsmInit() {

    watcher = new(Watcher)

    watcher.FSM = fsm.NewFSM(
    "paused",
    fsm.Events{
        // Рабочее состояние, до момента "Х" более 5 минут
        {Name: "work", Src: []string{"paused", "work_locked", "work_warning_locked", "locked"}, Dst: "worked"},

        // Рабочее состояние, до момента "Х" менее 5 минут
        {Name: "work_lock", Src: []string{"worked", "locked"}, Dst: "work_locked"},

        // Рабочее состояние, до момента "Х" менее 1 минут
        {Name: "work_warning_lock", Src: []string{"work_locked", "locked"}, Dst: "work_warning_locked"},

        // Момент "Х"
        {Name: "lock", Src: []string{"work_warning_locked"}, Dst: "locked"},

        // Пауза, все процессы остановлены
        {Name: "pause", Src: []string{"worked", "work_locked", "locked", "work_warning_locked"}, Dst: "paused"},
    },
    fsm.Callbacks{
        "enter_paused": func(e *fsm.Event) { watcher.enterPause(e) },
        "leave_paused": func(e *fsm.Event) { watcher.leavePause(e) },
        "enter_state": func(e *fsm.Event) { watcher.enterState(e) },
        "enter_worked": func(e *fsm.Event) { watcher.enterWork(e) },
        "enter_work_locked": func(e *fsm.Event) { watcher.enterWorkLock(e) },
        "enter_work_warning_locked": func(e *fsm.Event) { watcher.enterWorkWarningLock(e) },
        "enter_locked": func(e *fsm.Event) { watcher.enterLock(e) },
        "leave_locked": func(e *fsm.Event) { watcher.leaveLock(e) },
    },
    )

    if settings.RunAtStartup {
        err := watcher.FSM.Event("work")
        if err != nil {
            fmt.Println(err)
        }
    }
}

func windowInit() {

    window = api.GetMainWindow()
    window.Url(fmt.Sprintf("http://%s/lock", settings.Webserver_address))
}<commit_msg>icon const<commit_after>package core

import (
    "C"
    "fmt"
    "unsafe"
    "time"
    "strings"

    "github.com/looplab/fsm"
    st "./settings"
    api "./capi"
    "./audio"
    "./notify"
    "./webserver"
    "./xprint"
)

const (
    DoubleClick = 2
    SingleClick = 3
    LOCK_ICON = "static_source/images/icons/watch-red.png"
    WORK_ICON = "static_source/images/icons/watch-blue.png"
    PAUSE_ICON = "static_source/images/icons/watch-grey.png"
)

var (
    isWork bool
    watcher *Watcher
    settings *st.Settings
    systray api.SystemTray
    player *audio.Player
    window api.MainWindow
)

type Watcher struct {
    FSM *fsm.FSM
}

func (w *Watcher) enterPause(e *fsm.Event) {
    systray.SetIcon(PAUSE_ICON)
    settings.Paused = true
}

func (w *Watcher) leavePause(e *fsm.Event) {
    systray.SetIcon(WORK_ICON)
    settings.Paused = false
    settings.Work = 0
}

func (w *Watcher) enterWork(e *fsm.Event) {
    settings.Work = 0
    systray.SetIcon(WORK_ICON)
}

func (w *Watcher) enterWorkLock(e *fsm.Event) {
    systray.SetIcon(LOCK_ICON)
    showNotify()
}

func (w *Watcher) enterWorkWarningLock(e *fsm.Event) {
    systray.SetIcon(LOCK_ICON)
    showNotify()
}

func (w *Watcher) enterState(e *fsm.Event) {
    fmt.Printf("Enter state %s\n", e.Dst)
}

func (w *Watcher) enterLock(e *fsm.Event) {
    window.FullScreen()
    systray.SetIcon(LOCK_ICON)
}

func (w *Watcher) leaveLock(e *fsm.Event) {
    window.Hidde()
    settings.Lock = 0
    settings.Work = 0
}

func Run() {

    // init settings
    settings = st.SettingsPtr()
    settings.Init()
    settings.Load()

    systrayInit()
    playerInit()
    webserverInit()
    windowInit()
    fsmInit()
    loopInit()
}

func loop() {
    isWork = settings.Idle < time.Second
//    protected := settings.Idle < settings.Protect

    if settings.Paused {
        return
    }

    settings.Work += settings.Tick
    settings.TotalWork += settings.Tick

    switch watcher.FSM.Current() {
        case "worked":
            if isWork {
                if settings.Work >= (settings.WorkConst - 5 * time.Minute) {
                    watcher.FSM.Event("work_lock")
                } else if settings.Work >= (settings.WorkConst - 1 * time.Minute) {
                    watcher.FSM.Event("work_warning_lock")
                }
            }

        case "work_locked":
            if settings.Work < (settings.WorkConst - 5 * time.Minute) {
                watcher.FSM.Event("work")
            } else if settings.Work >= (settings.WorkConst - 1 * time.Minute) {
                watcher.FSM.Event("work_warning_lock")
            }

        case "work_warning_locked":
            if settings.Work <= (settings.WorkConst - 1 * time.Minute) {
                watcher.FSM.Event("work_locked")
            } else if settings.Work >= (settings.WorkConst) {
                watcher.FSM.Event("lock")
            }

        case "paused":

        case "locked":
            settings.Lock += settings.Tick
            settings.TotalIdle += settings.Tick

            if settings.Lock >= settings.LockConst {
                watcher.FSM.Event("work")
            }

    }
}

func systrayInit() {

    seconds := func(d time.Duration) int {
        ns := d.Nanoseconds()
        return int(ns / 1000000000)
    }

    thread := api.ApplicationThread()
    systray = api.GetSystemTray()
    systray.MoveToThread(thread)
    systray.SetIcon(PAUSE_ICON)
    systray.SetToolTip("Watcher")

    var TimeCallbackFunc = TimeCallback
    var DTimeCallbackFunc = DTimeCallback
    var IconActivatedCallbackFunc = IconActivatedCallback
    var RunAtStartupCallbackFunc = RunAtStartupCallback
    var AlarmCallbackFunc = AlarmCallback

    systray.SetTimeCallback(unsafe.Pointer(&TimeCallbackFunc))
    systray.SetDTimeCallback(unsafe.Pointer(&DTimeCallbackFunc))
    systray.SetIconActivatedCallback(unsafe.Pointer(&IconActivatedCallbackFunc))
    systray.SetRunAtStartupCallback(unsafe.Pointer(&RunAtStartupCallbackFunc))
    systray.SetAlarmCallback(unsafe.Pointer(&AlarmCallbackFunc))

    systray.SetVisible(true)

    // set value
    if settings != nil && settings.Default_timer != 0 {
        systray.SetDTime( seconds(settings.Default_timer) )
        systray.SetTime( seconds(settings.Default_timer) )
    }

    if settings.RunAtStartup {
        systray.SetRunAtStartup(1)
    } else {
        systray.SetRunAtStartup(0)
    }

    if settings.SoundEnabled {
        systray.SetAlarm(1)
        systray.SetAlarmInfo("Alarm is on")
    } else {
        systray.SetAlarm(3)
        systray.SetAlarmInfo("Alarm is off")
    }
}

func playerInit() {

    player = audio.PlayerPtr()
    if settings.Alarm_file != "" {
        player.File("static_source/audio/" + settings.Alarm_file)
    }
}

func loopInit() {

    go func() {
        ticker := time.Tick(settings.Tick)
        for {
            select {
            case <-ticker:
                settings.UpTime = time.Now().Sub(settings.StartTime)
                go xprint.Update()
                loop()
            }
        }
    }()
}

func webserverInit() {
    webserver.Run(settings.Webserver_address)
}

// systray callbacks
func TimeCallback(x C.int) {
    settings.WorkConst = time.Duration(x) * time.Second
    settings.Work = 0
}

func DTimeCallback(x C.int) {

    settings.Default_timer = time.Duration(x) * time.Second
    settings.Save()
}

func IconActivatedCallback(x C.int) {

    switch int(x) {
        case DoubleClick:
            if watcher.FSM.Current() != "paused" {
                watcher.FSM.Event("pause")
            } else {
                watcher.FSM.Event("work")
            }

        case SingleClick:

    }
}

func RunAtStartupCallback(x C.int) {
    if int(x) == 1 {
        settings.RunAtStartup = true
    } else {
        settings.RunAtStartup = false
    }

    settings.Save()
}

func AlarmCallback(x C.int) {

    if int(x) == 1 {
        settings.SoundEnabled = true
        systray.SetAlarmInfo("Alarm is on")
    } else {
        settings.SoundEnabled = false
        systray.SetAlarmInfo("Alarm is off")
    }

    settings.Save()
}

func strConverter(in string) (out string) {

    out = strings.Replace(in, "{idle_time}", fmt.Sprintf("%v", settings.Idle), -1)
    out = strings.Replace(out, "{work_time}", fmt.Sprintf("%v", settings.Work), -1)
    out = strings.Replace(out, "{lock}", fmt.Sprintf("%v", settings.LockConst), -1)
    out = strings.Replace(out, "{time_to_lock}", fmt.Sprintf("%v", settings.WorkConst - settings.Work), -1)
    return
}

func showNotify() {

    if settings.Work <= ( 3 * time.Minute) {
        systray.ShowMessage(strConverter(settings.Message_title), strConverter(settings.Message_body), 1)
        return
    }

    if settings.SoundEnabled {
        player.Play()
    }

    go notify.Show(strConverter(settings.Message_title), strConverter(settings.Message_body), settings.Message_image)
}

func fsmInit() {

    watcher = new(Watcher)

    watcher.FSM = fsm.NewFSM(
    "paused",
    fsm.Events{
        // Рабочее состояние, до момента "Х" более 5 минут
        {Name: "work", Src: []string{"paused", "work_locked", "work_warning_locked", "locked"}, Dst: "worked"},

        // Рабочее состояние, до момента "Х" менее 5 минут
        {Name: "work_lock", Src: []string{"worked", "locked"}, Dst: "work_locked"},

        // Рабочее состояние, до момента "Х" менее 1 минут
        {Name: "work_warning_lock", Src: []string{"work_locked", "locked"}, Dst: "work_warning_locked"},

        // Момент "Х"
        {Name: "lock", Src: []string{"work_warning_locked"}, Dst: "locked"},

        // Пауза, все процессы остановлены
        {Name: "pause", Src: []string{"worked", "work_locked", "locked", "work_warning_locked"}, Dst: "paused"},
    },
    fsm.Callbacks{
        "enter_paused": func(e *fsm.Event) { watcher.enterPause(e) },
        "leave_paused": func(e *fsm.Event) { watcher.leavePause(e) },
        "enter_state": func(e *fsm.Event) { watcher.enterState(e) },
        "enter_worked": func(e *fsm.Event) { watcher.enterWork(e) },
        "enter_work_locked": func(e *fsm.Event) { watcher.enterWorkLock(e) },
        "enter_work_warning_locked": func(e *fsm.Event) { watcher.enterWorkWarningLock(e) },
        "enter_locked": func(e *fsm.Event) { watcher.enterLock(e) },
        "leave_locked": func(e *fsm.Event) { watcher.leaveLock(e) },
    },
    )

    if settings.RunAtStartup {
        err := watcher.FSM.Event("work")
        if err != nil {
            fmt.Println(err)
        }
    }
}

func windowInit() {

    window = api.GetMainWindow()
    window.Url(fmt.Sprintf("http://%s/lock", settings.Webserver_address))
}<|endoftext|>