<commit_before>package tracker

import (
	"context"
	"errors"
	"net/http"
	"net/url"
	"time"

	"github.com/anacrolix/dht/v2/krpc"
)

// Marshalled as binary by the UDP client, so be careful making changes.
type AnnounceRequest struct {
	InfoHash   [20]byte
	PeerId     [20]byte
	Downloaded int64
	Left       int64 // If less than 0, math.MaxInt64 will be used for HTTP trackers instead.
	Uploaded   int64
	// Apparently this is optional. None can be used for announces done at
	// regular intervals.
	Event     AnnounceEvent
	IPAddress uint32
	Key       int32
	NumWant   int32 // How many peer addresses are desired. -1 for default.
	Port      uint16
} // 82 bytes

type AnnounceResponse struct {
	Interval int32 // Minimum seconds the local peer should wait before next announce.
	Leechers int32
	Seeders  int32
	Peers    []Peer
}

type AnnounceEvent int32

func (e AnnounceEvent) String() string {
	// See BEP 3, "event".
	return []string{"empty", "completed", "started", "stopped"}[e]
}

const (
	None      AnnounceEvent = iota
	Completed               // The local peer just completed the torrent.
	Started                 // The local peer has just resumed this torrent.
	Stopped                 // The local peer is leaving the swarm.
)

var (
	ErrBadScheme = errors.New("unknown scheme")
)

type Announce struct {
	TrackerUrl string
	Request    AnnounceRequest
	HostHeader string
	HTTPProxy  func(*http.Request) (*url.URL, error)
	ServerName string
	UserAgent  string
	UdpNetwork string
	// If the port is zero, it's assumed to be the same as the Request.Port.
	ClientIp4 krpc.NodeAddr
	// If the port is zero, it's assumed to be the same as the Request.Port.
	ClientIp6 krpc.NodeAddr
	Context   context.Context
}

// The code *is* the documentation.
const DefaultTrackerAnnounceTimeout = 15 * time.Second

func (me Announce) Do() (res AnnounceResponse, err error) {
	_url, err := url.Parse(me.TrackerUrl)
	if err != nil {
		return
	}
	if me.Context == nil {
		// This is just to maintain the old behaviour that should be a timeout of 15s. Users can
		// override it by providing their own Context. See comments elsewhere about longer timeouts
		// acting as rate limiting overloaded trackers.
		ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
		defer cancel()
		me.Context = ctx
	}
	switch _url.Scheme {
	case "http", "https":
		return announceHTTP(me, _url)
	case "udp", "udp4", "udp6":
		return announceUDP(me, _url)
	default:
		err = ErrBadScheme
		return
	}
}
<commit_msg>Fix "none" event for WebTorrent announces<commit_after>package tracker

import (
	"context"
	"errors"
	"net/http"
	"net/url"
	"time"

	"github.com/anacrolix/dht/v2/krpc"
)

// Marshalled as binary by the UDP client, so be careful making changes.
type AnnounceRequest struct {
	InfoHash   [20]byte
	PeerId     [20]byte
	Downloaded int64
	Left       int64 // If less than 0, math.MaxInt64 will be used for HTTP trackers instead.
	Uploaded   int64
	// Apparently this is optional. None can be used for announces done at
	// regular intervals.
	Event     AnnounceEvent
	IPAddress uint32
	Key       int32
	NumWant   int32 // How many peer addresses are desired. -1 for default.
	Port      uint16
} // 82 bytes

type AnnounceResponse struct {
	Interval int32 // Minimum seconds the local peer should wait before next announce.
	Leechers int32
	Seeders  int32
	Peers    []Peer
}

type AnnounceEvent int32

func (e AnnounceEvent) String() string {
	// See BEP 3, "event", and https://github.com/anacrolix/torrent/issues/416#issuecomment-751427001.
	return []string{"", "completed", "started", "stopped"}[e]
}

const (
	None      AnnounceEvent = iota
	Completed               // The local peer just completed the torrent.
	Started                 // The local peer has just resumed this torrent.
	Stopped                 // The local peer is leaving the swarm.
)

var (
	ErrBadScheme = errors.New("unknown scheme")
)

type Announce struct {
	TrackerUrl string
	Request    AnnounceRequest
	HostHeader string
	HTTPProxy  func(*http.Request) (*url.URL, error)
	ServerName string
	UserAgent  string
	UdpNetwork string
	// If the port is zero, it's assumed to be the same as the Request.Port.
	ClientIp4 krpc.NodeAddr
	// If the port is zero, it's assumed to be the same as the Request.Port.
	ClientIp6 krpc.NodeAddr
	Context   context.Context
}

// The code *is* the documentation.
const DefaultTrackerAnnounceTimeout = 15 * time.Second

func (me Announce) Do() (res AnnounceResponse, err error) {
	_url, err := url.Parse(me.TrackerUrl)
	if err != nil {
		return
	}
	if me.Context == nil {
		// This is just to maintain the old behaviour that should be a timeout of 15s. Users can
		// override it by providing their own Context. See comments elsewhere about longer timeouts
		// acting as rate limiting overloaded trackers.
		ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
		defer cancel()
		me.Context = ctx
	}
	switch _url.Scheme {
	case "http", "https":
		return announceHTTP(me, _url)
	case "udp", "udp4", "udp6":
		return announceUDP(me, _url)
	default:
		err = ErrBadScheme
		return
	}
}
<|endoftext|>


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

package opt

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/fun"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/num"
)

// Powell implements the multidimensional minimization by Powell's method (no derivatives required)
//
//   REFERENCES:
//   [1] Press WH, Teukolsky SA, Vetterling WT, Fnannery BP (2007) Numerical Recipes:
//       The Art of Scientific Computing. Third Edition. Cambridge University Press. 1235p.
//
type Powell struct {

	// configuration
	MaxIt   int     // max iterations
	Ftol    float64 // tolerance on f({x})
	Verbose bool    // show messages
	History bool    // save history

	// statistics and History (for debugging)
	NFeval int      // number of calls to Ffcn (function evaluations)
	It     int      // number of iterations from last call to Solve
	Hist   *History // history of optimization data (for debugging)

	// internal
	size int       // problem dimension
	ffcn fun.Sv    // scalar function of vector: y = f({x})
	x    la.Vector // auxiliary "current" point
	xe   la.Vector // auxiliary "extrapolated" point
	nAve la.Vector // average direction moved
	tiny float64   // small number for convergence check

	// access
	LS   *num.LineSolver // line solver wrapping Brent's method
	Nmat *la.Matrix      // matrix whose columns contain the directions n
}

// NewPowell returns a new multidimensional optimizer using Powell's method (no derivatives required)
//   size -- length(x)
//   ffcn -- scalar function of vector: y = f({x})
func NewPowell(size int, ffcn fun.Sv) (o *Powell) {
	o = new(Powell)
	o.size = size
	o.ffcn = ffcn
	o.MaxIt = 1000
	o.Ftol = 1e-8
	o.tiny = 1e-25
	o.LS = num.NewLineSolver(size, ffcn, nil)
	o.x = la.NewVector(size)
	o.xe = la.NewVector(size)
	o.nAve = la.NewVector(size)
	o.Nmat = la.NewMatrix(size, size)
	return
}

// Min solves minimization problem
//
//  Input:
//    x0 -- [size] initial starting point (will be modified)
//    reuseNmat -- use pre-computed Nmat containing the directions as columns
//
//  Output:
//    o.x -- will hold the point corresponding to the just found fmin
//
func (o *Powell) Min(x0 la.Vector, reuseNmat bool) (fmin float64) {

	// set Nmat with unit vectors
	if !reuseNmat {
		o.Nmat.SetDiag(1) // set diagonal
	}

	// initializations
	o.x.Apply(1, x0)   // x := x0
	fmin = o.ffcn(o.x) // fmin := f({x0})

	// history
	var λhist float64
	var nhist la.Vector
	if o.History {
		o.Hist = NewHistory(o.MaxIt, fmin, o.x, o.ffcn)
		nhist = la.NewVector(o.size)
	}

	// iterations
	for o.It = 0; o.It < o.MaxIt; o.It++ {

		// set iteration values
		fx := fmin  // iteration f({x})
		jDel := 0   // index of largest decrease
		delF := 0.0 // largest function decrease

		// loop over all directions in the set
		for jDir := 0; jDir < o.size; jDir++ {

			// minimize along direction jDir
			n := o.Nmat.GetCol(jDir)              // direction
			fold := fmin                          // save fmin
			λhist, fmin = o.LS.MinUpdateX(o.x, n) // x := x @ min

			// record direction if it corresponds to the largest decrease so far
			if fold-fmin > delF {
				delF = fold - fmin
				jDel = jDir + 1
			}

			// history
			if o.History {
				nhist.Apply(λhist, n)
				o.Hist.Append(fmin, o.x, nhist)
			}
		}

		// exit point
		if 2.0*(fx-fmin) <= o.Ftol*(math.Abs(fx)+math.Abs(fmin))+o.tiny {
			return
		}

		// update
		for i := 0; i < o.size; i++ {
			o.xe[i] = 2.0*o.x[i] - x0[i] // xe := 2⋅x - x0  extrapolated point
			o.nAve[i] = o.x[i] - x0[i]   // nAve := x - x0  average direction moved
			x0[i] = o.x[i]               // save the old starting point
		}

		// function value at extrapolated point
		fe := o.ffcn(o.xe)

		// move to the minimum of the new direction, and save the new direction
		if fe < fx {
			t := 2.0*(fx-2.0*fmin+fe)*math.Pow(fx-fmin-delF, 2) - delF*math.Pow(fx-fe, 2)
			if t < 0.0 {
				fmin = o.LS.Min(o.x, o.nAve)
				for i := 0; i < o.size; i++ {
					o.Nmat.Set(i, jDel-1, o.Nmat.Get(i, o.size-1))
					o.Nmat.Set(i, o.size-1, o.nAve[i])
				}
			}
		}
	}

	// did not converge
	chk.Panic("fail to converge after %d iterations", o.It)
	return
}
<commit_msg>Rename variable in Powell's method<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package opt

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/fun"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/num"
)

