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

//go:build linux && ppc
// +build linux
// +build ppc

package unix

import (
	"syscall"
	"unsafe"
)

//sys	dup2(oldfd int, newfd int) (err error)
//sysnb	EpollCreate(size int) (fd int, err error)
//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys	Fchown(fd int, uid int, gid int) (err error)
//sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys	Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
//sysnb	Getegid() (egid int)
//sysnb	Geteuid() (euid int)
//sysnb	Getgid() (gid int)
//sysnb	Getuid() (uid int)
//sysnb	InotifyInit() (fd int, err error)
//sys	Ioperm(from int, num int, on int) (err error)
//sys	Iopl(level int) (err error)
//sys	Lchown(path string, uid int, gid int) (err error)
//sys	Listen(s int, n int) (err error)
//sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys	Pause() (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys	setfsgid(gid int) (prev int, err error)
//sys	setfsuid(uid int) (prev int, err error)
//sysnb	Setregid(rgid int, egid int) (err error)
//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
//sysnb	Setreuid(ruid int, euid int) (err error)
//sys	Shutdown(fd int, how int) (err error)
//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys	Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb	setgroups(n int, list *_Gid_t) (err error)
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)

//sys	futimesat(dirfd int, path string, times *[2]Timeval) (err error)
//sysnb	Gettimeofday(tv *Timeval) (err error)
//sysnb	Time(t *Time_t) (tt Time_t, err error)
//sys	Utime(path string, buf *Utimbuf) (err error)
//sys	utimes(path string, times *[2]Timeval) (err error)

func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
	_, _, e1 := Syscall6(SYS_FADVISE64_64, uintptr(fd), uintptr(advice), uintptr(offset>>32), uintptr(offset), uintptr(length>>32), uintptr(length))
	if e1 != 0 {
		err = errnoErr(e1)
	}
	return
}

func seek(fd int, offset int64, whence int) (int64, syscall.Errno) {
	var newoffset int64
	offsetLow := uint32(offset & 0xffffffff)
	offsetHigh := uint32((offset >> 32) & 0xffffffff)
	_, _, err := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offsetHigh), uintptr(offsetLow), uintptr(unsafe.Pointer(&newoffset)), uintptr(whence), 0)
	return newoffset, err
}

func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
	newoffset, errno := seek(fd, offset, whence)
	if errno != 0 {
		return 0, errno
	}
	return newoffset, nil
}

func Fstatfs(fd int, buf *Statfs_t) (err error) {
	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = e
	}
	return
}

func Statfs(path string, buf *Statfs_t) (err error) {
	pathp, err := BytePtrFromString(path)
	if err != nil {
		return err
	}
	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = e
	}
	return
}

//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)

func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
	page := uintptr(offset / 4096)
	if offset != int64(page)*4096 {
		return 0, EINVAL
	}
	return mmap2(addr, length, prot, flags, fd, page)
}

func setTimespec(sec, nsec int64) Timespec {
	return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}

func setTimeval(sec, usec int64) Timeval {
	return Timeval{Sec: int32(sec), Usec: int32(usec)}
}

type rlimit32 struct {
	Cur uint32
	Max uint32
}

//sysnb	getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT

const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)

func Getrlimit(resource int, rlim *Rlimit) (err error) {
	err = Prlimit(0, resource, nil, rlim)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	err = getrlimit(resource, &rl)
	if err != nil {
		return
	}

	if rl.Cur == rlimInf32 {
		rlim.Cur = rlimInf64
	} else {
		rlim.Cur = uint64(rl.Cur)
	}

	if rl.Max == rlimInf32 {
		rlim.Max = rlimInf64
	} else {
		rlim.Max = uint64(rl.Max)
	}
	return
}

//sysnb	setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT

func Setrlimit(resource int, rlim *Rlimit) (err error) {
	err = Prlimit(0, resource, rlim, nil)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	if rlim.Cur == rlimInf64 {
		rl.Cur = rlimInf32
	} else if rlim.Cur < uint64(rlimInf32) {
		rl.Cur = uint32(rlim.Cur)
	} else {
		return EINVAL
	}
	if rlim.Max == rlimInf64 {
		rl.Max = rlimInf32
	} else if rlim.Max < uint64(rlimInf32) {
		rl.Max = uint32(rlim.Max)
	} else {
		return EINVAL
	}

	return setrlimit(resource, &rl)
}

func (r *PtraceRegs) PC() uint32 { return r.Nip }

func (r *PtraceRegs) SetPC(pc uint32) { r.Nip = pc }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint32(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint32(length)
}

func (msghdr *Msghdr) SetIovlen(length int) {
	msghdr.Iovlen = uint32(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint32(length)
}

func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
	rsa.Service_name_len = uint32(length)
}

//sysnb	pipe(p *[2]_C_int) (err error)

func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe(&pp)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

//sysnb	pipe2(p *[2]_C_int, flags int) (err error)

func Pipe2(p []int, flags int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, flags)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

//sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)

func Poll(fds []PollFd, timeout int) (n int, err error) {
	if len(fds) == 0 {
		return poll(nil, 0, timeout)
	}
	return poll(&fds[0], len(fds), timeout)
}

//sys	syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2

func SyncFileRange(fd int, off int64, n int64, flags int) error {
	// The sync_file_range and sync_file_range2 syscalls differ only in the
	// order of their arguments.
	return syncFileRange2(fd, flags, off, n)
}

//sys	kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)

func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
	cmdlineLen := len(cmdline)
	if cmdlineLen > 0 {
		// Account for the additional NULL byte added by
		// BytePtrFromString in kexecFileLoad. The kexec_file_load
		// syscall expects a NULL-terminated string.
		cmdlineLen++
	}
	return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
<commit_msg>unix: gofmt with Go 1.17<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux && ppc
// +build linux,ppc

package unix

import (
	"syscall"
	"unsafe"
)

//sys	dup2(oldfd int, newfd int) (err error)
//sysnb	EpollCreate(size int) (fd int, err error)
//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys	Fchown(fd int, uid int, gid int) (err error)
//sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys	Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
//sysnb	Getegid() (egid int)
//sysnb	Geteuid() (euid int)
//sysnb	Getgid() (gid int)
//sysnb	Getuid() (uid int)
//sysnb	InotifyInit() (fd int, err error)
//sys	Ioperm(from int, num int, on int) (err error)
//sys	Iopl(level int) (err error)
//sys	Lchown(path string, uid int, gid int) (err error)
//sys	Listen(s int, n int) (err error)
//sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys	Pause() (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys	setfsgid(gid int) (prev int, err error)
//sys	setfsuid(uid int) (prev int, err error)
//sysnb	Setregid(rgid int, egid int) (err error)
//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
//sysnb	Setreuid(ruid int, euid int) (err error)
//sys	Shutdown(fd int, how int) (err error)
//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys	Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb	setgroups(n int, list *_Gid_t) (err error)
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)

//sys	futimesat(dirfd int, path string, times *[2]Timeval) (err error)
//sysnb	Gettimeofday(tv *Timeval) (err error)
//sysnb	Time(t *Time_t) (tt Time_t, err error)
//sys	Utime(path string, buf *Utimbuf) (err error)
//sys	utimes(path string, times *[2]Timeval) (err error)

func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
	_, _, e1 := Syscall6(SYS_FADVISE64_64, uintptr(fd), uintptr(advice), uintptr(offset>>32), uintptr(offset), uintptr(length>>32), uintptr(length))
	if e1 != 0 {
		err = errnoErr(e1)
	}
	return
}

func seek(fd int, offset int64, whence int) (int64, syscall.Errno) {
	var newoffset int64
	offsetLow := uint32(offset & 0xffffffff)
	offsetHigh := uint32((offset >> 32) & 0xffffffff)
	_, _, err := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offsetHigh), uintptr(offsetLow), uintptr(unsafe.Pointer(&newoffset)), uintptr(whence), 0)
	return newoffset, err
}

func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
	newoffset, errno := seek(fd, offset, whence)
	if errno != 0 {
		return 0, errno
	}
	return newoffset, nil
}

func Fstatfs(fd int, buf *Statfs_t) (err error) {
	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = e
	}
	return
}

func Statfs(path string, buf *Statfs_t) (err error) {
	pathp, err := BytePtrFromString(path)
	if err != nil {
		return err
	}
	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = e
	}
	return
}

//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)

func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
	page := uintptr(offset / 4096)
	if offset != int64(page)*4096 {
		return 0, EINVAL
	}
	return mmap2(addr, length, prot, flags, fd, page)
}

func setTimespec(sec, nsec int64) Timespec {
	return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}

func setTimeval(sec, usec int64) Timeval {
	return Timeval{Sec: int32(sec), Usec: int32(usec)}
}

type rlimit32 struct {
	Cur uint32
	Max uint32
}

//sysnb	getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT

const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)

func Getrlimit(resource int, rlim *Rlimit) (err error) {
	err = Prlimit(0, resource, nil, rlim)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	err = getrlimit(resource, &rl)
	if err != nil {
		return
	}

	if rl.Cur == rlimInf32 {
		rlim.Cur = rlimInf64
	} else {
		rlim.Cur = uint64(rl.Cur)
	}

	if rl.Max == rlimInf32 {
		rlim.Max = rlimInf64
	} else {
		rlim.Max = uint64(rl.Max)
	}
	return
}

//sysnb	setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT

func Setrlimit(resource int, rlim *Rlimit) (err error) {
	err = Prlimit(0, resource, rlim, nil)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	if rlim.Cur == rlimInf64 {
		rl.Cur = rlimInf32
	} else if rlim.Cur < uint64(rlimInf32) {
		rl.Cur = uint32(rlim.Cur)
	} else {
		return EINVAL
	}
	if rlim.Max == rlimInf64 {
		rl.Max = rlimInf32
	} else if rlim.Max < uint64(rlimInf32) {
		rl.Max = uint32(rlim.Max)
	} else {
		return EINVAL
	}

	return setrlimit(resource, &rl)
}

func (r *PtraceRegs) PC() uint32 { return r.Nip }

func (r *PtraceRegs) SetPC(pc uint32) { r.Nip = pc }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint32(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint32(length)
}

func (msghdr *Msghdr) SetIovlen(length int) {
	msghdr.Iovlen = uint32(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint32(length)
}

func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
	rsa.Service_name_len = uint32(length)
}

//sysnb	pipe(p *[2]_C_int) (err error)

func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe(&pp)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

//sysnb	pipe2(p *[2]_C_int, flags int) (err error)

func Pipe2(p []int, flags int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, flags)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

//sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)

func Poll(fds []PollFd, timeout int) (n int, err error) {
	if len(fds) == 0 {
		return poll(nil, 0, timeout)
	}
	return poll(&fds[0], len(fds), timeout)
}

//sys	syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2

func SyncFileRange(fd int, off int64, n int64, flags int) error {
	// The sync_file_range and sync_file_range2 syscalls differ only in the
	// order of their arguments.
	return syncFileRange2(fd, flags, off, n)
}

//sys	kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)

func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
	cmdlineLen := len(cmdline)
	if cmdlineLen > 0 {
		// Account for the additional NULL byte added by
		// BytePtrFromString in kexecFileLoad. The kexec_file_load
		// syscall expects a NULL-terminated string.
		cmdlineLen++
	}
	return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
<|endoftext|>


<commit_before>package muniverse

import (
	"math"
	"testing"
	"time"
)

