<commit_before>package tablib

import (
	"bytes"
	"github.com/tealeg/xlsx"
	"gopkg.in/yaml.v2"
)

// Sheet represents a sheet in a Databook, holding a title (if any) and a dataset.
type Sheet struct {
	title   string
	dataset *Dataset
}

// Title return the title of the sheet.
func (s Sheet) Title() string {
	return s.title
}

// Dataset returns the dataset of the sheet.
func (s Sheet) Dataset() *Dataset {
	return s.dataset
}

// Databook represents a Databook which is an array of sheets.
type Databook struct {
	sheets map[string]Sheet
}

// NewDatabook constructs a new Databook.
func NewDatabook() *Databook {
	return &Databook{make(map[string]Sheet)}
}

// Sheets returns the sheets in the Databook.
func (d *Databook) Sheets() map[string]Sheet {
	return d.sheets
}

// Sheet returns the sheet with a specific title.
func (d *Databook) Sheet(title string) Sheet {
	return d.sheets[title]
}

// AddSheet adds a sheet to the Databook.
func (d *Databook) AddSheet(title string, dataset *Dataset) *Databook {
	d.sheets[title] = Sheet{title, dataset}
	return d
}

// SheetCount returns the number of sheets in the databook.
func (d *Databook) SheetCount() int {
	return len(d.sheets)
}

// JSON returns a JSON representation of the databook as string.
func (d *Databook) JSON() (string, error) {
	str := "["
	for _, s := range d.sheets {
		str += "{\"title\": \"" + s.title + "\", \"data\": "
		js, err := s.dataset.JSON()
		if err != nil {
			return "", err
		}
		str += js + "},"
	}
	str = str[:len(str)-1] + "]"
	return str, nil
}

// XML returns a XML representation of the Databook as string.
func (d *Databook) XML() string {
	str := "<databook>\n"
	for _, s := range d.sheets {
		str += "  <sheet>\n    <title>" + s.title + "</title>\n    "
		str += s.dataset.XMLWithTagNamePrefixIndent("row", "      ", "  ")
		str += "\n  </sheet>"
	}
	str += "\n</databook>"
	return str
}

// YAML returns a YAML representation of the databook as string.
func (d *Databook) YAML() (string, error) {
	y := make([]map[string]interface{}, len(d.sheets))
	i := 0
	for _, s := range d.sheets {
		y[i] = make(map[string]interface{})
		y[i]["title"] = s.title
		y[i]["dataset"] = s.dataset.Dict()
	}
	b, err := yaml.Marshal(y)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

// XLSX returns a XLSX representation of the databook as a byte array.
func (d *Databook) XLSX() ([]byte, error) {
	file := xlsx.NewFile()

	for _, s := range d.sheets {
		s.dataset.addXlsxSheetToFile(file, s.title)
	}

	var b bytes.Buffer
	file.Write(&b)
	return b.Bytes(), nil
}

// HTML returns a HTML representation of the databook as a byte array.
func (d *Databook) HTML() string {
	var b bytes.Buffer

	for _, s := range d.sheets {
		b.WriteString("
" + s.title + "
\n")
		b.WriteString(s.dataset.HTML())
		b.WriteString("\n\n")
	}

	return b.String()
}
<commit_msg>SheetCount -> Size<commit_after>package tablib

import (
	"bytes"
	"github.com/tealeg/xlsx"
	"gopkg.in/yaml.v2"
)

// Sheet represents a sheet in a Databook, holding a title (if any) and a dataset.
type Sheet struct {
	title   string
	dataset *Dataset
}

// Title return the title of the sheet.
func (s Sheet) Title() string {
	return s.title
}

// Dataset returns the dataset of the sheet.
func (s Sheet) Dataset() *Dataset {
	return s.dataset
}

// Databook represents a Databook which is an array of sheets.
type Databook struct {
	sheets map[string]Sheet
}

// NewDatabook constructs a new Databook.
func NewDatabook() *Databook {
	return &Databook{make(map[string]Sheet)}
}

// Sheets returns the sheets in the Databook.
func (d *Databook) Sheets() map[string]Sheet {
	return d.sheets
}

// Sheet returns the sheet with a specific title.
func (d *Databook) Sheet(title string) Sheet {
	return d.sheets[title]
}

// AddSheet adds a sheet to the Databook.
func (d *Databook) AddSheet(title string, dataset *Dataset) *Databook {
	d.sheets[title] = Sheet{title, dataset}
	return d
}

// Size returns the number of sheets in the databook.
func (d *Databook) Size() int {
	return len(d.sheets)
}

// JSON returns a JSON representation of the databook as string.
func (d *Databook) JSON() (string, error) {
	str := "["
	for _, s := range d.sheets {
		str += "{\"title\": \"" + s.title + "\", \"data\": "
		js, err := s.dataset.JSON()
		if err != nil {
			return "", err
		}
		str += js + "},"
	}
	str = str[:len(str)-1] + "]"
	return str, nil
}

// XML returns a XML representation of the Databook as string.
func (d *Databook) XML() string {
	str := "<databook>\n"
	for _, s := range d.sheets {
		str += "  <sheet>\n    <title>" + s.title + "</title>\n    "
		str += s.dataset.XMLWithTagNamePrefixIndent("row", "      ", "  ")
		str += "\n  </sheet>"
	}
	str += "\n</databook>"
	return str
}

// YAML returns a YAML representation of the databook as string.
func (d *Databook) YAML() (string, error) {
	y := make([]map[string]interface{}, len(d.sheets))
	i := 0
	for _, s := range d.sheets {
		y[i] = make(map[string]interface{})
		y[i]["title"] = s.title
		y[i]["dataset"] = s.dataset.Dict()
	}
	b, err := yaml.Marshal(y)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

// XLSX returns a XLSX representation of the databook as a byte array.
func (d *Databook) XLSX() ([]byte, error) {
	file := xlsx.NewFile()

	for _, s := range d.sheets {
		s.dataset.addXlsxSheetToFile(file, s.title)
	}

	var b bytes.Buffer
	file.Write(&b)
	return b.Bytes(), nil
}

// HTML returns a HTML representation of the databook as a byte array.
func (d *Databook) HTML() string {
	var b bytes.Buffer

	for _, s := range d.sheets {
		b.WriteString("
" + s.title + "
\n")
		b.WriteString(s.dataset.HTML())
		b.WriteString("\n\n")
	}

	return b.String()
}
<|endoftext|>


<commit_before>package types

import (
	"sync"

	"github.com/go-pg/pg/v9/internal"
)

type ValueScanner interface {
	ScanValue(rd Reader, n int) error
}

type ValueAppender interface {
	AppendValue(b []byte, flags int) ([]byte, error)
}

//------------------------------------------------------------------------------

// Safe represents a safe SQL query.
type Safe string

var _ ValueAppender = (*Safe)(nil)

func (q Safe) AppendValue(b []byte, flags int) ([]byte, error) {
	return append(b, q...), nil
}

//------------------------------------------------------------------------------

// DEPRECATED. Use Safe instead.
type Q string

var _ ValueAppender = (*Q)(nil)
var qWarn sync.Once

func (q Q) AppendValue(b []byte, flags int) ([]byte, error) {
	qWarn.Do(func() {
		internal.Logger.Printf("DEPRECATED: types.Q is replaced with types.Safe")
	})
	return append(b, q...), nil
}

//------------------------------------------------------------------------------

// Ident represents a SQL identifier, e.g. table or column name.
type Ident string

var _ ValueAppender = (*Ident)(nil)

func (f Ident) AppendValue(b []byte, flags int) ([]byte, error) {
	return AppendIdent(b, string(f), flags), nil
}

//------------------------------------------------------------------------------

// DEPRECATED. Use Ident instead.
type F string

var _ ValueAppender = (*F)(nil)
var fWarn sync.Once

func (f F) AppendValue(b []byte, flags int) ([]byte, error) {
	fWarn.Do(func() {
		internal.Logger.Printf("DEPRECATED: types.F is replaced with types.Ident")
	})
	return AppendIdent(b, string(f), flags), nil
}

//------------------------------------------------------------------------------

type Reader = internal.Reader
type BytesReader = internal.BytesReader

func NewBytesReader(buf []byte) *BytesReader {
	return internal.NewBytesReader(buf)
}
<commit_msg>types: improve message<commit_after>package types

import (
	"sync"

	"github.com/go-pg/pg/v9/internal"
)

type ValueScanner interface {
	ScanValue(rd Reader, n int) error
}

type ValueAppender interface {
	AppendValue(b []byte, flags int) ([]byte, error)
}

//------------------------------------------------------------------------------

// Safe represents a safe SQL query.
type Safe string

var _ ValueAppender = (*Safe)(nil)

func (q Safe) AppendValue(b []byte, flags int) ([]byte, error) {
	return append(b, q...), nil
}

//------------------------------------------------------------------------------

// DEPRECATED. Use Safe instead.
type Q string

var _ ValueAppender = (*Q)(nil)
var qWarn sync.Once

func (q Q) AppendValue(b []byte, flags int) ([]byte, error) {
	qWarn.Do(func() {
		internal.Logger.Printf("DEPRECATED: types.Q is replaced with pg.Safe")
	})
	return append(b, q...), nil
}

//------------------------------------------------------------------------------

// Ident represents a SQL identifier, e.g. table or column name.
type Ident string

var _ ValueAppender = (*Ident)(nil)

func (f Ident) AppendValue(b []byte, flags int) ([]byte, error) {
	return AppendIdent(b, string(f), flags), nil
}

//------------------------------------------------------------------------------

// DEPRECATED. Use Ident instead.
type F string

var _ ValueAppender = (*F)(nil)
var fWarn sync.Once

func (f F) AppendValue(b []byte, flags int) ([]byte, error) {
	fWarn.Do(func() {
		internal.Logger.Printf("DEPRECATED: types.F is replaced with pg.Ident")
	})
	return AppendIdent(b, string(f), flags), nil
}

//------------------------------------------------------------------------------

type Reader = internal.Reader
type BytesReader = internal.BytesReader

func NewBytesReader(buf []byte) *BytesReader {
	return internal.NewBytesReader(buf)
}
<|endoftext|>


<commit_before>package gps

import (
	"bytes"
	"fmt"
	"strings"
)

type errorLevel uint8

// TODO(sdboyer) consistent, sensible way of handling 'type' and 'severity' - or figure
// out that they're not orthogonal and collapse into just 'type'

const (
	warning errorLevel = 1 << iota
	mustResolve
	cannotResolve
)

func a2vs(a atom) string {
	if a.v == rootRev || a.v == nil {
		return "(root)"
	}

	return fmt.Sprintf("%s@%s", a.id.errString(), a.v)
}

type traceError interface {
	traceString() string
}

type noVersionError struct {
	pn    ProjectIdentifier
	fails []failedVersion
}

func (e *noVersionError) Error() string {
	if len(e.fails) == 0 {
		return fmt.Sprintf("No versions found for project %q.", e.pn.ProjectRoot)
	}

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot)
	for _, f := range e.fails {
		fmt.Fprintf(&buf, "\n\t%s: %s", f.v, f.f.Error())
	}

	return buf.String()
}

func (e *noVersionError) traceString() string {
	if len(e.fails) == 0 {
		return fmt.Sprintf("No versions found")
	}

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot)
	for _, f := range e.fails {
		if te, ok := f.f.(traceError); ok {
			fmt.Fprintf(&buf, "\n  %s: %s", f.v, te.traceString())
		} else {
			fmt.Fprintf(&buf, "\n  %s: %s", f.v, f.f.Error())
		}
	}

	return buf.String()
}

type disjointConstraintFailure struct {
	goal      dependency
	failsib   []dependency
	nofailsib []dependency
	c         Constraint
}

func (e *disjointConstraintFailure) Error() string {
	if len(e.failsib) == 1 {
		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with existing constraint %s from %s"
		return fmt.Sprintf(str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String(), e.failsib[0].dep.Constraint.String(), a2vs(e.failsib[0].depender))
	}

	var buf bytes.Buffer

	var sibs []dependency
	if len(e.failsib) > 1 {
		sibs = e.failsib

		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with the following existing constraints:\n"
		fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String())
	} else {
		sibs = e.nofailsib

		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which does not overlap with the intersection of existing constraints from other currently selected packages:\n"
		fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String())
	}

	for _, c := range sibs {
		fmt.Fprintf(&buf, "\t%s from %s\n", c.dep.Constraint.String(), a2vs(c.depender))
	}

	return buf.String()
}