// Powell implements the multidimensional minimization by Powell's method (no derivatives required)
//
//   REFERENCES:
//   [1] Press WH, Teukolsky SA, Vetterling WT, Fnannery BP (2007) Numerical Recipes:
//       The Art of Scientific Computing. Third Edition. Cambridge University Press. 1235p.
//
type Powell struct {

	// configuration
	MaxIt   int     // max iterations
	Ftol    float64 // tolerance on f({x})
	Verbose bool    // show messages
	History bool    // save history

	// statistics and History (for debugging)
	NFeval int      // number of calls to Ffcn (function evaluations)
	It     int      // number of iterations from last call to Solve
	Hist   *History // history of optimization data (for debugging)

	// internal
	size int       // problem dimension
	ffcn fun.Sv    // scalar function of vector: y = f({x})
	x    la.Vector // auxiliary "current" point
	xe   la.Vector // auxiliary "extrapolated" point
	nAve la.Vector // average direction moved
	tiny float64   // small number for convergence check

	// access
	LS   *num.LineSolver // line solver wrapping Brent's method
	Nmat *la.Matrix      // matrix whose columns contain the directions n
}

// NewPowell returns a new multidimensional optimizer using Powell's method (no derivatives required)
//   size -- length(x)
//   ffcn -- scalar function of vector: y = f({x})
func NewPowell(size int, ffcn fun.Sv) (o *Powell) {
	o = new(Powell)
	o.size = size
	o.ffcn = ffcn
	o.MaxIt = 1000
	o.Ftol = 1e-8
	o.tiny = 1e-25
	o.LS = num.NewLineSolver(size, ffcn, nil)
	o.x = la.NewVector(size)
	o.xe = la.NewVector(size)
	o.nAve = la.NewVector(size)
	o.Nmat = la.NewMatrix(size, size)
	return
}

// Min solves minimization problem
//
//  Input:
//    x0 -- [size] initial starting point (will be modified)
//    reuseNmat -- use pre-computed Nmat containing the directions as columns
//
//  Output:
//    o.x -- will hold the point corresponding to the just found fmin
//
func (o *Powell) Min(x0 la.Vector, reuseNmat bool) (fmin float64) {

	// set Nmat with unit vectors
	if !reuseNmat {
		o.Nmat.SetDiag(1) // set diagonal
	}

	// initializations
	o.x.Apply(1, x0)   // x := x0
	fmin = o.ffcn(o.x) // fmin := f({x0})

	// history
	var λhist float64
	var nhist la.Vector
	if o.History {
		o.Hist = NewHistory(o.MaxIt, fmin, o.x, o.ffcn)
		nhist = la.NewVector(o.size)
	}

	// iterations
	for o.It = 0; o.It < o.MaxIt; o.It++ {

		// set iteration values
		fx := fmin  // iteration f({x})
		delJ := 0   // index of largest decrease
		delF := 0.0 // largest function decrease

		// loop over all directions in the set
		for jDir := 0; jDir < o.size; jDir++ {

			// minimize along direction jDir
			n := o.Nmat.GetCol(jDir)              // direction
			fold := fmin                          // save fmin
			λhist, fmin = o.LS.MinUpdateX(o.x, n) // x := x @ min

			// record direction if it corresponds to the largest decrease so far
			if fold-fmin > delF {
				delF = fold - fmin
				delJ = jDir + 1
			}

			// history
			if o.History {
				nhist.Apply(λhist, n)
				o.Hist.Append(fmin, o.x, nhist)
			}
		}

		// exit point
		if 2.0*(fx-fmin) <= o.Ftol*(math.Abs(fx)+math.Abs(fmin))+o.tiny {
			return
		}

		// update
		for i := 0; i < o.size; i++ {
			o.xe[i] = 2.0*o.x[i] - x0[i] // xe := 2⋅x - x0  extrapolated point
			o.nAve[i] = o.x[i] - x0[i]   // nAve := x - x0  average direction moved
			x0[i] = o.x[i]               // save the old starting point
		}

		// function value at extrapolated point
		fe := o.ffcn(o.xe)

		// move to the minimum of the new direction, and save the new direction
		if fe < fx {
			t := 2.0*(fx-2.0*fmin+fe)*math.Pow(fx-fmin-delF, 2) - delF*math.Pow(fx-fe, 2)
			if t < 0.0 {
				fmin = o.LS.Min(o.x, o.nAve)
				for i := 0; i < o.size; i++ {
					o.Nmat.Set(i, delJ-1, o.Nmat.Get(i, o.size-1))
					o.Nmat.Set(i, o.size-1, o.nAve[i])
				}
			}
		}
	}

	// did not converge
	chk.Panic("fail to converge after %d iterations", o.It)
	return
}
<|endoftext|>


<commit_before>package orm

import (
	"errors"
	"reflect"
	"sort"
	"time"

	"github.com/ueffort/goutils/event"
)

type Conversion interface {
	FromDB([]byte) error
	ToDB() ([]byte, error)
}

type Schema struct {
	AutoIncrement string
	Primary       []string

	schemaType    reflect.Type
	schemaPtrType reflect.Type
	columns       map[string]*column
	fields        map[string]string
	record        interface{}

	softDelete bool
	createTime string
	updateTime string
	deleteTime string

	event event.Event
}

func NewSchema(record interface{}) (*Schema, error) {

	s := &Schema{
		AutoIncrement: "",
		Primary:       []string{},
		softDelete:    false,
		event:         event.New(),
	}
	err := s.With(record)
	return s, err
}

func (s *Schema) Default(field string, value interface{}) *Schema {
	s.columns[field].d = value
	return s
}

func (s *Schema) With(record interface{}) error {
	s.fields = make(map[string]string)
	s.columns = make(map[string]*column)
	value := reflect.ValueOf(record)
	if value.Kind() != reflect.Ptr || value.Elem().Kind() != reflect.Struct {
		return errors.New("needs a Struct pointer")
	}
	valueE := value.Elem()
	tp := reflect.TypeOf(record)
	t := tp.Elem()
	for k := 0; k < t.NumField(); k++ {
		col := t.Field(k)
		tag := col.Tag
		v := valueE.FieldByName(col.Name)
		d := v.Interface()
		_, required := tag.Lookup("required")
		t, tset := tag.Lookup("time")

		field := tag.Get("json")
		if field != "" {
			s.fields[col.Name] = field
		} else {
			s.fields[col.Name] = col.Name
		}

		c := &column{
			col.Name,
			col.Type,
			v,
			d,
			tag.Get("sql"),
			required,
			time.UTC,
		}
		if tset {
			switch t {
			case "local":
				c.zone = time.Local
			case "utc":
				c.zone = time.UTC
			default:
				zone, err := time.LoadLocation(t)
				if err != nil {
					return err
				}
				c.zone = zone
			}
		}
		s.columns[s.fields[col.Name]] = c
		key := tag.Get("orm")
		switch key {
		case "auto":
			s.SetAutoIncrement(col.Name)
		case "primary":
			s.SetPrimary(col.Name)
		case "deleteTime":
			s.SoftDelete(col.Name)
		case "createTime":
			s.SetCreateTime(col.Name)
		case "updateTime":
			s.SetUpdateTime(col.Name)
		}
	}
	s.record = record
	s.schemaType = t
	s.schemaPtrType = tp
	return nil
}

func (s *Schema) SetAutoIncrement(field string) *Schema {
	s.AutoIncrement = field
	s.Primary = []string{field}
	return s
}

func (s *Schema) SetPrimary(primary ...string) *Schema {
	s.Primary = append(s.Primary, primary...)
	return s
}

func (s *Schema) SetTime(createTime string, updateTime string, deleteTime string) *Schema {
	s.SetCreateTime(createTime)
	s.SetUpdateTime(updateTime)
	s.SoftDelete(deleteTime)
	return s
}

func (s *Schema) SetCreateTime(createTime string) *Schema {
	if createTime == "" {
		createTime = "CreateTime"
	}
	s.createTime = createTime
	s.columns[s.fields[createTime]].sql = "dateTime"
	return s
}

func (s *Schema) SetUpdateTime(updateTime string) *Schema {
	if updateTime == "" {
		updateTime = "UpdateTime"
	}
	s.updateTime = updateTime
	s.columns[s.fields[updateTime]].sql = "dateTime"
	return s
}

func (s *Schema) SoftDelete(deleteTime string) *Schema {
	if deleteTime == "" {
		deleteTime = "DeleteTime"
	}
	s.softDelete = true
	s.deleteTime = deleteTime
	s.columns[s.fields[deleteTime]].sql = "dateTime"
	return s
}

func (s *Schema) Set(record interface{}, field string, v interface{}) error {
	value := reflect.ValueOf(record)
	elem := value.Elem()
	if value.Kind() != reflect.Ptr || elem.Kind() != reflect.Struct {
		return errors.New("needs a Struct pointer")
	}
	fieldValue := elem.FieldByName(field)
	fieldValue.Set(reflect.ValueOf(v))
	return nil
}

func (s *Schema) Get(record interface{}, field string) (interface{}, error) {
	value := reflect.ValueOf(record)
	elem := value.Elem()
	if value.Kind() != reflect.Ptr || elem.Kind() != reflect.Struct {
		return nil, errors.New("needs a Struct pointer")
	}
	fieldValue := elem.FieldByName(field)
	return fieldValue.Interface(), nil
}

func (s *Schema) On(event string, f func(record interface{}) error) error {
	return s.event.On(event, f)
}

func (s *Schema) Emit(event string, record interface{}) error {
	_, err := s.event.Fire(event, record)
	return err
}

const (
	POSTGRES = "postgres"
	SQLITE   = "sqlite3"
	MYSQL    = "mysql"
	MSSQL    = "mssql"
	ORACLE   = "oracle"
)

const (
	UNKNOW_TYPE = iota
	TEXT_TYPE
	BLOB_TYPE
	TIME_TYPE
	NUMERIC_TYPE
)
const (
	zeroTime0 = "0000-00-00 00:00:00"
	zeroTime1 = "0001-01-01 00:00:00"
)

type column struct {
	f        string
	t        reflect.Type
	v        reflect.Value
	d        interface{}
	sql      string
	required bool
	zone     *time.Location
}

func (c *column) IsType(st int) bool {
	if t, ok := SqlTypes[c.sql]; ok && t == st {
		return true
	}
	return false
}

func (c *column) IsText() bool {
	return c.IsType(TEXT_TYPE)
}

func (c *column) IsBlob() bool {
	return c.IsType(BLOB_TYPE)
}