var BenchmarkEnvs = []string{"PopUp-v0", "FlappyBird-v0"}

func TestEnvs(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	for _, spec := range EnvSpecs {
		t.Run(spec.Name, func(t *testing.T) {
			env, err := NewEnv(spec)
			if err != nil {
				t.Error(err)
				return
			}
			defer env.Close()
			for i := 0; i < 2; i++ {
				if err := env.Reset(); err != nil {
					t.Error(err)
					t.Log(env.Log())
					break
				}
				if _, _, err := env.Step(time.Millisecond); err != nil {
					t.Error(err)
					t.Log(env.Log())
					break
				}
			}
		})
	}
}

func TestEnvObserve(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	for _, spec := range EnvSpecs {
		if !spec.AllCanvas {
			continue
		}
		t.Run(spec.Name, func(t *testing.T) {
			env, err := NewEnv(spec)
			if err != nil {
				t.Error(err)
				return
			}
			defer env.Close()
			if err := env.Reset(); err != nil {
				t.Log(env.Log())
				t.Fatal(err)
			}
			if _, _, err := env.Step(time.Millisecond * 30); err != nil {
				t.Log(env.Log())
				t.Fatal(err)
			}
			actualObs, err := env.Observe()
			if err != nil {
				t.Fatal(err)
			}
			env.(*rawEnv).spec.AllCanvas = false
			expectedObs, err := env.Observe()
			if err != nil {
				t.Fatal(err)
			}

			actual, actualWidth, actualHeight, err := RGB(actualObs)
			if err != nil {
				t.Fatal(err)
			}
			expected, expectedWidth, expectedHeight, err := RGB(expectedObs)
			if err != nil {
				t.Fatal(err)
			}
			if actualWidth != expectedWidth || actualHeight != expectedHeight {
				t.Fatalf("dimensions should be %dx%d but got %dx%d",
					expectedWidth, expectedHeight, actualWidth, actualHeight)
			}
			for i, a := range actual {
				x := expected[i]
				diff := math.Abs(float64(x) - float64(a))
				if math.Abs(diff) > 10 {
					t.Fatalf("pixel %d: got %d, expected %d", i, a, x)
				}
			}
		})
	}
}

func BenchmarkEnvObserve(b *testing.B) {
	for _, envName := range BenchmarkEnvs {
		for _, compression := range []bool{false, true} {
			name := envName
			if compression {
				name += "-Compressed"
			}
			b.Run(name, func(b *testing.B) {
				opts := &Options{}
				if compression {
					opts.Compression = true
					opts.CompressionQuality = 100
				}
				env, err := NewEnvOptions(SpecForName(envName), opts)
				if err != nil {
					b.Fatal(err)
				}
				defer env.Close()
				if err := env.Reset(); err != nil {
					b.Fatal(err)
				}
				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					if _, err := env.Observe(); err != nil {
						b.Fatal(err)
					}
				}
			})
		}
	}
}

func BenchmarkEnvReset(b *testing.B) {
	for _, envName := range BenchmarkEnvs {
		name := envName
		b.Run(name, func(b *testing.B) {
			env, err := NewEnv(SpecForName(envName))
			if err != nil {
				b.Fatal(err)
			}
			defer env.Close()
			if err := env.Reset(); err != nil {
				b.Fatal(err)
			}
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				if err := env.Reset(); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}
<commit_msg>don't time env.Close() in benchmarks<commit_after>package muniverse

import (
	"math"
	"testing"
	"time"
)

var BenchmarkEnvs = []string{"PopUp-v0", "FlappyBird-v0"}

func TestEnvs(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	for _, spec := range EnvSpecs {
		t.Run(spec.Name, func(t *testing.T) {
			env, err := NewEnv(spec)
			if err != nil {
				t.Error(err)
				return
			}
			defer env.Close()
			for i := 0; i < 2; i++ {
				if err := env.Reset(); err != nil {
					t.Error(err)
					t.Log(env.Log())
					break
				}
				if _, _, err := env.Step(time.Millisecond); err != nil {
					t.Error(err)
					t.Log(env.Log())
					break
				}
			}
		})
	}
}

func TestEnvObserve(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	for _, spec := range EnvSpecs {
		if !spec.AllCanvas {
			continue
		}
		t.Run(spec.Name, func(t *testing.T) {
			env, err := NewEnv(spec)
			if err != nil {
				t.Error(err)
				return
			}
			defer env.Close()
			if err := env.Reset(); err != nil {
				t.Log(env.Log())
				t.Fatal(err)
			}
			if _, _, err := env.Step(time.Millisecond * 30); err != nil {
				t.Log(env.Log())
				t.Fatal(err)
			}
			actualObs, err := env.Observe()
			if err != nil {
				t.Fatal(err)
			}
			env.(*rawEnv).spec.AllCanvas = false
			expectedObs, err := env.Observe()
			if err != nil {
				t.Fatal(err)
			}

			actual, actualWidth, actualHeight, err := RGB(actualObs)
			if err != nil {
				t.Fatal(err)
			}
			expected, expectedWidth, expectedHeight, err := RGB(expectedObs)
			if err != nil {
				t.Fatal(err)
			}
			if actualWidth != expectedWidth || actualHeight != expectedHeight {
				t.Fatalf("dimensions should be %dx%d but got %dx%d",
					expectedWidth, expectedHeight, actualWidth, actualHeight)
			}
			for i, a := range actual {
				x := expected[i]
				diff := math.Abs(float64(x) - float64(a))
				if math.Abs(diff) > 10 {
					t.Fatalf("pixel %d: got %d, expected %d", i, a, x)
				}
			}
		})
	}
}

func BenchmarkEnvObserve(b *testing.B) {
	for _, envName := range BenchmarkEnvs {
		for _, compression := range []bool{false, true} {
			name := envName
			if compression {
				name += "-Compressed"
			}
			b.Run(name, func(b *testing.B) {
				opts := &Options{}
				if compression {
					opts.Compression = true
					opts.CompressionQuality = 100
				}
				env, err := NewEnvOptions(SpecForName(envName), opts)
				if err != nil {
					b.Fatal(err)
				}
				defer env.Close()
				defer b.StopTimer()
				if err := env.Reset(); err != nil {
					b.Fatal(err)
				}
				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					if _, err := env.Observe(); err != nil {
						b.Fatal(err)
					}
				}
			})
		}
	}
}

func BenchmarkEnvReset(b *testing.B) {
	for _, envName := range BenchmarkEnvs {
		name := envName
		b.Run(name, func(b *testing.B) {
			env, err := NewEnv(SpecForName(envName))
			if err != nil {
				b.Fatal(err)
			}
			defer env.Close()
			defer b.StopTimer()
			if err := env.Reset(); err != nil {
				b.Fatal(err)
			}
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				if err := env.Reset(); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>package httptools

import (
	"net/http"
)

// VarsResponseWriter is a http.ResponseWriter which gives access
// to a map. The map can be filled with arbitrary data and is supposed
// to be out-of-band channel to pass data between handlers in a handler list
// or any kind of handler switch.
type VarsResponseWriter interface {
	http.ResponseWriter
	Vars() map[string]interface{}
}

// CheckResponseWriter is a http.ResponseWriter which saves wether it
// has been written to or not.
type CheckResponseWriter interface {
	http.ResponseWriter
	// Returns true if the headers have been written
	WasWritten() bool
}

func newOurResponseWriter(w http.ResponseWriter) *ourResponseWriter {
	vrw, ok := w.(VarsResponseWriter)
	if ok {
		return &ourResponseWriter{
			ResponseWriter: w,
			vars:           vrw.Vars(),
			written:        false,
		}
	}
	return &ourResponseWriter{
		ResponseWriter: w,
		vars:           map[string]interface{}{},
		written:        false,
	}
}

type ourResponseWriter struct {
	http.ResponseWriter
	vars    map[string]interface{}
	written bool
}

func (orw *ourResponseWriter) Vars() map[string]interface{} {
	return orw.vars
}

func (orw *ourResponseWriter) WasWritten() bool {
	return orw.written
}

func (orw *ourResponseWriter) WriteHeader(n int) {
	orw.written = true
	orw.ResponseWriter.WriteHeader(n)
}
<commit_msg>Make ourResponeWriter assertable to http.Hijacker<commit_after>package httptools

import (
	"net/http"
)

// VarsResponseWriter is a http.ResponseWriter which gives access
// to a map. The map can be filled with arbitrary data and is supposed
// to be out-of-band channel to pass data between handlers in a handler list
// or any kind of handler switch.
type VarsResponseWriter interface {
	http.ResponseWriter
	Vars() map[string]interface{}
}

// CheckResponseWriter is a http.ResponseWriter which saves wether it
// has been written to or not.
type CheckResponseWriter interface {
	http.ResponseWriter
	// Returns true if the headers have been written
	WasWritten() bool
}

func newOurResponseWriter(w http.ResponseWriter) *ourResponseWriter {
	orw := &ourResponseWriter{
		ResponseWriter: w,
		vars:           map[string]interface{}{},
		written:        false,
	}
	if vrw, ok := w.(VarsResponseWriter); ok {
		orw.vars = vrw.Vars()
	}
	if hijacker, ok := w.(http.Hijacker); ok {
		orw.Hijacker = hijacker
	}
	return orw
}

type ourResponseWriter struct {
	http.ResponseWriter
	http.Hijacker
	vars    map[string]interface{}
	written bool
}

func (orw *ourResponseWriter) Vars() map[string]interface{} {
	return orw.vars
}

func (orw *ourResponseWriter) WasWritten() bool {
	return orw.written
}

func (orw *ourResponseWriter) WriteHeader(n int) {
	orw.written = true
	orw.ResponseWriter.WriteHeader(n)
}
<|endoftext|>


<commit_before>package command

import (
	"encoding/json"
	"fmt"
	"io"
	"reflect"

	"github.com/ungerik/go-reflection"
)

type ResultsHandler interface {
	HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error
}

type ResultsHandlerFunc func(args Args, argVals, resultVals []reflect.Value, resultErr error) error

func (f ResultsHandlerFunc) HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	return f(args, argVals, resultVals, resultErr)
}

func resultsToInterfaces(results []reflect.Value) ([]interface{}, error) {
	r := make([]interface{}, len(results))
	for i, result := range results {
		resultInterface := result.Interface()

		if b, ok := resultInterface.([]byte); ok {
			r[i] = string(b)
			continue
		}

		switch reflection.DerefValue(result).Kind() {
		case reflect.Struct, reflect.Slice, reflect.Array:
			b, err := json.MarshalIndent(resultInterface, "", "  ")
			if err != nil {
				return nil, err
			}
			r[i] = string(b)
			continue
		}

		r[i] = resultInterface
	}
	return r, nil
}

// PrintTo calls fmt.Fprint on writer with the result values as varidic arguments
func PrintTo(writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		r, err := resultsToInterfaces(resultVals)
		if err != nil || len(r) == 0 {
			return err
		}
		_, err = fmt.Fprint(writer, r...)
		return err
	}
}

// PrintlnTo calls fmt.Fprintln on writer for every result
func PrintlnTo(writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, r := range results {
			_, err = fmt.Fprintln(writer, r)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// Println calls fmt.Println for every result
var Println ResultsHandlerFunc = func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	if resultErr != nil {
		return resultErr
	}
	results, err := resultsToInterfaces(resultVals)
	if err != nil || len(results) == 0 {
		return err
	}
	for _, r := range results {
		_, err = fmt.Println(r)
		if err != nil {
			return err
		}
	}
	return nil
}

// PrintlnWithPrefixTo calls fmt.Fprintln(writer, prefix, result) for every result value
func PrintlnWithPrefixTo(prefix string, writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, result := range results {
			_, err = fmt.Fprintln(writer, prefix, result)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// PrintlnWithPrefix calls fmt.Println(prefix, result) for every result value
func PrintlnWithPrefix(prefix string) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, result := range results {
			_, err = fmt.Println(prefix, result)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// Logger interface
type Logger interface {
	Printf(format string, args ...interface{})
}

// LogTo calls logger.Printf(fmt.Sprintln(results...))
func LogTo(logger Logger) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		logger.Printf(fmt.Sprintln(results...))
		return nil
	}
}

// LogWithPrefixTo calls logger.Printf(fmt.Sprintln(results...)) with prefix prepended to the results
func LogWithPrefixTo(prefix string, logger Logger) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		results = append([]interface{}{prefix}, results...)
		logger.Printf(fmt.Sprintln(results...))
		return nil
	}
}

// PrintlnText prints a fixed string if a command returns without an error
type PrintlnText string

func (t PrintlnText) HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	if resultErr != nil {
		return resultErr
	}
	_, err := fmt.Println(t)
	return err
}
<commit_msg>resultsToInterfaces error wrapping<commit_after>package command

import (
	"encoding/json"
	"fmt"
	"io"
	"reflect"

	"github.com/ungerik/go-reflection"
)

type ResultsHandler interface {
	HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error
}

type ResultsHandlerFunc func(args Args, argVals, resultVals []reflect.Value, resultErr error) error

func (f ResultsHandlerFunc) HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	return f(args, argVals, resultVals, resultErr)
}

func resultsToInterfaces(results []reflect.Value) ([]interface{}, error) {
	r := make([]interface{}, len(results))
	for i, result := range results {
		resultInterface := result.Interface()

		if b, ok := resultInterface.([]byte); ok {
			r[i] = string(b)
			continue
		}

		switch reflection.DerefValue(result).Kind() {
		case reflect.Struct, reflect.Slice, reflect.Array:
			b, err := json.MarshalIndent(resultInterface, "", "  ")
			if err != nil {
				return nil, fmt.Errorf("can't print command result as JSON because: %w", err)
			}
			r[i] = string(b)
			continue
		}

		r[i] = resultInterface
	}
	return r, nil
}

// PrintTo calls fmt.Fprint on writer with the result values as varidic arguments
func PrintTo(writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		r, err := resultsToInterfaces(resultVals)
		if err != nil || len(r) == 0 {
			return err
		}
		_, err = fmt.Fprint(writer, r...)
		return err
	}
}

// PrintlnTo calls fmt.Fprintln on writer for every result
func PrintlnTo(writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, r := range results {
			_, err = fmt.Fprintln(writer, r)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// Println calls fmt.Println for every result
var Println ResultsHandlerFunc = func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	if resultErr != nil {
		return resultErr
	}
	results, err := resultsToInterfaces(resultVals)
	if err != nil || len(results) == 0 {
		return err
	}
	for _, r := range results {
		_, err = fmt.Println(r)
		if err != nil {
			return err
		}
	}
	return nil
}

// PrintlnWithPrefixTo calls fmt.Fprintln(writer, prefix, result) for every result value
func PrintlnWithPrefixTo(prefix string, writer io.Writer) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, result := range results {
			_, err = fmt.Fprintln(writer, prefix, result)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// PrintlnWithPrefix calls fmt.Println(prefix, result) for every result value
func PrintlnWithPrefix(prefix string) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		for _, result := range results {
			_, err = fmt.Println(prefix, result)
			if err != nil {
				return err
			}
		}
		return nil
	}
}

// Logger interface
type Logger interface {
	Printf(format string, args ...interface{})
}

// LogTo calls logger.Printf(fmt.Sprintln(results...))
func LogTo(logger Logger) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		logger.Printf(fmt.Sprintln(results...))
		return nil
	}
}

