<commit_before>package raftkv

import (
	"encoding/gob"
	"fmt"
	"labrpc"
	"raft"
	"sort"
	"sync"
	"time"
)

const Debug = 0

func DPrintf(format string, a ...interface{}) (n int, err error) {
	if Debug > 0 {
		fmt.Printf(format, a...)
	}
	return
}

type Op struct {
	// Your definitions here.
	// Field names must start with capital letters,
	// otherwise RPC will break.
	Op     string //the operation
	Key    string
	Value  string
	Client uint32
	SeqNum uint32
}

type Entry struct {
	Op     string
	Value  string
	Index  int
	Client uint32
	SeqNum uint32
}

type RaftKV struct {
	sync.RWMutex
	me      int
	rf      *raft.Raft
	applyCh chan raft.ApplyMsg

	maxraftstate int // snapshot if log grows this big

	// Your definitions here.
	data      map[string]map[uint64]Entry
	committed map[uint32]uint32
	checkCode map[uint32]uint32
}

func (kv *RaftKV) CheckLeader(args *GetLeaderArgs, reply *GetLeaderReply) {
	term, isLeader := kv.rf.GetState()
	reply.WrongLeader = !isLeader
	reply.Term = term
	reply.Me = kv.me

	//reply.Committed = kv.committed[args.Client]
	//reply.CheckCode = kv.checkCode[args.Client]
}

func (kv *RaftKV) Get(args *GetArgs, reply *GetReply) {
	// Your code here.
	//fmt.Printf("Get :%d - WrongLeader:%v,Err:%v  \n",
	//	kv.me, putReply.WrongLeader, putReply.Err)
	//defer func() {
	//	reply.Committed = kv.committed[args.Client]
	//	reply.CheckCode = kv.checkCode[args.Client]
	//}()

	reply.WrongLeader = false
	reply.Err = ErrNoKey
	reply.Value = ""

	kv.RLock()
	values := ""
	//To Check entry with SeqNum is applied
	value, ok1 := kv.data[args.Key]
	if !ok1 {
		kv.RUnlock()
		DPrintf("Server GET No Key:%v exist\n", args.Key)
		return
	}

	//CliCmt := uint64(args.Client)<<32 + uint64(args.Committed)
	//fmt.Printf("CliCmt in Get: CliCmt:%v, Client:%v, Committed:%v\n", CliCmt, args.Client, args.Committed)

	var keys U64Array
	for key := range value {
		keys = append(keys, key)
	}
	sort.Sort(keys)
	for _, k := range keys {
		if value[k].Op == "Get" {
			continue
		}
		values += value[k].Value
	}
	kv.RUnlock()
	reply.Err = OK
	reply.Value = values
	//fmt.Printf("Get From leader:%d - Op{Key:%v, Value:%v} \n",
	//	kv.me, args.Key, values)
	DPrintf("Server GET OP{%v, %v, %v} success\n", "Get", args.Key, values)

}

func (kv *RaftKV) PutAppend(args *PutAppendArgs, reply *PutAppendReply) {
	defer func() {
		kv.RLock()
		reply.Committed = kv.committed[args.Client]
		reply.CheckCode = kv.checkCode[args.Client]
		kv.RUnlock()
	}()

	cmd := Op{
		Op:     args.Op,
		Key:    args.Key,
		Value:  args.Value,
		Client: args.Client,
		SeqNum: args.SeqNum}

	index, _, isLeader := kv.rf.Start(cmd)

	reply.WrongLeader = !isLeader
	reply.Err = ErrNoKey
	reply.Me = kv.me
	reply.Index = index

	if index == -1 {
		return
	}
	//fmt.Printf("Server:%d Put Start: - Op{Op:%v, Key:%v, Value:%v} index:%d Err:%v\n",
	//	kv.me, cmd.Op, cmd.Key, cmd.Value, index, reply.Err)
	t0 := time.Now()
	for time.Since(t0).Seconds() < 10 {
		time.Sleep(10 * time.Millisecond)
		_, isLeader = kv.rf.GetState()
		if !isLeader {
			reply.WrongLeader = !isLeader
			return
		}

		kv.RLock()
		entry, ok1 := kv.data[cmd.Key]
		if !ok1 {
			kv.RUnlock()
			continue
		}

		CliSeq := uint64(args.Client)<<32 + uint64(args.SeqNum)
		//fmt.Printf("CliSeq in PutAppend: CliSeq:%v, Client:%v, SeqNum:%v\n", CliSeq, args.Client, args.SeqNum)
		v, ok2 := entry[CliSeq]
		if !ok2 {
			kv.RUnlock()
			continue
		}
		//kv.printData()
		kv.RUnlock()
		reply.Err = OK
		//fmt.Printf("Leader:%d - Op{Op:%v, Key:%v, Value:%v} index:%d Err:%v\n",
		//	kv.me, cmd.Op, cmd.Key, cmd.Value, index, reply.Err)
		DPrintf("Server PUT OP{%v, %v, %v} success {WrongL:%v, Err:%v, Me:%v,Index:%v}\n",
			args.Op, args.Key, args.Value, reply.WrongLeader, reply.Err, reply.Me, index)
		if v.Value != cmd.Value {
			fmt.Printf("Warning the value is not matched after put\n")
		}
		return
	}
	fmt.Printf("Warning: Server take more than 10 Sec to PutApp\n")
}

//
// the tester calls Kill() when a RaftKV instance won't
// be needed again. you are not required to do anything
// in Kill(), but it might be convenient to (for example)
// turn off debug output from this instance.
//
func (kv *RaftKV) Kill() {
	kv.rf.Kill()
	// Your code here, if desired.
}

//
// servers[] contains the ports of the set of
// servers that will cooperate via Raft to
// form the fault-tolerant key/value service.
// me is the index of the current server in servers[].
// the k/v server should store snapshots with persister.SaveSnapshot(),
// and Raft should save its state (including log) with persister.SaveRaftState().
// the k/v server should snapshot when Raft's saved state exceeds maxraftstate bytes,
// in order to allow Raft to garbage-collect its log. if maxraftstate is -1,
// you don't need to snapshot.
// StartKVServer() must return quickly, so it should start goroutines
// for any long-running work.
//
func StartKVServer(servers []*labrpc.ClientEnd, me int, persister *raft.Persister, maxraftstate int) *RaftKV {
	// call gob.Register on structures you want
	// Go's RPC library to marshall/unmarshall.
	//fmt.Printf("StartKVServer :%d\n", me)
	gob.Register(Op{})

	kv := new(RaftKV)
	kv.me = me
	kv.maxraftstate = maxraftstate

	// You may need initialization code here.
	kv.applyCh = make(chan raft.ApplyMsg)
	kv.rf = raft.Make(servers, me, persister, kv.applyCh)

	// You may need initialization code here.
	kv.data = make(map[string]map[uint64]Entry)
	kv.committed = make(map[uint32]uint32)
	kv.checkCode = make(map[uint32]uint32)

	go func() {
		for msg := range kv.applyCh {
			kv.Lock()
			if cmd, ok := (msg.Command).(Op); ok {
				//kv.log[msg.Index] = cmd
				//fmt.Printf("KVRaft:%d - Op{Op:%v, Key:%v, Value:%v} index:%d\n",
				//	kv.me, cmd.Op, cmd.Key, cmd.Value, msg.Index)
				//CliSeq := uint64(cmd.Client<<32 + cmd.SeqNum)
				CliSeq := uint64(cmd.Client)<<32 + uint64(cmd.SeqNum)
				//fmt.Printf("CliSeq in Apply: CliSeq:%v, Client:%v, SeqNum:%v\n", CliSeq, cmd.Client, cmd.SeqNum)
				switch cmd.Op {
				case "Put":
					delete(kv.data, cmd.Key)
					entry := make(map[uint64]Entry)
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}

					kv.data[cmd.Key] = entry
					kv.committed[cmd.Client] = cmd.SeqNum
				case "Append":
					entry, ok := kv.data[cmd.Key]
					if !ok {
						entry = make(map[uint64]Entry)
					}
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}
					kv.committed[cmd.Client] = cmd.SeqNum
				case "Get":
					entry, ok := kv.data[cmd.Key]
					if !ok {
						entry = make(map[uint64]Entry)
					}
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}
					kv.checkCode[cmd.Client] = cmd.SeqNum
				}
			} else {
				fmt.Printf("The OP can not dry from msg\n")
			}
			kv.Unlock()
			//kv.printData(kv.me)
		}
	}()

	return kv
}

func (kv *RaftKV) printData(me int) {
	//if _, leader := kv.rf.GetState(); !leader {
	//	return
	//}
	fmt.Printf("%d Printing data ...\n", me)
	kv.RLock()
	for key, values := range kv.data {
		fmt.Printf("Key:%v \n", key)

		var keys U64Array
		for key := range values {
			keys = append(keys, key)
		}
		sort.Sort(keys)
		for _, k := range keys {
			//fmt.Printf("{%v - %v, %v, %v, %v} ",
			//	k, entry[k].Op, entry[k].Value, entry[k].Index, entry[k].Client)
			//fmt.Printf("{%v - %v, %v, %v} ",
			//	k, values[k].Op, values[k].Value, values[k].Index)
			fmt.Printf("{%v, %v, %v} ",
				values[k].Op, values[k].Value, values[k].Index)
		}
		fmt.Printf("\n")
	}
	kv.RUnlock()
	fmt.Printf("printData RUnlock()\n")
}
<commit_msg>Lab3B - Snapshot kickoff<commit_after>package raftkv

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"labrpc"
	"raft"
	"sort"
	"sync"
	"time"
)

const Debug = 0

func DPrintf(format string, a ...interface{}) (n int, err error) {
	if Debug > 0 {
		fmt.Printf(format, a...)
	}
	return
}

type Op struct {
	// Your definitions here.
	// Field names must start with capital letters,
	// otherwise RPC will break.
	Op     string //the operation
	Key    string
	Value  string
	Client uint32
	SeqNum uint32
}

type Entry struct {
	Op     string
	Value  string
	Index  int
	Client uint32
	SeqNum uint32
}

type RaftKV struct {
	sync.RWMutex
	me      int
	rf      *raft.Raft
	applyCh chan raft.ApplyMsg

	maxraftstate int // snapshot if log grows this big

	// Your definitions here.
	data      map[string]map[uint64]Entry
	zipData   map[string]string
	committed map[uint32]uint32
	checkCode map[uint32]uint32
}

func (kv *RaftKV) CheckLeader(args *GetLeaderArgs, reply *GetLeaderReply) {
	term, isLeader := kv.rf.GetState()
	reply.WrongLeader = !isLeader
	reply.Term = term
	reply.Me = kv.me

	//reply.Committed = kv.committed[args.Client]
	//reply.CheckCode = kv.checkCode[args.Client]
}

func (kv *RaftKV) Get(args *GetArgs, reply *GetReply) {
	// Your code here.
	//fmt.Printf("Get :%d - WrongLeader:%v,Err:%v  \n",
	//	kv.me, putReply.WrongLeader, putReply.Err)
	//defer func() {
	//	reply.Committed = kv.committed[args.Client]
	//	reply.CheckCode = kv.checkCode[args.Client]
	//}()

	reply.WrongLeader = false
	reply.Err = ErrNoKey
	reply.Value = ""

	kv.RLock()
	values := ""
	//To Check entry with SeqNum is applied
	value, ok1 := kv.data[args.Key]
	if !ok1 {
		kv.RUnlock()
		DPrintf("Server GET No Key:%v exist\n", args.Key)
		return
	}

	var keys U64Array
	for key := range value {
		keys = append(keys, key)
	}
	sort.Sort(keys)
	for _, k := range keys {
		if value[k].Op == "Get" {
			continue
		}
		values += value[k].Value
	}
	kv.RUnlock()
	reply.Err = OK
	reply.Value = values
	//fmt.Printf("Get From leader:%d - Op{Key:%v, Value:%v} \n",
	//	kv.me, args.Key, values)
	DPrintf("Server GET OP{%v, %v, %v} success\n", "Get", args.Key, values)

}