func (e *disjointConstraintFailure) traceString() string {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "constraint %s on %s disjoint with other dependers:\n", e.goal.dep.Constraint.String(), e.goal.dep.Ident.errString())
	for _, f := range e.failsib {
		fmt.Fprintf(
			&buf,
			"%s from %s (no overlap)\n",
			f.dep.Constraint.String(),
			a2vs(f.depender),
		)
	}
	for _, f := range e.nofailsib {
		fmt.Fprintf(
			&buf,
			"%s from %s (some overlap)\n",
			f.dep.Constraint.String(),
			a2vs(f.depender),
		)
	}

	return buf.String()
}

// Indicates that an atom could not be introduced because one of its dep
// constraints does not admit the currently-selected version of the target
// project.
type constraintNotAllowedFailure struct {
	goal dependency
	v    Version
}

func (e *constraintNotAllowedFailure) Error() string {
	return fmt.Sprintf(
		"Could not introduce %s, as it has a dependency on %s with constraint %s, which does not allow the currently selected version of %s",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.goal.dep.Constraint,
		e.v,
	)
}

func (e *constraintNotAllowedFailure) traceString() string {
	return fmt.Sprintf(
		"%s depends on %s with %s, but that's already selected at %s",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.ProjectRoot,
		e.goal.dep.Constraint,
		e.v,
	)
}

type versionNotAllowedFailure struct {
	goal       atom
	failparent []dependency
	c          Constraint
}

func (e *versionNotAllowedFailure) Error() string {
	if len(e.failparent) == 1 {
		return fmt.Sprintf(
			"Could not introduce %s, as it is not allowed by constraint %s from project %s.",
			a2vs(e.goal),
			e.failparent[0].dep.Constraint.String(),
			e.failparent[0].depender.id.errString(),
		)
	}

	var buf bytes.Buffer

	fmt.Fprintf(&buf, "Could not introduce %s, as it is not allowed by constraints from the following projects:\n", a2vs(e.goal))

	for _, f := range e.failparent {
		fmt.Fprintf(&buf, "\t%s from %s\n", f.dep.Constraint.String(), a2vs(f.depender))
	}

	return buf.String()
}

func (e *versionNotAllowedFailure) traceString() string {
	var buf bytes.Buffer

	fmt.Fprintf(&buf, "%s not allowed by constraint %s:\n", a2vs(e.goal), e.c.String())
	for _, f := range e.failparent {
		fmt.Fprintf(&buf, "  %s from %s\n", f.dep.Constraint.String(), a2vs(f.depender))
	}

	return buf.String()
}

type missingSourceFailure struct {
	goal ProjectIdentifier
	prob string
}

func (e *missingSourceFailure) Error() string {
	return fmt.Sprintf(e.prob, e.goal)
}

type badOptsFailure string

func (e badOptsFailure) Error() string {
	return string(e)
}

type sourceMismatchFailure struct {
	shared            ProjectRoot
	sel               []dependency
	current, mismatch string
	prob              atom
}

func (e *sourceMismatchFailure) Error() string {
	var cur []string
	for _, c := range e.sel {
		cur = append(cur, string(c.depender.id.ProjectRoot))
	}

	str := "Could not introduce %s, as it depends on %s from %s, but %s is already marked as coming from %s by %s"
	return fmt.Sprintf(str, a2vs(e.prob), e.shared, e.mismatch, e.shared, e.current, strings.Join(cur, ", "))
}

func (e *sourceMismatchFailure) traceString() string {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "disagreement on network addr for %s:\n", e.shared)

	fmt.Fprintf(&buf, "  %s from %s\n", e.mismatch, e.prob.id.errString())
	for _, dep := range e.sel {
		fmt.Fprintf(&buf, "  %s from %s\n", e.current, dep.depender.id.errString())
	}

	return buf.String()
}

type errDeppers struct {
	err     error
	deppers []atom
}
type checkeeHasProblemPackagesFailure struct {
	goal    atom
	failpkg map[string]errDeppers
}

func (e *checkeeHasProblemPackagesFailure) Error() string {
	var buf bytes.Buffer
	indent := ""

	if len(e.failpkg) > 1 {
		indent = "\t"
		fmt.Fprintf(
			&buf, "Could not introduce %s due to multiple problematic subpackages:\n",
			a2vs(e.goal),
		)
	}

	for pkg, errdep := range e.failpkg {
		var cause string
		if errdep.err == nil {
			cause = "is missing"
		} else {
			cause = fmt.Sprintf("does not contain usable Go code (%T).", errdep.err)
		}

		if len(e.failpkg) == 1 {
			fmt.Fprintf(
				&buf, "Could not introduce %s, as its subpackage %s %s.",
				a2vs(e.goal),
				pkg,
				cause,
			)
		} else {
			fmt.Fprintf(&buf, "\tSubpackage %s %s.", pkg, cause)
		}

		if len(errdep.deppers) == 1 {
			fmt.Fprintf(
				&buf, " (Package is required by %s.)",
				a2vs(errdep.deppers[0]),
			)
		} else {
			fmt.Fprintf(&buf, " Package is required by:")
			for _, pa := range errdep.deppers {
				fmt.Fprintf(&buf, "\n%s\t%s", indent, a2vs(pa))
			}
		}
	}

	return buf.String()
}

func (e *checkeeHasProblemPackagesFailure) traceString() string {
	var buf bytes.Buffer

	fmt.Fprintf(&buf, "%s at %s has problem subpkg(s):\n", e.goal.id.ProjectRoot, e.goal.v)
	for pkg, errdep := range e.failpkg {
		if errdep.err == nil {
			fmt.Fprintf(&buf, "\t%s is missing; ", pkg)
		} else {
			fmt.Fprintf(&buf, "\t%s has err (%T); ", pkg, errdep.err)
		}

		if len(errdep.deppers) == 1 {
			fmt.Fprintf(&buf, "required by %s.", a2vs(errdep.deppers[0]))
		} else {
			fmt.Fprintf(&buf, " required by:")
			for _, pa := range errdep.deppers {
				fmt.Fprintf(&buf, "\n\t\t%s at %s", pa.id.errString(), pa.v)
			}
		}
	}

	return buf.String()
}

type depHasProblemPackagesFailure struct {
	goal dependency
	v    Version
	pl   []string
	prob map[string]error
}

func (e *depHasProblemPackagesFailure) Error() string {
	fcause := func(pkg string) string {
		var cause string
		if err, has := e.prob[pkg]; has {
			cause = fmt.Sprintf("does not contain usable Go code (%T).", err)
		} else {
			cause = "is missing."
		}
		return cause
	}

	if len(e.pl) == 1 {
		return fmt.Sprintf(
			"Could not introduce %s, as it requires package %s from %s, but in version %s that package %s",
			a2vs(e.goal.depender),
			e.pl[0],
			e.goal.dep.Ident.errString(),
			e.v,
			fcause(e.pl[0]),
		)
	}

	var buf bytes.Buffer
	fmt.Fprintf(
		&buf, "Could not introduce %s, as it requires problematic packages from %s (current version %s):",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.v,
	)

	for _, pkg := range e.pl {
		fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
	}

	return buf.String()
}

func (e *depHasProblemPackagesFailure) traceString() string {
	var buf bytes.Buffer
	fcause := func(pkg string) string {
		var cause string
		if err, has := e.prob[pkg]; has {
			cause = fmt.Sprintf("has parsing err (%T).", err)
		} else {
			cause = "is missing"
		}
		return cause
	}

	fmt.Fprintf(
		&buf, "%s depping on %s at %s has problem subpkg(s):",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.v,
	)

	for _, pkg := range e.pl {
		fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
	}

	return buf.String()
}

// nonexistentRevisionFailure indicates that a revision constraint was specified
// for a given project, but that that revision does not exist in the source
// repository.
type nonexistentRevisionFailure struct {
	goal dependency
	r    Revision
}

func (e *nonexistentRevisionFailure) Error() string {
	return fmt.Sprintf(
		"Could not introduce %s, as it requires %s at revision %s, but that revision does not exist",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.r,
	)
}

func (e *nonexistentRevisionFailure) traceString() string {
	return fmt.Sprintf(
		"%s wants missing rev %s of %s",
		a2vs(e.goal.depender),
		e.r,
		e.goal.dep.Ident.errString(),
	)
}
<commit_msg>Docs on sourceMismatchFailure properties<commit_after>package gps

import (
	"bytes"
	"fmt"
	"strings"
)

type errorLevel uint8

// TODO(sdboyer) consistent, sensible way of handling 'type' and 'severity' - or figure
// out that they're not orthogonal and collapse into just 'type'

const (
	warning errorLevel = 1 << iota
	mustResolve
	cannotResolve
)

func a2vs(a atom) string {
	if a.v == rootRev || a.v == nil {
		return "(root)"
	}

	return fmt.Sprintf("%s@%s", a.id.errString(), a.v)
}

type traceError interface {
	traceString() string
}

type noVersionError struct {
	pn    ProjectIdentifier
	fails []failedVersion
}

func (e *noVersionError) Error() string {
	if len(e.fails) == 0 {
		return fmt.Sprintf("No versions found for project %q.", e.pn.ProjectRoot)
	}

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot)
	for _, f := range e.fails {
		fmt.Fprintf(&buf, "\n\t%s: %s", f.v, f.f.Error())
	}

	return buf.String()
}

func (e *noVersionError) traceString() string {
	if len(e.fails) == 0 {
		return fmt.Sprintf("No versions found")
	}

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot)
	for _, f := range e.fails {
		if te, ok := f.f.(traceError); ok {
			fmt.Fprintf(&buf, "\n  %s: %s", f.v, te.traceString())
		} else {
			fmt.Fprintf(&buf, "\n  %s: %s", f.v, f.f.Error())
		}
	}

	return buf.String()
}

type disjointConstraintFailure struct {
	goal      dependency
	failsib   []dependency
	nofailsib []dependency
	c         Constraint
}

func (e *disjointConstraintFailure) Error() string {
	if len(e.failsib) == 1 {
		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with existing constraint %s from %s"
		return fmt.Sprintf(str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String(), e.failsib[0].dep.Constraint.String(), a2vs(e.failsib[0].depender))
	}

	var buf bytes.Buffer

	var sibs []dependency
	if len(e.failsib) > 1 {
		sibs = e.failsib

		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with the following existing constraints:\n"
		fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String())
	} else {
		sibs = e.nofailsib

		str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which does not overlap with the intersection of existing constraints from other currently selected packages:\n"
		fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident.errString(), e.goal.dep.Constraint.String())
	}

	for _, c := range sibs {
		fmt.Fprintf(&buf, "\t%s from %s\n", c.dep.Constraint.String(), a2vs(c.depender))
	}

	return buf.String()
}

func (e *disjointConstraintFailure) traceString() string {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "constraint %s on %s disjoint with other dependers:\n", e.goal.dep.Constraint.String(), e.goal.dep.Ident.errString())
	for _, f := range e.failsib {
		fmt.Fprintf(
			&buf,
			"%s from %s (no overlap)\n",
			f.dep.Constraint.String(),
			a2vs(f.depender),
		)
	}
	for _, f := range e.nofailsib {
		fmt.Fprintf(
			&buf,
			"%s from %s (some overlap)\n",
			f.dep.Constraint.String(),
			a2vs(f.depender),
		)
	}

	return buf.String()
}

// Indicates that an atom could not be introduced because one of its dep
// constraints does not admit the currently-selected version of the target
// project.
type constraintNotAllowedFailure struct {
	goal dependency
	v    Version
}

func (e *constraintNotAllowedFailure) Error() string {
	return fmt.Sprintf(
		"Could not introduce %s, as it has a dependency on %s with constraint %s, which does not allow the currently selected version of %s",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.goal.dep.Constraint,
		e.v,
	)
}