// LogWithPrefixTo calls logger.Printf(fmt.Sprintln(results...)) with prefix prepended to the results
func LogWithPrefixTo(prefix string, logger Logger) ResultsHandlerFunc {
	return func(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
		if resultErr != nil {
			return resultErr
		}
		results, err := resultsToInterfaces(resultVals)
		if err != nil || len(results) == 0 {
			return err
		}
		results = append([]interface{}{prefix}, results...)
		logger.Printf(fmt.Sprintln(results...))
		return nil
	}
}

// PrintlnText prints a fixed string if a command returns without an error
type PrintlnText string

func (t PrintlnText) HandleResults(args Args, argVals, resultVals []reflect.Value, resultErr error) error {
	if resultErr != nil {
		return resultErr
	}
	_, err := fmt.Println(t)
	return err
}
<|endoftext|>


<commit_before>// Package logs provides structs for working with AWS CloudWatch Logs records.
package logs

import (
	"bytes"
	"compress/gzip"
	"encoding/json"

	"github.com/apex/go-apex"
	"github.com/apex/go-apex/kinesis"
)

// LogEvent represents a single log event.
type LogEvent struct {
	ID        string `json:"id"`
	Timestamp int64  `json:"timestamp"`
	Message   string `json:"message"`
}

// Event represents a Kinesis event with one or more records.
type Event struct {
	Records []*Record `json:"Records"`
}

// Record represents a single Kinesis record.
type Record struct {
	kinesis.Record
	Logs struct {
		Owner               string      `json:"owner"`
		LogGroup            string      `json:"logGroup"`
		LogStream           string      `json:"logStream"`
		SubscriptionFilters []string    `json:"subscriptionFilters"`
		MessageType         string      `json:"messageType"`
		LogEvents           []*LogEvent `json:"logEvents"`
	}
}

// Handler handles Logs events.
type Handler interface {
	HandleLogs(*Event, *apex.Context) error
}

// HandlerFunc unmarshals Logs events before passing control.
type HandlerFunc func(*Event, *apex.Context) error

// Handle implements apex.Handler.
func (h HandlerFunc) Handle(data json.RawMessage, ctx *apex.Context) (interface{}, error) {
	var event Event

	if err := json.Unmarshal(data, &event); err != nil {
		return nil, err
	}

	for _, record := range event.Records {
		r, err := gzip.NewReader(bytes.NewReader(record.Data()))
		if err != nil {
			return nil, err
		}

		if err = json.NewDecoder(r).Decode(&record.Logs); err != nil {
			return nil, err
		}

		if err := r.Close(); err != nil {
			return nil, err
		}
	}

	if err := h(&event, ctx); err != nil {
		return nil, err
	}

	return event, nil
}

// HandleFunc handles Logs events with callback function.
func HandleFunc(h HandlerFunc) {
	apex.Handle(h)
}

// Handle Logs events with handler.
func Handle(h Handler) {
	HandleFunc(HandlerFunc(h.HandleLogs))
}
<commit_msg>refactor logs with decode helper<commit_after>// Package logs provides structs for working with AWS CloudWatch Logs records.
package logs

import (
	"bytes"
	"compress/gzip"
	"encoding/json"

	"github.com/apex/go-apex"
	"github.com/apex/go-apex/kinesis"
)

// LogEvent represents a single log event.
type LogEvent struct {
	ID        string `json:"id"`
	Timestamp int64  `json:"timestamp"`
	Message   string `json:"message"`
}

// Event represents a Kinesis event with one or more records.
type Event struct {
	Records []*Record `json:"Records"`
}

// Record represents a single Kinesis record.
type Record struct {
	kinesis.Record
	Logs struct {
		Owner               string      `json:"owner"`
		LogGroup            string      `json:"logGroup"`
		LogStream           string      `json:"logStream"`
		SubscriptionFilters []string    `json:"subscriptionFilters"`
		MessageType         string      `json:"messageType"`
		LogEvents           []*LogEvent `json:"logEvents"`
	}
}

// Handler handles Logs events.
type Handler interface {
	HandleLogs(*Event, *apex.Context) error
}

// HandlerFunc unmarshals Logs events before passing control.
type HandlerFunc func(*Event, *apex.Context) error

// Handle implements apex.Handler.
func (h HandlerFunc) Handle(data json.RawMessage, ctx *apex.Context) (interface{}, error) {
	event := new(Event)

	if err := json.Unmarshal(data, event); err != nil {
		return nil, err
	}

	if err := decode(event); err != nil {
		return nil, err
	}

	if err := h(event, ctx); err != nil {
		return nil, err
	}

	return event, nil
}

// HandleFunc handles Logs events with callback function.
func HandleFunc(h HandlerFunc) {
	apex.Handle(h)
}

// Handle Logs events with handler.
func Handle(h Handler) {
	HandleFunc(HandlerFunc(h.HandleLogs))
}

// decode decodes the log payload which is gzipped.
func decode(event *Event) error {
	for _, record := range event.Records {
		r, err := gzip.NewReader(bytes.NewReader(record.Data()))
		if err != nil {
			return err
		}

		if err = json.NewDecoder(r).Decode(&record.Logs); err != nil {
			return err
		}

		if err := r.Close(); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"net"
	"encoding/json"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"syscall"
	"strconv"
	"time"
	"github.com/hoisie/redis"
)

var signalchan chan os.Signal
var client redis.Client

const (
	VERSION                 = "0.1.0"
	MAX_UNPROCESSED_PACKETS = 1000
	MAX_UDP_PACKET_SIZE     = 512
)

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	expiryInterval   = flag.Int64("expiry-interval", 1, "Expiry interval (seconds)")
	debug            = flag.Bool("debug", false, "print statistics sent to graphite")
	showVersion      = flag.Bool("version", false, "print version string")
)

const (
	ACTION_SET_WARN = "set-warn"
	ACTION_SET_ERR = "set-err"
	ACTION_BEAT = "beat"
)

const (
	STATE_PAUSED  = "paused"
	STATE_OK      = "ok"
	STATE_WARNING = "warning"
	STATE_ERROR   = "error"
)

type Cmd struct {
	Action   string
	Service  string
	Value    int
}

type Service struct {
	Name           string
	LastValue      int
	LastBeat       int64
	WarningTimeout int64
	ErrorTimeout   int64
	State          string
	Status         string
}

var (
	In       = make(chan *Cmd, MAX_UNPROCESSED_PACKETS)
)

func now() int64 { return time.Now().Unix() }

func getOrCreate(name string) (*Service, *Service) {
	service := &Service{
		Name: name,
		LastValue: -1,
		WarningTimeout: -1,
		ErrorTimeout: -1,
		State: STATE_PAUSED,
	}

	if data, err := client.Get("lb.service." + name); err == nil {
		json.Unmarshal(data, &service)
	}
	var ref = *service
	return service, &ref
}

func getExpiry(service *Service, timeout int64) int64 {
	if timeout <= 0 {
		return 0
	}
	return service.LastBeat + timeout
}

func service_get_next_expiry(service *Service, ts int64) int64 {
	var next int64 = 0
	var warningExpiry = getExpiry(service, service.WarningTimeout)
	var errorExpiry = getExpiry(service, service.ErrorTimeout)
	if warningExpiry > 0 && warningExpiry > ts && (next == 0 || warningExpiry < next) {
		next = warningExpiry
	}
	if errorExpiry > 0 && errorExpiry > ts && (next == 0 || errorExpiry < next) {
		next = errorExpiry
	}
	log.Printf("now: %d, warning: %d, error: %d, chosen: %d", ts, warningExpiry, errorExpiry, next)
	return next
}