func (kv *RaftKV) PutAppend(args *PutAppendArgs, reply *PutAppendReply) {
	defer func() {
		kv.RLock()
		reply.Committed = kv.committed[args.Client]
		reply.CheckCode = kv.checkCode[args.Client]
		kv.RUnlock()
	}()

	cmd := Op{
		Op:     args.Op,
		Key:    args.Key,
		Value:  args.Value,
		Client: args.Client,
		SeqNum: args.SeqNum}

	index, _, isLeader := kv.rf.Start(cmd)

	reply.WrongLeader = !isLeader
	reply.Err = ErrNoKey
	reply.Me = kv.me
	reply.Index = index

	if index == -1 {
		return
	}
	//fmt.Printf("Server:%d Put Start: - Op{Op:%v, Key:%v, Value:%v} index:%d Err:%v\n",
	//	kv.me, cmd.Op, cmd.Key, cmd.Value, index, reply.Err)
	t0 := time.Now()
	for time.Since(t0).Seconds() < 10 {
		time.Sleep(10 * time.Millisecond)
		_, isLeader = kv.rf.GetState()
		if !isLeader {
			reply.WrongLeader = !isLeader
			return
		}

		kv.RLock()
		entry, ok1 := kv.data[cmd.Key]
		if !ok1 {
			kv.RUnlock()
			continue
		}

		CliSeq := uint64(args.Client)<<32 + uint64(args.SeqNum)
		//fmt.Printf("CliSeq in PutAppend: CliSeq:%v, Client:%v, SeqNum:%v\n", CliSeq, args.Client, args.SeqNum)
		v, ok2 := entry[CliSeq]
		if !ok2 {
			kv.RUnlock()
			continue
		}
		//kv.printData()
		kv.RUnlock()
		reply.Err = OK
		//fmt.Printf("Leader:%d - Op{Op:%v, Key:%v, Value:%v} index:%d Err:%v\n",
		//	kv.me, cmd.Op, cmd.Key, cmd.Value, index, reply.Err)
		DPrintf("Server PUT OP{%v, %v, %v} success {WrongL:%v, Err:%v, Me:%v,Index:%v}\n",
			args.Op, args.Key, args.Value, reply.WrongLeader, reply.Err, reply.Me, index)
		if v.Value != cmd.Value {
			fmt.Printf("Warning the value is not matched after put\n")
		}
		return
	}
	fmt.Printf("Warning: Server take more than 10 Sec to PutApp\n")
}

//
// the tester calls Kill() when a RaftKV instance won't
// be needed again. you are not required to do anything
// in Kill(), but it might be convenient to (for example)
// turn off debug output from this instance.
//
func (kv *RaftKV) Kill() {
	kv.rf.Kill()
	// Your code here, if desired.
}

//
// servers[] contains the ports of the set of
// servers that will cooperate via Raft to
// form the fault-tolerant key/value service.
// me is the index of the current server in servers[].
// the k/v server should store snapshots with persister.SaveSnapshot(),
// and Raft should save its state (including log) with persister.SaveRaftState().
// the k/v server should snapshot when Raft's saved state exceeds maxraftstate bytes,
// in order to allow Raft to garbage-collect its log. if maxraftstate is -1,
// you don't need to snapshot.
// StartKVServer() must return quickly, so it should start goroutines
// for any long-running work.
//
func StartKVServer(servers []*labrpc.ClientEnd, me int, persister *raft.Persister, maxraftstate int) *RaftKV {
	// call gob.Register on structures you want
	// Go's RPC library to marshall/unmarshall.
	//fmt.Printf("StartKVServer :%d\n", me)
	gob.Register(Op{})

	kv := new(RaftKV)
	kv.me = me
	kv.maxraftstate = maxraftstate

	// You may need initialization code here.
	kv.applyCh = make(chan raft.ApplyMsg)
	kv.rf = raft.Make(servers, me, persister, kv.applyCh)

	// You may need initialization code here.
	kv.data = make(map[string]map[uint64]Entry)
	kv.zipData = make(map[string]string)
	kv.committed = make(map[uint32]uint32)
	kv.checkCode = make(map[uint32]uint32)

	go func() {
		for msg := range kv.applyCh {
			kv.Lock()

			if msg.UseSnapshot {
				if msg.Snapshot == nil || len(msg.Snapshot) < 1 {
					kv.Unlock()
					continue
				}
				clt := uint32(0)
				seq := uint32(0)
				r := bytes.NewBuffer(msg.Snapshot)
				d := gob.NewDecoder(r)
				d.Decode(&kv.zipData)
				d.Decode(&clt)
				d.Decode(&seq)

				for key := range kv.data {
					delete(kv.data, key)
					entry := make(map[uint64]Entry)
					CltSeq := uint64(clt)<<32 + uint64(seq)
					entry[CltSeq] = Entry{
						Value:  kv.zipData[key],
						Op:     "Put",
						Client: clt,
						Index:  msg.Index,
						SeqNum: seq}
					kv.data[key] = entry
				}
				kv.committed[clt] = seq
				kv.Unlock()
				continue
			}

			if cmd, ok := (msg.Command).(Op); ok {
				//fmt.Printf("KVRaft:%d - Op{Op:%v, Key:%v, Value:%v} index:%d\n",
				//	kv.me, cmd.Op, cmd.Key, cmd.Value, msg.Index)
				//CliSeq := uint64(cmd.Client<<32 + cmd.SeqNum)
				CliSeq := uint64(cmd.Client)<<32 + uint64(cmd.SeqNum)
				//fmt.Printf("CliSeq in Apply: CliSeq:%v, Client:%v, SeqNum:%v\n", CliSeq, cmd.Client, cmd.SeqNum)
				switch cmd.Op {
				case "Put":
					delete(kv.data, cmd.Key)
					entry := make(map[uint64]Entry)
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}

					kv.data[cmd.Key] = entry
					kv.committed[cmd.Client] = cmd.SeqNum
				case "Append":
					entry, ok := kv.data[cmd.Key]
					if !ok {
						entry = make(map[uint64]Entry)
					}
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}
					kv.committed[cmd.Client] = cmd.SeqNum
				case "Get":
					entry, ok := kv.data[cmd.Key]
					if !ok {
						entry = make(map[uint64]Entry)
					}
					entry[CliSeq] = Entry{
						Value:  cmd.Value,
						Op:     cmd.Op,
						Client: cmd.Client,
						Index:  msg.Index,
						SeqNum: cmd.SeqNum}
					kv.checkCode[cmd.Client] = cmd.SeqNum
				}

				if maxraftstate != -1 && persister.RaftStateSize() > maxraftstate {
					//zip kv.data and make a snapshort of data
					fmt.Printf("Start SnapShot %d\n", kv.me)
					kv.zip(msg.Index, cmd.Client, cmd.SeqNum)
					w := new(bytes.Buffer)
					e := gob.NewEncoder(w)
					e.Encode(kv.zipData)
					e.Encode(cmd.Client)
					e.Encode(cmd.SeqNum)
					data := w.Bytes()
					kv.rf.MakeSnapShot(msg.Index, data)
				}
			} else {
				fmt.Printf("The OP can not dry from msg\n")
			}
			//kv.printData(kv.me)

			kv.Unlock()
		} //end for
	}()

	return kv
}

func (kv *RaftKV) printData(me int) {
	//if _, leader := kv.rf.GetState(); !leader {
	//	return
	//}
	DPrintf("%d Printing data ...\n", me)
	kv.RLock()
	for key, values := range kv.data {
		fmt.Printf("Key:%v \n", key)

		var keys U64Array
		for key := range values {
			keys = append(keys, key)
		}
		sort.Sort(keys)
		for _, k := range keys {
			//fmt.Printf("{%v - %v, %v, %v, %v} ",
			//	k, entry[k].Op, entry[k].Value, entry[k].Index, entry[k].Client)
			//fmt.Printf("{%v - %v, %v, %v} ",
			//	k, values[k].Op, values[k].Value, values[k].Index)
			fmt.Printf("{%v, %v, %v} ",
				values[k].Op, values[k].Value, values[k].Index)
		}
		fmt.Printf("\n")
	}
	kv.RUnlock()
}

func (kv *RaftKV) zip(idx int, clt uint32, seq uint32) {

	for key := range kv.data {
		//Step 1 : Get all the key and values from kv.data
		values := ""
		value, _ := kv.data[key]

		var CltSeqs U64Array
		for seq := range value {
			CltSeqs = append(CltSeqs, seq)
		}
		sort.Sort(CltSeqs)
		for _, s := range CltSeqs {
			if value[s].Op == "Get" {
				continue
			}
			values += value[s].Value
		}
		kv.zipData[key] = values

		//step 2 : zip the kv.data and delete frage data in kv.data
		delete(kv.data, key)
		entry := make(map[uint64]Entry)
		CltSeq := uint64(clt)<<32 + uint64(seq)
		entry[CltSeq] = Entry{
			Value:  values,
			Op:     "Put",
			Client: clt,
			Index:  idx,
			SeqNum: seq}
		kv.data[key] = entry
	}
}
<|endoftext|>


<commit_before>package model

import (
	"github.com/elsonwu/restapi/model/attr"
	// "labix.org/v2/mgo"
	// "fmt"
	"labix.org/v2/mgo/bson"
	// "reflect"
)

func UserModel() (user *User) {
	user = new(User)
	user.Init()
	return
}

type User struct {
	Document    `bson:",inline" json:",inline"`
	FirstName   attr.String `bson:"first_name" json:"first_name"`
	Password    attr.String `bson:"password" json:"-"`
	LastName    attr.String `bson:"last_name" json:"last_name"`
	Email       attr.Email  `bson:"email" json:"email"`
	DisplayName attr.String `bson:"display_name" json:"display_name"`
	UserProfile UserProfile `bson:"profile" json:"profile"`
	UserDomain  UserDomain  `bson:"domain" json:"domain"`
}

func (self *User) Init() *User {
	if self.SetCollectionName(self.GetCollectionName()) {
		self.Document.doc = self
		self.UserDomain.owner = self
	}

	return self
}

func (self *User) New() (model *User) {
	model = new(User)
	model.Init()
	model.Document.isNew = true
	return
}

func (self *User) GetCollectionName() string {
	return "user"
}

func (self *User) Validate() bool {
	if !self.UserDomain.Validate() {
		for _, err := range self.UserDomain.GetErrors() {
			self.AddError(err)
		}

		return false
	}

	if self.Email.Get() == "" {
		self.AddError("Email cannot be empty.")
		return false
	}

	if !self.Email.Validate() {
		self.AddError("Email is invalid")
		return false
	}

	return true
}

func (self *User) BeforeSave() bool {
	if self.isNew {
		self.UserDomain.InitDomain()
	}

	return true
}

func (self *User) AfterFind() {
	self.Document.isNew = false
	self.DisplayName = self.FirstName + " " + self.LastName
}

func (self *User) FindAll(criteria Criteria) (models []*User, err error) {
	models = make([]*User, criteria.GetLimit())
	q := self.GetCollection().Find(criteria.GetConditions())
	q.Skip(criteria.GetOffset())
	q.Limit(criteria.GetLimit())
	q.All(&models)
	for k, _ := range models {
		models[k].Init()
		models[k].AfterFind()
	}
	return
}

func (self *User) Find(criteria Criteria) (*User, error) {
	q := self.GetCollection().Find(criteria.GetConditions())
	err := q.One(self)
	self.Init()
	self.AfterFind()
	return self, err
}

func (self *User) FindId(id string, criteria Criteria) (*User, error) {
	criteria.AddCondition("_id", "==", bson.ObjectIdHex(id))
	q := self.GetCollection().Find(criteria.GetConditions())
	err := q.One(self)
	self.Init()
	self.AfterFind()
	return self, err
}
<commit_msg>Move the field DisplayName to GetDisplayName method in user model<commit_after>package model

import (
	"github.com/elsonwu/restapi/model/attr"
	// "labix.org/v2/mgo"
	// "fmt"
	"labix.org/v2/mgo/bson"
	// "reflect"
)

func UserModel() (user *User) {
	user = new(User)
	user.Init()
	return
}