func (c *column) IsTime() bool {
	return c.IsType(TIME_TYPE)
}

func (c *column) IsNumeric() bool {
	return c.IsType(NUMERIC_TYPE)
}

func (c *column) IsJson() bool {
	return c.sql == Json || c.sql == Jsonb
}

var (
	Bit       = "BIT"
	TinyInt   = "TINYINT"
	SmallInt  = "SMALLINT"
	MediumInt = "MEDIUMINT"
	Int       = "INT"
	Integer   = "INTEGER"
	BigInt    = "BIGINT"

	Enum = "ENUM"
	Set  = "SET"

	Char       = "CHAR"
	Varchar    = "VARCHAR"
	NVarchar   = "NVARCHAR"
	TinyText   = "TINYTEXT"
	Text       = "TEXT"
	Clob       = "CLOB"
	MediumText = "MEDIUMTEXT"
	LongText   = "LONGTEXT"
	Uuid       = "UUID"

	Date       = "DATE"
	DateTime   = "DATETIME"
	Time       = "TIME"
	TimeStamp  = "TIMESTAMP"
	TimeStampz = "TIMESTAMPZ"

	Decimal = "DECIMAL"
	Numeric = "NUMERIC"

	Real   = "REAL"
	Float  = "FLOAT"
	Double = "DOUBLE"

	Binary     = "BINARY"
	VarBinary  = "VARBINARY"
	TinyBlob   = "TINYBLOB"
	Blob       = "BLOB"
	MediumBlob = "MEDIUMBLOB"
	LongBlob   = "LONGBLOB"
	Bytea      = "BYTEA"

	Bool    = "BOOL"
	Boolean = "BOOLEAN"

	Serial    = "SERIAL"
	BigSerial = "BIGSERIAL"

	Json  = "JSON"
	Jsonb = "JSONB"

	SqlTypes = map[string]int{
		Bit:       NUMERIC_TYPE,
		TinyInt:   NUMERIC_TYPE,
		SmallInt:  NUMERIC_TYPE,
		MediumInt: NUMERIC_TYPE,
		Int:       NUMERIC_TYPE,
		Integer:   NUMERIC_TYPE,
		BigInt:    NUMERIC_TYPE,

		Enum:  TEXT_TYPE,
		Set:   TEXT_TYPE,
		Json:  TEXT_TYPE,
		Jsonb: TEXT_TYPE,

		Char:       TEXT_TYPE,
		Varchar:    TEXT_TYPE,
		NVarchar:   TEXT_TYPE,
		TinyText:   TEXT_TYPE,
		Text:       TEXT_TYPE,
		MediumText: TEXT_TYPE,
		LongText:   TEXT_TYPE,
		Uuid:       TEXT_TYPE,
		Clob:       TEXT_TYPE,

		Date:       TIME_TYPE,
		DateTime:   TIME_TYPE,
		Time:       TIME_TYPE,
		TimeStamp:  TIME_TYPE,
		TimeStampz: TIME_TYPE,

		Decimal: NUMERIC_TYPE,
		Numeric: NUMERIC_TYPE,
		Real:    NUMERIC_TYPE,
		Float:   NUMERIC_TYPE,
		Double:  NUMERIC_TYPE,

		Binary:    BLOB_TYPE,
		VarBinary: BLOB_TYPE,

		TinyBlob:   BLOB_TYPE,
		Blob:       BLOB_TYPE,
		MediumBlob: BLOB_TYPE,
		LongBlob:   BLOB_TYPE,
		Bytea:      BLOB_TYPE,

		Bool: NUMERIC_TYPE,

		Serial:    NUMERIC_TYPE,
		BigSerial: NUMERIC_TYPE,
	}

	intTypes  = sort.StringSlice{"*int", "*int16", "*int32", "*int8"}
	uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"}
)

// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison
var (
	c_EMPTY_STRING       string
	c_BOOL_DEFAULT       bool
	c_BYTE_DEFAULT       byte
	c_COMPLEX64_DEFAULT  complex64
	c_COMPLEX128_DEFAULT complex128
	c_FLOAT32_DEFAULT    float32
	c_FLOAT64_DEFAULT    float64
	c_INT64_DEFAULT      int64
	c_UINT64_DEFAULT     uint64
	c_INT32_DEFAULT      int32
	c_UINT32_DEFAULT     uint32
	c_INT16_DEFAULT      int16
	c_UINT16_DEFAULT     uint16
	c_INT8_DEFAULT       int8
	c_UINT8_DEFAULT      uint8
	c_INT_DEFAULT        int
	c_UINT_DEFAULT       uint
	c_TIME_DEFAULT       time.Time
)

var (
	IntType   = reflect.TypeOf(c_INT_DEFAULT)
	Int8Type  = reflect.TypeOf(c_INT8_DEFAULT)
	Int16Type = reflect.TypeOf(c_INT16_DEFAULT)
	Int32Type = reflect.TypeOf(c_INT32_DEFAULT)
	Int64Type = reflect.TypeOf(c_INT64_DEFAULT)

	UintType   = reflect.TypeOf(c_UINT_DEFAULT)
	Uint8Type  = reflect.TypeOf(c_UINT8_DEFAULT)
	Uint16Type = reflect.TypeOf(c_UINT16_DEFAULT)
	Uint32Type = reflect.TypeOf(c_UINT32_DEFAULT)
	Uint64Type = reflect.TypeOf(c_UINT64_DEFAULT)

	Float32Type = reflect.TypeOf(c_FLOAT32_DEFAULT)
	Float64Type = reflect.TypeOf(c_FLOAT64_DEFAULT)

	Complex64Type  = reflect.TypeOf(c_COMPLEX64_DEFAULT)
	Complex128Type = reflect.TypeOf(c_COMPLEX128_DEFAULT)

	StringType = reflect.TypeOf(c_EMPTY_STRING)
	BoolType   = reflect.TypeOf(c_BOOL_DEFAULT)
	ByteType   = reflect.TypeOf(c_BYTE_DEFAULT)
	BytesType  = reflect.SliceOf(ByteType)

	TimeType = reflect.TypeOf(c_TIME_DEFAULT)
)

var (
	PtrIntType   = reflect.PtrTo(IntType)
	PtrInt8Type  = reflect.PtrTo(Int8Type)
	PtrInt16Type = reflect.PtrTo(Int16Type)
	PtrInt32Type = reflect.PtrTo(Int32Type)
	PtrInt64Type = reflect.PtrTo(Int64Type)

	PtrUintType   = reflect.PtrTo(UintType)
	PtrUint8Type  = reflect.PtrTo(Uint8Type)
	PtrUint16Type = reflect.PtrTo(Uint16Type)
	PtrUint32Type = reflect.PtrTo(Uint32Type)
	PtrUint64Type = reflect.PtrTo(Uint64Type)

	PtrFloat32Type = reflect.PtrTo(Float32Type)
	PtrFloat64Type = reflect.PtrTo(Float64Type)

	PtrComplex64Type  = reflect.PtrTo(Complex64Type)
	PtrComplex128Type = reflect.PtrTo(Complex128Type)

	PtrStringType = reflect.PtrTo(StringType)
	PtrBoolType   = reflect.PtrTo(BoolType)
	PtrByteType   = reflect.PtrTo(ByteType)

	PtrTimeType = reflect.PtrTo(TimeType)
)
<commit_msg>fix orm<commit_after>package orm

import (
	"errors"
	"reflect"
	"sort"
	"time"

	"github.com/ueffort/goutils/event"
)

type Conversion interface {
	FromDB([]byte) error
	ToDB() ([]byte, error)
}

type Schema struct {
	AutoIncrement string
	Primary       []string

	schemaType    reflect.Type
	schemaPtrType reflect.Type
	columns       map[string]*column
	fields        map[string]string
	record        interface{}

	softDelete bool
	createTime string
	updateTime string
	deleteTime string

	event event.Event
}

func NewSchema(record interface{}) (*Schema, error) {

	s := &Schema{
		AutoIncrement: "",
		Primary:       []string{},
		softDelete:    false,
		event:         event.New(),
	}
	err := s.With(record)
	return s, err
}

func (s *Schema) Default(field string, value interface{}) *Schema {
	s.columns[field].d = value
	return s
}

func (s *Schema) With(record interface{}) error {
	s.fields = make(map[string]string)
	s.columns = make(map[string]*column)
	value := reflect.ValueOf(record)
	if value.Kind() != reflect.Ptr || value.Elem().Kind() != reflect.Struct {
		return errors.New("needs a Struct pointer")
	}
	valueE := value.Elem()
	tp := reflect.TypeOf(record)
	t := tp.Elem()
	for k := 0; k < t.NumField(); k++ {
		col := t.Field(k)
		tag := col.Tag
		v := valueE.FieldByName(col.Name)
		if !v.CanInterface() {
			continue
		}
		d := v.Interface()
		_, required := tag.Lookup("required")
		t, tset := tag.Lookup("time")

		field := tag.Get("json")
		if field != "" {
			s.fields[col.Name] = field
		} else {
			s.fields[col.Name] = col.Name
		}

		c := &column{
			col.Name,
			col.Type,
			v,
			d,
			tag.Get("sql"),
			required,
			time.UTC,
		}
		if tset {
			switch t {
			case "local":
				c.zone = time.Local
			case "utc":
				c.zone = time.UTC
			default:
				zone, err := time.LoadLocation(t)
				if err != nil {
					return err
				}
				c.zone = zone
			}
		}
		s.columns[s.fields[col.Name]] = c
		key := tag.Get("orm")
		switch key {
		case "auto":
			s.SetAutoIncrement(col.Name)
		case "primary":
			s.SetPrimary(col.Name)
		case "deleteTime":
			s.SoftDelete(col.Name)
		case "createTime":
			s.SetCreateTime(col.Name)
		case "updateTime":
			s.SetUpdateTime(col.Name)
		}
	}
	s.record = record
	s.schemaType = t
	s.schemaPtrType = tp
	return nil
}

func (s *Schema) SetAutoIncrement(field string) *Schema {
	s.AutoIncrement = field
	s.Primary = []string{field}
	return s
}

func (s *Schema) SetPrimary(primary ...string) *Schema {
	s.Primary = append(s.Primary, primary...)
	return s
}