func (e *constraintNotAllowedFailure) traceString() string {
	return fmt.Sprintf(
		"%s depends on %s with %s, but that's already selected at %s",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.ProjectRoot,
		e.goal.dep.Constraint,
		e.v,
	)
}

type versionNotAllowedFailure struct {
	goal       atom
	failparent []dependency
	c          Constraint
}

func (e *versionNotAllowedFailure) Error() string {
	if len(e.failparent) == 1 {
		return fmt.Sprintf(
			"Could not introduce %s, as it is not allowed by constraint %s from project %s.",
			a2vs(e.goal),
			e.failparent[0].dep.Constraint.String(),
			e.failparent[0].depender.id.errString(),
		)
	}

	var buf bytes.Buffer

	fmt.Fprintf(&buf, "Could not introduce %s, as it is not allowed by constraints from the following projects:\n", a2vs(e.goal))

	for _, f := range e.failparent {
		fmt.Fprintf(&buf, "\t%s from %s\n", f.dep.Constraint.String(), a2vs(f.depender))
	}

	return buf.String()
}

func (e *versionNotAllowedFailure) traceString() string {
	var buf bytes.Buffer

	fmt.Fprintf(&buf, "%s not allowed by constraint %s:\n", a2vs(e.goal), e.c.String())
	for _, f := range e.failparent {
		fmt.Fprintf(&buf, "  %s from %s\n", f.dep.Constraint.String(), a2vs(f.depender))
	}

	return buf.String()
}

type missingSourceFailure struct {
	goal ProjectIdentifier
	prob string
}

func (e *missingSourceFailure) Error() string {
	return fmt.Sprintf(e.prob, e.goal)
}

type badOptsFailure string

func (e badOptsFailure) Error() string {
	return string(e)
}

type sourceMismatchFailure struct {
	// The ProjectRoot over which there is disagreement about where it should be
	// sourced from
	shared ProjectRoot
	// The current value for the network source
	current string
	// The mismatched value for the network source
	mismatch string
	// The currently selected dependencies which have agreed upon/established
	// the given network source
	sel []dependency
	// The atom with the constraint that has the new, incompatible network source
	prob atom
}

func (e *sourceMismatchFailure) Error() string {
	var cur []string
	for _, c := range e.sel {
		cur = append(cur, string(c.depender.id.ProjectRoot))
	}

	str := "Could not introduce %s, as it depends on %s from %s, but %s is already marked as coming from %s by %s"
	return fmt.Sprintf(str, a2vs(e.prob), e.shared, e.mismatch, e.shared, e.current, strings.Join(cur, ", "))
}

func (e *sourceMismatchFailure) traceString() string {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "disagreement on network addr for %s:\n", e.shared)

	fmt.Fprintf(&buf, "  %s from %s\n", e.mismatch, e.prob.id.errString())
	for _, dep := range e.sel {
		fmt.Fprintf(&buf, "  %s from %s\n", e.current, dep.depender.id.errString())
	}

	return buf.String()
}

type errDeppers struct {
	err     error
	deppers []atom
}
type checkeeHasProblemPackagesFailure struct {
	goal    atom
	failpkg map[string]errDeppers
}

func (e *checkeeHasProblemPackagesFailure) Error() string {
	var buf bytes.Buffer
	indent := ""

	if len(e.failpkg) > 1 {
		indent = "\t"
		fmt.Fprintf(
			&buf, "Could not introduce %s due to multiple problematic subpackages:\n",
			a2vs(e.goal),
		)
	}

	for pkg, errdep := range e.failpkg {
		var cause string
		if errdep.err == nil {
			cause = "is missing"
		} else {
			cause = fmt.Sprintf("does not contain usable Go code (%T).", errdep.err)
		}

		if len(e.failpkg) == 1 {
			fmt.Fprintf(
				&buf, "Could not introduce %s, as its subpackage %s %s.",
				a2vs(e.goal),
				pkg,
				cause,
			)
		} else {
			fmt.Fprintf(&buf, "\tSubpackage %s %s.", pkg, cause)
		}

		if len(errdep.deppers) == 1 {
			fmt.Fprintf(
				&buf, " (Package is required by %s.)",
				a2vs(errdep.deppers[0]),
			)
		} else {
			fmt.Fprintf(&buf, " Package is required by:")
			for _, pa := range errdep.deppers {
				fmt.Fprintf(&buf, "\n%s\t%s", indent, a2vs(pa))
			}
		}
	}

	return buf.String()
}

func (e *checkeeHasProblemPackagesFailure) traceString() string {
	var buf bytes.Buffer

	fmt.Fprintf(&buf, "%s at %s has problem subpkg(s):\n", e.goal.id.ProjectRoot, e.goal.v)
	for pkg, errdep := range e.failpkg {
		if errdep.err == nil {
			fmt.Fprintf(&buf, "\t%s is missing; ", pkg)
		} else {
			fmt.Fprintf(&buf, "\t%s has err (%T); ", pkg, errdep.err)
		}

		if len(errdep.deppers) == 1 {
			fmt.Fprintf(&buf, "required by %s.", a2vs(errdep.deppers[0]))
		} else {
			fmt.Fprintf(&buf, " required by:")
			for _, pa := range errdep.deppers {
				fmt.Fprintf(&buf, "\n\t\t%s at %s", pa.id.errString(), pa.v)
			}
		}
	}

	return buf.String()
}

type depHasProblemPackagesFailure struct {
	goal dependency
	v    Version
	pl   []string
	prob map[string]error
}

func (e *depHasProblemPackagesFailure) Error() string {
	fcause := func(pkg string) string {
		var cause string
		if err, has := e.prob[pkg]; has {
			cause = fmt.Sprintf("does not contain usable Go code (%T).", err)
		} else {
			cause = "is missing."
		}
		return cause
	}

	if len(e.pl) == 1 {
		return fmt.Sprintf(
			"Could not introduce %s, as it requires package %s from %s, but in version %s that package %s",
			a2vs(e.goal.depender),
			e.pl[0],
			e.goal.dep.Ident.errString(),
			e.v,
			fcause(e.pl[0]),
		)
	}

	var buf bytes.Buffer
	fmt.Fprintf(
		&buf, "Could not introduce %s, as it requires problematic packages from %s (current version %s):",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.v,
	)

	for _, pkg := range e.pl {
		fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
	}

	return buf.String()
}

func (e *depHasProblemPackagesFailure) traceString() string {
	var buf bytes.Buffer
	fcause := func(pkg string) string {
		var cause string
		if err, has := e.prob[pkg]; has {
			cause = fmt.Sprintf("has parsing err (%T).", err)
		} else {
			cause = "is missing"
		}
		return cause
	}

	fmt.Fprintf(
		&buf, "%s depping on %s at %s has problem subpkg(s):",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.v,
	)

	for _, pkg := range e.pl {
		fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
	}

	return buf.String()
}

// nonexistentRevisionFailure indicates that a revision constraint was specified
// for a given project, but that that revision does not exist in the source
// repository.
type nonexistentRevisionFailure struct {
	goal dependency
	r    Revision
}

func (e *nonexistentRevisionFailure) Error() string {
	return fmt.Sprintf(
		"Could not introduce %s, as it requires %s at revision %s, but that revision does not exist",
		a2vs(e.goal.depender),
		e.goal.dep.Ident.errString(),
		e.r,
	)
}

func (e *nonexistentRevisionFailure) traceString() string {
	return fmt.Sprintf(
		"%s wants missing rev %s of %s",
		a2vs(e.goal.depender),
		e.r,
		e.goal.dep.Ident.errString(),
	)
}
<|endoftext|>


<commit_before>// Package errors provides simple error handling primitives.
//
// The traditional error handling idiom in Go is roughly akin to
//
//      if err != nil {
//              return err
//      }
//
// which applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error.
//
// Adding context to an error
//
// The errors.Wrap function returns a new error that adds context to the
// original error. For example
//
//      _, err := ioutil.ReadAll(r)
//      if err != nil {
//              return errors.Wrap(err, "read failed")
//      }
//
// Retrieving the cause of an error
//
// Using errors.Wrap constructs a stack of errors, adding context to the
// preceding error. Depending on the nature of the error it may be necessary
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
//     type Causer interface {
//             Cause() error
//     }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be
// the original cause. For example:
//
//     switch err := errors.Cause(err).(type) {
//     case *MyError:
//             // handle specifically
//     default:
//             // unknown error
//     }
//
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface.
//
//     type Stacktrace interface {
//             Stacktrace() []Frame
//     }
package errors

import (
	"errors"
	"fmt"
	"io"
)

// New returns an error that formats as the given text.
func New(text string) error {
	return struct {
		error
		*stack
	}{
		errors.New(text),
		callers(),
	}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorf(format string, args ...interface{}) error {
	return struct {
		error
		*stack
	}{
		fmt.Errorf(format, args...),
		callers(),
	}
}

type cause struct {
	cause   error
	message string
}

func (c cause) Error() string   { return c.Message() + ": " + c.Cause().Error() }
func (c cause) Cause() error    { return c.cause }
func (c cause) Message() string { return c.message }

// Wrap returns an error annotating err with message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
	if err == nil {
		return nil
	}
	return struct {
		cause
		*stack
	}{
		cause{
			cause:   err,
			message: message,
		},
		callers(),
	}
}

// Wrapf returns an error annotating err with the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}
	return struct {
		cause
		*stack
	}{
		cause{
			cause:   err,
			message: fmt.Sprintf(format, args...),
		},
		callers(),
	}
}

type causer interface {
	Cause() error
}

// Cause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
//     type Causer interface {
//            Cause() error
//     }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func Cause(err error) error {
	for err != nil {
		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
	return err
}

// Fprint prints the error to the supplied writer.
// If the error implements the Causer interface described in Cause
// Print will recurse into the error's cause.
// If the error implements one of the following interfaces:
//
//     type Stacktrace interface {
//            Stacktrace() []Frame
//     }
//
// Print will also print the file and line of the error.
// If err is nil, nothing is printed.
//
// Deprecated: Fprint will be removed in version 0.7.
func Fprint(w io.Writer, err error) {
	type stacktrace interface {
		Stacktrace() []Frame
	}
	type message interface {
		Message() string
	}

	for err != nil {
		switch err := err.(type) {
		case stacktrace:
			frame := err.Stacktrace()[0]
			fmt.Fprintf(w, "%+v: ", frame)
		default:
			// de nada
		}
		switch err := err.(type) {
		case message:
			fmt.Fprintln(w, err.Message())
		default:
			fmt.Fprintln(w, err.Error())
		}

		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
}
<commit_msg>Remove Message interface (#39)<commit_after>// Package errors provides simple error handling primitives.
//
// The traditional error handling idiom in Go is roughly akin to
//
//      if err != nil {
//              return err
//      }
//
// which applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error.
//
// Adding context to an error
//
// The errors.Wrap function returns a new error that adds context to the
// original error. For example
//
//      _, err := ioutil.ReadAll(r)
//      if err != nil {
//              return errors.Wrap(err, "read failed")
//      }
//
// Retrieving the cause of an error
//
// Using errors.Wrap constructs a stack of errors, adding context to the
// preceding error. Depending on the nature of the error it may be necessary
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
//     type Causer interface {
//             Cause() error
//     }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be
// the original cause. For example:
//
//     switch err := errors.Cause(err).(type) {
//     case *MyError:
//             // handle specifically
//     default:
//             // unknown error
//     }
//
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface.
//
//     type Stacktrace interface {
//             Stacktrace() []Frame
//     }
package errors

import (
	"errors"
	"fmt"
	"io"
)

// New returns an error that formats as the given text.
func New(text string) error {
	return struct {
		error
		*stack
	}{
		errors.New(text),
		callers(),
	}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorf(format string, args ...interface{}) error {
	return struct {
		error
		*stack
	}{
		fmt.Errorf(format, args...),
		callers(),
	}
}

type cause struct {
	cause error
	msg   string
}

func (c cause) Error() string { return fmt.Sprintf("%v", c) }
func (c cause) Cause() error  { return c.cause }

func (c cause) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			io.WriteString(s, c.msg)
			return
		}
		fallthrough
	case 's':
		fmt.Fprintf(s, "%s: %v", c.msg, c.Cause())
	}
}