type User struct {
	Document    `bson:",inline" json:",inline"`
	FirstName   attr.String `bson:"first_name" json:"first_name"`
	Password    attr.String `bson:"password" json:"-"`
	LastName    attr.String `bson:"last_name" json:"last_name"`
	Email       attr.Email  `bson:"email" json:"email"`
	UserProfile UserProfile `bson:"profile" json:"profile"`
	UserDomain  UserDomain  `bson:"domain" json:"domain"`
}

func (self *User) Init() *User {
	if self.SetCollectionName(self.GetCollectionName()) {
		self.Document.doc = self
		self.UserDomain.owner = self
	}

	return self
}

func (self *User) New() (model *User) {
	model = new(User)
	model.Init()
	model.Document.isNew = true
	return
}

func (self *User) GetCollectionName() string {
	return "user"
}

func (self *User) Validate() bool {
	if !self.UserDomain.Validate() {
		for _, err := range self.UserDomain.GetErrors() {
			self.AddError(err)
		}

		return false
	}

	if self.Email.Get() == "" {
		self.AddError("Email cannot be empty.")
		return false
	}

	if !self.Email.Validate() {
		self.AddError("Email is invalid")
		return false
	}

	return true
}

func (self *User) BeforeSave() bool {
	if self.isNew {
		self.UserDomain.InitDomain()
	}

	return true
}

func (self *User) AfterFind() {
	self.Document.isNew = false
}

func (self *User) GetDisplayName() string {
	return self.FirstName.Get() + " " + self.LastName.Get()
}

func (self *User) FindAll(criteria Criteria) (models []*User, err error) {
	models = make([]*User, criteria.GetLimit())
	q := self.GetCollection().Find(criteria.GetConditions())
	q.Skip(criteria.GetOffset())
	q.Limit(criteria.GetLimit())
	q.All(&models)
	for k, _ := range models {
		models[k].Init()
		models[k].AfterFind()
	}
	return
}

func (self *User) Find(criteria Criteria) (*User, error) {
	q := self.GetCollection().Find(criteria.GetConditions())
	err := q.One(self)
	self.Init()
	self.AfterFind()
	return self, err
}

func (self *User) FindId(id string, criteria Criteria) (*User, error) {
	criteria.AddCondition("_id", "==", bson.ObjectIdHex(id))
	q := self.GetCollection().Find(criteria.GetConditions())
	err := q.One(self)
	self.Init()
	self.AfterFind()
	return self, err
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"

	"github.com/concourse/fly/rc"
)

type RenamePipelineCommand struct {
	Pipeline string `short:"o"  long:"old-name" required:"true"  description:"Pipeline to rename"`
	Name     string `short:"n"  long:"new-name" required:"true"  description:"Name to set as pipeline name"`
}

func (rp *RenamePipelineCommand) Execute([]string) error {
	client, err := rc.TargetClient(Fly.Target)
	if err != nil {
		return err
	}

	err = rc.ValidateClient(client, Fly.Target)
	if err != nil {
		return err
	}

	renamed, err := client.RenamePipeline(rp.Pipeline, rp.Name)
	if err != nil {
		return fmt.Errorf("client failed with error: %s\n", err)
	}

	if !renamed {
		return fmt.Errorf("failed to find pipeline")
	}

	fmt.Printf("pipeline successfully renamed to %s\n", rp.Name)

	return nil
}
<commit_msg>fix error handling in rename-pipeline<commit_after>package commands

import (
	"fmt"

	"github.com/concourse/fly/commands/internal/displayhelpers"
	"github.com/concourse/fly/rc"
)

type RenamePipelineCommand struct {
	Pipeline string `short:"o"  long:"old-name" required:"true"  description:"Pipeline to rename"`
	Name     string `short:"n"  long:"new-name" required:"true"  description:"Name to set as pipeline name"`
}

func (rp *RenamePipelineCommand) Execute([]string) error {
	client, err := rc.TargetClient(Fly.Target)
	if err != nil {
		return err
	}

	err = rc.ValidateClient(client, Fly.Target)
	if err != nil {
		return err
	}

	found, err := client.RenamePipeline(rp.Pipeline, rp.Name)
	if err != nil {
		return err
	}

	if !found {
		displayhelpers.Failf("pipeline '%s' not found\n", rp.Pipeline)
		return nil
	}

	fmt.Printf("pipeline successfully renamed to %s\n", rp.Name)

	return nil
}
<|endoftext|>


<commit_before>package versionCmd

import (
	// Stdlib
	"fmt"
	"os"

	// Internal
	"github.com/salsaflow/salsaflow/app/appflags"
	"github.com/salsaflow/salsaflow/commands/version/bump"
	"github.com/salsaflow/salsaflow/errs"
	"github.com/salsaflow/salsaflow/version"

	// Other
	"gopkg.in/tchap/gocli.v2"
)

var Command = &gocli.Command{
	UsageLine: "version",
	Short:     "various version-related actions",
	Long: `
  Print SalsaFlow version and exit. No more, no less.

  There are also some cool subcommands available. Check them out.
	`,
	Action: func(cmd *gocli.Command, args []string) {
		if len(args) != 0 {
			cmd.Usage()
			os.Exit(2)
		}

		ver, err := version.Get()
		if err != nil {
			errs.Fatal(err)
		}

		fmt.Println(ver)
	},
}

func init() {
	// Register global flags.
	appflags.RegisterGlobalFlags(&Command.Flags)

	// Register subcommands.
	Command.MustRegisterSubcommand(bumpCmd.Command)
}
<commit_msg>version: Fix wrong command description<commit_after>package versionCmd

import (
	// Stdlib
	"fmt"
	"os"

	// Internal
	"github.com/salsaflow/salsaflow/app/appflags"
	"github.com/salsaflow/salsaflow/commands/version/bump"
	"github.com/salsaflow/salsaflow/errs"
	"github.com/salsaflow/salsaflow/version"

	// Other
	"gopkg.in/tchap/gocli.v2"
)

var Command = &gocli.Command{
	UsageLine: "version",
	Short:     "print the current project version",
	Long: `
  Print the project version string as stored in the current branch.

  To check the version of SalsaFlow itself, use -version.

  There are also some subcommands available. Check them out.
	`,
	Action: func(cmd *gocli.Command, args []string) {
		if len(args) != 0 {
			cmd.Usage()
			os.Exit(2)
		}

		ver, err := version.Get()
		if err != nil {
			errs.Fatal(err)
		}

		fmt.Println(ver)
	},
}

func init() {
	// Register global flags.
	appflags.RegisterGlobalFlags(&Command.Flags)

	// Register subcommands.
	Command.MustRegisterSubcommand(bumpCmd.Command)
}
<|endoftext|>


<commit_before>package main

import (
	"sort"
	"sync"

	"github.com/vheon/picker/terminal"
)

type View struct {
	Height int
	Query  string
	Rows   []string
	Done   bool

	index  int
	prompt string
}

func (v *View) Index() int {
	return v.index
}

func (v *View) Selected() string {
	if len(v.Rows)-1 < v.index {
		return ""
	}
	return v.Rows[v.index]
}

func (v *View) Down() {
	if v.index < len(v.Rows)-1 {
		v.index++
	}
}

func (v *View) Up() {
	if v.index > 0 {
		v.index--
	}
}

func (v *View) ClearPrompt() {
	v.Query = ""
	v.prompt = ""
}

func (v *View) DrawOnTerminal(t *terminal.Terminal) {
	t.HideCursor()
	defer t.ShowCursor()

	start_row := t.Height - v.Height - 1

	for i, row := range v.toAnsiForm(t) {
		t.WriteToLine(start_row+i, row)
	}

	t.MoveTo(start_row, len(v.Query)+len(v.prompt))
}

func (v *View) toAnsiForm(t *terminal.Terminal) []string {
	rows := make([]string, v.Height+1)
	rows[0] = v.prompt + v.Query
	for i, row := range v.Rows {
		rows[i+1] = cutAt(row, t.Width)
	}
	if len(v.Rows) > 0 {
		rows[v.Index()+1] = terminal.AnsiInverted(v.Selected())
	}
	return rows
}

func cutAt(s string, width int) string {
	if len(s) > width {
		return s[:width]
	}
	return s
}

type Picker struct {
	all     []Candidate
	visible int
	blank   *View
}

func NewPicker(candidates []Candidate, visible int) *Picker {
	picker := &Picker{
		all:     candidates,
		visible: visible,
	}
	picker.blank = picker.doAnswer("")

	return picker
}

type Candidate struct {
	value string
	score float64
}

func NewCandidate(s string) Candidate {
	return Candidate{
		value: s,
		score: 1.0,
	}
}

type CandidateSlice []Candidate

func (cs CandidateSlice) Len() int           { return len(cs) }
func (cs CandidateSlice) Swap(i, j int)      { cs[i], cs[j] = cs[j], cs[i] }
func (cs CandidateSlice) Less(i, j int) bool { return cs[i].score > cs[j].score }

func (p *Picker) Answer(query string) *View {
	if query == "" {
		return p.blank
	}
	return p.doAnswer(query)
}

func (p *Picker) doAnswer(query string) *View {
	var wg sync.WaitGroup
	wg.Add(len(p.all))
	for i := range p.all {
		candidate := &p.all[i]
		go func(c *Candidate) {
			c.score = Score(c.value, query)
			wg.Done()
		}(candidate)
	}
	wg.Wait()

	sort.Sort(CandidateSlice(p.all))

	lines := []string{}
	for i, c := range p.all {
		if c.score == 0.0 || i >= p.visible {
			break
		}
		lines = append(lines, c.value)
	}

	return &View{
		Height: p.visible,
		Rows:   lines,
		Query:  query,
		Done:   false,
		index:  0,
		prompt: "> ",
	}
}
<commit_msg>Launch a fixed number of goroutine<commit_after>package main

import (
	"sort"
	"sync"

	"github.com/vheon/picker/terminal"
)

type View struct {
	Height int
	Query  string
	Rows   []string
	Done   bool

	index  int
	prompt string
}

func (v *View) Index() int {
	return v.index
}

func (v *View) Selected() string {
	if len(v.Rows)-1 < v.index {
		return ""
	}
	return v.Rows[v.index]
}

func (v *View) Down() {
	if v.index < len(v.Rows)-1 {
		v.index++
	}
}

func (v *View) Up() {
	if v.index > 0 {
		v.index--
	}
}

func (v *View) ClearPrompt() {
	v.Query = ""
	v.prompt = ""
}

func (v *View) DrawOnTerminal(t *terminal.Terminal) {
	t.HideCursor()
	defer t.ShowCursor()

	start_row := t.Height - v.Height - 1

	for i, row := range v.toAnsiForm(t) {
		t.WriteToLine(start_row+i, row)
	}

	t.MoveTo(start_row, len(v.Query)+len(v.prompt))
}

func (v *View) toAnsiForm(t *terminal.Terminal) []string {
	rows := make([]string, v.Height+1)
	rows[0] = v.prompt + v.Query
	for i, row := range v.Rows {
		rows[i+1] = cutAt(row, t.Width)
	}
	if len(v.Rows) > 0 {
		rows[v.Index()+1] = terminal.AnsiInverted(v.Selected())
	}
	return rows
}

func cutAt(s string, width int) string {
	if len(s) > width {
		return s[:width]
	}
	return s
}

type Picker struct {
	all     []Candidate
	visible int
	blank   *View
}

func NewPicker(candidates []Candidate, visible int) *Picker {
	picker := &Picker{
		all:     candidates,
		visible: visible,
	}
	picker.blank = picker.doAnswer("")

	return picker
}

type Candidate struct {
	value string
	score float64
}

func NewCandidate(s string) Candidate {
	return Candidate{
		value: s,
		score: 1.0,
	}
}

type CandidateSlice []Candidate

func (cs CandidateSlice) Len() int           { return len(cs) }
func (cs CandidateSlice) Swap(i, j int)      { cs[i], cs[j] = cs[j], cs[i] }
func (cs CandidateSlice) Less(i, j int) bool { return cs[i].score > cs[j].score }

func (p *Picker) Answer(query string) *View {
	if query == "" {
		return p.blank
	}
	return p.doAnswer(query)
}