func service_update_state(service *Service, ts int64) {
	service.State = STATE_OK
	var warningExpiry = getExpiry(service, service.WarningTimeout)
	var errorExpiry = getExpiry(service, service.ErrorTimeout)
	if warningExpiry > 0 && ts >= warningExpiry {
		service.State = STATE_WARNING
	}
	if errorExpiry > 0 && ts >= errorExpiry {
		service.State = STATE_ERROR
	}
}

func updateExpiry(service *Service, ts int64) {
	if service.State != STATE_PAUSED {
		if expiry := service_get_next_expiry(service, ts); expiry > 0 {
			client.Zadd("lb.expiry", []byte(service.Name), float64(expiry))
			return
		}
	}
	client.Zrem("lb.expiry", []byte(service.Name))
}

func service_save(service *Service, ref *Service) {
	if *service != *ref {
		log.Printf("service " + service.Name + ", " + ref.State + " -> " + service.State);
		b, _ := json.Marshal(service)
		client.Set("lb.service." + service.Name, b)
	}
}

func monitor() {
	period := time.Duration(*expiryInterval) * time.Second
	ticker := time.NewTicker(period)
	for {
		select {
		case sig := <-signalchan:
			fmt.Printf("!! Caught signal %d... shutting down\n", sig)
			return
		case <-ticker.C:
			var ts = now()
			log.Printf("TICK!")
			// get list of expired events
			if expired, err := client.Zrangebyscore("lb.expiry", 0, float64(now())); err == nil {
				for _, elem := range expired {
					var service, ref = getOrCreate(string(elem))
					service_update_state(service, ts);
					service_save(service, ref)
					updateExpiry(service, ts)
				}
			}
		case s := <-In:
			var ts = now()
			var service, ref = getOrCreate(s.Service)
			switch s.Action {
			case ACTION_SET_WARN:
				service.WarningTimeout = int64(s.Value)
			case ACTION_SET_ERR:
				service.ErrorTimeout = int64(s.Value)
			case ACTION_BEAT:
				service.LastBeat = ts
			}
			service_update_state(service, ts);
			service_save(service, ref)
			updateExpiry(service, ts)
		}
	}
}

var packetRegexp = regexp.MustCompile("^([^:]+)\\.(beat|warn|err):(-?[0-9]+)\\|(g|c|ms)(\\|@([0-9\\.]+))?\n?$")

func parseMessage(data []byte) []*Cmd {
	var output []*Cmd
	for _, line := range bytes.Split(data, []byte("\n")) {
		if len(line) == 0 {
			continue
		}

		item := packetRegexp.FindSubmatch(line)
		if len(item) == 0 {
			continue
		}

		var value int
		modifier := string(item[4])
		switch modifier {
		case "c":
			var vali, err = strconv.ParseInt(string(item[3]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseInt %s - %s", item[3], err)
				continue
			}
			value = int(vali)
		default:
			var valu, err = strconv.ParseUint(string(item[3]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseUint %s - %s", item[3], err)
				continue
			}
			value = int(valu)
		}
		var action string
		switch string(item[2]) {
		case "warn":
			action = ACTION_SET_WARN
		case "err":
			action = ACTION_SET_ERR
		case "beat":
			action = ACTION_BEAT
		}

		packet := &Cmd{
			Action: action,
			Service: string(item[1]),
			Value:    value,
		}
		output = append(output, packet)
	}
	return output
}

func udpListener() {
	address, _ := net.ResolveUDPAddr("udp", *serviceAddress)
	log.Printf("listening on %s", address)
	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()

	message := make([]byte, MAX_UDP_PACKET_SIZE)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range parseMessage(message[:n]) {
			In <- p
		}
	}
}

func main() {
	flag.Parse()
	if *showVersion {
		fmt.Printf("statsdaemon v%s (built w/%s)\n", VERSION, runtime.Version())
		return
	}

	signalchan = make(chan os.Signal, 1)
	signal.Notify(signalchan, syscall.SIGTERM)

	go udpListener()
	monitor()
}
<commit_msg>Better printouts<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"net"
	"encoding/json"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"syscall"
	"strconv"
	"time"
	"github.com/hoisie/redis"
)

var signalchan chan os.Signal
var client redis.Client

const (
	VERSION                 = "0.1.0"
	MAX_UNPROCESSED_PACKETS = 1000
	MAX_UDP_PACKET_SIZE     = 512
)

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	expiryInterval   = flag.Int64("expiry-interval", 1, "Expiry interval (seconds)")
	debug            = flag.Bool("debug", false, "print statistics sent to graphite")
	showVersion      = flag.Bool("version", false, "print version string")
)

const (
	ACTION_SET_WARN = "set-warn"
	ACTION_SET_ERR = "set-err"
	ACTION_BEAT = "beat"
)

const (
	STATE_PAUSED  = "paused"
	STATE_OK      = "ok"
	STATE_WARNING = "warning"
	STATE_ERROR   = "error"
)

type Cmd struct {
	Action   string
	Service  string
	Value    int
}

type Service struct {
	Name           string
	LastValue      int
	LastBeat       int64
	WarningTimeout int64
	ErrorTimeout   int64
	State          string
	Status         string
}

var (
	In       = make(chan *Cmd, MAX_UNPROCESSED_PACKETS)
)

func now() int64 { return time.Now().Unix() }

func getOrCreate(name string) (*Service, *Service) {
	service := &Service{
		Name: name,
		LastValue: -1,
		WarningTimeout: -1,
		ErrorTimeout: -1,
		State: STATE_PAUSED,
	}

	if data, err := client.Get("lb.service." + name); err == nil {
		json.Unmarshal(data, &service)
	}
	var ref = *service
	return service, &ref
}

func getExpiry(service *Service, timeout int64) int64 {
	if timeout <= 0 {
		return 0
	}
	return service.LastBeat + timeout
}

func service_get_next_expiry(service *Service, ts int64) int64 {
	var next int64 = 0
	var warningExpiry = getExpiry(service, service.WarningTimeout)
	var errorExpiry = getExpiry(service, service.ErrorTimeout)
	if warningExpiry > 0 && warningExpiry > ts && (next == 0 || warningExpiry < next) {
		next = warningExpiry
	}
	if errorExpiry > 0 && errorExpiry > ts && (next == 0 || errorExpiry < next) {
		next = errorExpiry
	}
	log.Printf("now: %d, warning: %d, error: %d, chosen: %d", ts, warningExpiry, errorExpiry, next)
	return next
}

func service_update_state(service *Service, ts int64) {
	service.State = STATE_OK
	var warningExpiry = getExpiry(service, service.WarningTimeout)
	var errorExpiry = getExpiry(service, service.ErrorTimeout)
	if warningExpiry > 0 && ts >= warningExpiry {
		service.State = STATE_WARNING
	}
	if errorExpiry > 0 && ts >= errorExpiry {
		service.State = STATE_ERROR
	}
}

func updateExpiry(service *Service, ts int64) {
	if service.State != STATE_PAUSED {
		if expiry := service_get_next_expiry(service, ts); expiry > 0 {
			client.Zadd("lb.expiry", []byte(service.Name), float64(expiry))
			return
		}
	}
	client.Zrem("lb.expiry", []byte(service.Name))
}

func service_save(service *Service, ref *Service) {
	if *service != *ref {
		if service.State != ref.State {
			log.Printf("service %s, state %s -> %s", service.Name, ref.State, service.State)
		}
		if service.WarningTimeout != ref.WarningTimeout {
			log.Printf("service %s, warn %d -> %d", service.Name, ref.WarningTimeout, service.WarningTimeout)
		}
		if service.ErrorTimeout != ref.ErrorTimeout {
			log.Printf("service %s, err %d -> %d", service.Name, ref.ErrorTimeout, service.ErrorTimeout)
		}
		b, _ := json.Marshal(service)
		client.Set("lb.service." + service.Name, b)
	}
}

func monitor() {
	period := time.Duration(*expiryInterval) * time.Second
	ticker := time.NewTicker(period)
	for {
		select {
		case sig := <-signalchan:
			fmt.Printf("!! Caught signal %d... shutting down\n", sig)
			return
		case <-ticker.C:
			var ts = now()
			log.Printf("TICK!")
			// get list of expired events
			if expired, err := client.Zrangebyscore("lb.expiry", 0, float64(now())); err == nil {
				for _, elem := range expired {
					var service, ref = getOrCreate(string(elem))
					service_update_state(service, ts);
					service_save(service, ref)
					updateExpiry(service, ts)
				}
			}
		case s := <-In:
			var ts = now()
			var service, ref = getOrCreate(s.Service)
			switch s.Action {
			case ACTION_SET_WARN:
				service.WarningTimeout = int64(s.Value)
			case ACTION_SET_ERR:
				service.ErrorTimeout = int64(s.Value)
			case ACTION_BEAT:
				service.LastBeat = ts
			}
			service_update_state(service, ts);
			service_save(service, ref)
			updateExpiry(service, ts)
		}
	}
}

var packetRegexp = regexp.MustCompile("^([^:]+)\\.(beat|warn|err):(-?[0-9]+)\\|(g|c|ms)(\\|@([0-9\\.]+))?\n?$")