// Wrap returns an error annotating err with message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
	if err == nil {
		return nil
	}
	return struct {
		cause
		*stack
	}{
		cause{
			cause: err,
			msg:   message,
		},
		callers(),
	}
}

// Wrapf returns an error annotating err with the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}
	return struct {
		cause
		*stack
	}{
		cause{
			cause: err,
			msg:   fmt.Sprintf(format, args...),
		},
		callers(),
	}
}

type causer interface {
	Cause() error
}

// Cause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
//     type Causer interface {
//            Cause() error
//     }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func Cause(err error) error {
	for err != nil {
		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
	return err
}

// Fprint prints the error to the supplied writer.
// If the error implements the Causer interface described in Cause
// Print will recurse into the error's cause.
// If the error implements one of the following interfaces:
//
//     type Stacktrace interface {
//            Stacktrace() []Frame
//     }
//
// Print will also print the file and line of the error.
// If err is nil, nothing is printed.
//
// Deprecated: Fprint will be removed in version 0.7.
func Fprint(w io.Writer, err error) {
	type stacktrace interface {
		Stacktrace() []Frame
	}

	for err != nil {
		switch err := err.(type) {
		case stacktrace:
			frame := err.Stacktrace()[0]
			fmt.Fprintf(w, "%+v: ", frame)
		default:
			// de nada
		}
		fmt.Fprintf(w, "%+v\n", err)

		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
}
<|endoftext|>


<commit_before>package jwt

import (
	"errors"
)

// Error constants
var (
	ErrInvalidKey       = errors.New("key is invalid or of invalid type")
	ErrHashUnavailable  = errors.New("the requested hash function is unavailable")
	ErrNoTokenInRequest = errors.New("no token present in request")
)

// The errors that might occur when parsing and validating a token
const (
	ValidationErrorMalformed        uint32 = 1 << iota // Token is malformed
	ValidationErrorUnverifiable                        // Token could not be verified because of signing problems
	ValidationErrorSignatureInvalid                    // Signature validation failed
	ValidationErrorExpired                             // Exp validation failed
	ValidationErrorNotValidYet                         // NBF validation failed
)

// The error from Parse if token is not valid
type ValidationError struct {
	err    string
	Errors uint32 // bitfield.  see ValidationError... constants
}

// Validation error is an error type
func (e ValidationError) Error() string {
	if e.err == "" {
		return "token is invalid"
	}
	return e.err
}

// No errors
func (e *ValidationError) valid() bool {
	if e.Errors > 0 {
		return false
	}
	return true
}
<commit_msg>Add validation error bit for generic validation error.<commit_after>package jwt

import (
	"errors"
)

// Error constants
var (
	ErrInvalidKey       = errors.New("key is invalid or of invalid type")
	ErrHashUnavailable  = errors.New("the requested hash function is unavailable")
	ErrNoTokenInRequest = errors.New("no token present in request")
)

// The errors that might occur when parsing and validating a token
const (
	ValidationErrorMalformed        uint32 = 1 << iota // Token is malformed
	ValidationErrorUnverifiable                        // Token could not be verified because of signing problems
	ValidationErrorSignatureInvalid                    // Signature validation failed
	ValidationErrorExpired                             // Exp validation failed
	ValidationErrorNotValidYet                         // NBF validation failed
	ValidationErrorClaimsInvalid                       // Generic claims validation error
)

// The error from Parse if token is not valid
type ValidationError struct {
	err    string
	Errors uint32 // bitfield.  see ValidationError... constants
}

// Validation error is an error type
func (e ValidationError) Error() string {
	if e.err == "" {
		return "token is invalid"
	}
	return e.err
}

// No errors
func (e *ValidationError) valid() bool {
	if e.Errors > 0 {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"runtime"
)

const (
	VERSION = "0.21"
)

var cmdVersion = &Command{
	Run:       runVersion,
	UsageLine: "version",
	Short:     "print Weed File System version",
	Long:      `Version prints the Weed File System version`,
}

func runVersion(cmd *Command, args []string) bool {
	if len(args) != 0 {
		cmd.Usage()
	}

	fmt.Printf("version %s %s %s\n", VERSION, runtime.GOOS, runtime.GOARCH)
	return true
}
<commit_msg>bump up version<commit_after>package main

import (
	"fmt"
	"runtime"
)

const (
	VERSION = "0.22"
)

var cmdVersion = &Command{
	Run:       runVersion,
	UsageLine: "version",
	Short:     "print Weed File System version",
	Long:      `Version prints the Weed File System version`,
}

func runVersion(cmd *Command, args []string) bool {
	if len(args) != 0 {
		cmd.Usage()
	}

	fmt.Printf("version %s %s %s\n", VERSION, runtime.GOOS, runtime.GOARCH)
	return true
}
<|endoftext|>


<commit_before>package main

import "container/heap"

type event interface {
	Rank() int
	Action(*game)
	Renew(*game, int)
}

type iEvent struct {
	Event event
	Index int
}

type eventQueue []iEvent

func (evq eventQueue) Len() int {
	return len(evq)
}

func (evq eventQueue) Less(i, j int) bool {
	return evq[i].Event.Rank() < evq[j].Event.Rank() ||
		evq[i].Event.Rank() == evq[j].Event.Rank() && evq[i].Index < evq[j].Index
}

func (evq eventQueue) Swap(i, j int) {
	evq[i], evq[j] = evq[j], evq[i]
}

func (evq *eventQueue) Push(x interface{}) {
	no := x.(iEvent)
	*evq = append(*evq, no)
}

func (evq *eventQueue) Pop() interface{} {
	old := *evq
	n := len(old)
	no := old[n-1]
	*evq = old[0 : n-1]
	return no
}

type simpleAction int

const (
	PlayerTurn simpleAction = iota
	Teleportation
	BerserkEnd
	SlowEnd
	ExhaustionEnd
	HasteEnd
	EvasionEnd
	LignificationEnd
	ConfusionEnd
	NauseaEnd
	DisabledShieldEnd
	CorrosionEnd
	DigEnd
	SwapEnd
	ShadowsEnd
)

func (g *game) PushEvent(ev event) {
	iev := iEvent{Event: ev, Index: g.EventIndex}
	g.EventIndex++
	heap.Push(g.Events, iev)
}

func (g *game) PushAgainEvent(ev event) {
	iev := iEvent{Event: ev, Index: 0}
	heap.Push(g.Events, iev)
}

func (g *game) PopIEvent() iEvent {
	iev := heap.Pop(g.Events).(iEvent)
	return iev
}

type simpleEvent struct {
	ERank   int
	EAction simpleAction
}

func (sev *simpleEvent) Rank() int {
	return sev.ERank
}

func (sev *simpleEvent) Renew(g *game, delay int) {
	sev.ERank += delay
	if delay == 0 {
		g.PushAgainEvent(sev)
	} else {
		g.PushEvent(sev)
	}
}

func (sev *simpleEvent) Action(g *game) {
	switch sev.EAction {
	case PlayerTurn:
		g.ComputeNoise()
		g.LogNextTick = g.LogIndex
		g.AutoNext = g.AutoPlayer(sev)
		if g.AutoNext {
			g.TurnStats()
			return
		}
		g.Quit = g.ui.HandlePlayerTurn(g, sev)
		if g.Quit {
			return
		}
		g.TurnStats()
	case Teleportation:
		if !g.Player.HasStatus(StatusLignification) {
			g.Teleportation(sev)
		} else {
			g.Print("Lignification prevented teleportation.")
		}
		g.Player.Statuses[StatusTele] = 0
	case BerserkEnd:
		g.Player.Statuses[StatusBerserk] = 0
		g.Player.Statuses[StatusSlow] = 1
		g.Player.Statuses[StatusExhausted] = 1
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		g.PrintStyled("You are no longer berserk.", logStatusEnd)
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 90 + RandInt(30), EAction: SlowEnd})
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 270 + RandInt(60), EAction: ExhaustionEnd})
		g.ui.StatusEndAnimation(g)
	case SlowEnd:
		g.PrintStyled("You feel no longer slow.", logStatusEnd)
		g.Player.Statuses[StatusSlow] = 0
		g.ui.StatusEndAnimation(g)
	case ExhaustionEnd:
		g.PrintStyled("You feel no longer exhausted.", logStatusEnd)
		g.Player.Statuses[StatusExhausted] = 0
		g.ui.StatusEndAnimation(g)
	case HasteEnd:
		g.Player.Statuses[StatusSwift]--
		if g.Player.Statuses[StatusSwift] == 0 {
			g.PrintStyled("You feel no longer speedy.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case EvasionEnd:
		g.Player.Statuses[StatusAgile]--
		if g.Player.Statuses[StatusAgile] == 0 {
			g.PrintStyled("You feel no longer agile.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case LignificationEnd:
		g.Player.Statuses[StatusLignification]--
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		if g.Player.Statuses[StatusLignification] == 0 {
			g.PrintStyled("You feel no longer attached to the ground.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case ConfusionEnd:
		g.PrintStyled("You feel no longer confused.", logStatusEnd)
		g.Player.Statuses[StatusConfusion] = 0
		g.ui.StatusEndAnimation(g)
	case NauseaEnd:
		g.PrintStyled("You feel no longer sick.", logStatusEnd)
		g.Player.Statuses[StatusNausea] = 0
		g.ui.StatusEndAnimation(g)
	case DisabledShieldEnd:
		g.PrintStyled("You manage to free your shield from the projectile.", logStatusEnd)
		g.Player.Statuses[StatusDisabledShield] = 0
		g.ui.StatusEndAnimation(g)
	case CorrosionEnd:
		g.Player.Statuses[StatusCorrosion]--
		if g.Player.Statuses[StatusCorrosion] == 0 {
			g.PrintStyled("Your equipment is now free from acid.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case DigEnd:
		g.Player.Statuses[StatusDig] = 0
		if g.Player.Statuses[StatusDig] == 0 {
			g.PrintStyled("You feel no longer like an earth dragon.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case SwapEnd:
		g.Player.Statuses[StatusSwap] = 0
		if g.Player.Statuses[StatusSwap] == 0 {
			g.PrintStyled("You feel no longer dancing.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case ShadowsEnd:
		g.Player.Statuses[StatusShadows] = 0
		if g.Player.Statuses[StatusShadows] == 0 {
			g.PrintStyled("Shadows leaved you.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	}
}

type monsterAction int

const (
	MonsterTurn monsterAction = iota
	MonsConfusionEnd
	MonsExhaustionEnd
)

type monsterEvent struct {
	ERank   int
	NMons   int
	EAction monsterAction
}

func (mev *monsterEvent) Rank() int {
	return mev.ERank
}

func (mev *monsterEvent) Action(g *game) {
	switch mev.EAction {
	case MonsterTurn:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.HandleTurn(g, mev)
		}
	case MonsConfusionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsConfused] = 0
			g.Printf("The %s is no longer confused.", mons.Kind)
		}
	case MonsExhaustionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsExhausted] = 0
		}
	}
}

func (mev *monsterEvent) Renew(g *game, delay int) {
	mev.ERank += delay
	g.PushEvent(mev)
}

type cloudAction int

const (
	CloudEnd cloudAction = iota
	ObstructionEnd
	FireProgression
)

type cloudEvent struct {
	ERank   int
	Pos     position
	EAction cloudAction
}

func (cev *cloudEvent) Rank() int {
	return cev.ERank
}

func (cev *cloudEvent) Action(g *game) {
	switch cev.EAction {
	case CloudEnd:
		delete(g.Clouds, cev.Pos)
		g.ComputeLOS()
	case ObstructionEnd:
		if !g.Player.LOS[cev.Pos] && g.Dungeon.Cell(cev.Pos).T == WallCell {
			g.WrongWall[cev.Pos] = true
		} else {
			delete(g.TemporalWalls, cev.Pos)
		}
		if g.Dungeon.Cell(cev.Pos).T == FreeCell {
			break
		}
		g.Dungeon.SetCell(cev.Pos, FreeCell)
		g.MakeNoise(TemporalWallNoise, cev.Pos)
		g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
		g.ComputeLOS()
	case FireProgression:
		if _, ok := g.Clouds[cev.Pos]; !ok {
			break
		}
		g.BurnCreature(cev.Pos, cev)
		if RandInt(10) == 0 {
			delete(g.Clouds, cev.Pos)
			g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
			g.ComputeLOS()
			break
		}
		for _, pos := range g.Dungeon.FreeNeighbors(cev.Pos) {
			if RandInt(3) > 0 {
				continue
			}
			g.Burn(pos, cev)
		}
		cev.Renew(g, 10)
	}
}

func (g *game) BurnCreature(pos position, ev event) {
	mons := g.MonsterAt(pos)
	if mons.Exists() {
		mons.HP -= 1 + RandInt(10)
		if mons.HP <= 0 {
			g.PrintfStyled("%s is killed by the fire.", logPlayerHit, mons.Kind.Definite(true))
			g.HandleKill(mons, ev)
		} else {
			mons.MakeAwareIfHurt(g)
		}
	}
	if pos == g.Player.Pos {
		damage := 1 + RandInt(10)
		if damage > g.Player.HP {
			damage = 1 + RandInt(10)
		}
		g.Player.HP -= damage
		g.PrintfStyled("The fire burns you (%d dmg).", logMonsterHit, damage)
		if g.Player.HP+damage < 10 {
			g.Stats.TimesLucky++
		}
		g.StopAuto()
	}
}

func (g *game) Burn(pos position, ev event) {
	if _, ok := g.Clouds[pos]; ok {
		return
	}
	_, okFungus := g.Fungus[pos]
	_, okDoor := g.Doors[pos]
	if !okFungus && !okDoor {
		return
	}
	g.Stats.Burns++
	foliage := true
	delete(g.Fungus, pos)
	if _, ok := g.Doors[pos]; ok {
		delete(g.Doors, pos)
		foliage = false
		g.Print("The door vanishes in flames.")
	}
	g.Clouds[pos] = CloudFire
	if !g.Player.LOS[pos] {
		if foliage {
			g.WrongFoliage[pos] = true
		} else {
			g.WrongDoor[pos] = true
		}
	}
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 10, EAction: FireProgression, Pos: pos})
	g.BurnCreature(pos, ev)
}

func (cev *cloudEvent) Renew(g *game, delay int) {
	cev.ERank += delay
	g.PushEvent(cev)
}
<commit_msg>update LOS<commit_after>package main

import "container/heap"

type event interface {
	Rank() int
	Action(*game)
	Renew(*game, int)
}

type iEvent struct {
	Event event
	Index int
}

type eventQueue []iEvent

func (evq eventQueue) Len() int {
	return len(evq)
}

func (evq eventQueue) Less(i, j int) bool {
	return evq[i].Event.Rank() < evq[j].Event.Rank() ||
		evq[i].Event.Rank() == evq[j].Event.Rank() && evq[i].Index < evq[j].Index
}

func (evq eventQueue) Swap(i, j int) {
	evq[i], evq[j] = evq[j], evq[i]
}

func (evq *eventQueue) Push(x interface{}) {
	no := x.(iEvent)
	*evq = append(*evq, no)
}

func (evq *eventQueue) Pop() interface{} {
	old := *evq
	n := len(old)
	no := old[n-1]
	*evq = old[0 : n-1]
	return no
}

type simpleAction int

const (
	PlayerTurn simpleAction = iota
	Teleportation
	BerserkEnd
	SlowEnd
	ExhaustionEnd
	HasteEnd
	EvasionEnd
	LignificationEnd
	ConfusionEnd
	NauseaEnd
	DisabledShieldEnd
	CorrosionEnd
	DigEnd
	SwapEnd
	ShadowsEnd
)

func (g *game) PushEvent(ev event) {
	iev := iEvent{Event: ev, Index: g.EventIndex}
	g.EventIndex++
	heap.Push(g.Events, iev)
}

func (g *game) PushAgainEvent(ev event) {
	iev := iEvent{Event: ev, Index: 0}
	heap.Push(g.Events, iev)
}

func (g *game) PopIEvent() iEvent {
	iev := heap.Pop(g.Events).(iEvent)
	return iev
}

type simpleEvent struct {
	ERank   int
	EAction simpleAction
}

func (sev *simpleEvent) Rank() int {
	return sev.ERank
}

func (sev *simpleEvent) Renew(g *game, delay int) {
	sev.ERank += delay
	if delay == 0 {
		g.PushAgainEvent(sev)
	} else {
		g.PushEvent(sev)
	}
}

func (sev *simpleEvent) Action(g *game) {
	switch sev.EAction {
	case PlayerTurn:
		g.ComputeNoise()
		g.LogNextTick = g.LogIndex
		g.AutoNext = g.AutoPlayer(sev)
		if g.AutoNext {
			g.TurnStats()
			return
		}
		g.Quit = g.ui.HandlePlayerTurn(g, sev)
		if g.Quit {
			return
		}
		g.TurnStats()
	case Teleportation:
		if !g.Player.HasStatus(StatusLignification) {
			g.Teleportation(sev)
		} else {
			g.Print("Lignification prevented teleportation.")
		}
		g.Player.Statuses[StatusTele] = 0
	case BerserkEnd:
		g.Player.Statuses[StatusBerserk] = 0
		g.Player.Statuses[StatusSlow] = 1
		g.Player.Statuses[StatusExhausted] = 1
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		g.PrintStyled("You are no longer berserk.", logStatusEnd)
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 90 + RandInt(30), EAction: SlowEnd})
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 270 + RandInt(60), EAction: ExhaustionEnd})
		g.ui.StatusEndAnimation(g)
	case SlowEnd:
		g.PrintStyled("You feel no longer slow.", logStatusEnd)
		g.Player.Statuses[StatusSlow] = 0
		g.ui.StatusEndAnimation(g)
	case ExhaustionEnd:
		g.PrintStyled("You feel no longer exhausted.", logStatusEnd)
		g.Player.Statuses[StatusExhausted] = 0
		g.ui.StatusEndAnimation(g)
	case HasteEnd:
		g.Player.Statuses[StatusSwift]--
		if g.Player.Statuses[StatusSwift] == 0 {
			g.PrintStyled("You feel no longer speedy.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case EvasionEnd:
		g.Player.Statuses[StatusAgile]--
		if g.Player.Statuses[StatusAgile] == 0 {
			g.PrintStyled("You feel no longer agile.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case LignificationEnd:
		g.Player.Statuses[StatusLignification]--
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		if g.Player.Statuses[StatusLignification] == 0 {
			g.PrintStyled("You feel no longer attached to the ground.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case ConfusionEnd:
		g.PrintStyled("You feel no longer confused.", logStatusEnd)
		g.Player.Statuses[StatusConfusion] = 0
		g.ui.StatusEndAnimation(g)
	case NauseaEnd:
		g.PrintStyled("You feel no longer sick.", logStatusEnd)
		g.Player.Statuses[StatusNausea] = 0
		g.ui.StatusEndAnimation(g)
	case DisabledShieldEnd:
		g.PrintStyled("You manage to free your shield from the projectile.", logStatusEnd)
		g.Player.Statuses[StatusDisabledShield] = 0
		g.ui.StatusEndAnimation(g)
	case CorrosionEnd:
		g.Player.Statuses[StatusCorrosion]--
		if g.Player.Statuses[StatusCorrosion] == 0 {
			g.PrintStyled("Your equipment is now free from acid.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case DigEnd:
		g.Player.Statuses[StatusDig] = 0
		if g.Player.Statuses[StatusDig] == 0 {
			g.PrintStyled("You feel no longer like an earth dragon.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case SwapEnd:
		g.Player.Statuses[StatusSwap] = 0
		if g.Player.Statuses[StatusSwap] == 0 {
			g.PrintStyled("You feel no longer dancing.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
		}
	case ShadowsEnd:
		g.Player.Statuses[StatusShadows] = 0
		if g.Player.Statuses[StatusShadows] == 0 {
			g.PrintStyled("Shadows leaved you.", logStatusEnd)
			g.ui.StatusEndAnimation(g)
			g.ComputeLOS()
			g.MakeMonstersAware()
		}
	}
}

type monsterAction int

const (
	MonsterTurn monsterAction = iota
	MonsConfusionEnd
	MonsExhaustionEnd
)

type monsterEvent struct {
	ERank   int
	NMons   int
	EAction monsterAction
}

func (mev *monsterEvent) Rank() int {
	return mev.ERank
}

func (mev *monsterEvent) Action(g *game) {
	switch mev.EAction {
	case MonsterTurn:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.HandleTurn(g, mev)
		}
	case MonsConfusionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsConfused] = 0
			g.Printf("The %s is no longer confused.", mons.Kind)
		}
	case MonsExhaustionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsExhausted] = 0
		}
	}
}

func (mev *monsterEvent) Renew(g *game, delay int) {
	mev.ERank += delay
	g.PushEvent(mev)
}

type cloudAction int

const (
	CloudEnd cloudAction = iota
	ObstructionEnd
	FireProgression
)

type cloudEvent struct {
	ERank   int
	Pos     position
	EAction cloudAction
}

func (cev *cloudEvent) Rank() int {
	return cev.ERank
}

func (cev *cloudEvent) Action(g *game) {
	switch cev.EAction {
	case CloudEnd:
		delete(g.Clouds, cev.Pos)
		g.ComputeLOS()
	case ObstructionEnd:
		if !g.Player.LOS[cev.Pos] && g.Dungeon.Cell(cev.Pos).T == WallCell {
			g.WrongWall[cev.Pos] = true
		} else {
			delete(g.TemporalWalls, cev.Pos)
		}
		if g.Dungeon.Cell(cev.Pos).T == FreeCell {
			break
		}
		g.Dungeon.SetCell(cev.Pos, FreeCell)
		g.MakeNoise(TemporalWallNoise, cev.Pos)
		g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
		g.ComputeLOS()
	case FireProgression:
		if _, ok := g.Clouds[cev.Pos]; !ok {
			break
		}
		g.BurnCreature(cev.Pos, cev)
		if RandInt(10) == 0 {
			delete(g.Clouds, cev.Pos)
			g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
			g.ComputeLOS()
			break
		}
		for _, pos := range g.Dungeon.FreeNeighbors(cev.Pos) {
			if RandInt(3) > 0 {
				continue
			}
			g.Burn(pos, cev)
		}
		cev.Renew(g, 10)
	}
}

func (g *game) BurnCreature(pos position, ev event) {
	mons := g.MonsterAt(pos)
	if mons.Exists() {
		mons.HP -= 1 + RandInt(10)
		if mons.HP <= 0 {
			g.PrintfStyled("%s is killed by the fire.", logPlayerHit, mons.Kind.Definite(true))
			g.HandleKill(mons, ev)
		} else {
			mons.MakeAwareIfHurt(g)
		}
	}
	if pos == g.Player.Pos {
		damage := 1 + RandInt(10)
		if damage > g.Player.HP {
			damage = 1 + RandInt(10)
		}
		g.Player.HP -= damage
		g.PrintfStyled("The fire burns you (%d dmg).", logMonsterHit, damage)
		if g.Player.HP+damage < 10 {
			g.Stats.TimesLucky++
		}
		g.StopAuto()
	}
}

func (g *game) Burn(pos position, ev event) {
	if _, ok := g.Clouds[pos]; ok {
		return
	}
	_, okFungus := g.Fungus[pos]
	_, okDoor := g.Doors[pos]
	if !okFungus && !okDoor {
		return
	}
	g.Stats.Burns++
	foliage := true
	delete(g.Fungus, pos)
	if _, ok := g.Doors[pos]; ok {
		delete(g.Doors, pos)
		foliage = false
		g.Print("The door vanishes in flames.")
	}
	g.Clouds[pos] = CloudFire
	if !g.Player.LOS[pos] {
		if foliage {
			g.WrongFoliage[pos] = true
		} else {
			g.WrongDoor[pos] = true
		}
	}
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 10, EAction: FireProgression, Pos: pos})
	g.BurnCreature(pos, ev)
}

func (cev *cloudEvent) Renew(g *game, delay int) {
	cev.ERank += delay
	g.PushEvent(cev)
}
<|endoftext|>


<commit_before>package main

import "container/heap"

type event interface {
	Rank() int
	Action(*game)
	Renew(*game, int)
}

type iEvent struct {
	Event event
	Index int
}

type eventQueue []iEvent

func (evq eventQueue) Len() int {
	return len(evq)
}

func (evq eventQueue) Less(i, j int) bool {
	return evq[i].Event.Rank() < evq[j].Event.Rank() ||
		evq[i].Event.Rank() == evq[j].Event.Rank() && evq[i].Index < evq[j].Index
}

func (evq eventQueue) Swap(i, j int) {
	evq[i], evq[j] = evq[j], evq[i]
}

func (evq *eventQueue) Push(x interface{}) {
	no := x.(iEvent)
	*evq = append(*evq, no)
}

func (evq *eventQueue) Pop() interface{} {
	old := *evq
	n := len(old)
	no := old[n-1]
	*evq = old[0 : n-1]
	return no
}

type simpleAction int

const (
	PlayerTurn simpleAction = iota
	HealPlayer
	MPRegen
	Teleportation
	BerserkEnd
	SlowEnd
	ExhaustionEnd
	HasteEnd
	EvasionEnd
	LignificationEnd
	ConfusionEnd
	NauseaEnd
	DisabledShieldEnd
	CorrosionEnd
)

func (g *game) PushEvent(ev event) {
	iev := iEvent{Event: ev, Index: g.EventIndex}
	g.EventIndex++
	heap.Push(g.Events, iev)
}

func (g *game) PopIEvent() iEvent {
	iev := heap.Pop(g.Events).(iEvent)
	return iev
}

type simpleEvent struct {
	ERank   int
	EAction simpleAction
}

func (sev *simpleEvent) Rank() int {
	return sev.ERank
}

func (sev *simpleEvent) Renew(g *game, delay int) {
	sev.ERank += delay
	g.PushEvent(sev)
}

func (sev *simpleEvent) Action(g *game) {
	switch sev.EAction {
	case PlayerTurn:
		g.ComputeNoise()
		g.LogNextTick = g.LogIndex
		g.AutoNext = g.AutoPlayer(sev)
		if g.AutoNext {
			return
		}
		g.Quit = g.ui.HandlePlayerTurn(g, sev)
		if g.Quit {
			return
		}
	case HealPlayer:
		g.HealPlayer(sev)
	case MPRegen:
		g.MPRegen(sev)
	case Teleportation:
		g.Teleportation(sev)
		g.Player.Statuses[StatusTele] = 0
	case BerserkEnd:
		g.Player.Statuses[StatusBerserk]--
		g.Player.Statuses[StatusSlow]++
		g.Player.Statuses[StatusExhausted]++
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		g.PrintStyled("You are no longer berserk.", logStatusEnd)
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 90 + RandInt(40), EAction: SlowEnd})
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 270 + RandInt(60), EAction: ExhaustionEnd})
	case SlowEnd:
		g.PrintStyled("You feel no longer slow.", logStatusEnd)
		g.Player.Statuses[StatusSlow]--
	case ExhaustionEnd:
		g.PrintStyled("You feel no longer exhausted.", logStatusEnd)
		g.Player.Statuses[StatusExhausted]--
	case HasteEnd:
		g.Player.Statuses[StatusSwift]--
		if g.Player.Statuses[StatusSwift] == 0 {
			g.PrintStyled("You feel no longer speedy.", logStatusEnd)
		}
	case EvasionEnd:
		g.Player.Statuses[StatusAgile]--
		if g.Player.Statuses[StatusAgile] == 0 {
			g.PrintStyled("You feel no longer agile.", logStatusEnd)
		}
	case LignificationEnd:
		g.Player.Statuses[StatusLignification]--
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		if g.Player.Statuses[StatusLignification] == 0 {
			g.PrintStyled("You feel no longer attached to the ground.", logStatusEnd)
		}
	case ConfusionEnd:
		g.PrintStyled("You feel no longer confused.", logStatusEnd)
		g.Player.Statuses[StatusConfusion]--
	case NauseaEnd:
		g.PrintStyled("You feel no longer sick.", logStatusEnd)
		g.Player.Statuses[StatusNausea]--
	case DisabledShieldEnd:
		g.PrintStyled("You manage to free your shield from the projectile.", logStatusEnd)
		g.Player.Statuses[StatusDisabledShield]--
	case CorrosionEnd:
		g.Player.Statuses[StatusCorrosion]--
		if g.Player.Statuses[StatusCorrosion] == 0 {
			g.PrintStyled("Your equipment is now free from acid.", logStatusEnd)
		}
	}
}

type monsterAction int

const (
	MonsterTurn monsterAction = iota
	HealMonster
	MonsConfusionEnd
	MonsExhaustionEnd
)

type monsterEvent struct {
	ERank   int
	NMons   int
	EAction monsterAction
}

func (mev *monsterEvent) Rank() int {
	return mev.ERank
}

func (mev *monsterEvent) Action(g *game) {
	switch mev.EAction {
	case MonsterTurn:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.HandleTurn(g, mev)
		}
	case HealMonster:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Heal(g, mev)
		}
	case MonsConfusionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsConfused] = 0
			g.Printf("The %s is no longer confused.", mons.Kind)
		}
	case MonsExhaustionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsExhausted] = 0
		}
	}
}