func (p *Picker) doAnswer(query string) *View {
	all := make(chan *Candidate)
	go func() {
		for i := range p.all {
			all <- &p.all[i]
		}
		close(all)
	}()

	var wg sync.WaitGroup
	for i := 0; i < 64; i++ {
		wg.Add(1)
		go func() {
			for c := range all {
				c.score = Score(c.value, query)
			}
			wg.Done()
		}()
	}
	wg.Wait()

	sort.Sort(CandidateSlice(p.all))

	lines := []string{}
	for i, c := range p.all {
		if c.score == 0.0 || i >= p.visible {
			break
		}
		lines = append(lines, c.value)
	}

	return &View{
		Height: p.visible,
		Rows:   lines,
		Query:  query,
		Done:   false,
		index:  0,
		prompt: "> ",
	}
}
<|endoftext|>


<commit_before>package pigeon

// Version represents pigeon's semantic version.
const Version = "v1.0.0"
<commit_msg>Bump up to v1.1.0<commit_after>package pigeon

// Version represents pigeon's semantic version.
const Version = "v1.1.0"
<|endoftext|>


<commit_before>package store

import "io"

// Searcher is an interface for the different searcher params
type Searcher interface {
	// expr returns a sqlite snippet used in the WHERE clause.
	Expr() string
	// params returns the required parameters for the sqlite snippet.
	Params() []interface{}
}

// between is a searcher which searches for values between (inclusive) the
// given values.
type between struct {
	col      string
	from, to int
}

// Between returns a Searcher that looks for an integer between two values
func Between(column string, from, to int) Searcher {
	return between{column, from, to}
}

func (b between) Expr() string {
	return "[" + b.col + "] BETWEEN ? AND ?"
}

func (b between) Params() []interface{} {
	return []interface{}{b.from, b.to}
}

// like implements a search which uses the LIKE syntax in a WHERE clause.
type like struct {
	col, likeStr string
}

// Like returns a Searcher that looks for similar strings
func Like(column, likeStr string) Searcher {
	return like{column, likeStr}
}

func (l like) Expr() string {
	return "[" + l.col + "] LIKE ?"
}

func (l like) Params() []interface{} {
	return []interface{}{l.likeStr}
}

type notLike struct {
	col, notLikeStr string
}

// NotLike returns a Searcher that excludes results with similar strings
func NotLike(column, notLikeStr string) Searcher {
	return notLike{column, notLikeStr}
}

func (n notLike) Expr() string {
	return "[" + n.col + "] NOT LIKE ?"
}

func (n notLike) Params() []interface{} {
	return []interface{}{n.notLikeStr}
}

type matchString struct {
	col, match string
}

// MatchString searches for an exact (case-insensitive) string match on the given column
func MatchString(column, match string) Searcher {
	return matchString{column, match}
}

func (m matchString) Expr() string {
	return "[" + m.col + "] = ?"
}

func (m matchString) Params() []interface{} {
	return []interface{}{m.match}
}

type matchInt struct {
	col   string
	match int
}

// MatchInt searches for an exact integer match on the given column
func MatchInt(column string, match int) Searcher {
	return matchInt{column, match}
}

func (m matchInt) Expr() string {
	return "[" + m.col + "] = ?"
}

func (m matchInt) Params() []interface{} {
	return []interface{}{m.match}
}

type or []Searcher

// Or returns a Searcher that matches for any of the given searchers
func Or(searchers ...Searcher) Searcher {
	return or(searchers)
}

func (o or) Expr() string {
	expr := "( "
	for n, searcher := range o {
		if n > 0 {
			expr += " OR "
		}
		expr += searcher.Expr()
	}
	expr += " )"
	return expr
}

func (o or) Params() []interface{} {
	p := make([]interface{}, 0, len(o))
	for _, searcher := range o {
		p = append(p, searcher.Params())
	}
	return p
}

// Search is used for a custom (non primary key) search on a table.
//
// Returns the number of items found and an error if any occurred.
func (s *Store) Search(data []Interface, offset int, params ...Searcher) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(data) == 0 {
		return 0, nil
	}
	table := tableName(data[0])
	cols := data[0].Get()
	vars := make([]string, 0, len(cols))
	first := true
	columns := ""
	for col := range cols {
		if first {
			first = false
		} else {
			columns += ", "
		}
		columns += "[" + col + "]"
		vars = append(vars, col)
	}
	var clause string
	paramVars := make([]interface{}, 0, len(params)+2)
	if len(params) > 0 {
		clause = "WHERE "
		first = true
		for _, param := range params {
			if first {
				first = false
			} else {
				clause += " AND "
			}
			clause += param.Expr()
			paramVars = append(paramVars, param.Params()...)
		}
	}
	var sortBy, dir string
	if s, ok := data[0].(sort); ok {
		sortBy = s.sortBy
		if s.asc {
			dir = "ASC"
		} else {
			dir = "DESC"
		}
	} else {
		sortBy = data[0].Key()
		dir = "ASC"
	}
	sql := "SELECT " + columns + " FROM [" + table + "] " + clause + " ORDER BY [" + sortBy + "] " + dir + " LIMIT ? OFFSET ?;"
	stmt, err := s.db.Query(sql, append(paramVars, len(data), offset)...)
	stmtVars := statement{Stmt: stmt, vars: vars}
	pos := 0
	for ; err == nil; err = stmt.Next() {
		if typeName := tableName(data[pos]); typeName != table {
			err = UnmatchedType{table, typeName}
		} else {
			err = stmtVars.Scan(stmtVars.Vars(data[pos].Get())...)
			pos++
		}
	}
	if err != nil && err != io.EOF {
		return pos, err
	}

	return pos, nil
}

// SearchCount performs the search and returns the number of results
func (s *Store) SearchCount(data Interface, params ...Searcher) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	table := tableName(data)
	first := true
	var clause string
	paramVars := make([]interface{}, 0, len(params))
	if len(params) > 0 {
		clause = "WHERE "
		for _, param := range params {
			if first {
				first = false
			} else {
				clause += " AND "
			}
			clause += param.Expr()
			paramVars = append(paramVars, param.Params()...)
		}
	}
	sql := "SELECT count(1) FROM [" + table + "] " + clause + ";"
	stmt, err := s.db.Query(sql, paramVars...)
	if err != nil {
		return 0, err
	}
	count := 0
	err = stmt.Scan(&count)
	if err != nil && err != io.EOF {
		return 0, err
	}
	return count, nil
}

//Errors

// UnknownColumn is an error that occurrs when a search parameter requires a
// column which does not exist for the given type.
type UnknownColumn string

func (u UnknownColumn) Error() string {
	return "unknown column: " + string(u)
}
<commit_msg>Added And searcher<commit_after>package store

import "io"

// Searcher is an interface for the different searcher params
type Searcher interface {
	// expr returns a sqlite snippet used in the WHERE clause.
	Expr() string
	// params returns the required parameters for the sqlite snippet.
	Params() []interface{}
}

// between is a searcher which searches for values between (inclusive) the
// given values.
type between struct {
	col      string
	from, to int
}

// Between returns a Searcher that looks for an integer between two values
func Between(column string, from, to int) Searcher {
	return between{column, from, to}
}

func (b between) Expr() string {
	return "[" + b.col + "] BETWEEN ? AND ?"
}

func (b between) Params() []interface{} {
	return []interface{}{b.from, b.to}
}

// like implements a search which uses the LIKE syntax in a WHERE clause.
type like struct {
	col, likeStr string
}

// Like returns a Searcher that looks for similar strings
func Like(column, likeStr string) Searcher {
	return like{column, likeStr}
}

func (l like) Expr() string {
	return "[" + l.col + "] LIKE ?"
}

func (l like) Params() []interface{} {
	return []interface{}{l.likeStr}
}

type notLike struct {
	col, notLikeStr string
}

// NotLike returns a Searcher that excludes results with similar strings
func NotLike(column, notLikeStr string) Searcher {
	return notLike{column, notLikeStr}
}

func (n notLike) Expr() string {
	return "[" + n.col + "] NOT LIKE ?"
}

func (n notLike) Params() []interface{} {
	return []interface{}{n.notLikeStr}
}

type matchString struct {
	col, match string
}

// MatchString searches for an exact (case-insensitive) string match on the given column
func MatchString(column, match string) Searcher {
	return matchString{column, match}
}

func (m matchString) Expr() string {
	return "[" + m.col + "] = ?"
}

func (m matchString) Params() []interface{} {
	return []interface{}{m.match}
}

type matchInt struct {
	col   string
	match int
}

// MatchInt searches for an exact integer match on the given column
func MatchInt(column string, match int) Searcher {
	return matchInt{column, match}
}

func (m matchInt) Expr() string {
	return "[" + m.col + "] = ?"
}

func (m matchInt) Params() []interface{} {
	return []interface{}{m.match}
}

type or []Searcher

// Or returns a Searcher that matches for any of the given searchers
func Or(searchers ...Searcher) Searcher {
	return or(searchers)
}

func (o or) Expr() string {
	expr := "( "
	for n, searcher := range o {
		if n > 0 {
			expr += " OR "
		}
		expr += searcher.Expr()
	}
	expr += " )"
	return expr
}

func (o or) Params() []interface{} {
	p := make([]interface{}, 0, len(o))
	for _, searcher := range o {
		p = append(p, searcher.Params())
	}
	return p
}

type and []Searcher

// And returns a Search that matches all of the given searches. Useful for
// within an Or Searcher
func And(searchers ...Searcher) Searcher {
	return and(searchers)
}

func (a and) Expr() string {
	expr := "( "
	for n, searcher := range a {
		if n > 0 {
			expr += " AND "
		}
		expr += searcher.Expr()
	}
	expr += " )"
	return expr
}

func (a and) Params() []interface{} {
	p := make([]interface{}, 0, len(a))
	for _, searcher := range a {
		p = append(p, searcher.Params())
	}
	return p
}

// Search is used for a custom (non primary key) search on a table.
//
// Returns the number of items found and an error if any occurred.
func (s *Store) Search(data []Interface, offset int, params ...Searcher) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(data) == 0 {
		return 0, nil
	}
	table := tableName(data[0])
	cols := data[0].Get()
	vars := make([]string, 0, len(cols))
	first := true
	columns := ""
	for col := range cols {
		if first {
			first = false
		} else {
			columns += ", "
		}
		columns += "[" + col + "]"
		vars = append(vars, col)
	}
	var clause string
	paramVars := make([]interface{}, 0, len(params)+2)
	if len(params) > 0 {
		clause = "WHERE "
		first = true
		for _, param := range params {
			if first {
				first = false
			} else {
				clause += " AND "
			}
			clause += param.Expr()
			paramVars = append(paramVars, param.Params()...)
		}
	}
	var sortBy, dir string
	if s, ok := data[0].(sort); ok {
		sortBy = s.sortBy
		if s.asc {
			dir = "ASC"
		} else {
			dir = "DESC"
		}
	} else {
		sortBy = data[0].Key()
		dir = "ASC"
	}
	sql := "SELECT " + columns + " FROM [" + table + "] " + clause + " ORDER BY [" + sortBy + "] " + dir + " LIMIT ? OFFSET ?;"
	stmt, err := s.db.Query(sql, append(paramVars, len(data), offset)...)
	stmtVars := statement{Stmt: stmt, vars: vars}
	pos := 0
	for ; err == nil; err = stmt.Next() {
		if typeName := tableName(data[pos]); typeName != table {
			err = UnmatchedType{table, typeName}
		} else {
			err = stmtVars.Scan(stmtVars.Vars(data[pos].Get())...)
			pos++
		}
	}
	if err != nil && err != io.EOF {
		return pos, err
	}

	return pos, nil
}