func parseMessage(data []byte) []*Cmd {
	var output []*Cmd
	for _, line := range bytes.Split(data, []byte("\n")) {
		if len(line) == 0 {
			continue
		}

		item := packetRegexp.FindSubmatch(line)
		if len(item) == 0 {
			continue
		}

		var value int
		modifier := string(item[4])
		switch modifier {
		case "c":
			var vali, err = strconv.ParseInt(string(item[3]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseInt %s - %s", item[3], err)
				continue
			}
			value = int(vali)
		default:
			var valu, err = strconv.ParseUint(string(item[3]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseUint %s - %s", item[3], err)
				continue
			}
			value = int(valu)
		}
		var action string
		switch string(item[2]) {
		case "warn":
			action = ACTION_SET_WARN
		case "err":
			action = ACTION_SET_ERR
		case "beat":
			action = ACTION_BEAT
		}

		packet := &Cmd{
			Action: action,
			Service: string(item[1]),
			Value:    value,
		}
		output = append(output, packet)
	}
	return output
}

func udpListener() {
	address, _ := net.ResolveUDPAddr("udp", *serviceAddress)
	log.Printf("listening on %s", address)
	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()

	message := make([]byte, MAX_UDP_PACKET_SIZE)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range parseMessage(message[:n]) {
			In <- p
		}
	}
}

func main() {
	flag.Parse()
	if *showVersion {
		fmt.Printf("statsdaemon v%s (built w/%s)\n", VERSION, runtime.Version())
		return
	}

	signalchan = make(chan os.Signal, 1)
	signal.Notify(signalchan, syscall.SIGTERM)

	go udpListener()
	monitor()
}
<|endoftext|>


<commit_before>package esso

import (
	"github.com/gorilla/mux"
	"html/template"
	"net/http"
)

var App = mux.NewRouter()

func init() {
	App.HandleFunc("/", ArticlesHandler)
	App.HandleFunc("/articles/", ArticlesHandler)
	App.HandleFunc("/articles/{slug}", ArticleHandler)
	App.Handle("/static/{page:.*}", http.FileServer(http.Dir("public")))
}

var baseTpl = template.Must(template.ParseFiles("templates/base.html"))

var articleList Articles
var articleMap ArticleMap

func init() {
	var err error
	articleList, err = LoadArticles("articles/*.html")
	if err != nil {
		panic(err)
	}
	articleMap = articleList.ArticleMap()
}

var articlesTpl = template.Must(template.Must(baseTpl.Clone()).ParseFiles("templates/article.html"))

func ArticlesHandler(w http.ResponseWriter, r *http.Request) {
	data := Page{Articles: articleList, Title: "Essocony: All Articles"}
	articleTpl.Execute(w, data)
}

var articleTpl = template.Must(template.Must(baseTpl.Clone()).ParseFiles("templates/article.html"))

func ArticleHandler(w http.ResponseWriter, r *http.Request) {
	slug := mux.Vars(r)["slug"]
	article, found := articleMap[slug]
	if !found {
		http.NotFound(w, r)
		return
	}
	data := Page{Articles: Articles{article}, Title: "Essocony: " + article.Title}
	articlesTpl.Execute(w, data)
}
<commit_msg>update<commit_after>package esso

import (
	"github.com/gorilla/mux"
	"html/template"
	"net/http"
)

var App = mux.NewRouter()

var ArticleSlice Articles
var ArticleHash ArticleMap

func init() {
	var err error
	ArticleSlice, err = LoadArticles("articles/*.html")
	if err != nil {
		panic(err)
	}
	ArticleHash = ArticleSlice.ArticleMap()
	App.HandleFunc("/", ArticlesHandler)
	App.HandleFunc("/articles/", ArticlesHandler)
	App.HandleFunc("/articles/{slug}", ArticleHandler)
	App.Handle("/static/{page:.*}", http.FileServer(http.Dir("public")))
}

var baseTpl = template.Must(template.ParseFiles("templates/base.html"))

var articlesTpl = template.Must(template.Must(baseTpl.Clone()).ParseFiles("templates/article.html"))

func ArticlesHandler(w http.ResponseWriter, r *http.Request) {
	data := Page{Articles: ArticleSlice, Title: "Essocony: All Articles"}
	articleTpl.Execute(w, data)
}

var articleTpl = template.Must(template.Must(baseTpl.Clone()).ParseFiles("templates/article.html"))

func ArticleHandler(w http.ResponseWriter, r *http.Request) {
	slug := mux.Vars(r)["slug"]
	article, found := ArticleHash[slug]
	if !found {
		http.NotFound(w, r)
		return
	}
	data := Page{Articles: Articles{article}, Title: "Essocony: " + article.Title}
	articlesTpl.Execute(w, data)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
)

var (
	erroring    = false
	maxprocs    = 4
	testPattern = regexp.MustCompile(`test/test-([a-z\-]+)\.sh`)
)

func mainIntegration() {
	if maxprocs < 1 {
		maxprocs = 1
	}

	files := testFiles()

	if len(files) == 0 {
		fmt.Println("no tests to run")
		os.Exit(1)
	}

	var wg sync.WaitGroup
	tests := make(chan string, len(files))
	output := make(chan string, len(files))

	for _, file := range files {
		tests <- file
	}

	go printOutput(output)
	for i := 0; i < maxprocs; i++ {
		wg.Add(1)
		go worker(tests, output, &wg)
	}

	close(tests)
	wg.Wait()
	close(output)
	printOutput(output)

	if erroring {
		os.Exit(1)
	}
}

func runTest(output chan string, test string) {
	out, err := exec.Command("/bin/bash", test).CombinedOutput()
	if err != nil {
		erroring = true
	}

	output <- strings.TrimSpace(string(out))
}

func printOutput(output <-chan string) {
	for {
		select {
		case out, ok := <-output:
			if !ok {
				return
			}

			fmt.Println(out)
		}
	}
}

func worker(tests <-chan string, output chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		select {
		case testname, ok := <-tests:
			if !ok {
				return
			}
			runTest(output, testname)
		}
	}
}

func testFiles() []string {
	if len(os.Args) < 4 {
		return allTestFiles()
	}

	fileMap := make(map[string]bool)
	for _, file := range allTestFiles() {
		fileMap[file] = true
	}

	files := make([]string, 0, len(os.Args)-3)
	for _, arg := range os.Args {
		fullname := "test/test-" + arg + ".sh"
		if fileMap[fullname] {
			files = append(files, fullname)
		}
	}

	return files
}

func allTestFiles() []string {
	files := make([]string, 0, 100)
	filepath.Walk("test", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() || !testPattern.MatchString(path) {
			return nil
		}
		files = append(files, path)
		return nil
	})
	return files
}
<commit_msg>Make sure we don't accidentally run *.sh.orig (merge remnants) in test<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
)

var (
	erroring    = false
	maxprocs    = 4
	testPattern = regexp.MustCompile(`test/test-([a-z\-]+)\.sh$`)
)

func mainIntegration() {
	if maxprocs < 1 {
		maxprocs = 1
	}

	files := testFiles()

	if len(files) == 0 {
		fmt.Println("no tests to run")
		os.Exit(1)
	}

	var wg sync.WaitGroup
	tests := make(chan string, len(files))
	output := make(chan string, len(files))

	for _, file := range files {
		tests <- file
	}

	go printOutput(output)
	for i := 0; i < maxprocs; i++ {
		wg.Add(1)
		go worker(tests, output, &wg)
	}

	close(tests)
	wg.Wait()
	close(output)
	printOutput(output)

	if erroring {
		os.Exit(1)
	}
}

func runTest(output chan string, test string) {
	out, err := exec.Command("/bin/bash", test).CombinedOutput()
	if err != nil {
		erroring = true
	}

	output <- strings.TrimSpace(string(out))
}

func printOutput(output <-chan string) {
	for {
		select {
		case out, ok := <-output:
			if !ok {
				return
			}

			fmt.Println(out)
		}
	}
}

func worker(tests <-chan string, output chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		select {
		case testname, ok := <-tests:
			if !ok {
				return
			}
			runTest(output, testname)
		}
	}
}

func testFiles() []string {
	if len(os.Args) < 4 {
		return allTestFiles()
	}

	fileMap := make(map[string]bool)
	for _, file := range allTestFiles() {
		fileMap[file] = true
	}

	files := make([]string, 0, len(os.Args)-3)
	for _, arg := range os.Args {
		fullname := "test/test-" + arg + ".sh"
		if fileMap[fullname] {
			files = append(files, fullname)
		}
	}

	return files
}

func allTestFiles() []string {
	files := make([]string, 0, 100)
	filepath.Walk("test", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() || !testPattern.MatchString(path) {
			return nil
		}
		files = append(files, path)
		return nil
	})
	return files
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"image"
	_ "image/jpeg"
	"log"
	"mime"
	"os"
	"path/filepath"

	"github.com/agorf/goexif/exif"
	_ "github.com/mattn/go-sqlite3"
)

type Photo struct {
	Aperture      sql.NullFloat64
	Camera        sql.NullString
	ExposureComp  sql.NullInt64
	ExposureTime  sql.NullFloat64
	Flash         sql.NullString
	FocalLength   sql.NullFloat64
	FocalLength35 sql.NullInt64
	Folder        string
	Height        int
	ISO           sql.NullInt64
	Lat           sql.NullFloat64
	Lens          sql.NullString
	Lng           sql.NullFloat64
	Path          string
	Size          int64
	Taken         sql.NullString
	Width         int
}

var (
	db                                                             *sql.DB
	selectSetStmt, selectPhotoStmt, insertSetStmt, insertPhotoStmt *sql.Stmt
)

func decodePhotoExif(photo *Photo, x *exif.Exif) {
	taken, err := x.DateTime()
	if err == nil {
		photo.Taken.String = taken.UTC().Format("2006-01-02 15:04:05")
		photo.Taken.Valid = true
	}

	lat, lng, err := x.LatLong()
	if err == nil {
		photo.Lat.Float64 = lat
		photo.Lat.Valid = true
		photo.Lng.Float64 = lng
		photo.Lng.Valid = true
	}

	orientTag, err := x.Get(exif.Orientation)
	if err == nil {
		switch orientTag.String() {
		case "5", "6", "7", "8": // rotated
			photo.Width, photo.Height = photo.Height, photo.Width // swap
		}
	}

	camMakeTag, err := x.Get(exif.Make)
	if err == nil {
		photo.Camera.String, _ = camMakeTag.StringVal()
		photo.Camera.Valid = true
	}

	camModelTag, err := x.Get(exif.Model)
	if err == nil {
		cameraModel, _ := camModelTag.StringVal()

		if photo.Camera.Valid {
			photo.Camera.String = fmt.Sprintf("%s %s", photo.Camera.String, cameraModel)
		} else {
			photo.Camera.String = cameraModel
			photo.Camera.Valid = true
		}
	}

	lensMakeTag, err := x.Get(exif.LensMake)
	if err == nil {
		photo.Lens.String, _ = lensMakeTag.StringVal()
		photo.Lens.Valid = true
	}

	lensModelTag, err := x.Get(exif.LensModel)
	if err == nil {
		lensModel, _ := lensModelTag.StringVal()

		if photo.Lens.Valid {
			photo.Lens.String = fmt.Sprintf("%s %s", photo.Lens.String, lensModel)
		} else {
			photo.Lens.String = lensModel
			photo.Lens.Valid = true
		}
	}

	focalLenTag, err := x.Get(exif.FocalLength)
	if err == nil {
		numer, denom, _ := focalLenTag.Rat2(0)
		photo.FocalLength.Float64 = float64(numer) / float64(denom)
		photo.FocalLength.Valid = true
	}

	focalLen35Tag, err := x.Get(exif.FocalLengthIn35mmFilm)
	if err == nil {
		photo.FocalLength35.Int64, _ = focalLen35Tag.Int64(0)
		photo.FocalLength35.Valid = true
	}

	apertureTag, err := x.Get(exif.FNumber)
	if err == nil {
		numer, denom, _ := apertureTag.Rat2(0)
		photo.Aperture.Float64 = float64(numer) / float64(denom)
		photo.Aperture.Valid = true
	}

	expTimeTag, err := x.Get(exif.ExposureTime)
	if err == nil {
		numer, denom, _ := expTimeTag.Rat2(0)
		photo.ExposureTime.Float64 = float64(numer) / float64(denom)
		photo.ExposureTime.Valid = true
	}

	isoTag, err := x.Get(exif.ISOSpeedRatings)
	if err == nil {
		photo.ISO.Int64, _ = isoTag.Int64(0)
		photo.ISO.Valid = true
	}

	expBiasTag, err := x.Get(exif.ExposureBiasValue)
	if err == nil {
		photo.ExposureComp.Int64, _ = expBiasTag.Int64(0)
		photo.ExposureComp.Valid = true
	}

	flash, err := x.Flash()
	if err == nil {
		photo.Flash.String = flash
		photo.Flash.Valid = true
	}
}

func decodePhoto(path string) (*Photo, error) {
	var photo Photo

	photo.Path = path
	photo.Folder = filepath.Base(filepath.Dir(path))

	f, err := os.Open(path)
	if err != nil {
		return &photo, err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return &photo, err
	}
	photo.Size = fi.Size()

	img, _, err := image.DecodeConfig(f)
	if err != nil {
		return &photo, err
	}
	photo.Width, photo.Height = img.Width, img.Height

	f.Seek(0, 0) // rewind

	x, err := exif.Decode(f)
	if err == nil { // EXIF data exists
		decodePhotoExif(&photo, x)
	}

	return &photo, nil
}