func (s *Schema) SetTime(createTime string, updateTime string, deleteTime string) *Schema {
	s.SetCreateTime(createTime)
	s.SetUpdateTime(updateTime)
	s.SoftDelete(deleteTime)
	return s
}

func (s *Schema) SetCreateTime(createTime string) *Schema {
	if createTime == "" {
		createTime = "CreateTime"
	}
	s.createTime = createTime
	s.columns[s.fields[createTime]].sql = "dateTime"
	return s
}

func (s *Schema) SetUpdateTime(updateTime string) *Schema {
	if updateTime == "" {
		updateTime = "UpdateTime"
	}
	s.updateTime = updateTime
	s.columns[s.fields[updateTime]].sql = "dateTime"
	return s
}

func (s *Schema) SoftDelete(deleteTime string) *Schema {
	if deleteTime == "" {
		deleteTime = "DeleteTime"
	}
	s.softDelete = true
	s.deleteTime = deleteTime
	s.columns[s.fields[deleteTime]].sql = "dateTime"
	return s
}

func (s *Schema) Set(record interface{}, field string, v interface{}) error {
	value := reflect.ValueOf(record)
	elem := value.Elem()
	if value.Kind() != reflect.Ptr || elem.Kind() != reflect.Struct {
		return errors.New("needs a Struct pointer")
	}
	fieldValue := elem.FieldByName(field)
	fieldValue.Set(reflect.ValueOf(v))
	return nil
}

func (s *Schema) Get(record interface{}, field string) (interface{}, error) {
	value := reflect.ValueOf(record)
	elem := value.Elem()
	if value.Kind() != reflect.Ptr || elem.Kind() != reflect.Struct {
		return nil, errors.New("needs a Struct pointer")
	}
	fieldValue := elem.FieldByName(field)
	return fieldValue.Interface(), nil
}

func (s *Schema) On(event string, f func(record interface{}) error) error {
	return s.event.On(event, f)
}

func (s *Schema) Emit(event string, record interface{}) error {
	_, err := s.event.Fire(event, record)
	return err
}

const (
	POSTGRES = "postgres"
	SQLITE   = "sqlite3"
	MYSQL    = "mysql"
	MSSQL    = "mssql"
	ORACLE   = "oracle"
)

const (
	UNKNOW_TYPE = iota
	TEXT_TYPE
	BLOB_TYPE
	TIME_TYPE
	NUMERIC_TYPE
)
const (
	zeroTime0 = "0000-00-00 00:00:00"
	zeroTime1 = "0001-01-01 00:00:00"
)

type column struct {
	f        string
	t        reflect.Type
	v        reflect.Value
	d        interface{}
	sql      string
	required bool
	zone     *time.Location
}

func (c *column) IsType(st int) bool {
	if t, ok := SqlTypes[c.sql]; ok && t == st {
		return true
	}
	return false
}

func (c *column) IsText() bool {
	return c.IsType(TEXT_TYPE)
}

func (c *column) IsBlob() bool {
	return c.IsType(BLOB_TYPE)
}

func (c *column) IsTime() bool {
	return c.IsType(TIME_TYPE)
}

func (c *column) IsNumeric() bool {
	return c.IsType(NUMERIC_TYPE)
}

func (c *column) IsJson() bool {
	return c.sql == Json || c.sql == Jsonb
}

var (
	Bit       = "BIT"
	TinyInt   = "TINYINT"
	SmallInt  = "SMALLINT"
	MediumInt = "MEDIUMINT"
	Int       = "INT"
	Integer   = "INTEGER"
	BigInt    = "BIGINT"

	Enum = "ENUM"
	Set  = "SET"

	Char       = "CHAR"
	Varchar    = "VARCHAR"
	NVarchar   = "NVARCHAR"
	TinyText   = "TINYTEXT"
	Text       = "TEXT"
	Clob       = "CLOB"
	MediumText = "MEDIUMTEXT"
	LongText   = "LONGTEXT"
	Uuid       = "UUID"

	Date       = "DATE"
	DateTime   = "DATETIME"
	Time       = "TIME"
	TimeStamp  = "TIMESTAMP"
	TimeStampz = "TIMESTAMPZ"

	Decimal = "DECIMAL"
	Numeric = "NUMERIC"

	Real   = "REAL"
	Float  = "FLOAT"
	Double = "DOUBLE"

	Binary     = "BINARY"
	VarBinary  = "VARBINARY"
	TinyBlob   = "TINYBLOB"
	Blob       = "BLOB"
	MediumBlob = "MEDIUMBLOB"
	LongBlob   = "LONGBLOB"
	Bytea      = "BYTEA"

	Bool    = "BOOL"
	Boolean = "BOOLEAN"

	Serial    = "SERIAL"
	BigSerial = "BIGSERIAL"

	Json  = "JSON"
	Jsonb = "JSONB"

	SqlTypes = map[string]int{
		Bit:       NUMERIC_TYPE,
		TinyInt:   NUMERIC_TYPE,
		SmallInt:  NUMERIC_TYPE,
		MediumInt: NUMERIC_TYPE,
		Int:       NUMERIC_TYPE,
		Integer:   NUMERIC_TYPE,
		BigInt:    NUMERIC_TYPE,

		Enum:  TEXT_TYPE,
		Set:   TEXT_TYPE,
		Json:  TEXT_TYPE,
		Jsonb: TEXT_TYPE,

		Char:       TEXT_TYPE,
		Varchar:    TEXT_TYPE,
		NVarchar:   TEXT_TYPE,
		TinyText:   TEXT_TYPE,
		Text:       TEXT_TYPE,
		MediumText: TEXT_TYPE,
		LongText:   TEXT_TYPE,
		Uuid:       TEXT_TYPE,
		Clob:       TEXT_TYPE,

		Date:       TIME_TYPE,
		DateTime:   TIME_TYPE,
		Time:       TIME_TYPE,
		TimeStamp:  TIME_TYPE,
		TimeStampz: TIME_TYPE,

		Decimal: NUMERIC_TYPE,
		Numeric: NUMERIC_TYPE,
		Real:    NUMERIC_TYPE,
		Float:   NUMERIC_TYPE,
		Double:  NUMERIC_TYPE,

		Binary:    BLOB_TYPE,
		VarBinary: BLOB_TYPE,

		TinyBlob:   BLOB_TYPE,
		Blob:       BLOB_TYPE,
		MediumBlob: BLOB_TYPE,
		LongBlob:   BLOB_TYPE,
		Bytea:      BLOB_TYPE,

		Bool: NUMERIC_TYPE,

		Serial:    NUMERIC_TYPE,
		BigSerial: NUMERIC_TYPE,
	}

	intTypes  = sort.StringSlice{"*int", "*int16", "*int32", "*int8"}
	uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"}
)

// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison
var (
	c_EMPTY_STRING       string
	c_BOOL_DEFAULT       bool
	c_BYTE_DEFAULT       byte
	c_COMPLEX64_DEFAULT  complex64
	c_COMPLEX128_DEFAULT complex128
	c_FLOAT32_DEFAULT    float32
	c_FLOAT64_DEFAULT    float64
	c_INT64_DEFAULT      int64
	c_UINT64_DEFAULT     uint64
	c_INT32_DEFAULT      int32
	c_UINT32_DEFAULT     uint32
	c_INT16_DEFAULT      int16
	c_UINT16_DEFAULT     uint16
	c_INT8_DEFAULT       int8
	c_UINT8_DEFAULT      uint8
	c_INT_DEFAULT        int
	c_UINT_DEFAULT       uint
	c_TIME_DEFAULT       time.Time
)

var (
	IntType   = reflect.TypeOf(c_INT_DEFAULT)
	Int8Type  = reflect.TypeOf(c_INT8_DEFAULT)
	Int16Type = reflect.TypeOf(c_INT16_DEFAULT)
	Int32Type = reflect.TypeOf(c_INT32_DEFAULT)
	Int64Type = reflect.TypeOf(c_INT64_DEFAULT)

	UintType   = reflect.TypeOf(c_UINT_DEFAULT)
	Uint8Type  = reflect.TypeOf(c_UINT8_DEFAULT)
	Uint16Type = reflect.TypeOf(c_UINT16_DEFAULT)
	Uint32Type = reflect.TypeOf(c_UINT32_DEFAULT)
	Uint64Type = reflect.TypeOf(c_UINT64_DEFAULT)

	Float32Type = reflect.TypeOf(c_FLOAT32_DEFAULT)
	Float64Type = reflect.TypeOf(c_FLOAT64_DEFAULT)

	Complex64Type  = reflect.TypeOf(c_COMPLEX64_DEFAULT)
	Complex128Type = reflect.TypeOf(c_COMPLEX128_DEFAULT)

	StringType = reflect.TypeOf(c_EMPTY_STRING)
	BoolType   = reflect.TypeOf(c_BOOL_DEFAULT)
	ByteType   = reflect.TypeOf(c_BYTE_DEFAULT)
	BytesType  = reflect.SliceOf(ByteType)

	TimeType = reflect.TypeOf(c_TIME_DEFAULT)
)

var (
	PtrIntType   = reflect.PtrTo(IntType)
	PtrInt8Type  = reflect.PtrTo(Int8Type)
	PtrInt16Type = reflect.PtrTo(Int16Type)
	PtrInt32Type = reflect.PtrTo(Int32Type)
	PtrInt64Type = reflect.PtrTo(Int64Type)

	PtrUintType   = reflect.PtrTo(UintType)
	PtrUint8Type  = reflect.PtrTo(Uint8Type)
	PtrUint16Type = reflect.PtrTo(Uint16Type)
	PtrUint32Type = reflect.PtrTo(Uint32Type)
	PtrUint64Type = reflect.PtrTo(Uint64Type)

	PtrFloat32Type = reflect.PtrTo(Float32Type)
	PtrFloat64Type = reflect.PtrTo(Float64Type)

	PtrComplex64Type  = reflect.PtrTo(Complex64Type)
	PtrComplex128Type = reflect.PtrTo(Complex128Type)

	PtrStringType = reflect.PtrTo(StringType)
	PtrBoolType   = reflect.PtrTo(BoolType)
	PtrByteType   = reflect.PtrTo(ByteType)

	PtrTimeType = reflect.PtrTo(TimeType)
)
<|endoftext|>


<commit_before>package pages