// SearchCount performs the search and returns the number of results
func (s *Store) SearchCount(data Interface, params ...Searcher) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	table := tableName(data)
	first := true
	var clause string
	paramVars := make([]interface{}, 0, len(params))
	if len(params) > 0 {
		clause = "WHERE "
		for _, param := range params {
			if first {
				first = false
			} else {
				clause += " AND "
			}
			clause += param.Expr()
			paramVars = append(paramVars, param.Params()...)
		}
	}
	sql := "SELECT count(1) FROM [" + table + "] " + clause + ";"
	stmt, err := s.db.Query(sql, paramVars...)
	if err != nil {
		return 0, err
	}
	count := 0
	err = stmt.Scan(&count)
	if err != nil && err != io.EOF {
		return 0, err
	}
	return count, nil
}

//Errors

// UnknownColumn is an error that occurrs when a search parameter requires a
// column which does not exist for the given type.
type UnknownColumn string

func (u UnknownColumn) Error() string {
	return "unknown column: " + string(u)
}
<|endoftext|>


<commit_before>package vlc

// #cgo LDFLAGS: -lvlc
// #include <vlc/vlc.h>
// #include <stdlib.h>
import "C"
import (
	"errors"
	"unsafe"
)

type Player struct {
	player *C.libvlc_media_player_t
	media  *Media
}

func (p *Player) Release() error {
	if p.player == nil {
		return nil
	}

	if p.media != nil {
		if err := p.media.Release(); err != nil {
			return err
		}

		p.media = nil
	}

	C.libvlc_media_player_release(p.player)
	return getError()
}

func (p *Player) Play() error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if p.IsPlaying() {
		return nil
	}

	if C.libvlc_media_player_play(p.player) < 0 {
		return getError()
	}

	return nil
}

func (p *Player) IsPlaying() bool {
	if p.player == nil {
		return false
	}

	return C.libvlc_media_player_is_playing(p.player) != 0
}

func (p *Player) Stop() error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if !p.IsPlaying() {
		return nil
	}

	C.libvlc_media_player_stop(p.player)
	return getError()
}

func (p *Player) Pause(pause bool) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	toggle := 0
	if pause {
		toggle = 1
	}

	C.libvlc_media_player_set_pause(p.player, C.int(toggle))
	return getError()
}

func (p *Player) Volume() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_audio_get_volume(p.player)), getError()
}

func (p *Player) SetVolume(volume int) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_audio_set_volume(p.player, C.int(volume))
	return getError()
}

func (p *Player) SetMedia(path string, local bool) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if p.media != nil {
		if err := p.media.Release(); err != nil {
			return err
		}

		p.media = nil
	}

	media, err := newMedia(path, local)
	if err != nil {
		return err
	}

	p.media = media
	C.libvlc_media_player_set_media(p.player, media.media)

	return getError()
}

func (p *Player) SetAudioOutput(output string) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	cOutput := C.CString(output)
	defer C.free(unsafe.Pointer(cOutput))

	if C.libvlc_audio_output_set(p.player, cOutput) != 0 {
		return getError()
	}

	return nil
}

// GetLength returns media length in milliseconds.
func (p *Player) MediaLength() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_media_player_get_length(p.player)), getError()
}

// MediaState returns the state of the current media.
func (p *Player) MediaState() (MediaState, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	state := int(C.libvlc_media_player_get_state(p.player))
	return MediaState(state), getError()
}

// GetPosition returns media position as a
// float percentage between 0.0 and 1.0.
func (p *Player) MediaPosition() (float32, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return float32(C.libvlc_media_player_get_position(p.player)), getError()
}

// SetPosition sets media position as percentage between 0.0 and 1.0.
// Some formats and protocols do not support this.
func (p *Player) SetMediaPosition(pos float32) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_media_player_set_position(p.player, C.float(pos))
	return getError()
}

// GetTime returns media time in milliseconds.
func (p *Player) MediaTime() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_media_player_get_time(p.player)), getError()
}

// SetTime sets the media time in milliseconds.
// Some formats and protocals do not support this.
func (p *Player) SetMediaTime(t int) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_media_player_set_time(p.player, C.libvlc_time_t(int64(t)))
	return getError()
}
<commit_msg>Update player functions documentation strings<commit_after>package vlc

// #cgo LDFLAGS: -lvlc
// #include <vlc/vlc.h>
// #include <stdlib.h>
import "C"
import (
	"errors"
	"unsafe"
)

type Player struct {
	player *C.libvlc_media_player_t
	media  *Media
}

func (p *Player) Release() error {
	if p.player == nil {
		return nil
	}

	if p.media != nil {
		if err := p.media.Release(); err != nil {
			return err
		}

		p.media = nil
	}

	C.libvlc_media_player_release(p.player)
	return getError()
}

func (p *Player) Play() error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if p.IsPlaying() {
		return nil
	}

	if C.libvlc_media_player_play(p.player) < 0 {
		return getError()
	}

	return nil
}

func (p *Player) IsPlaying() bool {
	if p.player == nil {
		return false
	}

	return C.libvlc_media_player_is_playing(p.player) != 0
}

func (p *Player) Stop() error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if !p.IsPlaying() {
		return nil
	}

	C.libvlc_media_player_stop(p.player)
	return getError()
}

func (p *Player) Pause(pause bool) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	toggle := 0
	if pause {
		toggle = 1
	}

	C.libvlc_media_player_set_pause(p.player, C.int(toggle))
	return getError()
}

func (p *Player) Volume() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_audio_get_volume(p.player)), getError()
}

func (p *Player) SetVolume(volume int) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_audio_set_volume(p.player, C.int(volume))
	return getError()
}

func (p *Player) SetMedia(path string, local bool) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	if p.media != nil {
		if err := p.media.Release(); err != nil {
			return err
		}

		p.media = nil
	}

	media, err := newMedia(path, local)
	if err != nil {
		return err
	}

	p.media = media
	C.libvlc_media_player_set_media(p.player, media.media)

	return getError()
}

func (p *Player) SetAudioOutput(output string) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	cOutput := C.CString(output)
	defer C.free(unsafe.Pointer(cOutput))

	if C.libvlc_audio_output_set(p.player, cOutput) != 0 {
		return getError()
	}

	return nil
}

// MediaLength returns media length in milliseconds.
func (p *Player) MediaLength() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_media_player_get_length(p.player)), getError()
}

// MediaState returns the state of the current media.
func (p *Player) MediaState() (MediaState, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	state := int(C.libvlc_media_player_get_state(p.player))
	return MediaState(state), getError()
}

// MediaPosition returns media position as a
// float percentage between 0.0 and 1.0.
func (p *Player) MediaPosition() (float32, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return float32(C.libvlc_media_player_get_position(p.player)), getError()
}

// SetMediaPosition sets media position as percentage between 0.0 and 1.0.
// Some formats and protocols do not support this.
func (p *Player) SetMediaPosition(pos float32) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_media_player_set_position(p.player, C.float(pos))
	return getError()
}

// MediaTime returns media time in milliseconds.
func (p *Player) MediaTime() (int, error) {
	if p.player == nil {
		return 0, errors.New("A player must first be initialized")
	}

	return int(C.libvlc_media_player_get_time(p.player)), getError()
}

// SetMediaTime sets the media time in milliseconds.
// Some formats and protocals do not support this.
func (p *Player) SetMediaTime(t int) error {
	if p.player == nil {
		return errors.New("A player must first be initialized")
	}

	C.libvlc_media_player_set_time(p.player, C.libvlc_time_t(int64(t)))
	return getError()
}
<|endoftext|>


<commit_before>package main

import (
	"container/heap"
	"errors"
	"fmt"
)

type player struct {
	LOS         map[position]bool
	Rays        rayMap
	Pos         position
	HP          int
	MP          int
	Consumables map[consumable]int
	Gold        int
	Target      position
	Statuses    map[status]int
	Armour      armour
	Weapon      weapon
	Shield      shield
	Aptitudes   map[aptitude]bool
	Rods        map[rod]*rodProps
}

func (p *player) HPMax() int {
	hpmax := 40
	if p.Aptitudes[AptHealthy] {
		hpmax += 10
	}
	return hpmax
}

func (p *player) MPMax() int {
	mpmax := 10
	if p.Aptitudes[AptMagic] {
		mpmax += 5
	}
	return mpmax
}

func (p *player) Accuracy() int {
	acc := 15
	if p.Aptitudes[AptAccurate] {
		acc += 3
	}
	return acc
}

func (p *player) Armor() int {
	ar := 0
	switch p.Armour {
	case LeatherArmour:
		ar += 3
	case ChainMail:
		ar += 4
	case PlateArmour:
		ar += 6
	}
	if p.Aptitudes[AptScales] {
		ar += 2
	}
	if p.HasStatus(StatusLignification) {
		ar = 8 + ar/2
	}
	if p.HasStatus(StatusCorrosion) {
		ar -= 2 * p.Statuses[StatusCorrosion]
		if ar < 0 {
			ar = 0
		}
	}
	return ar
}

func (p *player) Attack() int {
	attack := p.Weapon.Attack()
	if p.Aptitudes[AptStrong] {
		attack += attack / 5
	}
	if p.HasStatus(StatusCorrosion) {
		penalty := p.Statuses[StatusCorrosion]
		if penalty > 5 {
			penalty = 5
		}
		attack -= penalty
	}
	return attack
}

func (p *player) Block() int {
	block := p.Shield.Block()
	if p.HasStatus(StatusDisabledShield) {
		block /= 3
	}
	return block
}

func (p *player) Evasion() int {
	ev := 15
	if p.Aptitudes[AptAgile] {
		ev += 3
	}
	if p.HasStatus(StatusAgile) {
		ev += 5
	}
	return ev
}

func (p *player) HasStatus(st status) bool {
	return p.Statuses[st] > 0
}

func (p *player) AptitudeCount() int {
	count := 0
	for _, b := range p.Aptitudes {
		if b {
			count++
		}
	}
	return count
}

func (g *game) AutoToDir(ev event) bool {
	if g.MonsterInLOS() == nil {
		err := g.MovePlayer(g.Player.Pos.To(*g.AutoDir), ev)
		if err != nil {
			g.Print(err.Error())
			g.AutoDir = nil
			return false
		}
		return true
	}
	g.AutoDir = nil
	return false
}

func (g *game) GoToDir(dir direction, ev event) error {
	if g.MonsterInLOS() != nil {
		g.AutoDir = nil
		return errors.New("You cannot travel while there are monsters in view.")
	}
	err := g.MovePlayer(g.Player.Pos.To(dir), ev)
	if err != nil {
		return err
	}
	g.AutoDir = &dir
	return nil
}

func (g *game) MoveToTarget(ev event) bool {
	if g.MonsterInLOS() == nil {
		path := g.PlayerPath(g.Player.Pos, *g.AutoTarget)
		if len(path) > 1 {
			err := g.MovePlayer(path[len(path)-2], ev)
			if err != nil {
				g.Print(err.Error())
				g.AutoTarget = nil
				return false
			}
			return true
		}
	}
	g.AutoTarget = nil
	return false
}

func (g *game) WaitTurn(ev event) {
	// XXX Really wait for 10 ?
	g.ScummingAction(ev)
	ev.Renew(g, 10)
}

func (g *game) ExistsMonster() bool {
	for _, mons := range g.Monsters {
		if mons.Exists() {
			return true
		}
	}
	return false
}

func (g *game) ScummingAction(ev event) {
	if g.Player.HP == g.Player.HPMax() && g.Player.MP == g.Player.MPMax() {
		g.Scumming++
	}
	if g.Scumming == 100 {
		if g.ExistsMonster() {
			g.Print("You feel a little bored.")
		}
	}
	if g.Scumming > 120 {
		if !g.ExistsMonster() {
			g.Scumming = 0
			return
		}
		g.Player.HP = g.Player.HP / 2
		if RandInt(2) == 0 {
			g.MakeNoise(100, g.Player.Pos)
			neighbors := g.Dungeon.Neighbors(g.Player.Pos)
			for _, pos := range neighbors {
				if RandInt(3) != 0 {
					g.Dungeon.SetCell(pos, FreeCell)
				}
			}
			g.Print("You hear a terrible explosion coming from the ground. You are lignified.")
			g.Player.Statuses[StatusLignification]++
			heap.Push(g.Events, &simpleEvent{ERank: ev.Rank() + 240 + RandInt(10), EAction: LignificationEnd})
		} else {
			delay := 20 + RandInt(5)
			g.Player.Statuses[StatusTele]++
			heap.Push(g.Events, &simpleEvent{ERank: ev.Rank() + delay, EAction: Teleportation})
			g.Print("Something hurt you! You feel unstable.")
		}
		g.Scumming = 0
	}
}