func (mev *monsterEvent) Renew(g *game, delay int) {
	mev.ERank += delay
	g.PushEvent(mev)
}

type cloudAction int

const (
	CloudEnd cloudAction = iota
	ObstructionEnd
	FireProgression
)

type cloudEvent struct {
	ERank   int
	Pos     position
	EAction cloudAction
}

func (cev *cloudEvent) Rank() int {
	return cev.ERank
}

func (cev *cloudEvent) Action(g *game) {
	switch cev.EAction {
	case CloudEnd:
		delete(g.Clouds, cev.Pos)
		g.ComputeLOS()
	case ObstructionEnd:
		if !g.Player.LOS[cev.Pos] && g.Dungeon.Cell(cev.Pos).T == WallCell {
			g.UnknownDig[cev.Pos] = true
		} else {
			delete(g.TemporalWalls, cev.Pos)
		}
		if g.Dungeon.Cell(cev.Pos).T == FreeCell {
			break
		}
		g.Dungeon.SetCell(cev.Pos, FreeCell)
		g.MakeNoise(15, cev.Pos)
		g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
		g.ComputeLOS()
	case FireProgression:
		if _, ok := g.Clouds[cev.Pos]; !ok {
			break
		}
		g.BurnCreature(cev.Pos, cev)
		if RandInt(10) == 0 {
			delete(g.Clouds, cev.Pos)
			g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
			g.ComputeLOS()
			break
		}
		for _, pos := range g.Dungeon.FreeNeighbors(cev.Pos) {
			if RandInt(3) > 0 {
				continue
			}
			g.Burn(pos, cev)
		}
		cev.Renew(g, 10)
	}
}