func storePhoto(photo *Photo) error {
	var setId, photoId int64

	row := selectSetStmt.QueryRow(photo.Folder)
	if err := row.Scan(&setId); err == sql.ErrNoRows { // set does not exist
		result, err := insertSetStmt.Exec(photo.Folder) // create it
		if err != nil {
			return err
		}

		setId, err = result.LastInsertId()
		if err != nil {
			return err
		}
	}

	row = selectPhotoStmt.QueryRow(photo.Path)
	if err := row.Scan(&photoId); err == sql.ErrNoRows { // photo does not exist
		result, err := insertPhotoStmt.Exec(photo.Aperture, photo.Camera,
			photo.ExposureComp, photo.ExposureTime, photo.Flash, photo.FocalLength,
			photo.FocalLength35, photo.Height, photo.ISO, photo.Lat, photo.Lens,
			photo.Lng, photo.Path, setId, photo.Size, photo.Taken, photo.Width) // create it
		if err != nil {
			return err
		}

		photoId, err = result.LastInsertId()
		if err != nil {
			return err
		}

		fmt.Fprintf(os.Stderr, "photos id=%d path=%s\n", photoId, photo.Path)
	}

	return nil
}

func walk(path string, info os.FileInfo, err error) error {
	if err != nil { // error walking "path"
		return nil // skip
	}

	if info.IsDir() {
		return nil // skip
	}

	if mime.TypeByExtension(filepath.Ext(path)) != "image/jpeg" { // not JPEG
		return nil // skip
	}

	photo, err := decodePhoto(path)
	if err == nil {
		storePhoto(photo)
	}

	return nil // next
}