func (g *game) FairAction() {
	g.Scumming -= 10
	if g.Scumming < 0 {
		g.Scumming = 0
	}
}

func (g *game) Rest(ev event) error {
	if g.MonsterInLOS() != nil {
		return fmt.Errorf("You cannot sleep while monsters are in view.")
	}
	if g.Player.HP == g.Player.HPMax() && g.Player.MP == g.Player.MPMax() && !g.Player.HasStatus(StatusExhausted) &&
		!g.Player.HasStatus(StatusConfusion) && !g.Player.HasStatus(StatusLignification) {
		return errors.New("You do not need to rest.")
	}
	g.WaitTurn(ev)
	g.Resting = true
	return nil
}

func (g *game) Equip(ev event) error {
	if eq, ok := g.Equipables[g.Player.Pos]; ok {
		eq.Equip(g)
		ev.Renew(g, 10)
		return nil
	}
	return errors.New("Found nothing to equip here.")
}

func (g *game) Teleportation(ev event) {
	var pos position
	i := 0
	count := 0
	for {
		count++
		if count > 1000 {
			panic("Teleportation")
		}
		pos = g.FreeCell()
		if pos.Distance(g.Player.Pos) < 15 && i < 1000 {
			i++
			continue
		}
		break

	}
	g.Player.Statuses[StatusTele]--
	if g.Dungeon.Valid(pos) {
		// should always happen
		g.Player.Pos = pos
		g.Print("You feel yourself teleported away.")
		g.ComputeLOS()
		g.MakeMonstersAware()
	} else {
		g.Print("Something went wrong with the teleportation.")
	}
}

func (g *game) MovePlayer(pos position, ev event) error {
	if !g.Dungeon.Valid(pos) || g.Dungeon.Cell(pos).T == WallCell {
		return errors.New("You cannot move there.")
	}
	if g.Player.HasStatus(StatusConfusion) {
		switch pos.Dir(g.Player.Pos) {
		case E, N, W, S:
		default:
			return errors.New("You cannot use diagonal movements while confused.")
		}
	}
	delay := 10
	switch g.Dungeon.Cell(pos).T {
	case FreeCell:
		mons, _ := g.MonsterAt(pos)
		if !mons.Exists() {
			if g.Player.HasStatus(StatusLignification) {
				return errors.New("You cannot move while lignified")
			}
			g.Player.Pos = pos
			if g.Gold[pos] > 0 {
				g.Player.Gold += g.Gold[pos]
				delete(g.Gold, pos)
			}
			if c, ok := g.Collectables[pos]; ok && c != nil {
				g.Player.Consumables[c.Consumable] += c.Quantity
				delete(g.Collectables, pos)
				if c.Quantity > 1 {
					g.Printf("You take %d %s.", c.Quantity, c.Consumable.Plural())
				} else {
					g.Printf("You take %s.", Indefinite(c.Consumable.String(), false))
				}
			}
			if r, ok := g.Rods[pos]; ok {
				g.Player.Rods[r] = &rodProps{Charge: r.MaxCharge() - 1}
				delete(g.Rods, pos)
				g.Printf("You take a %s.", r)
				g.StoryPrintf("You found and took a %s.", r)
			}
			g.ComputeLOS()
			if g.Autoexploring {
				mons := g.MonsterInLOS()
				if mons.Exists() {
					g.Printf("You see %s (%v).", Indefinite(mons.Kind.String(), false), mons.State)
				}
				g.FairAction()
			} else {
				g.ScummingAction(ev)
			}
			g.MakeMonstersAware()
			if g.Player.Aptitudes[AptFast] {
				// only fast for movement
				delay -= 2
			}
			if g.Player.HasStatus(StatusSwift) {
				// only fast for movement
				delay -= 3
			}
		} else {
			g.FairAction()
			g.AttackMonster(mons)
		}
	}
	if g.Player.HasStatus(StatusBerserk) {
		delay -= 3
	}
	if g.Player.HasStatus(StatusSlow) {
		delay += 3
	}
	ev.Renew(g, delay)
	return nil
}

func (g *game) HealPlayer(ev event) {
	if g.Player.HP < g.Player.HPMax() {
		g.Player.HP++
	}
	delay := 50
	if g.Player.Aptitudes[AptRegen] {
		delay = 25
	}
	ev.Renew(g, delay)
}

func (g *game) MPRegen(ev event) {
	if g.Player.MP < g.Player.MPMax() {
		g.Player.MP++
	}
	delay := 100
	ev.Renew(g, delay)
}
<commit_msg>make lignification a little better<commit_after>package main

import (
	"container/heap"
	"errors"
	"fmt"
)

type player struct {
	LOS         map[position]bool
	Rays        rayMap
	Pos         position
	HP          int
	MP          int
	Consumables map[consumable]int
	Gold        int
	Target      position
	Statuses    map[status]int
	Armour      armour
	Weapon      weapon
	Shield      shield
	Aptitudes   map[aptitude]bool
	Rods        map[rod]*rodProps
}

func (p *player) HPMax() int {
	hpmax := 40
	if p.Aptitudes[AptHealthy] {
		hpmax += 10
	}
	return hpmax
}

func (p *player) MPMax() int {
	mpmax := 10
	if p.Aptitudes[AptMagic] {
		mpmax += 5
	}
	return mpmax
}

func (p *player) Accuracy() int {
	acc := 15
	if p.Aptitudes[AptAccurate] {
		acc += 3
	}
	return acc
}

func (p *player) Armor() int {
	ar := 0
	switch p.Armour {
	case LeatherArmour:
		ar += 3
	case ChainMail:
		ar += 4
	case PlateArmour:
		ar += 6
	}
	if p.Aptitudes[AptScales] {
		ar += 2
	}
	if p.HasStatus(StatusLignification) {
		ar = 9 + ar/2
	}
	if p.HasStatus(StatusCorrosion) {
		ar -= 2 * p.Statuses[StatusCorrosion]
		if ar < 0 {
			ar = 0
		}
	}
	return ar
}

func (p *player) Attack() int {
	attack := p.Weapon.Attack()
	if p.Aptitudes[AptStrong] {
		attack += attack / 5
	}
	if p.HasStatus(StatusCorrosion) {
		penalty := p.Statuses[StatusCorrosion]
		if penalty > 5 {
			penalty = 5
		}
		attack -= penalty
	}
	return attack
}

func (p *player) Block() int {
	block := p.Shield.Block()
	if p.HasStatus(StatusDisabledShield) {
		block /= 3
	}
	return block
}

func (p *player) Evasion() int {
	ev := 15
	if p.Aptitudes[AptAgile] {
		ev += 3
	}
	if p.HasStatus(StatusAgile) {
		ev += 5
	}
	return ev
}

func (p *player) HasStatus(st status) bool {
	return p.Statuses[st] > 0
}

func (p *player) AptitudeCount() int {
	count := 0
	for _, b := range p.Aptitudes {
		if b {
			count++
		}
	}
	return count
}

func (g *game) AutoToDir(ev event) bool {
	if g.MonsterInLOS() == nil {
		err := g.MovePlayer(g.Player.Pos.To(*g.AutoDir), ev)
		if err != nil {
			g.Print(err.Error())
			g.AutoDir = nil
			return false
		}
		return true
	}
	g.AutoDir = nil
	return false
}

func (g *game) GoToDir(dir direction, ev event) error {
	if g.MonsterInLOS() != nil {
		g.AutoDir = nil
		return errors.New("You cannot travel while there are monsters in view.")
	}
	err := g.MovePlayer(g.Player.Pos.To(dir), ev)
	if err != nil {
		return err
	}
	g.AutoDir = &dir
	return nil
}

func (g *game) MoveToTarget(ev event) bool {
	if g.MonsterInLOS() == nil {
		path := g.PlayerPath(g.Player.Pos, *g.AutoTarget)
		if len(path) > 1 {
			err := g.MovePlayer(path[len(path)-2], ev)
			if err != nil {
				g.Print(err.Error())
				g.AutoTarget = nil
				return false
			}
			return true
		}
	}
	g.AutoTarget = nil
	return false
}

func (g *game) WaitTurn(ev event) {
	// XXX Really wait for 10 ?
	g.ScummingAction(ev)
	ev.Renew(g, 10)
}

func (g *game) ExistsMonster() bool {
	for _, mons := range g.Monsters {
		if mons.Exists() {
			return true
		}
	}
	return false
}

func (g *game) ScummingAction(ev event) {
	if g.Player.HP == g.Player.HPMax() && g.Player.MP == g.Player.MPMax() {
		g.Scumming++
	}
	if g.Scumming == 100 {
		if g.ExistsMonster() {
			g.Print("You feel a little bored.")
		}
	}
	if g.Scumming > 120 {
		if !g.ExistsMonster() {
			g.Scumming = 0
			return
		}
		g.Player.HP = g.Player.HP / 2
		if RandInt(2) == 0 {
			g.MakeNoise(100, g.Player.Pos)
			neighbors := g.Dungeon.Neighbors(g.Player.Pos)
			for _, pos := range neighbors {
				if RandInt(3) != 0 {
					g.Dungeon.SetCell(pos, FreeCell)
				}
			}
			g.Print("You hear a terrible explosion coming from the ground. You are lignified.")
			g.Player.Statuses[StatusLignification]++
			heap.Push(g.Events, &simpleEvent{ERank: ev.Rank() + 240 + RandInt(10), EAction: LignificationEnd})
		} else {
			delay := 20 + RandInt(5)
			g.Player.Statuses[StatusTele]++
			heap.Push(g.Events, &simpleEvent{ERank: ev.Rank() + delay, EAction: Teleportation})
			g.Print("Something hurt you! You feel unstable.")
		}
		g.Scumming = 0
	}
}

func (g *game) FairAction() {
	g.Scumming -= 10
	if g.Scumming < 0 {
		g.Scumming = 0
	}
}

func (g *game) Rest(ev event) error {
	if g.MonsterInLOS() != nil {
		return fmt.Errorf("You cannot sleep while monsters are in view.")
	}
	if g.Player.HP == g.Player.HPMax() && g.Player.MP == g.Player.MPMax() && !g.Player.HasStatus(StatusExhausted) &&
		!g.Player.HasStatus(StatusConfusion) && !g.Player.HasStatus(StatusLignification) {
		return errors.New("You do not need to rest.")
	}
	g.WaitTurn(ev)
	g.Resting = true
	return nil
}

func (g *game) Equip(ev event) error {
	if eq, ok := g.Equipables[g.Player.Pos]; ok {
		eq.Equip(g)
		ev.Renew(g, 10)
		return nil
	}
	return errors.New("Found nothing to equip here.")
}

func (g *game) Teleportation(ev event) {
	var pos position
	i := 0
	count := 0
	for {
		count++
		if count > 1000 {
			panic("Teleportation")
		}
		pos = g.FreeCell()
		if pos.Distance(g.Player.Pos) < 15 && i < 1000 {
			i++
			continue
		}
		break

	}
	g.Player.Statuses[StatusTele]--
	if g.Dungeon.Valid(pos) {
		// should always happen
		g.Player.Pos = pos
		g.Print("You feel yourself teleported away.")
		g.ComputeLOS()
		g.MakeMonstersAware()
	} else {
		g.Print("Something went wrong with the teleportation.")
	}
}