func (g *game) BurnCreature(pos position, ev event) {
	mons, _ := g.MonsterAt(pos)
	if mons.Exists() {
		mons.HP -= 1 + RandInt(10)
		if mons.HP <= 0 {
			g.PrintfStyled("%s is killed by the fire.", logPlayerHit, mons.Kind.Definite(true))
			g.HandleKill(mons, ev)
		}
	}
	if pos == g.Player.Pos {
		damage := 1 + RandInt(10)
		g.Player.HP -= damage
		g.PrintfStyled("The fire burns you (%d damage).", logMonsterHit, damage)
	}
}

func (g *game) Burn(pos position, ev event) {
	if _, ok := g.Clouds[pos]; ok {
		return
	}
	_, okFungus := g.Fungus[pos]
	_, okDoor := g.Doors[pos]
	if !okFungus && !okDoor {
		return
	}
	delete(g.Fungus, pos)
	delete(g.Doors, pos)
	g.Clouds[pos] = CloudFire
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 10, EAction: FireProgression, Pos: pos})
	g.BurnCreature(pos, ev)
}

func (cev *cloudEvent) Renew(g *game, delay int) {
	cev.ERank += delay
	g.PushEvent(cev)
}
<commit_msg>add log message when a door catches fire<commit_after>package main

import "container/heap"

type event interface {
	Rank() int
	Action(*game)
	Renew(*game, int)
}

type iEvent struct {
	Event event
	Index int
}

type eventQueue []iEvent

func (evq eventQueue) Len() int {
	return len(evq)
}

func (evq eventQueue) Less(i, j int) bool {
	return evq[i].Event.Rank() < evq[j].Event.Rank() ||
		evq[i].Event.Rank() == evq[j].Event.Rank() && evq[i].Index < evq[j].Index
}

func (evq eventQueue) Swap(i, j int) {
	evq[i], evq[j] = evq[j], evq[i]
}

func (evq *eventQueue) Push(x interface{}) {
	no := x.(iEvent)
	*evq = append(*evq, no)
}

func (evq *eventQueue) Pop() interface{} {
	old := *evq
	n := len(old)
	no := old[n-1]
	*evq = old[0 : n-1]
	return no
}

type simpleAction int

const (
	PlayerTurn simpleAction = iota
	HealPlayer
	MPRegen
	Teleportation
	BerserkEnd
	SlowEnd
	ExhaustionEnd
	HasteEnd
	EvasionEnd
	LignificationEnd
	ConfusionEnd
	NauseaEnd
	DisabledShieldEnd
	CorrosionEnd
)

func (g *game) PushEvent(ev event) {
	iev := iEvent{Event: ev, Index: g.EventIndex}
	g.EventIndex++
	heap.Push(g.Events, iev)
}

func (g *game) PopIEvent() iEvent {
	iev := heap.Pop(g.Events).(iEvent)
	return iev
}

type simpleEvent struct {
	ERank   int
	EAction simpleAction
}

func (sev *simpleEvent) Rank() int {
	return sev.ERank
}

func (sev *simpleEvent) Renew(g *game, delay int) {
	sev.ERank += delay
	g.PushEvent(sev)
}

func (sev *simpleEvent) Action(g *game) {
	switch sev.EAction {
	case PlayerTurn:
		g.ComputeNoise()
		g.LogNextTick = g.LogIndex
		g.AutoNext = g.AutoPlayer(sev)
		if g.AutoNext {
			return
		}
		g.Quit = g.ui.HandlePlayerTurn(g, sev)
		if g.Quit {
			return
		}
	case HealPlayer:
		g.HealPlayer(sev)
	case MPRegen:
		g.MPRegen(sev)
	case Teleportation:
		g.Teleportation(sev)
		g.Player.Statuses[StatusTele] = 0
	case BerserkEnd:
		g.Player.Statuses[StatusBerserk]--
		g.Player.Statuses[StatusSlow]++
		g.Player.Statuses[StatusExhausted]++
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		g.PrintStyled("You are no longer berserk.", logStatusEnd)
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 90 + RandInt(40), EAction: SlowEnd})
		g.PushEvent(&simpleEvent{ERank: sev.Rank() + 270 + RandInt(60), EAction: ExhaustionEnd})
	case SlowEnd:
		g.PrintStyled("You feel no longer slow.", logStatusEnd)
		g.Player.Statuses[StatusSlow]--
	case ExhaustionEnd:
		g.PrintStyled("You feel no longer exhausted.", logStatusEnd)
		g.Player.Statuses[StatusExhausted]--
	case HasteEnd:
		g.Player.Statuses[StatusSwift]--
		if g.Player.Statuses[StatusSwift] == 0 {
			g.PrintStyled("You feel no longer speedy.", logStatusEnd)
		}
	case EvasionEnd:
		g.Player.Statuses[StatusAgile]--
		if g.Player.Statuses[StatusAgile] == 0 {
			g.PrintStyled("You feel no longer agile.", logStatusEnd)
		}
	case LignificationEnd:
		g.Player.Statuses[StatusLignification]--
		g.Player.HP -= int(10 * g.Player.HP / Max(g.Player.HPMax(), g.Player.HP))
		if g.Player.Statuses[StatusLignification] == 0 {
			g.PrintStyled("You feel no longer attached to the ground.", logStatusEnd)
		}
	case ConfusionEnd:
		g.PrintStyled("You feel no longer confused.", logStatusEnd)
		g.Player.Statuses[StatusConfusion]--
	case NauseaEnd:
		g.PrintStyled("You feel no longer sick.", logStatusEnd)
		g.Player.Statuses[StatusNausea]--
	case DisabledShieldEnd:
		g.PrintStyled("You manage to free your shield from the projectile.", logStatusEnd)
		g.Player.Statuses[StatusDisabledShield]--
	case CorrosionEnd:
		g.Player.Statuses[StatusCorrosion]--
		if g.Player.Statuses[StatusCorrosion] == 0 {
			g.PrintStyled("Your equipment is now free from acid.", logStatusEnd)
		}
	}
}