import (
	"encoding/json"
	"fmt"
	"github.com/elcuervo/geoip"
	mw "github.com/elcuervo/minimalweather/minimalweather"
	"github.com/ianoshen/uaparser"
	"html/template"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

type Homepage struct {
	w  http.ResponseWriter
	r  *http.Request
	cw *CityWeather
}

func (h *Homepage) getCoords() mw.Coordinates {
	var coords mw.Coordinates
	location_cookie, err := h.r.Cookie("mw-location")

	if err == nil {
		log.Println("From Cookie cache")
		parts := strings.Split(location_cookie.Value, "|")
		lat, _ := strconv.ParseFloat(parts[0], 64)
		lng, _ := strconv.ParseFloat(parts[1], 64)
		coords = mw.Coordinates{lat, lng}
	} else {
		log.Println("From geolocation")
		geo := h.geolocate()
		coords = mw.Coordinates{geo.Location.Latitude, geo.Location.Longitude}
	}

	return coords
}

func (h *Homepage) ipFromRemote() string {
	index := strings.LastIndex(h.r.RemoteAddr, ":")
	if index == -1 {
		return h.r.RemoteAddr
	}
	return h.r.RemoteAddr[:index]
}

func (h *Homepage) ipAddress() string {
	development := os.Getenv("DEVELOPMENT")
	if development != "" {
		return "186.52.170.66"
	}

	hdr := h.r.Header
	hdrRealIp := hdr.Get("X-Real-Ip")
	hdrForwardedFor := hdr.Get("X-Forwarded-For")

	if hdrRealIp == "" && hdrForwardedFor == "" {
		return h.ipFromRemote()
	}

	if hdrForwardedFor != "" {
		// X-Forwarded-For is potentially a list of addresses separated with ","
		parts := strings.Split(hdrForwardedFor, ",")
		for i, p := range parts {
			parts[i] = strings.TrimSpace(p)
		}
		// TODO: should return first non-local address
		return parts[0]
	}
	return hdrRealIp
}

func (h *Homepage) geolocate() geoip.Geolocation {
	var user_addr string

	user_addr = h.ipAddress()
	log.Println(user_addr)

	return <-mw.GetLocation(user_addr)
}

func (h *Homepage) handleUnit() {
	unit_cookie, err := h.r.Cookie("mw-unit")
	if err == nil {
		h.cw.Unit = unit_cookie.Value
	} else {
		if h.cw.City.Country == "US" {
			h.cw.Unit = "F"
		} else {
			h.cw.Unit = "C"
		}
	}

	// Finds if it's night
	t := time.Unix(int64(h.cw.Weather.Time), 0)
	hour := t.Hour()
	night := hour >= 20 || hour <= 8

	if night {
		h.cw.Gradient = "night_"
	} else {
		h.cw.Gradient = "day_"
	}

	switch {
	case h.cw.Weather.Temperature < 18:
		h.cw.Gradient = h.cw.Gradient + "cold"
	case h.cw.Weather.Temperature > 17 && h.cw.Weather.Temperature < 21:
		h.cw.Gradient = h.cw.Gradient + "normal"
	case h.cw.Weather.Temperature > 20:
		h.cw.Gradient = h.cw.Gradient + "hot"
	}

	if h.cw.Unit == "F" {
		h.cw.Weather.Temperature = ((h.cw.Weather.Temperature * 9) / 5) + 32
	}

	h.cw.Celsius = h.cw.Unit == "C"
}

func (h *Homepage) saveCityCache(city mw.City) {
	cookie := &http.Cookie{
		Name:  "mw-location",
		Value: fmt.Sprintf("%f|%f", city.Coords.Lat, city.Coords.Lng),
		Path:  "/",
	}

	http.SetCookie(h.w, cookie)

	city_cookie := &http.Cookie{
		Name:  "mw-city",
		Value: fmt.Sprintf("%s", url.QueryEscape(city.Name)),
		Path:  "/",
	}

	http.SetCookie(h.w, city_cookie)
}

func (h *Homepage) isiOS() bool {
	ua := uaparser.Parse(h.r.UserAgent())
	desktop, _ := h.r.Cookie("mw-desktop")

	return desktop != nil ||
		ua.Device.Name == "iPad" ||
		ua.Device.Name == "iPod" ||
		ua.Device.Name == "iPhone"
}

func (h *Homepage) weatherApp() {
	coords := h.getCoords()
	city := <-mw.FindByCoords(coords)
	weather := <-mw.GetWeather(city.Coords)

	h.cw = &CityWeather{City: city, Weather: weather}

	h.handleUnit()
	h.saveCityCache(city)

	t, _ := template.ParseFiles("./website/index.html")
	out, err := json.Marshal(h.cw)
	h.cw.JSON = string(out)
	h.cw.Weather.Temperature = math.Floor(h.cw.Weather.Temperature)
	err = t.Execute(h.w, h.cw)

	if err != nil {
		http.Error(h.w, err.Error(), http.StatusInternalServerError)
	}
}

type Landing struct{}

func (h *Homepage) landingPage() {
	t, _ := template.ParseFiles("./website/landing.html")
	err := t.Execute(h.w, new(Landing))

	if err != nil {
		http.Error(h.w, err.Error(), http.StatusInternalServerError)
	}
}

func (h *Homepage) Render() {
	if h.isiOS() {
		h.weatherApp()
	} else {
		h.landingPage()
	}
}

func NewHomepage(w http.ResponseWriter, req *http.Request) *Homepage {
	home := new(Homepage)
	home.w = w
	home.r = req

	return home
}
<commit_msg>Add time logging to realize how does go handle it<commit_after>package pages

import (
	"encoding/json"
	"fmt"
	"github.com/elcuervo/geoip"
	mw "github.com/elcuervo/minimalweather/minimalweather"
	"github.com/ianoshen/uaparser"
	"html/template"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

type Homepage struct {
	w  http.ResponseWriter
	r  *http.Request
	cw *CityWeather
}

func (h *Homepage) getCoords() mw.Coordinates {
	var coords mw.Coordinates
	location_cookie, err := h.r.Cookie("mw-location")

	if err == nil {
		log.Println("From Cookie cache")
		parts := strings.Split(location_cookie.Value, "|")
		lat, _ := strconv.ParseFloat(parts[0], 64)
		lng, _ := strconv.ParseFloat(parts[1], 64)
		coords = mw.Coordinates{lat, lng}
	} else {
		log.Println("From geolocation")
		geo := h.geolocate()
		coords = mw.Coordinates{geo.Location.Latitude, geo.Location.Longitude}
	}

	return coords
}

func (h *Homepage) ipFromRemote() string {
	index := strings.LastIndex(h.r.RemoteAddr, ":")
	if index == -1 {
		return h.r.RemoteAddr
	}
	return h.r.RemoteAddr[:index]
}

func (h *Homepage) ipAddress() string {
	development := os.Getenv("DEVELOPMENT")
	if development != "" {
		return "186.52.170.66"
	}

	hdr := h.r.Header
	hdrRealIp := hdr.Get("X-Real-Ip")
	hdrForwardedFor := hdr.Get("X-Forwarded-For")

	if hdrRealIp == "" && hdrForwardedFor == "" {
		return h.ipFromRemote()
	}

	if hdrForwardedFor != "" {
		// X-Forwarded-For is potentially a list of addresses separated with ","
		parts := strings.Split(hdrForwardedFor, ",")
		for i, p := range parts {
			parts[i] = strings.TrimSpace(p)
		}
		// TODO: should return first non-local address
		return parts[0]
	}
	return hdrRealIp
}

func (h *Homepage) geolocate() geoip.Geolocation {
	var user_addr string

	user_addr = h.ipAddress()
	log.Println(user_addr)

	return <-mw.GetLocation(user_addr)
}

func (h *Homepage) handleUnit() {
	unit_cookie, err := h.r.Cookie("mw-unit")
	if err == nil {
		h.cw.Unit = unit_cookie.Value
	} else {
		if h.cw.City.Country == "US" {
			h.cw.Unit = "F"
		} else {
			h.cw.Unit = "C"
		}
	}

	// Finds if it's night
	t := time.Unix(int64(h.cw.Weather.Time), 0)
	hour := t.Hour()
	log.Println("Current time is:", hour)
	night := hour >= 20 || hour <= 8

	if night {
		h.cw.Gradient = "night_"
	} else {
		h.cw.Gradient = "day_"
	}

	switch {
	case h.cw.Weather.Temperature < 18:
		h.cw.Gradient = h.cw.Gradient + "cold"
	case h.cw.Weather.Temperature > 17 && h.cw.Weather.Temperature < 21:
		h.cw.Gradient = h.cw.Gradient + "normal"
	case h.cw.Weather.Temperature > 20:
		h.cw.Gradient = h.cw.Gradient + "hot"
	}

	if h.cw.Unit == "F" {
		h.cw.Weather.Temperature = ((h.cw.Weather.Temperature * 9) / 5) + 32
	}

	h.cw.Celsius = h.cw.Unit == "C"
}

func (h *Homepage) saveCityCache(city mw.City) {
	cookie := &http.Cookie{
		Name:  "mw-location",
		Value: fmt.Sprintf("%f|%f", city.Coords.Lat, city.Coords.Lng),
		Path:  "/",
	}

	http.SetCookie(h.w, cookie)

	city_cookie := &http.Cookie{
		Name:  "mw-city",
		Value: fmt.Sprintf("%s", url.QueryEscape(city.Name)),
		Path:  "/",
	}

	http.SetCookie(h.w, city_cookie)
}

func (h *Homepage) isiOS() bool {
	ua := uaparser.Parse(h.r.UserAgent())
	desktop, _ := h.r.Cookie("mw-desktop")

	return desktop != nil ||
		ua.Device.Name == "iPad" ||
		ua.Device.Name == "iPod" ||
		ua.Device.Name == "iPhone"
}

func (h *Homepage) weatherApp() {
	coords := h.getCoords()
	city := <-mw.FindByCoords(coords)
	weather := <-mw.GetWeather(city.Coords)

	h.cw = &CityWeather{City: city, Weather: weather}

	h.handleUnit()
	h.saveCityCache(city)

	t, _ := template.ParseFiles("./website/index.html")
	out, err := json.Marshal(h.cw)
	h.cw.JSON = string(out)
	h.cw.Weather.Temperature = math.Floor(h.cw.Weather.Temperature)
	err = t.Execute(h.w, h.cw)

	if err != nil {
		http.Error(h.w, err.Error(), http.StatusInternalServerError)
	}
}

type Landing struct{}

func (h *Homepage) landingPage() {
	t, _ := template.ParseFiles("./website/landing.html")
	err := t.Execute(h.w, new(Landing))

	if err != nil {
		http.Error(h.w, err.Error(), http.StatusInternalServerError)
	}
}

func (h *Homepage) Render() {
	if h.isiOS() {
		h.weatherApp()
	} else {
		h.landingPage()
	}
}

func NewHomepage(w http.ResponseWriter, req *http.Request) *Homepage {
	home := new(Homepage)
	home.w = w
	home.r = req

	return home
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
	"testing"
)

func TestParseKeysList(t *testing.T) {
	list := "host,status"
	expect := []string{"host", "status"}
	actual := ParseKeysList(list)
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf("ParseKeysList(%q) = %q, want %q",
			list, actual, expect)
	}
}
<commit_msg>Add normal cases<commit_after>package main

import (
	"reflect"
	"testing"
)

var ParseKeysListTests = []struct {
	list string
	keys []string
}{
	// normal
	{`host`, []string{`host`}},
	{`host,status`, []string{`host`, `status`}},
	{`host,status,size`, []string{`host`, `status`, `size`}},
}

func TestParseKeysList(t *testing.T) {
	for _, test := range ParseKeysListTests {
		expect := test.keys
		actual := ParseKeysList(test.list)
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf("ParseKeysList(%q) = %q, want %q",
				test.list, actual, expect)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

package xml

import (
	"bytes";
	"io";
	"os";
	"reflect";
	"strings";
)

// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
// an XML element is an order-dependent collection of anonymous
// values, while a data structure is an order-independent collection
// of named values.
// See package json for a textual representation more suitable
// to data structures.

// Unmarshal parses an XML element from r and uses the
// reflect library to fill in an arbitrary struct, slice, or string
// pointed at by val.  Well-formed data that does not fit
// into val is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string "attr";
//		Addr string;
//	}
//
//	type Result struct {
//		XMLName xml.Name "result";
//		Name string;
//		Phone string;
//		Email []Email;
//	}
//
//	var result = Result{ "name", "phone", nil }
//
// unmarshalling the XML input
//
//	<result>
//		<email where="home">
//			<addr>gre@example.com</addr>
//		</email>
//		<email where='work'>
//			<addr>gre@work.com</addr>
//		</email>
//		<name>Grace R. Emlin</name>
//		<address>123 Main Street</address>
//	</result>
//
// via Unmarshal(r, &result) is equivalent to assigning
//
//	r = Result{
//		xml.Name{"", "result"},
//		"Grace R. Emlin",	// name
//		"phone",	// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the XML <address> element was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match XML element names to struct field names.
//
// Unmarshal maps an XML element to a struct using the following rules:
//
//   * If the struct has a field named XMLName of type xml.Name,
//      Unmarshal records the element name in that field.
//
//   * If the XMLName field has an associated tag string of the form
//      "tag" or "namespace-URL tag", the XML element must have
//      the given tag (and, optionally, name space) or else Unmarshal
//      returns an error.
//
//   * If the XML element has an attribute whose name matches a
//      struct field of type string with tag "attr", Unmarshal records
//      the attribute value in that field.
//
//   * If the XML element contains character data, that data is
//      accumulated in the first struct field that has tag "chardata".
//      The struct field may have type []byte or string.
//      If there is no such field, the character data is discarded.
//
//   * If the XML element contains a sub-element whose name
//      matches a struct field whose tag is neither "attr" nor "chardata",
//      Unmarshal maps the sub-element to that struct field.
//
// Unmarshal maps an XML element to a string or []byte by saving the
// concatenation of that elements character data in the string or []byte.
//
// Unmarshal maps an XML element to a slice by extending the length
// of the slice and mapping the element to the newly created value.
//
func Unmarshal(r io.Reader, val interface{}) os.Error {
	v, ok := reflect.NewValue(val).(*reflect.PtrValue);
	if !ok {
		return os.NewError("non-pointer passed to Unmarshal");
	}
	p := NewParser(r);
	elem := v.Elem();
	for {
		err := p.unmarshal(elem, nil);
		if err != nil {
			if err == os.EOF {
				break;
			}
			return err;
		}
	}
	return nil;
}

// An UnmarshalError represents an error in the unmarshalling process.
type UnmarshalError string
func (e UnmarshalError) String() string {
	return string(e);
}

// Unmarshal a single XML element into val.
func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
	// Find start element if we need it.
	if start == nil {
		for {
			tok, err := p.Token();
			if err != nil {
				return err;
			}
			if t, ok := tok.(StartElement); ok {
				start = &t;
				break;
			}
		}
	}

	var (
		data []byte;
		saveData reflect.Value;
		sv *reflect.StructValue;
		styp *reflect.StructType;
	)
	switch v := val.(type) {
	case *reflect.SliceValue:
		typ := v.Type().(*reflect.SliceType);
		if _, ok := typ.Elem().(*reflect.Uint8Type); ok {
			// []byte
			saveData = v;
			break;
		}

		// Slice of element values.
		// Grow slice.
		n := v.Len();
		if n >= v.Cap() {
			ncap := 2*n;
			if ncap < 4 {
				ncap = 4;
			}
			new := reflect.MakeSlice(typ, n, ncap);
			reflect.ArrayCopy(new, v);
			v.Set(new);
		}
		v.SetLen(n+1);

		// Recur to read element into slice.
		if err := p.unmarshal(v.Elem(n), start); err != nil {
			v.SetLen(n);
			return err;
		}
		return nil;

	case *reflect.StringValue:
		saveData = v;

	case *reflect.StructValue:
		sv = v;
		typ := sv.Type().(*reflect.StructType);
		styp = typ;
		// Assign name.
		if f, ok := typ.FieldByName("XMLName"); ok {
			// Validate element name.
			if f.Tag != "" {
				tag := f.Tag;
				ns := "";
				i := strings.LastIndex(tag, " ");
				if i >= 0 {
					ns, tag = tag[0:i], tag[i+1:len(tag)];
				}
				if tag != start.Name.Local {
					return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">");
				}
				if ns != "" && ns != start.Name.Space {
					e := "expected element <" + tag + "> in name space " + ns + " but have ";
					if start.Name.Space == "" {
						e += "no name space";
					} else {
						e += start.Name.Space;
					}
					return UnmarshalError(e);
				}
			}

			// Save
			v := sv.FieldByIndex(f.Index);
			if _, ok := v.Interface().(Name); !ok {
				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name");
			}
			v.(*reflect.StructValue).Set(reflect.NewValue(start.Name).(*reflect.StructValue));
		}

		// Assign attributes.
		// Also, determine whether we need to save character data.
		for i, n := 0, typ.NumField(); i < n; i++ {
			f := typ.Field(i);
			switch f.Tag {
			case "attr":
				strv, ok := sv.FieldByIndex(f.Index).(*reflect.StringValue);
				if !ok {
					return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string");
				}
				// Look for attribute.
				val := "";
				k := strings.ToLower(f.Name);
				for _, a := range start.Attr {
					if strings.ToLower(a.Name.Local) == k {
						val = a.Value;
						break;
					}
				}
				strv.Set(val);

			case "chardata":
				if saveData == nil {
					saveData = sv.FieldByIndex(f.Index);
				}
			}
		}
	}

	// Find end element.
	// Process sub-elements along the way.
Loop:
	for {
		tok, err := p.Token();
		if err != nil {
			return err;
		}
		switch t := tok.(type) {
		case StartElement:
			// Sub-element.
			if sv != nil {
				k := strings.ToLower(t.Name.Local);
				for i, n := 0, styp.NumField(); i < n; i++ {
					f := styp.Field(i);
					if strings.ToLower(f.Name) == k {
						if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil {
							return err;
						}
						continue Loop;
					}
				}
			}
			// Not saving sub-element but still have to skip over it.
			if err := p.skip(); err != nil {
				return err;
			}

		case EndElement:
			break Loop;

		case CharData:
			if saveData != nil {
				data = bytes.Add(data, t);
			}
		}
	}

	// Save accumulated character data
	if saveData != nil {
		switch t := saveData.(type) {
		case *reflect.StringValue:
			t.Set(string(data));
		case *reflect.SliceValue:
			t.Set(reflect.NewValue(data).(*reflect.SliceValue));
		}
	}

	return nil;
}

// Have already read a start element.
// Read tokens until we find the end element.
// Token is taking care of making sure the
// end element matches the start element we saw.
func (p *Parser) skip() os.Error {
	for {
		tok, err := p.Token();
		if err != nil {
			return err;
		}
		switch t := tok.(type) {
		case StartElement:
			if err := p.skip(); err != nil {
				return err;
			}
		case EndElement:
			return nil;
		}
	}
	panic("unreachable");
}
<commit_msg>make reader more useful for lower-level clients: 	* expose p.Skip 	* expose p.Unmarshal 	* wildcard struct field "Any" 	* unmarshal into bool 	* unmarshal into xml.Name 	* unmarshal into pointer<commit_after>// Copyright 2009 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.

package xml

import (
	"bytes";
	"io";
	"os";
	"reflect";
	"strings";
)

// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
// an XML element is an order-dependent collection of anonymous
// values, while a data structure is an order-independent collection
// of named values.
// See package json for a textual representation more suitable
// to data structures.

// Unmarshal parses an XML element from r and uses the
// reflect library to fill in an arbitrary struct, slice, or string
// pointed at by val.  Well-formed data that does not fit
// into val is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string "attr";
//		Addr string;
//	}
//
//	type Result struct {
//		XMLName xml.Name "result";
//		Name string;
//		Phone string;
//		Email []Email;
//	}
//
//	var result = Result{ "name", "phone", nil }
//
// unmarshalling the XML input
//
//	<result>
//		<email where="home">
//			<addr>gre@example.com</addr>
//		</email>
//		<email where='work'>
//			<addr>gre@work.com</addr>
//		</email>
//		<name>Grace R. Emlin</name>
//		<address>123 Main Street</address>
//	</result>
//
// via Unmarshal(r, &result) is equivalent to assigning
//
//	r = Result{
//		xml.Name{"", "result"},
//		"Grace R. Emlin",	// name
//		"phone",	// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the XML <address> element was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match XML element names to struct field names.
//
// Unmarshal maps an XML element to a struct using the following rules:
//
//   * If the struct has a field named XMLName of type xml.Name,
//      Unmarshal records the element name in that field.
//
//   * If the XMLName field has an associated tag string of the form
//      "tag" or "namespace-URL tag", the XML element must have
//      the given tag (and, optionally, name space) or else Unmarshal
//      returns an error.
//
//   * If the XML element has an attribute whose name matches a
//      struct field of type string with tag "attr", Unmarshal records
//      the attribute value in that field.
//
//   * If the XML element contains character data, that data is
//      accumulated in the first struct field that has tag "chardata".
//      The struct field may have type []byte or string.
//      If there is no such field, the character data is discarded.
//
//   * If the XML element contains a sub-element whose name
//      matches a struct field whose tag is neither "attr" nor "chardata",
//      Unmarshal maps the sub-element to that struct field.
//      Otherwise, if the struct has a field named Any, unmarshal
//      maps the sub-element to that struct field.
//
// Unmarshal maps an XML element to a string or []byte by saving the
// concatenation of that elements character data in the string or []byte.
//
// Unmarshal maps an XML element to a slice by extending the length
// of the slice and mapping the element to the newly created value.
//
// Unmarshal maps an XML element to a bool by setting the bool to true.
//
// Unmarshal maps an XML element to an xml.Name by recording the
// element name.
//
// Unmarshal maps an XML element to a pointer by setting the pointer
// to a freshly allocated value and then mapping the element to that value.
//
func Unmarshal(r io.Reader, val interface{}) os.Error {
	v, ok := reflect.NewValue(val).(*reflect.PtrValue);
	if !ok {
		return os.NewError("non-pointer passed to Unmarshal");
	}
	p := NewParser(r);
	elem := v.Elem();
	err := p.unmarshal(elem, nil);
	if err != nil {
		return err;
	}
	return nil;
}

// An UnmarshalError represents an error in the unmarshalling process.
type UnmarshalError string
func (e UnmarshalError) String() string {
	return string(e);
}

// The Parser's Unmarshal method is like xml.Unmarshal
// except that it can be passed a pointer to the initial start element,
// useful when a client reads some raw XML tokens itself
// but also defers to Unmarshal for some elements.
// Passing a nil start element indicates that Unmarshal should
// read the token stream to find the start element.
func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error {
	v, ok := reflect.NewValue(val).(*reflect.PtrValue);
	if !ok {
		return os.NewError("non-pointer passed to Unmarshal");
	}
	return p.unmarshal(v.Elem(), start);
}

// Unmarshal a single XML element into val.
func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
	// Find start element if we need it.
	if start == nil {
		for {
			tok, err := p.Token();
			if err != nil {
				return err;
			}
			if t, ok := tok.(StartElement); ok {
				start = &t;
				break;
			}
		}
	}

	if pv, ok := val.(*reflect.PtrValue); ok {
		zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem());
		pv.PointTo(zv);
		val = zv;
	}

	var (
		data []byte;
		saveData reflect.Value;
		sv *reflect.StructValue;
		styp *reflect.StructType;
	)
	switch v := val.(type) {
	case *reflect.BoolValue:
		v.Set(true);

	case *reflect.SliceValue:
		typ := v.Type().(*reflect.SliceType);
		if _, ok := typ.Elem().(*reflect.Uint8Type); ok {
			// []byte
			saveData = v;
			break;
		}

		// Slice of element values.
		// Grow slice.
		n := v.Len();
		if n >= v.Cap() {
			ncap := 2*n;
			if ncap < 4 {
				ncap = 4;
			}
			new := reflect.MakeSlice(typ, n, ncap);
			reflect.ArrayCopy(new, v);
			v.Set(new);
		}
		v.SetLen(n+1);

		// Recur to read element into slice.
		if err := p.unmarshal(v.Elem(n), start); err != nil {
			v.SetLen(n);
			return err;
		}
		return nil;

	case *reflect.StringValue:
		saveData = v;

	case *reflect.StructValue:
		if _, ok := v.Interface().(Name); ok {
			v.Set(reflect.NewValue(start.Name).(*reflect.StructValue));
			break;
		}

		sv = v;
		typ := sv.Type().(*reflect.StructType);
		styp = typ;
		// Assign name.
		if f, ok := typ.FieldByName("XMLName"); ok {
			// Validate element name.
			if f.Tag != "" {
				tag := f.Tag;
				ns := "";
				i := strings.LastIndex(tag, " ");
				if i >= 0 {
					ns, tag = tag[0:i], tag[i+1:len(tag)];
				}
				if tag != start.Name.Local {
					return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">");
				}
				if ns != "" && ns != start.Name.Space {
					e := "expected element <" + tag + "> in name space " + ns + " but have ";
					if start.Name.Space == "" {
						e += "no name space";
					} else {
						e += start.Name.Space;
					}
					return UnmarshalError(e);
				}
			}

			// Save
			v := sv.FieldByIndex(f.Index);
			if _, ok := v.Interface().(Name); !ok {
				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name");
			}
			v.(*reflect.StructValue).Set(reflect.NewValue(start.Name).(*reflect.StructValue));
		}

		// Assign attributes.
		// Also, determine whether we need to save character data.
		for i, n := 0, typ.NumField(); i < n; i++ {
			f := typ.Field(i);
			switch f.Tag {
			case "attr":
				strv, ok := sv.FieldByIndex(f.Index).(*reflect.StringValue);
				if !ok {
					return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string");
				}
				// Look for attribute.
				val := "";
				k := strings.ToLower(f.Name);
				for _, a := range start.Attr {
					if strings.ToLower(a.Name.Local) == k {
						val = a.Value;
						break;
					}
				}
				strv.Set(val);

			case "chardata":
				if saveData == nil {
					saveData = sv.FieldByIndex(f.Index);
				}
			}
		}
	}

	// Find end element.
	// Process sub-elements along the way.