func (g *game) MovePlayer(pos position, ev event) error {
	if !g.Dungeon.Valid(pos) || g.Dungeon.Cell(pos).T == WallCell {
		return errors.New("You cannot move there.")
	}
	if g.Player.HasStatus(StatusConfusion) {
		switch pos.Dir(g.Player.Pos) {
		case E, N, W, S:
		default:
			return errors.New("You cannot use diagonal movements while confused.")
		}
	}
	delay := 10
	switch g.Dungeon.Cell(pos).T {
	case FreeCell:
		mons, _ := g.MonsterAt(pos)
		if !mons.Exists() {
			if g.Player.HasStatus(StatusLignification) {
				return errors.New("You cannot move while lignified")
			}
			g.Player.Pos = pos
			if g.Gold[pos] > 0 {
				g.Player.Gold += g.Gold[pos]
				delete(g.Gold, pos)
			}
			if c, ok := g.Collectables[pos]; ok && c != nil {
				g.Player.Consumables[c.Consumable] += c.Quantity
				delete(g.Collectables, pos)
				if c.Quantity > 1 {
					g.Printf("You take %d %s.", c.Quantity, c.Consumable.Plural())
				} else {
					g.Printf("You take %s.", Indefinite(c.Consumable.String(), false))
				}
			}
			if r, ok := g.Rods[pos]; ok {
				g.Player.Rods[r] = &rodProps{Charge: r.MaxCharge() - 1}
				delete(g.Rods, pos)
				g.Printf("You take a %s.", r)
				g.StoryPrintf("You found and took a %s.", r)
			}
			g.ComputeLOS()
			if g.Autoexploring {
				mons := g.MonsterInLOS()
				if mons.Exists() {
					g.Printf("You see %s (%v).", Indefinite(mons.Kind.String(), false), mons.State)
				}
				g.FairAction()
			} else {
				g.ScummingAction(ev)
			}
			g.MakeMonstersAware()
			if g.Player.Aptitudes[AptFast] {
				// only fast for movement
				delay -= 2
			}
			if g.Player.HasStatus(StatusSwift) {
				// only fast for movement
				delay -= 3
			}
		} else {
			g.FairAction()
			g.AttackMonster(mons)
		}
	}
	if g.Player.HasStatus(StatusBerserk) {
		delay -= 3
	}
	if g.Player.HasStatus(StatusSlow) {
		delay += 3
	}
	ev.Renew(g, delay)
	return nil
}

func (g *game) HealPlayer(ev event) {
	if g.Player.HP < g.Player.HPMax() {
		g.Player.HP++
	}
	delay := 50
	if g.Player.Aptitudes[AptRegen] {
		delay = 25
	}
	ev.Renew(g, delay)
}

func (g *game) MPRegen(ev event) {
	if g.Player.MP < g.Player.MPMax() {
		g.Player.MP++
	}
	delay := 100
	ev.Renew(g, delay)
}
<|endoftext|>


<commit_before>package yorm

import (
	"bytes"
	"database/sql"
	"reflect"
	"strings"
)

type sqlScanner interface {
	Scan(dest ...interface{}) error
}

//Select query records(s) from a table.
func Select(i interface{}, condition string, args ...interface{}) error {
	return defaultExecutor.Select(i, condition, args...)
}

//SelectByPK select by pk.
func SelectByPK(i interface{}, tableName ...string) error {
	return defaultExecutor.SelectByPK(i, tableName...)
}

// select by the primary key,the table name param means you can select from other tables
func (ex *executor) SelectByPK(i interface{}, tableName ...string) error {
	if !reflect.ValueOf(i).IsValid() {
		return ErrNotSupported
	}
	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	queryClause := buildSelectSql(q, tableName...)
	queryClause.WriteString("WHERE ")
	queryClause.WriteString(q.pkColumn.name)
	queryClause.WriteString("=?")
	return ex.query(i, queryClause.String(), reflect.ValueOf(i).Elem().FieldByName(q.pkColumn.fieldName).Int())
}

//Query do a select operation.
// if the is a struct ,you need not write select x,y,z,you need only write the where condition ...
func (ex *executor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}
	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ex.query(i, condition, args...)
	}

	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

func buildSelectSql(q *tableSetter, tableName ...string) *bytes.Buffer {
	queryClause := bytes.NewBufferString("SELECT ")
	splitDot := ","
	for loop := 0; loop < len(q.columns); loop++ {
		if loop == len(q.columns)-1 {
			splitDot = " "
		}
		queryClause.WriteString(q.columns[loop].name)
		queryClause.WriteString(splitDot)
	}
	queryClause.WriteString("FROM ")
	queryClause.WriteString(append(tableName, q.table)[0])
	queryClause.WriteString(" ")
	return queryClause
}

//Query do a query operation.
func (ex *executor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()
	var err error
	var stmt *sql.Stmt
	stmt, err = ex.getStmt(query)
	if stmt == nil {
		return err
	}
	if typ.Kind() == reflect.Slice {
		rows, err := stmt.Query(args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, stmt.QueryRow(args...))

}

func queryOne(i interface{}, row *sql.Row) error {
	if row == nil {
		return ErrIllegalParams
	}
	return convertAssignRow(i, row)
}
func queryList(i interface{}, rows *sql.Rows) error {
	if rows == nil {
		return ErrIllegalParams
	}
	return convertAssignRows(i, rows)
}

func convertAssignRows(i interface{}, rows *sql.Rows) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()
	if typ.Kind() != reflect.Slice {
		return ErrNonSlice
	}
	typ = typ.Elem()
	var q *tableSetter
	var err error
	if typ.Kind() == reflect.Struct {
		q, err = newTableSetter(reflect.New(typ))
		if q == nil {
			return err
		}
	}
	size := 0
	v := reflect.Indirect(reflect.ValueOf(i))
	ti := newPtrInterface(typ)
	for rows.Next() {
		if size >= v.Cap() {
			newCap := v.Cap()
			if newCap == 0 {
				newCap = 1
			} else {
				if newCap < 1024 {
					newCap += newCap
				} else {
					newCap += newCap / 4
				}
			}
			nv := reflect.MakeSlice(v.Type(), v.Len(), newCap)
			reflect.Copy(nv, v)
			v.Set(nv)
		}
		if size >= v.Len() {
			v.SetLen(size + 1)
		}
		st := reflect.New(typ)
		st = st.Elem()
		if q != nil {
			err := scanValue(rows, q, st)
			if err != nil {
				return err
			}
		} else {
			rows.Scan(ti)
			st.Set(reflect.ValueOf(ti).Elem())
		}
		v.Index(size).Set(st)
		size++
	}
	return nil
}
func convertAssignRow(i interface{}, row *sql.Row) error {
	typ := reflect.TypeOf(i)

	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() != reflect.Struct {
		return row.Scan(i)
	}

	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	st := reflect.ValueOf(i).Elem()
	return scanValue(row, q, st)
}
<commit_msg>sql 优化<commit_after>package yorm

import (
	"bytes"
	"database/sql"
	"reflect"
	"strings"
)

type sqlScanner interface {
	Scan(dest ...interface{}) error
}

//Select query records(s) from a table.
func Select(i interface{}, condition string, args ...interface{}) error {
	return defaultExecutor.Select(i, condition, args...)
}

//SelectByPK select by pk.
func SelectByPK(i interface{}, tableName ...string) error {
	return defaultExecutor.SelectByPK(i, tableName...)
}

// select by the primary key,the table name param means you can select from other tables
func (ex *executor) SelectByPK(i interface{}, tableName ...string) error {
	if !reflect.ValueOf(i).IsValid() {
		return ErrNotSupported
	}
	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	queryClause := buildSelectSql(q, tableName...)
	queryClause.WriteString("WHERE ")
	queryClause.WriteString(q.pkColumn.name)
	queryClause.WriteString("=? LIMIT 1")
	return ex.query(i, queryClause.String(), reflect.ValueOf(i).Elem().FieldByName(q.pkColumn.fieldName).Int())
}

//Query do a select operation.
// if the is a struct ,you need not write select x,y,z,you need only write the where condition ...
func (ex *executor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}
	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ex.query(i, condition, args...)
	}

	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

func buildSelectSql(q *tableSetter, tableName ...string) *bytes.Buffer {
	queryClause := bytes.NewBufferString("SELECT ")
	splitDot := ","
	for loop := 0; loop < len(q.columns); loop++ {
		if loop == len(q.columns)-1 {
			splitDot = " "
		}
		queryClause.WriteString(q.columns[loop].name)
		queryClause.WriteString(splitDot)
	}
	queryClause.WriteString("FROM ")
	queryClause.WriteString(append(tableName, q.table)[0])
	queryClause.WriteString(" ")
	return queryClause
}

//Query do a query operation.
func (ex *executor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()
	var err error
	var stmt *sql.Stmt
	stmt, err = ex.getStmt(query)
	if stmt == nil {
		return err
	}
	if typ.Kind() == reflect.Slice {
		rows, err := stmt.Query(args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, stmt.QueryRow(args...))

}

func queryOne(i interface{}, row *sql.Row) error {
	if row == nil {
		return ErrIllegalParams
	}
	return convertAssignRow(i, row)
}
func queryList(i interface{}, rows *sql.Rows) error {
	if rows == nil {
		return ErrIllegalParams
	}
	return convertAssignRows(i, rows)
}

func convertAssignRows(i interface{}, rows *sql.Rows) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()
	if typ.Kind() != reflect.Slice {
		return ErrNonSlice
	}
	typ = typ.Elem()
	var q *tableSetter
	var err error
	if typ.Kind() == reflect.Struct {
		q, err = newTableSetter(reflect.New(typ))
		if q == nil {
			return err
		}
	}
	size := 0
	v := reflect.Indirect(reflect.ValueOf(i))
	ti := newPtrInterface(typ)
	for rows.Next() {
		if size >= v.Cap() {
			newCap := v.Cap()
			if newCap == 0 {
				newCap = 1
			} else {
				if newCap < 1024 {
					newCap += newCap
				} else {
					newCap += newCap / 4
				}
			}
			nv := reflect.MakeSlice(v.Type(), v.Len(), newCap)
			reflect.Copy(nv, v)
			v.Set(nv)
		}
		if size >= v.Len() {
			v.SetLen(size + 1)
		}
		st := reflect.New(typ)
		st = st.Elem()
		if q != nil {
			err := scanValue(rows, q, st)
			if err != nil {
				return err
			}
		} else {
			rows.Scan(ti)
			st.Set(reflect.ValueOf(ti).Elem())
		}
		v.Index(size).Set(st)
		size++
	}
	return nil
}
func convertAssignRow(i interface{}, row *sql.Row) error {
	typ := reflect.TypeOf(i)

	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() != reflect.Struct {
		return row.Scan(i)
	}

	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	st := reflect.ValueOf(i).Elem()
	return scanValue(row, q, st)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"
)

var DEBUG = false
var if_bind *string
var apps_target *string
var management_target *string
var apps_proxy *httputil.ReverseProxy
var management_proxy *httputil.ReverseProxy

func defaultHandler(w http.ResponseWriter, req *http.Request) {
	if DEBUG {
		fmt.Printf("[%v] %+v\n", time.Now(), req)
	}
	ext := path.Ext(req.URL.Path)
	if last := len(req.URL.Path); ext == "" && req.URL.Path[last-1:] != "/" {
		req.URL.Path = req.URL.Path + "/"
	}
	if strings.HasPrefix(req.URL.String(), "/protonet/") {
		management_proxy.ServeHTTP(w, req)
	} else {
		apps_proxy.ServeHTTP(w, req)
	}
}