type monsterAction int

const (
	MonsterTurn monsterAction = iota
	HealMonster
	MonsConfusionEnd
	MonsExhaustionEnd
)

type monsterEvent struct {
	ERank   int
	NMons   int
	EAction monsterAction
}

func (mev *monsterEvent) Rank() int {
	return mev.ERank
}

func (mev *monsterEvent) Action(g *game) {
	switch mev.EAction {
	case MonsterTurn:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.HandleTurn(g, mev)
		}
	case HealMonster:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Heal(g, mev)
		}
	case MonsConfusionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsConfused] = 0
			g.Printf("The %s is no longer confused.", mons.Kind)
		}
	case MonsExhaustionEnd:
		mons := g.Monsters[mev.NMons]
		if mons.Exists() {
			mons.Statuses[MonsExhausted] = 0
		}
	}
}

func (mev *monsterEvent) Renew(g *game, delay int) {
	mev.ERank += delay
	g.PushEvent(mev)
}

type cloudAction int

const (
	CloudEnd cloudAction = iota
	ObstructionEnd
	FireProgression
)

type cloudEvent struct {
	ERank   int
	Pos     position
	EAction cloudAction
}

func (cev *cloudEvent) Rank() int {
	return cev.ERank
}

func (cev *cloudEvent) Action(g *game) {
	switch cev.EAction {
	case CloudEnd:
		delete(g.Clouds, cev.Pos)
		g.ComputeLOS()
	case ObstructionEnd:
		if !g.Player.LOS[cev.Pos] && g.Dungeon.Cell(cev.Pos).T == WallCell {
			g.UnknownDig[cev.Pos] = true
		} else {
			delete(g.TemporalWalls, cev.Pos)
		}
		if g.Dungeon.Cell(cev.Pos).T == FreeCell {
			break
		}
		g.Dungeon.SetCell(cev.Pos, FreeCell)
		g.MakeNoise(15, cev.Pos)
		g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
		g.ComputeLOS()
	case FireProgression:
		if _, ok := g.Clouds[cev.Pos]; !ok {
			break
		}
		g.BurnCreature(cev.Pos, cev)
		if RandInt(10) == 0 {
			delete(g.Clouds, cev.Pos)
			g.Fog(cev.Pos, 1, &simpleEvent{ERank: cev.Rank()})
			g.ComputeLOS()
			break
		}
		for _, pos := range g.Dungeon.FreeNeighbors(cev.Pos) {
			if RandInt(3) > 0 {
				continue
			}
			g.Burn(pos, cev)
		}
		cev.Renew(g, 10)
	}
}

func (g *game) BurnCreature(pos position, ev event) {
	mons, _ := g.MonsterAt(pos)
	if mons.Exists() {
		mons.HP -= 1 + RandInt(10)
		if mons.HP <= 0 {
			g.PrintfStyled("%s is killed by the fire.", logPlayerHit, mons.Kind.Definite(true))
			g.HandleKill(mons, ev)
		}
	}
	if pos == g.Player.Pos {
		damage := 1 + RandInt(10)
		g.Player.HP -= damage
		g.PrintfStyled("The fire burns you (%d damage).", logMonsterHit, damage)
	}
}

func (g *game) Burn(pos position, ev event) {
	if _, ok := g.Clouds[pos]; ok {
		return
	}
	_, okFungus := g.Fungus[pos]
	_, okDoor := g.Doors[pos]
	if !okFungus && !okDoor {
		return
	}
	delete(g.Fungus, pos)
	if _, ok := g.Doors[pos]; ok {
		delete(g.Doors, pos)
		g.Print("The door vanishes in flames.")
	}
	g.Clouds[pos] = CloudFire
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 10, EAction: FireProgression, Pos: pos})
	g.BurnCreature(pos, ev)
}

func (cev *cloudEvent) Renew(g *game, delay int) {
	cev.ERank += delay
	g.PushEvent(cev)
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).

package client

import (
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"net/url"
	"time"

	syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
	"github.com/syncthing/syncthing/lib/relay/protocol"
	"github.com/syncthing/syncthing/lib/sync"
)

type ProtocolClient struct {
	URI         *url.URL
	Invitations chan protocol.SessionInvitation

	closeInvitationsOnFinish bool

	config *tls.Config

	timeout time.Duration

	stop    chan struct{}
	stopped chan struct{}

	conn *tls.Conn

	mut       sync.RWMutex
	connected bool
	latency   time.Duration
}

func NewProtocolClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) *ProtocolClient {
	closeInvitationsOnFinish := false
	if invitations == nil {
		closeInvitationsOnFinish = true
		invitations = make(chan protocol.SessionInvitation)
	}

	return &ProtocolClient{
		URI:         uri,
		Invitations: invitations,

		closeInvitationsOnFinish: closeInvitationsOnFinish,

		config: configForCerts(certs),

		timeout: time.Minute * 2,

		stop:    make(chan struct{}),
		stopped: make(chan struct{}),

		mut:       sync.NewRWMutex(),
		connected: false,
	}
}

func (c *ProtocolClient) Serve() {
	c.stop = make(chan struct{})
	c.stopped = make(chan struct{})
	defer close(c.stopped)

	if err := c.connect(); err != nil {
		l.Debugln("Relay connect:", err)
		return
	}

	l.Debugln(c, "connected", c.conn.RemoteAddr())

	if err := c.join(); err != nil {
		c.conn.Close()
		l.Infoln("Relay join:", err)
		return
	}

	if err := c.conn.SetDeadline(time.Time{}); err != nil {
		l.Infoln("Relay set deadline:", err)
		return
	}

	l.Debugln(c, "joined", c.conn.RemoteAddr(), "via", c.conn.LocalAddr())

	defer c.cleanup()
	c.mut.Lock()
	c.connected = true
	c.mut.Unlock()

	messages := make(chan interface{})
	errors := make(chan error, 1)

	go messageReader(c.conn, messages, errors)

	timeout := time.NewTimer(c.timeout)

	for {
		select {
		case message := <-messages:
			timeout.Reset(c.timeout)
			log.Printf("%s received message %T", c, message)

			switch msg := message.(type) {
			case protocol.Ping:
				if err := protocol.WriteMessage(c.conn, protocol.Pong{}); err != nil {
					l.Infoln("Relay write:", err)
					return

				}
				l.Debugln(c, "sent pong")

			case protocol.SessionInvitation:
				ip := net.IP(msg.Address)
				if len(ip) == 0 || ip.IsUnspecified() {
					msg.Address = c.conn.RemoteAddr().(*net.TCPAddr).IP[:]
				}
				c.Invitations <- msg

			default:
				l.Infoln("Relay: protocol error: unexpected message %v", msg)
				return
			}

		case <-c.stop:
			l.Debugln(c, "stopping")
			return

		case err := <-errors:
			l.Infoln("Relay received:", err)
			return

		case <-timeout.C:
			l.Debugln(c, "timed out")
			return
		}
	}
}

func (c *ProtocolClient) Stop() {
	if c.stop == nil {
		return
	}

	close(c.stop)
	<-c.stopped
}

func (c *ProtocolClient) StatusOK() bool {
	c.mut.RLock()
	con := c.connected
	c.mut.RUnlock()
	return con
}

func (c *ProtocolClient) Latency() time.Duration {
	c.mut.RLock()
	lat := c.latency
	c.mut.RUnlock()
	return lat
}

func (c *ProtocolClient) String() string {
	return fmt.Sprintf("ProtocolClient@%p", c)
}

func (c *ProtocolClient) connect() error {
	if c.URI.Scheme != "relay" {
		return fmt.Errorf("Unsupported relay schema: %v", c.URI.Scheme)
	}

	t0 := time.Now()
	tcpConn, err := net.Dial("tcp", c.URI.Host)
	if err != nil {
		return err
	}

	c.mut.Lock()
	c.latency = time.Since(t0)
	c.mut.Unlock()

	conn := tls.Client(tcpConn, c.config)
	if err = conn.Handshake(); err != nil {
		return err
	}

	if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
		conn.Close()
		return err
	}

	if err := performHandshakeAndValidation(conn, c.URI); err != nil {
		conn.Close()
		return err
	}

	c.conn = conn
	return nil
}

func (c *ProtocolClient) cleanup() {
	if c.closeInvitationsOnFinish {
		close(c.Invitations)
		c.Invitations = make(chan protocol.SessionInvitation)
	}

	l.Debugln(c, "cleaning up")

	c.mut.Lock()
	c.connected = false
	c.mut.Unlock()

	c.conn.Close()
}

func (c *ProtocolClient) join() error {
	if err := protocol.WriteMessage(c.conn, protocol.JoinRelayRequest{}); err != nil {
		return err
	}

	message, err := protocol.ReadMessage(c.conn)
	if err != nil {
		return err
	}

	switch msg := message.(type) {
	case protocol.Response:
		if msg.Code != 0 {
			return fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
		}

	default:
		return fmt.Errorf("protocol error: expecting response got %v", msg)
	}

	return nil
}

func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
	if err := conn.Handshake(); err != nil {
		return err
	}

	cs := conn.ConnectionState()
	if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != protocol.ProtocolName {
		return fmt.Errorf("protocol negotiation error")
	}

	q := uri.Query()
	relayIDs := q.Get("id")
	if relayIDs != "" {
		relayID, err := syncthingprotocol.DeviceIDFromString(relayIDs)
		if err != nil {
			return fmt.Errorf("relay address contains invalid verification id: %s", err)
		}

		certs := cs.PeerCertificates
		if cl := len(certs); cl != 1 {
			return fmt.Errorf("unexpected certificate count: %d", cl)
		}

		remoteID := syncthingprotocol.NewDeviceID(certs[0].Raw)
		if remoteID != relayID {
			return fmt.Errorf("relay id does not match. Expected %v got %v", relayID, remoteID)
		}
	}

	return nil
}

func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- error) {
	for {
		msg, err := protocol.ReadMessage(conn)
		if err != nil {
			errors <- err
			return
		}
		messages <- msg
	}
}
<commit_msg>Silence spurious debug (fixes #2369)<commit_after>// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).

package client

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/url"
	"time"

	syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
	"github.com/syncthing/syncthing/lib/relay/protocol"
	"github.com/syncthing/syncthing/lib/sync"
)

type ProtocolClient struct {
	URI         *url.URL
	Invitations chan protocol.SessionInvitation

	closeInvitationsOnFinish bool

	config *tls.Config

	timeout time.Duration

	stop    chan struct{}
	stopped chan struct{}

	conn *tls.Conn

	mut       sync.RWMutex
	connected bool
	latency   time.Duration
}

func NewProtocolClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) *ProtocolClient {
	closeInvitationsOnFinish := false
	if invitations == nil {
		closeInvitationsOnFinish = true
		invitations = make(chan protocol.SessionInvitation)
	}

	return &ProtocolClient{
		URI:         uri,
		Invitations: invitations,

		closeInvitationsOnFinish: closeInvitationsOnFinish,

		config: configForCerts(certs),

		timeout: time.Minute * 2,

		stop:    make(chan struct{}),
		stopped: make(chan struct{}),

		mut:       sync.NewRWMutex(),
		connected: false,
	}
}