Loop:
	for {
		tok, err := p.Token();
		if err != nil {
			return err;
		}
		switch t := tok.(type) {
		case StartElement:
			// Sub-element.
			// Look up by tag name.
			// If that fails, fall back to mop-up field named "Any".
			if sv != nil {
				k := strings.ToLower(t.Name.Local);
				any := -1;
				for i, n := 0, styp.NumField(); i < n; i++ {
					f := styp.Field(i);
					if strings.ToLower(f.Name) == k {
						if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil {
							return err;
						}
						continue Loop;
					}
					if any < 0 && f.Name == "Any" {
						any = i;
					}
				}
				if any >= 0 {
					if err := p.unmarshal(sv.FieldByIndex(styp.Field(any).Index), &t); err != nil {
						return err;
					}
					continue Loop;
				}
			}
			// Not saving sub-element but still have to skip over it.
			if err := p.Skip(); err != nil {
				return err;
			}

		case EndElement:
			break Loop;

		case CharData:
			if saveData != nil {
				data = bytes.Add(data, t);
			}
		}
	}

	// Save accumulated character data
	if saveData != nil {
		switch t := saveData.(type) {
		case *reflect.StringValue:
			t.Set(string(data));
		case *reflect.SliceValue:
			t.Set(reflect.NewValue(data).(*reflect.SliceValue));
		}
	}

	return nil;
}