func updatePhotoSiblings() error {
	var prevId, prevSetId int

	tx, err := db.Begin()
	if err != nil {
		return err
	}

	updatePrevPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET prev_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updatePrevPhotoStmt.Close()

	updateNextPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET next_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateNextPhotoStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id FROM photos ORDER BY set_id, taken_at
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId int
		rows.Scan(&id, &setId)

		if setId == prevSetId && prevId > 0 {
			updatePrevPhotoStmt.Exec(prevId, id)
			fmt.Fprintf(os.Stderr, "photos id=%d prev_photo_id=%d\n", id, prevId)
			updateNextPhotoStmt.Exec(id, prevId)
			fmt.Fprintf(os.Stderr, "photos id=%d next_photo_id=%d\n", prevId, id)
		}

		prevId = id
		prevSetId = setId
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func updateSets() error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	photosCountStmt, err := tx.Prepare(`
	SELECT COUNT(*) FROM photos WHERE set_id = ?
	`)
	if err != nil {
		return err
	}
	defer photosCountStmt.Close()

	updateSetStmt, err := tx.Prepare(`
	UPDATE sets
	SET photos_count = ?, taken_at = ?, thumb_photo_id = ?
	WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateSetStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id, MIN(taken_at) FROM photos GROUP BY set_id
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId, photosCount int
		var taken sql.NullString

		rows.Scan(&id, &setId, &taken)

		row := photosCountStmt.QueryRow(setId)
		row.Scan(&photosCount)

		updateSetStmt.Exec(photosCount, taken, id, setId)
		fmt.Fprintf(os.Stderr, "sets id=%d photos_count=%d taken=%q thumb_photo_id=%d\n", setId, photosCount, taken.String, id)
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func main() {
	var err error

	if len(os.Args) == 1 {
		fmt.Fprintf(os.Stderr, "usage: %v path [path...]\n", os.Args[0])
		return
	}

	db, err = sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	selectSetStmt, err = db.Prepare("SELECT id FROM sets WHERE name = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectSetStmt.Close()

	selectPhotoStmt, err = db.Prepare("SELECT id FROM photos WHERE path = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectPhotoStmt.Close()

	insertSetStmt, err = db.Prepare("INSERT INTO sets (name) VALUES (?)")
	if err != nil {
		log.Fatal(err)
	}
	defer insertSetStmt.Close()

	insertPhotoStmt, err = db.Prepare(`
	INSERT INTO photos (
	aperture, camera, exposure_comp, exposure_time, flash, focal_length,
	focal_length_35, height, iso, lat, lens, lng, path, set_id, size, taken_at,
	width
	)
	VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer insertPhotoStmt.Close()

	for i := 1; i < len(os.Args); i++ {
		filepath.Walk(os.Args[i], walk)
	}

	updatePhotoSiblings()
	updateSets()
}
<commit_msg>Convert rational to float without dividing the fraction<commit_after>package main

import (
	"database/sql"
	"fmt"
	"image"
	_ "image/jpeg"
	"log"
	"mime"
	"os"
	"path/filepath"

	"github.com/agorf/goexif/exif"
	_ "github.com/mattn/go-sqlite3"
)

type Photo struct {
	Aperture      sql.NullFloat64
	Camera        sql.NullString
	ExposureComp  sql.NullInt64
	ExposureTime  sql.NullFloat64
	Flash         sql.NullString
	FocalLength   sql.NullFloat64
	FocalLength35 sql.NullInt64
	Folder        string
	Height        int
	ISO           sql.NullInt64
	Lat           sql.NullFloat64
	Lens          sql.NullString
	Lng           sql.NullFloat64
	Path          string
	Size          int64
	Taken         sql.NullString
	Width         int
}

var (
	db                                                             *sql.DB
	selectSetStmt, selectPhotoStmt, insertSetStmt, insertPhotoStmt *sql.Stmt
)

func decodePhotoExif(photo *Photo, x *exif.Exif) {
	taken, err := x.DateTime()
	if err == nil {
		photo.Taken.String = taken.UTC().Format("2006-01-02 15:04:05")
		photo.Taken.Valid = true
	}

	lat, lng, err := x.LatLong()
	if err == nil {
		photo.Lat.Float64 = lat
		photo.Lat.Valid = true
		photo.Lng.Float64 = lng
		photo.Lng.Valid = true
	}

	orientTag, err := x.Get(exif.Orientation)
	if err == nil {
		switch orientTag.String() {
		case "5", "6", "7", "8": // rotated
			photo.Width, photo.Height = photo.Height, photo.Width // swap
		}
	}

	camMakeTag, err := x.Get(exif.Make)
	if err == nil {
		photo.Camera.String, _ = camMakeTag.StringVal()
		photo.Camera.Valid = true
	}

	camModelTag, err := x.Get(exif.Model)
	if err == nil {
		cameraModel, _ := camModelTag.StringVal()

		if photo.Camera.Valid {
			photo.Camera.String = fmt.Sprintf("%s %s", photo.Camera.String, cameraModel)
		} else {
			photo.Camera.String = cameraModel
			photo.Camera.Valid = true
		}
	}

	lensMakeTag, err := x.Get(exif.LensMake)
	if err == nil {
		photo.Lens.String, _ = lensMakeTag.StringVal()
		photo.Lens.Valid = true
	}

	lensModelTag, err := x.Get(exif.LensModel)
	if err == nil {
		lensModel, _ := lensModelTag.StringVal()

		if photo.Lens.Valid {
			photo.Lens.String = fmt.Sprintf("%s %s", photo.Lens.String, lensModel)
		} else {
			photo.Lens.String = lensModel
			photo.Lens.Valid = true
		}
	}

	focalLenTag, err := x.Get(exif.FocalLength)
	if err == nil {
		focalLen, _ := focalLenTag.Rat(0)
		photo.FocalLength.Float64, _ = focalLen.Float64()
		photo.FocalLength.Valid = true
	}

	focalLen35Tag, err := x.Get(exif.FocalLengthIn35mmFilm)
	if err == nil {
		photo.FocalLength35.Int64, _ = focalLen35Tag.Int64(0)
		photo.FocalLength35.Valid = true
	}

	apertureTag, err := x.Get(exif.FNumber)
	if err == nil {
		aperture, _ := apertureTag.Rat(0)
		photo.Aperture.Float64, _ = aperture.Float64()
		photo.Aperture.Valid = true
	}

	expTimeTag, err := x.Get(exif.ExposureTime)
	if err == nil {
		expTime, _ := expTimeTag.Rat(0)
		photo.ExposureTime.Float64, _ = expTime.Float64()
		photo.ExposureTime.Valid = true
	}

	isoTag, err := x.Get(exif.ISOSpeedRatings)
	if err == nil {
		photo.ISO.Int64, _ = isoTag.Int64(0)
		photo.ISO.Valid = true
	}

	expBiasTag, err := x.Get(exif.ExposureBiasValue)
	if err == nil {
		photo.ExposureComp.Int64, _ = expBiasTag.Int64(0)
		photo.ExposureComp.Valid = true
	}

	flash, err := x.Flash()
	if err == nil {
		photo.Flash.String = flash
		photo.Flash.Valid = true
	}
}

func decodePhoto(path string) (*Photo, error) {
	var photo Photo

	photo.Path = path
	photo.Folder = filepath.Base(filepath.Dir(path))

	f, err := os.Open(path)
	if err != nil {
		return &photo, err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return &photo, err
	}
	photo.Size = fi.Size()

	img, _, err := image.DecodeConfig(f)
	if err != nil {
		return &photo, err
	}
	photo.Width, photo.Height = img.Width, img.Height

	f.Seek(0, 0) // rewind

	x, err := exif.Decode(f)
	if err == nil { // EXIF data exists
		decodePhotoExif(&photo, x)
	}

	return &photo, nil
}

func storePhoto(photo *Photo) error {
	var setId, photoId int64

	row := selectSetStmt.QueryRow(photo.Folder)
	if err := row.Scan(&setId); err == sql.ErrNoRows { // set does not exist
		result, err := insertSetStmt.Exec(photo.Folder) // create it
		if err != nil {
			return err
		}

		setId, err = result.LastInsertId()
		if err != nil {
			return err
		}
	}

	row = selectPhotoStmt.QueryRow(photo.Path)
	if err := row.Scan(&photoId); err == sql.ErrNoRows { // photo does not exist
		result, err := insertPhotoStmt.Exec(photo.Aperture, photo.Camera,
			photo.ExposureComp, photo.ExposureTime, photo.Flash, photo.FocalLength,
			photo.FocalLength35, photo.Height, photo.ISO, photo.Lat, photo.Lens,
			photo.Lng, photo.Path, setId, photo.Size, photo.Taken, photo.Width) // create it
		if err != nil {
			return err
		}

		photoId, err = result.LastInsertId()
		if err != nil {
			return err
		}

		fmt.Fprintf(os.Stderr, "photos id=%d path=%s\n", photoId, photo.Path)
	}

	return nil
}

func walk(path string, info os.FileInfo, err error) error {
	if err != nil { // error walking "path"
		return nil // skip
	}

	if info.IsDir() {
		return nil // skip
	}

	if mime.TypeByExtension(filepath.Ext(path)) != "image/jpeg" { // not JPEG
		return nil // skip
	}

	photo, err := decodePhoto(path)
	if err == nil {
		storePhoto(photo)
	}

	return nil // next
}

func updatePhotoSiblings() error {
	var prevId, prevSetId int

	tx, err := db.Begin()
	if err != nil {
		return err
	}

	updatePrevPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET prev_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updatePrevPhotoStmt.Close()

	updateNextPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET next_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateNextPhotoStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id FROM photos ORDER BY set_id, taken_at
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId int
		rows.Scan(&id, &setId)

		if setId == prevSetId && prevId > 0 {
			updatePrevPhotoStmt.Exec(prevId, id)
			fmt.Fprintf(os.Stderr, "photos id=%d prev_photo_id=%d\n", id, prevId)
			updateNextPhotoStmt.Exec(id, prevId)
			fmt.Fprintf(os.Stderr, "photos id=%d next_photo_id=%d\n", prevId, id)
		}

		prevId = id
		prevSetId = setId
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func updateSets() error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	photosCountStmt, err := tx.Prepare(`
	SELECT COUNT(*) FROM photos WHERE set_id = ?
	`)
	if err != nil {
		return err
	}
	defer photosCountStmt.Close()

	updateSetStmt, err := tx.Prepare(`
	UPDATE sets
	SET photos_count = ?, taken_at = ?, thumb_photo_id = ?
	WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateSetStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id, MIN(taken_at) FROM photos GROUP BY set_id
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId, photosCount int
		var taken sql.NullString

		rows.Scan(&id, &setId, &taken)

		row := photosCountStmt.QueryRow(setId)
		row.Scan(&photosCount)

		updateSetStmt.Exec(photosCount, taken, id, setId)
		fmt.Fprintf(os.Stderr, "sets id=%d photos_count=%d taken=%q thumb_photo_id=%d\n", setId, photosCount, taken.String, id)
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func main() {
	var err error

	if len(os.Args) == 1 {
		fmt.Fprintf(os.Stderr, "usage: %v path [path...]\n", os.Args[0])
		return
	}

	db, err = sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	selectSetStmt, err = db.Prepare("SELECT id FROM sets WHERE name = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectSetStmt.Close()

	selectPhotoStmt, err = db.Prepare("SELECT id FROM photos WHERE path = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectPhotoStmt.Close()

	insertSetStmt, err = db.Prepare("INSERT INTO sets (name) VALUES (?)")
	if err != nil {
		log.Fatal(err)
	}
	defer insertSetStmt.Close()

	insertPhotoStmt, err = db.Prepare(`
	INSERT INTO photos (
	aperture, camera, exposure_comp, exposure_time, flash, focal_length,
	focal_length_35, height, iso, lat, lens, lng, path, set_id, size, taken_at,
	width
	)
	VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer insertPhotoStmt.Close()

	for i := 1; i < len(os.Args); i++ {
		filepath.Walk(os.Args[i], walk)
	}

	updatePhotoSiblings()
	updateSets()
}
<|endoftext|>


<commit_before>package main

import (
	log "github.com/sirupsen/logrus"
	"github.com/yuin/gopher-lua"
)

// Extra Lua functions

const luacode = `
-- Given the name of a python script in the same directory,
-- return the outputted lines as a table
function py(filename)
  if filename == nil then
    return {}
  end
  local cmd = "python " .. scriptdir() .. "/" .. filename
  local f = assert(io.popen(cmd, 'r'))
  local a = {}
  for line in f:lines() do
    table.insert(a, line)
  end
  f:close()
  return a
end

-- Given the name of an executable (or executable script) in the same directory,
-- return the outputted lines as a table
function run(given_command)
  if given_command == nil then
    return {}
  end
  local cmd = "cd " .. scriptdir() .. "; " .. given_command
  local f = assert(io.popen(cmd, 'r'))
  local a = {}
  for line in f:lines() do
    table.insert(a, line)
  end
  f:close()
  return a
end

-- List a table
function dir(t)
  if t == nil then
    t = _G
  end
  local output = {}
  for k, v in pairs(t) do
	table.insert(output, string.format("%-16s\t->\t%s", tostring(k), tostring(v)))
  end
  return table.concat(output, "\n")
end
`

// Lua function for converting a table to JSON (string or int)
func loadExtras(L *lua.LState) int {
	if err := L.DoString(luacode); err != nil {
		log.Error("Could not load Lua extras!")
		log.Error(err)
	}
	//L.Push(lua.LString("Loaded extra functions"))
	//return 1 // number of results
	return 0 // number of results
}

func exportExtras(L *lua.LState) {
	// Load extra Lua functions
	//L.SetGlobal("extras", L.NewFunction(loadExtras))
	loadExtras(L)
}
<commit_msg>Remove a comment<commit_after>package main

import (
	log "github.com/sirupsen/logrus"
	"github.com/yuin/gopher-lua"
)

// Extra Lua functions

const luacode = `
-- Given the name of a python script in the same directory,
-- return the outputted lines as a table
function py(filename)
  if filename == nil then
    return {}
  end
  local cmd = "python " .. scriptdir() .. "/" .. filename
  local f = assert(io.popen(cmd, 'r'))
  local a = {}
  for line in f:lines() do
    table.insert(a, line)
  end
  f:close()
  return a
end

-- Given the name of an executable (or executable script) in the same directory,
-- return the outputted lines as a table
function run(given_command)
  if given_command == nil then
    return {}
  end
  local cmd = "cd " .. scriptdir() .. "; " .. given_command
  local f = assert(io.popen(cmd, 'r'))
  local a = {}
  for line in f:lines() do
    table.insert(a, line)
  end
  f:close()
  return a
end

-- List a table
function dir(t)
  if t == nil then
    t = _G
  end
  local output = {}
  for k, v in pairs(t) do
	table.insert(output, string.format("%-16s\t->\t%s", tostring(k), tostring(v)))
  end
  return table.concat(output, "\n")
end
`

// Lua function for converting a table to JSON (string or int)
func loadExtras(L *lua.LState) int {
	if err := L.DoString(luacode); err != nil {
		log.Error("Could not load Lua extras!")
		log.Error(err)
	}
	return 0 // number of results
}

func exportExtras(L *lua.LState) {
	// Load extra Lua functions
	//L.SetGlobal("extras", L.NewFunction(loadExtras))
	loadExtras(L)
}
<|endoftext|>


<commit_before>package mail

import (
	"bytes"
	"mime/multipart"
	"net/textproto"
	"time"
)

// MIMEPart represents a MIME section with headers and message
type MIMEPart struct {
	Headers textproto.MIMEHeader
	Message []byte
}

// NewMIMEPart returns an empty MIME section with headers and message
func NewMIMEPart() MIMEPart {
	part := MIMEPart{}
	part.Headers = make(textproto.MIMEHeader)
	return part
}

func checkedWrite(buffer bytes.Buffer, s string) {
	_, err := buffer.WriteString(s)
	if err != nil {
		panic(err)
	}
}

// ConstructEmail constructs an email to the given recipient consisting of the two MIMEParts
func ConstructEmail(recipient string, parts ...MIMEPart) string {
	var mail bytes.Buffer
	multipartWriter := multipart.NewWriter(&mail)
	checkedWrite(mail, "\r\n")
	checkedWrite(mail, "From: Test GPG Validation Server <test-gpg-validation-server@tngtech.com>\r\n")
	checkedWrite(mail, "To: "+recipient+"\r\n")
	checkedWrite(mail, "Date: "+time.Now().Format(time.RFC1123Z)+"\r\n")
	checkedWrite(mail, "Subject: GPG Key Validation\r\n")
	// checkedWrite(mail, "X-Pgp-Agent: github.com/TNG/gpg-validation-server\r\n")
	// In-Reply-To: <5719D0CA.7000609@tngtech.com>
	checkedWrite(mail, "Content-Transfer-Encoding: 7bit\r\n")
	// Message-Id: <77777770-1111-2222-3333-444444444444@tngtech.com>
	// References: <88888888-2222-4232-2321-121312312312@tngtech.com> <12389DDA.0000123@tngtech.com>
	// checkedWrite(mail, "Content-Description: OpenPGP encrypted message\r\n")
	checkedWrite(mail, "X-Mailer: github.com/TNG/gpg-validation-server\r\n")

	// Now follow the MIME Headers
	checkedWrite(mail, "Mime-Version: 1.0 (Golang 1.6)\r\n")
	// checkedWrite(mail, "Content-Type: multipart/encrypted; boundary=\"" + multipartWriter.Boundary() + "\"; protocol=\"application/pgp-encrypted\";\r\n")
	checkedWrite(mail, "Content-Type: multipart/plain; boundary=\""+multipartWriter.Boundary()+"\";\r\n")
	checkedWrite(mail, "\r\n")
	checkedWrite(mail, "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)\r\n")

	for _, part := range parts {
		partWriter, _ := multipartWriter.CreatePart(part.Headers)
		_, err := partWriter.Write(part.Message)
		if err != nil {
			panic(err)
		}
	}
	err := multipartWriter.Close()
	if err != nil {
		panic(err)
	}
	return mail.String()
}
<commit_msg>Minor doc string correction<commit_after>package mail

import (
	"bytes"
	"mime/multipart"
	"net/textproto"
	"time"
)

// MIMEPart represents a MIME section with headers and message
type MIMEPart struct {
	Headers textproto.MIMEHeader
	Message []byte
}

// NewMIMEPart returns an empty MIME section
func NewMIMEPart() MIMEPart {
	part := MIMEPart{}
	part.Headers = make(textproto.MIMEHeader)
	return part
}

func checkedWrite(buffer bytes.Buffer, s string) {
	_, err := buffer.WriteString(s)
	if err != nil {
		panic(err)
	}
}

// ConstructEmail constructs an email to the given recipient consisting of the given MIMEParts
func ConstructEmail(recipient string, parts ...MIMEPart) string {
	var mail bytes.Buffer
	multipartWriter := multipart.NewWriter(&mail)
	checkedWrite(mail, "\r\n")
	checkedWrite(mail, "From: Test GPG Validation Server <test-gpg-validation-server@tngtech.com>\r\n")
	checkedWrite(mail, "To: "+recipient+"\r\n")
	checkedWrite(mail, "Date: "+time.Now().Format(time.RFC1123Z)+"\r\n")
	checkedWrite(mail, "Subject: GPG Key Validation\r\n")
	// checkedWrite(mail, "X-Pgp-Agent: github.com/TNG/gpg-validation-server\r\n")
	// In-Reply-To: <5719D0CA.7000609@tngtech.com>
	checkedWrite(mail, "Content-Transfer-Encoding: 7bit\r\n")
	// Message-Id: <77777770-1111-2222-3333-444444444444@tngtech.com>
	// References: <88888888-2222-4232-2321-121312312312@tngtech.com> <12389DDA.0000123@tngtech.com>
	// checkedWrite(mail, "Content-Description: OpenPGP encrypted message\r\n")
	checkedWrite(mail, "X-Mailer: github.com/TNG/gpg-validation-server\r\n")

	// Now follow the MIME Headers
	checkedWrite(mail, "Mime-Version: 1.0 (Golang 1.6)\r\n")
	// checkedWrite(mail, "Content-Type: multipart/encrypted; boundary=\"" + multipartWriter.Boundary() + "\"; protocol=\"application/pgp-encrypted\";\r\n")
	checkedWrite(mail, "Content-Type: multipart/plain; boundary=\""+multipartWriter.Boundary()+"\";\r\n")
	checkedWrite(mail, "\r\n")
	checkedWrite(mail, "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)\r\n")

	for _, part := range parts {
		partWriter, _ := multipartWriter.CreatePart(part.Headers)
		_, err := partWriter.Write(part.Message)
		if err != nil {
			panic(err)
		}
	}
	err := multipartWriter.Close()
	if err != nil {
		panic(err)
	}
	return mail.String()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/couchbaselabs/logg"
	"github.com/tleyden/checkerlution"
	ng "github.com/tleyden/neurgo"
)

func main() {

	logg.LogKeys["MAIN"] = true

	ng.SeedRandom()

	redTeam := checkerlution.RED_TEAM
	game := checkerlution.NewGame(redTeam)
	game.GameLoop()

}
<commit_msg>fixup main<commit_after>package main

import (
	"github.com/couchbaselabs/logg"
	"github.com/tleyden/checkerlution"
	cbot "github.com/tleyden/checkers-bot"
	ng "github.com/tleyden/neurgo"
)

func main() {

	logg.LogKeys["MAIN"] = true

	ng.SeedRandom()

	thinker := new(checkerlution.Checkerlution)
	redTeam := cbot.RED_TEAM
	game := cbot.NewGame(redTeam, thinker)
	game.GameLoop()

}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"time"

	"github.com/coderjz/gorogue/game"
	"github.com/nsf/termbox-go"
)

const animationSpeed = 10 * time.Millisecond

const (
	StateIntroScrolling = iota
	StateIntroScrolled
	StateInstructions
	StateMainGame
	StateGameOverStarting
	StateGameOverMenuDisplayed
	StateDisplayLeaveDialog
	StateWonGame
)

func main() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}

	defer termbox.Close()

	eventQueue := make(chan termbox.Event)
	go func() {
		for {
			eventQueue <- termbox.PollEvent()
		}
	}()

	log.SetFlags(log.Lshortfile)
	logFileName := "./logs"
	f, err := os.Create(logFileName)
	if err != nil {
		panic("Cannot make log file")
	}
	log.SetOutput(f)

	log.Printf("\n\nStarting game at %s", time.Now().Format("010206_030405"))

	//TODO: Check terminal size (termbox.Size(), if not big enough and output error message)
	//Maybe do that in the render itself or do it here with a check in the game loop?

	state := StateIntroScrolling

	intro := game.NewIntro()
	intro.Render() //This is asynchronous
	intro.ScrollCompleted = func() {
		state = StateIntroScrolled
	}

	instructions := game.Instructions{}
	gameover := game.NewGameOver()
	gameover.MenuDisplayed = func() {
		state = StateGameOverMenuDisplayed
	}
	var mainGame *game.Game
	var leaveDialog *game.LeaveDialog
	var gameWin *game.GameWin

	for {
		ev := <-eventQueue
		switch state {
		case StateIntroScrolling:
			if ev.Key == termbox.KeyEsc {
				return
			}
			intro.CompleteScrolling()
		case StateIntroScrolled:
			if ev.Key == termbox.KeyEsc {
				return
			}

			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				intro.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				intro.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch intro.GetSelectedChoice() {
				case 0: //Start game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: //Instructions
					instructions.Render()
					state = StateInstructions
				case 2: //Exit
					return
				}
			}
		case StateInstructions:
			if ev.Key == termbox.KeyEsc || ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				state = StateIntroScrolled
				intro.RenderScrolled()
			}
		case StateMainGame:
			playerActed := false
			//Copy logic here from main game logic
			switch {
			case ev.Key == termbox.KeyArrowUp || ev.Ch == 'k':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.UP)
			case ev.Key == termbox.KeyArrowDown || ev.Ch == 'j':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.DOWN)
			case ev.Key == termbox.KeyArrowLeft || ev.Ch == 'h':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.LEFT)
			case ev.Key == termbox.KeyArrowRight || ev.Ch == 'l':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.RIGHT)
			case ev.Key == termbox.KeySpace:
				if mainGame.OnDungeonExit() {
					if mainGame.HasChalice {
						gameWin = game.NewGameWin()
						gameWin.Render()
						state = StateWonGame
					} else {
						leaveDialog = game.NewLeaveDialog()
						leaveDialog.Render()
						state = StateDisplayLeaveDialog
					}
				} else if mainGame.OnChalice() {
					mainGame.TakeChalice()
					playerActed = true
				} else {
					playerActed = mainGame.ChangeFloor()
				}
			case ev.Key == termbox.KeyEsc:
				return
			}

			if !playerActed {
				time.Sleep(animationSpeed)
				continue
			}

			mainGame.HealPlayerFromActions()
			mainGame.UpdateFOV()
			mainGame.UpdateMonsters()
			if mainGame.IsGameOver {
				mainGame.ClearMessages()
				mainGame.StopMessageChan()
				state = StateGameOverStarting
				go gameover.Render(mainGame.GetPlayerPos())
				continue
			}
			mainGame.Render()
			time.Sleep(animationSpeed)
		case StateGameOverStarting:
			if ev.Key == termbox.KeyEsc {
				return
			}
		case StateGameOverMenuDisplayed:
			if ev.Key == termbox.KeyEsc {
				return
			}

			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				gameover.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				gameover.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch gameover.GetSelectedChoice() {
				case 0: //Start new game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: //Exit
					return
				}
			}
		case StateWonGame:
			if ev.Key == termbox.KeyEsc {
				return
			}
			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				gameWin.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				gameWin.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch gameWin.GetSelectedChoice() {
				case 0: //Start new game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: // Exit
					return
				}
			}
		case StateDisplayLeaveDialog:
			if ev.Key == termbox.KeyEsc {
				mainGame.Render()
				state = StateMainGame
			} else if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				leaveDialog.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				leaveDialog.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch leaveDialog.GetSelectedChoice() {
				case 0: // Stay in game
					mainGame.Render()
					state = StateMainGame
				case 1: // Go home (exit)
					mainGame.StopMessageChan()
					state = StateIntroScrolled
					intro := game.NewIntro()
					intro.RenderScrolled()
				}
			}
		}
	}
}
<commit_msg>Must validate that events are key presses<commit_after>package main