func (c *ProtocolClient) Serve() {
	c.stop = make(chan struct{})
	c.stopped = make(chan struct{})
	defer close(c.stopped)

	if err := c.connect(); err != nil {
		l.Debugln("Relay connect:", err)
		return
	}

	l.Debugln(c, "connected", c.conn.RemoteAddr())

	if err := c.join(); err != nil {
		c.conn.Close()
		l.Infoln("Relay join:", err)
		return
	}

	if err := c.conn.SetDeadline(time.Time{}); err != nil {
		l.Infoln("Relay set deadline:", err)
		return
	}

	l.Debugln(c, "joined", c.conn.RemoteAddr(), "via", c.conn.LocalAddr())

	defer c.cleanup()
	c.mut.Lock()
	c.connected = true
	c.mut.Unlock()

	messages := make(chan interface{})
	errors := make(chan error, 1)

	go messageReader(c.conn, messages, errors)

	timeout := time.NewTimer(c.timeout)

	for {
		select {
		case message := <-messages:
			timeout.Reset(c.timeout)
			l.Debugf("%s received message %T", c, message)

			switch msg := message.(type) {
			case protocol.Ping:
				if err := protocol.WriteMessage(c.conn, protocol.Pong{}); err != nil {
					l.Infoln("Relay write:", err)
					return

				}
				l.Debugln(c, "sent pong")

			case protocol.SessionInvitation:
				ip := net.IP(msg.Address)
				if len(ip) == 0 || ip.IsUnspecified() {
					msg.Address = c.conn.RemoteAddr().(*net.TCPAddr).IP[:]
				}
				c.Invitations <- msg

			default:
				l.Infoln("Relay: protocol error: unexpected message %v", msg)
				return
			}

		case <-c.stop:
			l.Debugln(c, "stopping")
			return

		case err := <-errors:
			l.Infoln("Relay received:", err)
			return

		case <-timeout.C:
			l.Debugln(c, "timed out")
			return
		}
	}
}

func (c *ProtocolClient) Stop() {
	if c.stop == nil {
		return
	}

	close(c.stop)
	<-c.stopped
}

func (c *ProtocolClient) StatusOK() bool {
	c.mut.RLock()
	con := c.connected
	c.mut.RUnlock()
	return con
}

func (c *ProtocolClient) Latency() time.Duration {
	c.mut.RLock()
	lat := c.latency
	c.mut.RUnlock()
	return lat
}

func (c *ProtocolClient) String() string {
	return fmt.Sprintf("ProtocolClient@%p", c)
}

func (c *ProtocolClient) connect() error {
	if c.URI.Scheme != "relay" {
		return fmt.Errorf("Unsupported relay schema: %v", c.URI.Scheme)
	}

	t0 := time.Now()
	tcpConn, err := net.Dial("tcp", c.URI.Host)
	if err != nil {
		return err
	}

	c.mut.Lock()
	c.latency = time.Since(t0)
	c.mut.Unlock()

	conn := tls.Client(tcpConn, c.config)
	if err = conn.Handshake(); err != nil {
		return err
	}

	if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
		conn.Close()
		return err
	}

	if err := performHandshakeAndValidation(conn, c.URI); err != nil {
		conn.Close()
		return err
	}

	c.conn = conn
	return nil
}

func (c *ProtocolClient) cleanup() {
	if c.closeInvitationsOnFinish {
		close(c.Invitations)
		c.Invitations = make(chan protocol.SessionInvitation)
	}

	l.Debugln(c, "cleaning up")

	c.mut.Lock()
	c.connected = false
	c.mut.Unlock()

	c.conn.Close()
}

func (c *ProtocolClient) join() error {
	if err := protocol.WriteMessage(c.conn, protocol.JoinRelayRequest{}); err != nil {
		return err
	}

	message, err := protocol.ReadMessage(c.conn)
	if err != nil {
		return err
	}

	switch msg := message.(type) {
	case protocol.Response:
		if msg.Code != 0 {
			return fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
		}

	default:
		return fmt.Errorf("protocol error: expecting response got %v", msg)
	}

	return nil
}

func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
	if err := conn.Handshake(); err != nil {
		return err
	}

	cs := conn.ConnectionState()
	if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != protocol.ProtocolName {
		return fmt.Errorf("protocol negotiation error")
	}

	q := uri.Query()
	relayIDs := q.Get("id")
	if relayIDs != "" {
		relayID, err := syncthingprotocol.DeviceIDFromString(relayIDs)
		if err != nil {
			return fmt.Errorf("relay address contains invalid verification id: %s", err)
		}

		certs := cs.PeerCertificates
		if cl := len(certs); cl != 1 {
			return fmt.Errorf("unexpected certificate count: %d", cl)
		}

		remoteID := syncthingprotocol.NewDeviceID(certs[0].Raw)
		if remoteID != relayID {
			return fmt.Errorf("relay id does not match. Expected %v got %v", relayID, remoteID)
		}
	}

	return nil
}

func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- error) {
	for {
		msg, err := protocol.ReadMessage(conn)
		if err != nil {
			errors <- err
			return
		}
		messages <- msg
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/driver/desktop"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("fyne")

	// w.Resize(fyne.NewSize(300, 300))
	// w.SetFixedSize(true)
	w.SetFullScreen(true)

	ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}
	w.Canvas().AddShortcut(&ctrlTab, func(s fyne.Shortcut) {
		log.Println("ups")
		w.Hide()
	})

	hello := widget.NewLabel("Hello Fyne!")

	img := canvas.NewImageFromFile("logo.png")
	img.FillMode = canvas.ImageFillOriginal

	w.SetContent(container.NewVBox(
		img,
		hello,
		widget.NewButton("Hi!", func() {
			hello.SetText("Welcome :)")
			w.CenterOnScreen()
		}),
		widget.NewButton("Quit", func() {
			a.Quit()
		}),
	))

	// w.RequestFocus() // TODO(dvrkps): panic on macos.

	w.ShowAndRun()
}
<commit_msg>fyne: add altF4<commit_after>package main

import (
	"strconv"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/driver/desktop"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("fyne")

	w.Resize(fyne.NewSize(300, 300))
	w.SetFixedSize(true)
	//w.SetFullScreen(true)

	counter := 0

	hello := widget.NewLabel("0")

	incCounter := func(c *int) {
		*c++
		hello.SetText(strconv.Itoa(*c))
	}

	img := canvas.NewImageFromFile("logo.png")
	img.FillMode = canvas.ImageFillOriginal

	w.SetContent(container.NewVBox(
		img,
		hello,
		widget.NewButton("inc", func() {
			incCounter(&counter)
		}),
		widget.NewButton("Quit", func() {
			a.Quit()
		}),
	))

	altF4 := desktop.CustomShortcut{KeyName: fyne.KeyF4, Modifier: desktop.AltModifier}
	w.Canvas().AddShortcut(&altF4, func(s fyne.Shortcut) {
		incCounter(&counter)
		w.Hide()
		time.Sleep(3e9)
		w.Show()
	})

	w.CenterOnScreen()

	// w.RequestFocus() // TODO(dvrkps): panic on macos.

	w.ShowAndRun()
}
<|endoftext|>


<commit_before>package game

import (
	"encoding/json"
	"fmt"
	"time"

	// "bitbucket.org/pushkin_ivan/clever-snake/game/playground"
	"github.com/golang/glog"
	"golang.org/x/net/context"
)

type Game struct {
	cxt context.Context
}

type errStartingGame struct {
	err error
}

func (e *errStartingGame) Error() string {
	return "cannot create game: " + e.err.Error()
}

func NewGame(cxt context.Context, pgW, pgH uint8) (*Game, error) {
	if err := cxt.Err(); err != nil {
		return nil, &errStartingGame{err}
	}

	return &Game{cxt}, nil
}

func (g *Game) StartGame() chan interface{} {
	output := make(chan interface{})

	go func() {
		defer close(output)
		defer glog.Infoln("finishing game")

		// all running objects work like this code:
		for {
			select {
			case <-g.cxt.Done():
				return
			case <-time.Tick(time.Second * 3):
				output <- "test"
			}
		}
	}()

	return output
}

type StartPlayerFunc func(cxt context.Context, input <-chan *Command,
) (<-chan interface{}, error)

func (*Game) StartPlayer(cxt context.Context, input <-chan *Command,
) (<-chan interface{}, error) {
	if err := cxt.Err(); err != nil {
		return nil, fmt.Errorf("cannot start player: %s", err)
	}

	output := make(chan interface{})

	go func() {

		defer close(output)
		defer glog.Infoln("finishing player")

		select {
		case <-cxt.Done():
		case <-time.After(time.Second):
		}

		for {
			select {
			case <-cxt.Done():
				return
			case cmd := <-input:
				if cmd == nil {
					return
				}
				output <- "received cmd =)"
			}
		}
	}()

	return output, nil
}

/////////////////////////////////////////////////////////////////////

type Object json.Marshaler

type ObjectSet map[uint16]Object

type Command struct {
	Command string          `json:"command"`
	Params  json.RawMessage `json:"params"`
}

type Notice struct {
}

// type ObjectContainer map[uint16]interface{}

// func (c *ObjectContainer) MarshalJSON() ([]byte, error) {
// 	return json.Marshal(struct {
// 		Id     uint16      `json:"id"`
// 		Type   string      `json:"type"`
// 		Object interface{} `json:"object"`
// 	}{})
// }

// func (*Game) API_CMD()
<commit_msg>created playground in game object<commit_after>package game

import (
	"encoding/json"
	"fmt"
	"time"

	"bitbucket.org/pushkin_ivan/clever-snake/game/playground"
	"github.com/golang/glog"
	"golang.org/x/net/context"
)

type Game struct {
	cxt context.Context
	pg  *playground.Playground
}

type errStartingGame struct {
	err error
}

func (e *errStartingGame) Error() string {
	return "cannot create game: " + e.err.Error()
}

func NewGame(cxt context.Context, pgW, pgH uint8) (*Game, error) {
	if err := cxt.Err(); err != nil {
		return nil, &errStartingGame{err}
	}

	pg, err := playground.NewPlayground(pgW, pgH)
	if err != nil {
		return nil, &errStartingGame{err}
	}

	return &Game{cxt, pg}, nil
}

func (g *Game) StartGame() chan interface{} {
	output := make(chan interface{})

	go func() {
		defer close(output)
		defer glog.Infoln("finishing game")

		// all running objects work like this code:
		for {
			select {
			case <-g.cxt.Done():
				return
			case <-time.Tick(time.Second * 3):
				output <- "test"
			}
		}
	}()

	return output
}

type StartPlayerFunc func(cxt context.Context, input <-chan *Command,
) (<-chan interface{}, error)

func (*Game) StartPlayer(cxt context.Context, input <-chan *Command,
) (<-chan interface{}, error) {
	if err := cxt.Err(); err != nil {
		return nil, fmt.Errorf("cannot start player: %s", err)
	}

	output := make(chan interface{})

	go func() {

		defer close(output)
		defer glog.Infoln("finishing player")

		select {
		case <-cxt.Done():
		case <-time.After(time.Second):
		}

		for {
			select {
			case <-cxt.Done():
				return
			case cmd := <-input:
				if cmd == nil {
					return
				}
				output <- "received cmd =)"
			}
		}
	}()

	return output, nil
}

/////////////////////////////////////////////////////////////////////

type Object json.Marshaler

type ObjectSet map[uint16]Object

type Command struct {
	Command string          `json:"command"`
	Params  json.RawMessage `json:"params"`
}

type Notice struct {
}

// type ObjectContainer map[uint16]interface{}

// func (c *ObjectContainer) MarshalJSON() ([]byte, error) {
// 	return json.Marshal(struct {
// 		Id     uint16      `json:"id"`
// 		Type   string      `json:"type"`
// 		Object interface{} `json:"object"`
// 	}{})
// }

// func (*Game) API_CMD()
<|endoftext|>