// Have already read a start element.
// Read tokens until we find the end element.
// Token is taking care of making sure the
// end element matches the start element we saw.
func (p *Parser) Skip() os.Error {
	for {
		tok, err := p.Token();
		if err != nil {
			return err;
		}
		switch t := tok.(type) {
		case StartElement:
			if err := p.Skip(); err != nil {
				return err;
			}
		case EndElement:
			return nil;
		}
	}
	panic("unreachable");
}
<|endoftext|>


<commit_before>package instructions

import (
	"github.com/zxh0/jvm.go/jvmgo/jvm/rtda"
	rtc "github.com/zxh0/jvm.go/jvmgo/jvm/rtda/class"
)

// Fetch field from object
type getfield struct{ Index16Instruction }

func (self *getfield) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	ref := stack.PopRef()
	if ref == nil {
		frame.Thread().ThrowNPE()
		return
	}

	cp := frame.Method().ConstantPool()
	kFieldRef := cp.GetConstant(self.index).(*rtc.ConstantFieldref)
	field := kFieldRef.InstanceField()
	val := field.GetValue(ref)

	stack.Push(val)
}

// Get static field from class
type getstatic struct{ Index16Instruction }

func (self *getstatic) Execute(frame *rtda.Frame) {
	cp := frame.Method().Class().ConstantPool()
	kFieldRef := cp.GetConstant(self.index).(*rtc.ConstantFieldref)
	field := kFieldRef.StaticField()

	class := field.Class()
	if class.InitializationNotStarted() {
		frame.RevertNextPC() // undo getstatic
		frame.Thread().InitClass(class)
		return
	}

	val := field.GetStaticValue()
	frame.OperandStack().Push(val)
}
<commit_msg>optimization<commit_after>package instructions

import (
	"github.com/zxh0/jvm.go/jvmgo/jvm/rtda"
	rtc "github.com/zxh0/jvm.go/jvmgo/jvm/rtda/class"
)

// Fetch field from object
type getfield struct {
	Index16Instruction
	field *rtc.Field
}

func (self *getfield) Execute(frame *rtda.Frame) {
	if self.field == nil {
		cp := frame.Method().ConstantPool()
		kFieldRef := cp.GetConstant(self.index).(*rtc.ConstantFieldref)
		self.field = kFieldRef.InstanceField()
	}

	stack := frame.OperandStack()
	ref := stack.PopRef()
	if ref == nil {
		frame.Thread().ThrowNPE()
		return
	}

	val := self.field.GetValue(ref)
	stack.Push(val)
}

// Get static field from class
type getstatic struct {
	Index16Instruction
	field *rtc.Field
}

func (self *getstatic) Execute(frame *rtda.Frame) {
	if self.field == nil {
		cp := frame.Method().Class().ConstantPool()
		kFieldRef := cp.GetConstant(self.index).(*rtc.ConstantFieldref)
		self.field = kFieldRef.StaticField()
	}

	class := self.field.Class()
	if class.InitializationNotStarted() {
		frame.RevertNextPC() // undo getstatic
		frame.Thread().InitClass(class)
		return
	}

	val := self.field.GetStaticValue()
	frame.OperandStack().Push(val)
}
<|endoftext|>