import (
	"log"
	"os"
	"time"

	"github.com/coderjz/gorogue/game"
	"github.com/nsf/termbox-go"
)

const animationSpeed = 10 * time.Millisecond

const (
	StateIntroScrolling = iota
	StateIntroScrolled
	StateInstructions
	StateMainGame
	StateGameOverStarting
	StateGameOverMenuDisplayed
	StateDisplayLeaveDialog
	StateWonGame
)

func main() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}

	defer termbox.Close()

	eventKeyPressQueue := make(chan termbox.Event)
	go func() {
		for {
			ev := termbox.PollEvent()
			if ev.Type != termbox.EventKey {
				continue
			}
			eventKeyPressQueue <- ev
		}
	}()

	log.SetFlags(log.Lshortfile)
	logFileName := "./logs"
	f, err := os.Create(logFileName)
	if err != nil {
		panic("Cannot make log file")
	}
	log.SetOutput(f)

	log.Printf("\n\nStarting game at %s", time.Now().Format("010206_030405"))

	//TODO: Check terminal size (termbox.Size(), if not big enough and output error message)
	//Maybe do that in the render itself or do it here with a check in the game loop?

	state := StateIntroScrolling

	intro := game.NewIntro()
	intro.Render() //This is asynchronous
	intro.ScrollCompleted = func() {
		state = StateIntroScrolled
	}

	instructions := game.Instructions{}
	gameover := game.NewGameOver()
	gameover.MenuDisplayed = func() {
		state = StateGameOverMenuDisplayed
	}
	var mainGame *game.Game
	var leaveDialog *game.LeaveDialog
	var gameWin *game.GameWin

	for {
		ev := <-eventKeyPressQueue
		switch state {
		case StateIntroScrolling:
			if ev.Key == termbox.KeyEsc {
				return
			}
			intro.CompleteScrolling()
		case StateIntroScrolled:
			if ev.Key == termbox.KeyEsc {
				return
			}

			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				intro.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				intro.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch intro.GetSelectedChoice() {
				case 0: //Start game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: //Instructions
					instructions.Render()
					state = StateInstructions
				case 2: //Exit
					return
				}
			}
		case StateInstructions:
			if ev.Key == termbox.KeyEsc || ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				state = StateIntroScrolled
				intro.RenderScrolled()
			}
		case StateMainGame:
			playerActed := false
			//Copy logic here from main game logic
			switch {
			case ev.Key == termbox.KeyArrowUp || ev.Ch == 'k':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.UP)
			case ev.Key == termbox.KeyArrowDown || ev.Ch == 'j':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.DOWN)
			case ev.Key == termbox.KeyArrowLeft || ev.Ch == 'h':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.LEFT)
			case ev.Key == termbox.KeyArrowRight || ev.Ch == 'l':
				mainGame.ClearMessages()
				playerActed = mainGame.MovePlayer(game.RIGHT)
			case ev.Key == termbox.KeySpace:
				if mainGame.OnDungeonExit() {
					if mainGame.HasChalice {
						gameWin = game.NewGameWin()
						gameWin.Render()
						state = StateWonGame
					} else {
						leaveDialog = game.NewLeaveDialog()
						leaveDialog.Render()
						state = StateDisplayLeaveDialog
					}
				} else if mainGame.OnChalice() {
					mainGame.TakeChalice()
					playerActed = true
				} else {
					playerActed = mainGame.ChangeFloor()
				}
			case ev.Key == termbox.KeyEsc:
				return
			}

			if !playerActed {
				time.Sleep(animationSpeed)
				continue
			}

			mainGame.HealPlayerFromActions()
			mainGame.UpdateFOV()
			mainGame.UpdateMonsters()
			if mainGame.IsGameOver {
				mainGame.ClearMessages()
				mainGame.StopMessageChan()
				state = StateGameOverStarting
				go gameover.Render(mainGame.GetPlayerPos())
				continue
			}
			mainGame.Render()
			time.Sleep(animationSpeed)
		case StateGameOverStarting:
			if ev.Key == termbox.KeyEsc {
				return
			}
		case StateGameOverMenuDisplayed:
			if ev.Key == termbox.KeyEsc {
				return
			}

			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				gameover.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				gameover.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch gameover.GetSelectedChoice() {
				case 0: //Start new game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: //Exit
					return
				}
			}
		case StateWonGame:
			if ev.Key == termbox.KeyEsc {
				return
			}
			if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				gameWin.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				gameWin.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch gameWin.GetSelectedChoice() {
				case 0: //Start new game
					mainGame = game.NewGame()
					mainGame.UpdateFOV()
					mainGame.Render()
					state = StateMainGame
				case 1: // Exit
					return
				}
			}
		case StateDisplayLeaveDialog:
			if ev.Key == termbox.KeyEsc {
				mainGame.Render()
				state = StateMainGame
			} else if ev.Key == termbox.KeyArrowUp || ev.Ch == 'k' {
				leaveDialog.SelectPrevChoice()
			} else if ev.Key == termbox.KeyArrowDown || ev.Ch == 'j' {
				leaveDialog.SelectNextChoice()
			} else if ev.Key == termbox.KeySpace || ev.Key == termbox.KeyEnter {
				switch leaveDialog.GetSelectedChoice() {
				case 0: // Stay in game
					mainGame.Render()
					state = StateMainGame
				case 1: // Go home (exit)
					mainGame.StopMessageChan()
					state = StateIntroScrolled
					intro := game.NewIntro()
					intro.RenderScrolled()
				}
			}
		}
	}
}
<|endoftext|>