func main() {
	if_bind = flag.String("interface", "127.0.0.1:3001", "server interface to bind")
	apps_target = flag.String("apps", "http://127.0.0.1:8080", "target URL for apps reverse proxy")
	management_target = flag.String("management", "http://127.0.0.1:8081", "target URL for management reverse proxy")
	flag.Parse()

	fmt.Printf("Interface:      %v\n", *if_bind)
	fmt.Printf("Apps-Url:       %v\n", *apps_target)
	fmt.Printf("Management-Url: %v\n", *management_target)

	apps_target_url, _ := url.Parse(*apps_target)
	management_target_url, _ := url.Parse(*management_target)

	apps_proxy = httputil.NewSingleHostReverseProxy(apps_target_url)
	management_proxy = httputil.NewSingleHostReverseProxy(management_target_url)

	go func() {
		signal_chan := make(chan os.Signal, 10)
		signal.Notify(signal_chan, syscall.SIGUSR1)
		for true {
			<-signal_chan
			DEBUG = !DEBUG
			fmt.Printf("Set debug to %v.\n", DEBUG)
		}
	}()

	http.HandleFunc("/", defaultHandler)
	err := http.ListenAndServe(*if_bind, nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>always redirect with trailing slash<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"
)

var DEBUG = false
var if_bind *string
var apps_target *string
var management_target *string
var apps_proxy *httputil.ReverseProxy
var management_proxy *httputil.ReverseProxy

func defaultHandler(w http.ResponseWriter, req *http.Request) {
	if DEBUG {
		fmt.Printf("[%v] %+v\n", time.Now(), req)
	}
	ext := path.Ext(req.URL.Path)
	if last := len(req.URL.Path); ext == "" && req.URL.Path[last-1:] != "/" {
		url := req.URL.Path + "/" // Always redirect with trailing slash
		http.Redirect(w, req, url, http.StatusMovedPermanently)
	} else if strings.HasPrefix(req.URL.String(), "/admin/") {
		management_proxy.ServeHTTP(w, req)
	} else {
		apps_proxy.ServeHTTP(w, req)
	}
}

func main() {
	if_bind = flag.String("interface", "127.0.0.1:3001", "server interface to bind")
	apps_target = flag.String("apps", "http://127.0.0.1:8080", "target URL for apps reverse proxy")
	management_target = flag.String("management", "http://127.0.0.1:8081", "target URL for management reverse proxy")
	flag.Parse()

	fmt.Printf("Interface:      %v\n", *if_bind)
	fmt.Printf("Apps-Url:       %v\n", *apps_target)
	fmt.Printf("Management-Url: %v\n", *management_target)

	apps_target_url, _ := url.Parse(*apps_target)
	management_target_url, _ := url.Parse(*management_target)

	apps_proxy = httputil.NewSingleHostReverseProxy(apps_target_url)
	management_proxy = httputil.NewSingleHostReverseProxy(management_target_url)

	go func() {
		signal_chan := make(chan os.Signal, 10)
		signal.Notify(signal_chan, syscall.SIGUSR1)
		for true {
			<-signal_chan
			DEBUG = !DEBUG
			fmt.Printf("Set debug to %v.\n", DEBUG)
		}
	}()

	http.HandleFunc("/", defaultHandler)
	err := http.ListenAndServe(*if_bind, nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package quic

type Server struct {
	St      *Transport
	clients []*Client
}

func (self *Server) FramePacket(frames []*Frame) {}

func (self *Server) PublicResetPacket() {}

func (self *Server) VersionNegotiationPacket() {}

func (self *Server) checkProposedVersion(prppVersion uint32) bool {
	// compare the proposed version to lists
	return true
}
<commit_msg>implement loop for waiting client's connection<commit_after>package quic

import (
	"github.com/ami-GS/gQUIC/utils"
)

type Server struct {
	St              *Transport
	Clients         map[uint64]*Client
	SupportVersions []uint32
}

func NewServer() (*Server, error) {
	st, err := NewTransport("cert", "key")
	if err != nil {
		return nil, err
	}
	return &Server{
		St:      st,
		Clients: make(map[uint64]*Client),
	}, nil
}

func (self *Server) ListenAndServe(addPair string) error {
	udpAddr, err := utils.ParseAddressPair(addPair)
	if err != nil {
		return err
	}

	err = self.St.Listen(udpAddr)
	if err != nil {
		return err
	}

	for {
		p, _, rAddr, err := self.St.Recv()
		if err != nil {
			break
		}
		client, ok := self.Clients[p.GetConnectionID()]
		if ok {
			client.RecvChan <- p
		} else {
			client, err = NewClient(true) // true stands for server side object
			if err != nil {
				break
			}
			client.Conn, err = NewConnection(rAddr)
			client.Conn.ConnectionID = p.GetConnectionID()
			if err != nil {
				break
			}
			self.Clients[p.GetConnectionID()] = client
			go client.ReadLoop()
			client.RecvChan <- p
		}
	}

	return err
}

func (self *Server) FramePacket(frames []*Frame) {}

func (self *Server) PublicResetPacket() {}

func (self *Server) VersionNegotiationPacket() {}

func (self *Server) checkProposedVersion(prppVersion uint32) bool {
	// compare the proposed version to lists
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
	"os"
"github.com/molejs/mole-server/mole"
)

func getenv(k, defaultVal string) string {
	v := os.Getenv(k)
	if v == "" {
		v = defaultVal
	}

	return v
}

func main() {
	gin.SetMode(gin.ReleaseMode)

	var (
		r            = gin.Default()
		addr         = getenv("MOLE_ADDR", ":8080")
		cert         = os.Getenv("MOLE_CERT")
		key          = os.Getenv("MOLE_KEY")
		mongoAddr    = getenv("MOLE_MONGO_ADDR", "127.0.0.1:27017")
		dbName       = getenv("MOLE_DB_NAME", "mole")
		dbMiddleware = mole.DatabaseMiddleware(mongoAddr, dbName)
	)

	r.POST("/logs", dbMiddleware, mole.ReportHandler)
	r.GET("/logs", dbMiddleware, mole.RetrieveHandler)

	if cert != "" && key != "" {
		r.RunTLS(addr, cert, key)
	} else {
		r.Run(addr)
	}
}
<commit_msg>Add CORS<commit_after>package main

import (
	"github.com/gin-gonic/gin"
	"github.com/itsjamie/gin-cors"
	"github.com/molejs/mole-server/mole"
	"os"
	"time"
)

func getenv(k, defaultVal string) string {
	v := os.Getenv(k)
	if v == "" {
		v = defaultVal
	}

	return v
}

func main() {
	gin.SetMode(gin.ReleaseMode)

	var (
		r            = gin.Default()
		addr         = getenv("MOLE_ADDR", ":8080")
		cert         = os.Getenv("MOLE_CERT")
		key          = os.Getenv("MOLE_KEY")
		mongoAddr    = getenv("MOLE_MONGO_ADDR", "127.0.0.1:27017")
		dbName       = getenv("MOLE_DB_NAME", "mole")
		dbMiddleware = mole.DatabaseMiddleware(mongoAddr, dbName)
	)

	r.Use(cors.Middleware(cors.Config{
		Origins:         "*",
		Methods:         "PUT, POST",
		RequestHeaders:  "Origin, Authorization, Content-Type",
		ExposedHeaders:  "",
		MaxAge:          50 * time.Second,
		Credentials:     false,
		ValidateHeaders: false,
	}))

	r.POST("/logs", dbMiddleware, mole.ReportHandler)
	r.GET("/logs", dbMiddleware, mole.RetrieveHandler)

	if cert != "" && key != "" {
		r.RunTLS(addr, cert, key)
	} else {
		r.Run(addr)
	}
}
<|endoftext|>


<commit_before>package gmod

import (
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/u35s/gmod/lib/gtime"
)

const frameWarningTime = 100 * gtime.MillisecondN
const baseFrame uint = 40

type serverState uint

func (this *serverState) String() string {
	switch *this {
	case serverStateInit:
		return "init"
	case serverStateWait:
		return "wait"
	case serverStateRun:
		return "runing"
	case serverStateEnd:
		return "stopping"
	}
	return "null"
}

const (
	ServerStateNull serverState = iota
	serverStateInit
	serverStateWait
	serverStateRun
	serverStateEnd
)

type server struct {
	mods         []Moder
	state        serverState
	frameRunTime uint
}

func (this *server) start() {
	this.setFrameRunTime(baseFrame * 2)
}

func (this *server) init() {
	var timer gtime.Timer
	timer.Reset()
	for i := range this.mods {
		this.mods[i].Init()
	}
	log.Printf("server mod init,time %v second", timer.Elapse()/gtime.SecondN)
}

func (this *server) wait() bool {
	for i := range this.mods {
		if !this.mods[i].Wait() {
			return false
		}
	}
	return true
}

func (this *server) run() {
	for i := range this.mods {
		this.mods[i].Run()
	}
}

func (this *server) end() {
	var timer gtime.Timer
	timer.Reset()
	for i := range this.mods {
		this.mods[i].End()
	}
	log.Printf("server mod end,time %v second", timer.Elapse()/gtime.SecondN)
}

func (this *server) signal() {
	var sigChan = make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT)
	select {
	case <-sigChan:
		this.setState(serverStateEnd)
	}
}

func (this *server) loop() {
	var timer gtime.Timer
	for {
		timer.Reset()
		switch this.state {
		case serverStateInit:
			this.init()
			this.setState(serverStateWait)
		case serverStateWait:
			if this.wait() {
				this.setState(serverStateRun)
			}
		case serverStateRun:
			this.run()
		case serverStateEnd:
			this.end()
			return
		default:
		}
		e := timer.Elapse()
		if e < this.frameRunTime {
			sleep := this.frameRunTime - e
			time.Sleep(time.Duration(sleep))
		} else if e > frameWarningTime {
			log.Printf("this frame run time in %v millisecond", e/gtime.MillisecondN)
		}

	}
}

func (this *server) setState(state serverState) {
	this.state = state
	log.Printf("set server sate %v", state.String())
}

func (this *server) setFrameRunTime(runTime uint) {
	this.frameRunTime = runTime * gtime.MillisecondN
	log.Printf("set frame run time %v millisecond", runTime)
}

var srv *server

func init() {
	srv = new(server)
	srv.start()
	go srv.signal()
}

func Run(mods ...Moder) {
	srv.mods = append(srv.mods, mods...)
	srv.setState(serverStateInit)
	srv.loop()
}
<commit_msg>remove log<commit_after>package gmod

import (
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/u35s/gmod/lib/gtime"
)

const frameWarningTime = 100 * gtime.MillisecondN
const baseFrame uint = 40

type serverState uint

func (this *serverState) String() string {
	switch *this {
	case serverStateInit:
		return "init"
	case serverStateWait:
		return "wait"
	case serverStateRun:
		return "runing"
	case serverStateEnd:
		return "stopping"
	}
	return "null"
}

const (
	ServerStateNull serverState = iota
	serverStateInit
	serverStateWait
	serverStateRun
	serverStateEnd
)

type server struct {
	mods         []Moder
	state        serverState
	frameRunTime uint
}

func (this *server) start() {
	this.setFrameRunTime(baseFrame * 2)
}

func (this *server) init() {
	var timer gtime.Timer
	timer.Reset()
	for i := range this.mods {
		this.mods[i].Init()
	}
	log.Printf("server mod init,time %v second", timer.Elapse()/gtime.SecondN)
}

func (this *server) wait() bool {
	for i := range this.mods {
		if !this.mods[i].Wait() {
			return false
		}
	}
	return true
}

func (this *server) run() {
	for i := range this.mods {
		this.mods[i].Run()
	}
}

func (this *server) end() {
	var timer gtime.Timer
	timer.Reset()
	for i := range this.mods {
		this.mods[i].End()
	}
	log.Printf("server mod end,time %v second", timer.Elapse()/gtime.SecondN)
}

func (this *server) signal() {
	var sigChan = make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT)
	select {
	case <-sigChan:
		this.setState(serverStateEnd)
	}
}

func (this *server) loop() {
	var timer gtime.Timer
	for {
		timer.Reset()
		switch this.state {
		case serverStateInit:
			this.init()
			this.setState(serverStateWait)
		case serverStateWait:
			if this.wait() {
				this.setState(serverStateRun)
			}
		case serverStateRun:
			this.run()
		case serverStateEnd:
			this.end()
			return
		default:
		}
		e := timer.Elapse()
		if e < this.frameRunTime {
			sleep := this.frameRunTime - e
			time.Sleep(time.Duration(sleep))
		} else if e > frameWarningTime {
			log.Printf("this frame run time in %v millisecond", e/gtime.MillisecondN)
		}

	}
}

func (this *server) setState(state serverState) {
	this.state = state
	log.Printf("set server sate %v", state.String())
}

func (this *server) setFrameRunTime(runTime uint) {
	this.frameRunTime = runTime * gtime.MillisecondN
}

var srv *server

func init() {
	srv = new(server)
	srv.start()
	go srv.signal()
}

func Run(mods ...Moder) {
	srv.mods = append(srv.mods, mods...)
	srv.setState(serverStateInit)
	srv.loop()
}
<|endoftext|>