<commit_before>package wallet

import (
	"path/filepath"
	"testing"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/consensus"
	"github.com/NebulousLabs/Sia/modules/gateway"
	"github.com/NebulousLabs/Sia/modules/miner"
	"github.com/NebulousLabs/Sia/modules/transactionpool"
	"github.com/NebulousLabs/Sia/types"
	"github.com/NebulousLabs/fastrand"
)

// A Wallet tester contains a ConsensusTester and has a bunch of helpful
// functions for facilitating wallet integration testing.
type walletTester struct {
	cs      modules.ConsensusSet
	gateway modules.Gateway
	tpool   modules.TransactionPool
	miner   modules.TestMiner
	wallet  *Wallet

	walletMasterKey crypto.TwofishKey

	persistDir string
}

// createWalletTester takes a testing.T and creates a WalletTester.
func createWalletTester(name string) (*walletTester, error) {
	// Create the modules
	testdir := build.TempDir(modules.WalletDir, name)
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, err
	}
	w, err := New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	var masterKey crypto.TwofishKey
	fastrand.Read(masterKey[:])
	_, err = w.Encrypt(masterKey)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(masterKey)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}

	// Assemble all components into a wallet tester.
	wt := &walletTester{
		cs:      cs,
		gateway: g,
		tpool:   tp,
		miner:   m,
		wallet:  w,

		walletMasterKey: masterKey,

		persistDir: testdir,
	}

	// Mine blocks until there is money in the wallet.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		b, _ := wt.miner.FindBlock()
		err := wt.cs.AcceptBlock(b)
		if err != nil {
			return nil, err
		}
	}
	return wt, nil
}

// createBlankWalletTester creates a wallet tester that has not mined any
// blocks or encrypted the wallet.
func createBlankWalletTester(name string) (*walletTester, error) {
	// Create the modules
	testdir := build.TempDir(modules.WalletDir, name)
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, err
	}
	w, err := New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all components into a wallet tester.
	wt := &walletTester{
		gateway: g,
		cs:      cs,
		tpool:   tp,
		miner:   m,
		wallet:  w,

		persistDir: testdir,
	}
	return wt, nil
}

// closeWt closes all of the modules in the wallet tester.
func (wt *walletTester) closeWt() error {
	errs := []error{
		wt.gateway.Close(),
		wt.cs.Close(),
		wt.tpool.Close(),
		wt.miner.Close(),
		wt.wallet.Close(),
	}
	return build.JoinErrors(errs, "; ")
}

// TestNilInputs tries starting the wallet using nil inputs.
func TestNilInputs(t *testing.T) {
	testdir := build.TempDir(modules.WalletDir, t.Name())
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		t.Fatal(err)
	}

	wdir := filepath.Join(testdir, modules.WalletDir)
	_, err = New(cs, nil, wdir)
	if err != errNilTpool {
		t.Error(err)
	}
	_, err = New(nil, tp, wdir)
	if err != errNilConsensusSet {
		t.Error(err)
	}
	_, err = New(nil, nil, wdir)
	if err != errNilConsensusSet {
		t.Error(err)
	}
}

// TestAllAddresses checks that AllAddresses returns all of the wallet's
// addresses in sorted order.
func TestAllAddresses(t *testing.T) {
	wt, err := createBlankWalletTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()

	wt.wallet.keys[types.UnlockHash{1}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{5}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{0}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{2}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{4}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{3}] = spendableKey{}
	addrs := wt.wallet.AllAddresses()
	for i := range addrs {
		if addrs[i][0] != byte(i) {
			t.Error("address sorting failed:", i, addrs[i][0])
		}
	}
}

// TestCloseWallet tries to close the wallet.
func TestCloseWallet(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}
	testdir := build.TempDir(modules.WalletDir, t.Name())
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		t.Fatal(err)
	}
	wdir := filepath.Join(testdir, modules.WalletDir)
	w, err := New(cs, tp, wdir)
	if err != nil {
		t.Fatal(err)
	}
	if err := w.Close(); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>add TestRescanning<commit_after>package wallet

import (
	"path/filepath"
	"testing"
	"time"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/consensus"
	"github.com/NebulousLabs/Sia/modules/gateway"
	"github.com/NebulousLabs/Sia/modules/miner"
	"github.com/NebulousLabs/Sia/modules/transactionpool"
	"github.com/NebulousLabs/Sia/types"
	"github.com/NebulousLabs/fastrand"
)

// A Wallet tester contains a ConsensusTester and has a bunch of helpful
// functions for facilitating wallet integration testing.
type walletTester struct {
	cs      modules.ConsensusSet
	gateway modules.Gateway
	tpool   modules.TransactionPool
	miner   modules.TestMiner
	wallet  *Wallet

	walletMasterKey crypto.TwofishKey

	persistDir string
}

// createWalletTester takes a testing.T and creates a WalletTester.
func createWalletTester(name string) (*walletTester, error) {
	// Create the modules
	testdir := build.TempDir(modules.WalletDir, name)
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, err
	}
	w, err := New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	var masterKey crypto.TwofishKey
	fastrand.Read(masterKey[:])
	_, err = w.Encrypt(masterKey)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(masterKey)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}

	// Assemble all components into a wallet tester.
	wt := &walletTester{
		cs:      cs,
		gateway: g,
		tpool:   tp,
		miner:   m,
		wallet:  w,

		walletMasterKey: masterKey,

		persistDir: testdir,
	}

	// Mine blocks until there is money in the wallet.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		b, _ := wt.miner.FindBlock()
		err := wt.cs.AcceptBlock(b)
		if err != nil {
			return nil, err
		}
	}
	return wt, nil
}

// createBlankWalletTester creates a wallet tester that has not mined any
// blocks or encrypted the wallet.
func createBlankWalletTester(name string) (*walletTester, error) {
	// Create the modules
	testdir := build.TempDir(modules.WalletDir, name)
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, err
	}
	w, err := New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all components into a wallet tester.
	wt := &walletTester{
		gateway: g,
		cs:      cs,
		tpool:   tp,
		miner:   m,
		wallet:  w,

		persistDir: testdir,
	}
	return wt, nil
}

// closeWt closes all of the modules in the wallet tester.
func (wt *walletTester) closeWt() error {
	errs := []error{
		wt.gateway.Close(),
		wt.cs.Close(),
		wt.tpool.Close(),
		wt.miner.Close(),
		wt.wallet.Close(),
	}
	return build.JoinErrors(errs, "; ")
}

// TestNilInputs tries starting the wallet using nil inputs.
func TestNilInputs(t *testing.T) {
	testdir := build.TempDir(modules.WalletDir, t.Name())
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		t.Fatal(err)
	}

	wdir := filepath.Join(testdir, modules.WalletDir)
	_, err = New(cs, nil, wdir)
	if err != errNilTpool {
		t.Error(err)
	}
	_, err = New(nil, tp, wdir)
	if err != errNilConsensusSet {
		t.Error(err)
	}
	_, err = New(nil, nil, wdir)
	if err != errNilConsensusSet {
		t.Error(err)
	}
}

// TestAllAddresses checks that AllAddresses returns all of the wallet's
// addresses in sorted order.
func TestAllAddresses(t *testing.T) {
	wt, err := createBlankWalletTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()

	wt.wallet.keys[types.UnlockHash{1}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{5}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{0}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{2}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{4}] = spendableKey{}
	wt.wallet.keys[types.UnlockHash{3}] = spendableKey{}
	addrs := wt.wallet.AllAddresses()
	for i := range addrs {
		if addrs[i][0] != byte(i) {
			t.Error("address sorting failed:", i, addrs[i][0])
		}
	}
}

// TestCloseWallet tries to close the wallet.
func TestCloseWallet(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}
	testdir := build.TempDir(modules.WalletDir, t.Name())
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		t.Fatal(err)
	}
	wdir := filepath.Join(testdir, modules.WalletDir)
	w, err := New(cs, tp, wdir)
	if err != nil {
		t.Fatal(err)
	}
	if err := w.Close(); err != nil {
		t.Fatal(err)
	}
}

// TestRescanning verifies that calling Rescanning during a scan operation
// returns true, and false otherwise.
func TestRescanning(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()

	// A fresh wallet should not be rescanning.
	if wt.wallet.Rescanning() {
		t.Fatal("fresh wallet should not report that a scan is underway")
	}

	// lock the wallet
	wt.wallet.Lock()

	// spawn an unlock goroutine
	errChan := make(chan error)
	go func() {
		// acquire the write lock so that Unlock acquires the trymutex, but
		// cannot proceed further
		wt.wallet.mu.Lock()
		errChan <- wt.wallet.Unlock(wt.walletMasterKey)
	}()

	// wait for goroutine to start, after which Rescanning should return true
	time.Sleep(time.Millisecond * 10)
	if !wt.wallet.Rescanning() {
		t.Fatal("wallet should report that a scan is underway")
	}

	// release the mutex and allow the call to complete
	wt.wallet.mu.Unlock()
	if err := <-errChan; err != nil {
		t.Fatal("unlock failed:", err)
	}

	// Rescanning should now return false again
	if wt.wallet.Rescanning() {
		t.Fatal("wallet should not report that a scan is underway")
	}
}
<|endoftext|>


<commit_before>package apollostats

import (
	"html"
	"strings"
)

// Func to take care of garbled text data.
func filter_string(s string) string {
	// Fuck it, might aswell assume all text has been escaped.
	tmp := html.UnescapeString(s)

	// Usually seen in the character table.
	tmp = strings.Replace(tmp, "&", "&", -1)

	// Usually seen in the room names in the death table.
	tmp = strings.Trim(tmp, "ÿ")

	tmp = strings.TrimSpace(tmp)
	return tmp
}
<commit_msg>Remove unneeded html entity filter.<commit_after>package apollostats

import (
	"html"
	"strings"
)

// Func to take care of garbled text data.
func filter_string(s string) string {
	// Fuck it, might aswell assume all text has been escaped.
	tmp := html.UnescapeString(s)

	// Usually seen in the room names in the death table.
	tmp = strings.Trim(tmp, "ÿ")

	tmp = strings.TrimSpace(tmp)
	return tmp
}
<|endoftext|>