<commit_before>package service

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net/http"
	"runtime"
	"time"

	"math"
	"os"
	"strconv"
	"sync"

	"github.com/syou6162/go-active-learning/lib/example"
	"github.com/syou6162/go-active-learning/lib/fetcher"
	"github.com/syou6162/go-active-learning/lib/model"
	"github.com/syou6162/go-active-learning/lib/util"
)

func (app *goActiveLearningApp) InsertOrUpdateExample(e *model.Example) error {
	return app.repo.InsertOrUpdateExample(e)
}

func (app *goActiveLearningApp) UpdateScore(e *model.Example) error {
	return app.repo.UpdateScore(e)
}

func (app *goActiveLearningApp) InsertExampleFromScanner(scanner *bufio.Scanner) (*model.Example, error) {
	return app.repo.InsertExampleFromScanner(scanner)
}

func (app *goActiveLearningApp) InsertExamplesFromReader(reader io.Reader) error {
	return app.repo.InsertExamplesFromReader(reader)
}

func (app *goActiveLearningApp) ReadExamples() (model.Examples, error) {
	return app.repo.ReadExamples()
}

func (app *goActiveLearningApp) ReadRecentExamples(from time.Time) (model.Examples, error) {
	return app.repo.ReadRecentExamples(from)
}

func (app *goActiveLearningApp) ReadExamplesByLabel(label model.LabelType, limit int) (model.Examples, error) {
	return app.repo.ReadExamplesByLabel(label, limit)
}

func (app *goActiveLearningApp) ReadLabeledExamples(limit int) (model.Examples, error) {
	return app.repo.ReadLabeledExamples(limit)
}

func (app *goActiveLearningApp) ReadPositiveExamples(limit int) (model.Examples, error) {
	return app.repo.ReadPositiveExamples(limit)
}

func (app *goActiveLearningApp) ReadNegativeExamples(limit int) (model.Examples, error) {
	return app.repo.ReadNegativeExamples(limit)
}

func (app *goActiveLearningApp) ReadUnlabeledExamples(limit int) (model.Examples, error) {
	return app.repo.ReadUnlabeledExamples(limit)
}

func (app *goActiveLearningApp) SearchPositiveScoredExamples(limit int) (model.Examples, error) {
	return app.repo.SearchPositiveScoredExamples(limit)
}

func (app *goActiveLearningApp) FindExampleByUlr(url string) (*model.Example, error) {
	return app.repo.FindExampleByUlr(url)
}

func (app *goActiveLearningApp) SearchExamplesByUlrs(urls []string) (model.Examples, error) {
	return app.repo.SearchExamplesByUlrs(urls)
}

func (app *goActiveLearningApp) SearchExamplesByKeywords(keywords []string, aggregator string, limit int) (model.Examples, error) {
	return app.repo.SearchExamplesByKeywords(keywords, aggregator, limit)
}

func (app *goActiveLearningApp) DeleteAllExamples() error {
	return app.repo.DeleteAllExamples()
}

func (app *goActiveLearningApp) UpdateExampleMetadata(e model.Example) error {
	if err := app.repo.InsertOrUpdateExample(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured proccessing %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateFeatureVector(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating feature vector %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateHatenaBookmark(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating bookmark info %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateReferringTweets(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating twitter info %s %s", e.Url, err.Error()))
	}
	return nil
}

func (app *goActiveLearningApp) UpdateExamplesMetadata(examples model.Examples) error {
	for _, e := range examples {
		app.UpdateExampleMetadata(*e)
	}
	return nil
}

func hatenaBookmarkByExampleId(hatenaBookmarks []*model.HatenaBookmark) map[int]*model.HatenaBookmark {
	result := make(map[int]*model.HatenaBookmark)
	for _, hb := range hatenaBookmarks {
		result[hb.ExampleId] = hb
	}
	return result
}

func (app *goActiveLearningApp) AttachMetadata(examples model.Examples) error {
	// make sure that example id must be filled
	for _, e := range examples {
		if e.Id == 0 {
			tmp, err := app.FindExampleByUlr(e.Url)
			if err != nil {
				return err
			}
			e.Id = tmp.Id
		}
	}

	fvList, err := app.repo.SearchFeatureVector(examples)
	if err != nil {
		return err
	}

	for _, e := range examples {
		if fv, ok := fvList[e.Id]; ok {
			e.Fv = fv
		}
	}

	return app.AttachLightMetadata(examples)
}

func (app *goActiveLearningApp) AttachLightMetadata(examples model.Examples) error {
	hatenaBookmarks, err := app.repo.SearchHatenaBookmarks(examples)
	if err != nil {
		return err
	}
	hbByid := hatenaBookmarkByExampleId(hatenaBookmarks)
	for _, e := range examples {
		if b, ok := hbByid[e.Id]; ok {
			e.HatenaBookmark = b
		} else {
			e.HatenaBookmark = &model.HatenaBookmark{Bookmarks: []*model.Bookmark{}}
		}
	}

	referringTweetsById, err := app.repo.SearchReferringTweetsList(examples)
	if err != nil {
		return err
	}
	for _, e := range examples {
		if t, ok := referringTweetsById[e.Id]; ok {
			e.ReferringTweets = &t
		} else {
			e.ReferringTweets = &model.ReferringTweets{}
		}
	}
	return nil
}

func (app *goActiveLearningApp) AddExamplesToList(listName string, examples model.Examples) error {
	return app.cache.AddExamplesToList(listName, examples)
}

func (app *goActiveLearningApp) GetUrlsFromList(listName string, from int64, to int64) ([]string, error) {
	return app.cache.GetUrlsFromList(listName, from, to)
}

func (app *goActiveLearningApp) ExistMetadata(e model.Example) bool {
	tmp, err := app.FindExampleByUlr(e.Url)
	if err != nil {
		return false
	}

	if tmp.StatusCode == http.StatusOK {
		return true
	}
	return false
}

func fetchMetaData(e *model.Example) error {
	article, err := fetcher.GetArticle(e.Url)
	if err != nil {
		return err
	}

	e.Title = article.Title
	e.FinalUrl = article.Url
	e.Description = article.Description
	e.OgDescription = article.OgDescription
	e.OgType = article.OgType
	e.OgImage = article.OgImage
	e.Body = article.Body
	e.StatusCode = article.StatusCode
	e.Favicon = article.Favicon
	e.Fv = util.RemoveDuplicate(example.ExtractFeatures(*e))

	return nil
}

func (app *goActiveLearningApp) Fetch(examples model.Examples) {
	batchSize := 100
	examplesList := make([]model.Examples, 0)
	n := len(examples)

	for i := 0; i < n; i += batchSize {
		max := int(math.Min(float64(i+batchSize), float64(n)))
		examplesList = append(examplesList, examples[i:max])
	}
	for _, l := range examplesList {
		examplesWithMetaData := model.Examples{}
		examplesWithEmptyMetaData := model.Examples{}
		for _, e := range l {
			if !app.ExistMetadata(*e) {
				examplesWithEmptyMetaData = append(examplesWithEmptyMetaData, e)
			} else {
				examplesWithMetaData = append(examplesWithMetaData, e)
			}
		}
		app.AttachMetadata(examplesWithMetaData)

		wg := &sync.WaitGroup{}
		cpus := runtime.NumCPU()
		runtime.GOMAXPROCS(cpus)
		sem := make(chan struct{}, batchSize)
		for idx, e := range examplesWithEmptyMetaData {
			wg.Add(1)
			sem <- struct{}{}
			go func(e *model.Example, idx int) {
				defer wg.Done()
				cnt, err := app.cache.GetErrorCount(e.Url)
				if err != nil {
					log.Println(err.Error())
				}
				if cnt < 5 {
					fmt.Fprintln(os.Stderr, "Fetching("+strconv.Itoa(idx)+"): "+e.Url)
					if err := fetchMetaData(e); err != nil {
						app.cache.IncErrorCount(e.Url)
						log.Println(err.Error())
					}
				}
				<-sem
			}(e, idx)
		}
		wg.Wait()
	}
}
<commit_msg>あまりに巨大な特徴量は弾く<commit_after>package service

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net/http"
	"runtime"
	"time"

	"math"
	"os"
	"strconv"
	"sync"

	"github.com/syou6162/go-active-learning/lib/example"
	"github.com/syou6162/go-active-learning/lib/fetcher"
	"github.com/syou6162/go-active-learning/lib/model"
	"github.com/syou6162/go-active-learning/lib/util"
)

func (app *goActiveLearningApp) InsertOrUpdateExample(e *model.Example) error {
	return app.repo.InsertOrUpdateExample(e)
}

func (app *goActiveLearningApp) UpdateScore(e *model.Example) error {
	return app.repo.UpdateScore(e)
}

func (app *goActiveLearningApp) InsertExampleFromScanner(scanner *bufio.Scanner) (*model.Example, error) {
	return app.repo.InsertExampleFromScanner(scanner)
}

func (app *goActiveLearningApp) InsertExamplesFromReader(reader io.Reader) error {
	return app.repo.InsertExamplesFromReader(reader)
}

func (app *goActiveLearningApp) ReadExamples() (model.Examples, error) {
	return app.repo.ReadExamples()
}

func (app *goActiveLearningApp) ReadRecentExamples(from time.Time) (model.Examples, error) {
	return app.repo.ReadRecentExamples(from)
}

func (app *goActiveLearningApp) ReadExamplesByLabel(label model.LabelType, limit int) (model.Examples, error) {
	return app.repo.ReadExamplesByLabel(label, limit)
}

func (app *goActiveLearningApp) ReadLabeledExamples(limit int) (model.Examples, error) {
	return app.repo.ReadLabeledExamples(limit)
}

func (app *goActiveLearningApp) ReadPositiveExamples(limit int) (model.Examples, error) {
	return app.repo.ReadPositiveExamples(limit)
}

func (app *goActiveLearningApp) ReadNegativeExamples(limit int) (model.Examples, error) {
	return app.repo.ReadNegativeExamples(limit)
}

func (app *goActiveLearningApp) ReadUnlabeledExamples(limit int) (model.Examples, error) {
	return app.repo.ReadUnlabeledExamples(limit)
}

func (app *goActiveLearningApp) SearchPositiveScoredExamples(limit int) (model.Examples, error) {
	return app.repo.SearchPositiveScoredExamples(limit)
}

func (app *goActiveLearningApp) FindExampleByUlr(url string) (*model.Example, error) {
	return app.repo.FindExampleByUlr(url)
}

func (app *goActiveLearningApp) SearchExamplesByUlrs(urls []string) (model.Examples, error) {
	return app.repo.SearchExamplesByUlrs(urls)
}

func (app *goActiveLearningApp) SearchExamplesByKeywords(keywords []string, aggregator string, limit int) (model.Examples, error) {
	return app.repo.SearchExamplesByKeywords(keywords, aggregator, limit)
}

func (app *goActiveLearningApp) DeleteAllExamples() error {
	return app.repo.DeleteAllExamples()
}

func (app *goActiveLearningApp) UpdateExampleMetadata(e model.Example) error {
	if err := app.repo.InsertOrUpdateExample(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured proccessing %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateFeatureVector(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating feature vector %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateHatenaBookmark(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating bookmark info %s %s", e.Url, err.Error()))
	}
	if err := app.repo.UpdateReferringTweets(&e); err != nil {
		log.Println(fmt.Sprintf("Error occured updating twitter info %s %s", e.Url, err.Error()))
	}
	return nil
}

func (app *goActiveLearningApp) UpdateExamplesMetadata(examples model.Examples) error {
	for _, e := range examples {
		app.UpdateExampleMetadata(*e)
	}
	return nil
}

func hatenaBookmarkByExampleId(hatenaBookmarks []*model.HatenaBookmark) map[int]*model.HatenaBookmark {
	result := make(map[int]*model.HatenaBookmark)
	for _, hb := range hatenaBookmarks {
		result[hb.ExampleId] = hb
	}
	return result
}

func (app *goActiveLearningApp) AttachMetadata(examples model.Examples) error {
	// make sure that example id must be filled
	for _, e := range examples {
		if e.Id == 0 {
			tmp, err := app.FindExampleByUlr(e.Url)
			if err != nil {
				return err
			}
			e.Id = tmp.Id
		}
	}

	fvList, err := app.repo.SearchFeatureVector(examples)
	if err != nil {
		return err
	}

	for _, e := range examples {
		if fv, ok := fvList[e.Id]; ok {
			e.Fv = fv
		}
	}

	return app.AttachLightMetadata(examples)
}

func (app *goActiveLearningApp) AttachLightMetadata(examples model.Examples) error {
	hatenaBookmarks, err := app.repo.SearchHatenaBookmarks(examples)
	if err != nil {
		return err
	}
	hbByid := hatenaBookmarkByExampleId(hatenaBookmarks)
	for _, e := range examples {
		if b, ok := hbByid[e.Id]; ok {
			e.HatenaBookmark = b
		} else {
			e.HatenaBookmark = &model.HatenaBookmark{Bookmarks: []*model.Bookmark{}}
		}
	}

	referringTweetsById, err := app.repo.SearchReferringTweetsList(examples)
	if err != nil {
		return err
	}
	for _, e := range examples {
		if t, ok := referringTweetsById[e.Id]; ok {
			e.ReferringTweets = &t
		} else {
			e.ReferringTweets = &model.ReferringTweets{}
		}
	}
	return nil
}

func (app *goActiveLearningApp) AddExamplesToList(listName string, examples model.Examples) error {
	return app.cache.AddExamplesToList(listName, examples)
}

func (app *goActiveLearningApp) GetUrlsFromList(listName string, from int64, to int64) ([]string, error) {
	return app.cache.GetUrlsFromList(listName, from, to)
}

func (app *goActiveLearningApp) ExistMetadata(e model.Example) bool {
	tmp, err := app.FindExampleByUlr(e.Url)
	if err != nil {
		return false
	}

	if tmp.StatusCode == http.StatusOK {
		return true
	}
	return false
}

func fetchMetaData(e *model.Example) error {
	article, err := fetcher.GetArticle(e.Url)
	if err != nil {
		return err
	}

	e.Title = article.Title
	e.FinalUrl = article.Url
	e.Description = article.Description
	e.OgDescription = article.OgDescription
	e.OgType = article.OgType
	e.OgImage = article.OgImage
	e.Body = article.Body
	e.StatusCode = article.StatusCode
	e.Favicon = article.Favicon

	fv := util.RemoveDuplicate(example.ExtractFeatures(*e))
	if len(fv) > 100000 {
		return fmt.Errorf("too large features (N = %d) for %s", len(fv), e.FinalUrl)
	}
	e.Fv = fv

	return nil
}

func (app *goActiveLearningApp) Fetch(examples model.Examples) {
	batchSize := 100
	examplesList := make([]model.Examples, 0)
	n := len(examples)

	for i := 0; i < n; i += batchSize {
		max := int(math.Min(float64(i+batchSize), float64(n)))
		examplesList = append(examplesList, examples[i:max])
	}
	for _, l := range examplesList {
		examplesWithMetaData := model.Examples{}
		examplesWithEmptyMetaData := model.Examples{}
		for _, e := range l {
			if !app.ExistMetadata(*e) {
				examplesWithEmptyMetaData = append(examplesWithEmptyMetaData, e)
			} else {
				examplesWithMetaData = append(examplesWithMetaData, e)
			}
		}
		app.AttachMetadata(examplesWithMetaData)

		wg := &sync.WaitGroup{}
		cpus := runtime.NumCPU()
		runtime.GOMAXPROCS(cpus)
		sem := make(chan struct{}, batchSize)
		for idx, e := range examplesWithEmptyMetaData {
			wg.Add(1)
			sem <- struct{}{}
			go func(e *model.Example, idx int) {
				defer wg.Done()
				cnt, err := app.cache.GetErrorCount(e.Url)
				if err != nil {
					log.Println(err.Error())
				}
				if cnt < 5 {
					fmt.Fprintln(os.Stderr, "Fetching("+strconv.Itoa(idx)+"): "+e.Url)
					if err := fetchMetaData(e); err != nil {
						app.cache.IncErrorCount(e.Url)
						log.Println(err.Error())
					}
				}
				<-sem
			}(e, idx)
		}
		wg.Wait()
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Jigsaw Operations LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"errors"
	"log"
	"net"
	"time"

	"sync"

	"github.com/shadowsocks/go-shadowsocks2/shadowaead"
	"github.com/shadowsocks/go-shadowsocks2/socks"
)

type mode int

const (
	remoteServer mode = iota
	relayClient
	socksClient
)

const udpBufSize = 64 * 1024

// upack decripts src into dst. It tries each cipher until it finds one that authenticates
// correctly. dst and src must not overlap.
func unpack(dst, src []byte, ciphers map[string]shadowaead.Cipher) ([]byte, shadowaead.Cipher, error) {
	for id, cipher := range ciphers {
		log.Printf("Trying UDP cipher %v", id)
		buf, err := shadowaead.Unpack(dst, src, cipher)
		if err != nil {
			log.Printf("Failed UDP cipher %v: %v", id, err)
			continue
		}
		log.Printf("Selected UDP cipher %v", id)
		return buf, cipher, nil
	}
	return nil, nil, errors.New("could not find valid cipher")
}

// Listen on addr for encrypted packets and basically do UDP NAT.
func udpRemote(c net.PacketConn, ciphers map[string]shadowaead.Cipher) {
	defer c.Close()

	nm := newNATmap(config.UDPTimeout)
	cipherBuf := make([]byte, udpBufSize)
	buf := make([]byte, udpBufSize)

	for {
		func() {
			n, raddr, err := c.ReadFrom(cipherBuf)
			defer log.Printf("Done with %v", raddr.String())
			if err != nil {
				log.Printf("UDP remote read error: %v", err)
				return
			}
			log.Printf("Request from %v", raddr)
			buf, cipher, err := unpack(buf, cipherBuf[:n], ciphers)
			if err != nil {
				log.Printf("UDP remote read error: %v", err)
				return
			}

			tgtAddr := socks.SplitAddr(buf[:n])
			if tgtAddr == nil {
				log.Printf("failed to split target address from packet: %q", buf[:n])
				return
			}

			tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
			if err != nil {
				log.Printf("failed to resolve target UDP address: %v", err)
				return
			}

			payload := buf[len(tgtAddr):n]

			pc := nm.Get(raddr.String())
			if pc == nil {
				pc, err = net.ListenPacket("udp", "")
				if err != nil {
					log.Printf("UDP remote listen error: %v", err)
					return
				}

				nm.Add(raddr, shadowaead.NewPacketConn(c, cipher), pc, remoteServer)
			}

			_, err = pc.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
			if err != nil {
				log.Printf("UDP remote write error: %v", err)
				return
			}
		}()
	}
}

// Packet NAT table
type natmap struct {
	sync.RWMutex
	m       map[string]net.PacketConn
	timeout time.Duration
}

func newNATmap(timeout time.Duration) *natmap {
	m := &natmap{}
	m.m = make(map[string]net.PacketConn)
	m.timeout = timeout
	return m
}

func (m *natmap) Get(key string) net.PacketConn {
	m.RLock()
	defer m.RUnlock()
	return m.m[key]
}

func (m *natmap) Set(key string, pc net.PacketConn) {
	m.Lock()
	defer m.Unlock()

	m.m[key] = pc
}

func (m *natmap) Del(key string) net.PacketConn {
	m.Lock()
	defer m.Unlock()

	pc, ok := m.m[key]
	if ok {
		delete(m.m, key)
		return pc
	}
	return nil
}

func (m *natmap) Add(peer net.Addr, dst, src net.PacketConn, role mode) {
	m.Set(peer.String(), src)

	go func() {
		timedCopy(dst, peer, src, m.timeout, role)
		if pc := m.Del(peer.String()); pc != nil {
			pc.Close()
		}
	}()
}

// copy from src to dst at target with read timeout
func timedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration, role mode) error {
	buf := make([]byte, udpBufSize)

	for {
		src.SetReadDeadline(time.Now().Add(timeout))
		n, raddr, err := src.ReadFrom(buf)
		if err != nil {
			return err
		}

		switch role {
		case remoteServer: // server -> client: add original packet source
			srcAddr := socks.ParseAddr(raddr.String())
			copy(buf[len(srcAddr):], buf[:n])
			copy(buf, srcAddr)
			_, err = dst.WriteTo(buf[:len(srcAddr)+n], target)
		case relayClient: // client -> user: strip original packet source
			srcAddr := socks.SplitAddr(buf[:n])
			_, err = dst.WriteTo(buf[len(srcAddr):n], target)
		case socksClient: // client -> socks5 program: just set RSV and FRAG = 0
			_, err = dst.WriteTo(append([]byte{0, 0, 0}, buf[:n]...), target)
		}

		if err != nil {
			return err
		}
	}
}
<commit_msg>Fix UDP<commit_after>// Copyright 2018 Jigsaw Operations LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"errors"
	"log"
	"net"
	"time"

	"sync"

	"github.com/shadowsocks/go-shadowsocks2/shadowaead"
	"github.com/shadowsocks/go-shadowsocks2/socks"
)

type mode int

const (
	remoteServer mode = iota
	relayClient
	socksClient
)

const udpBufSize = 64 * 1024

// upack decripts src into dst. It tries each cipher until it finds one that authenticates
// correctly. dst and src must not overlap.
func unpack(dst, src []byte, ciphers map[string]shadowaead.Cipher) ([]byte, shadowaead.Cipher, error) {
	for id, cipher := range ciphers {
		log.Printf("Trying UDP cipher %v", id)
		buf, err := shadowaead.Unpack(dst, src, cipher)
		if err != nil {
			log.Printf("Failed UDP cipher %v: %v", id, err)
			continue
		}
		log.Printf("Selected UDP cipher %v", id)
		return buf, cipher, nil
	}
	return nil, nil, errors.New("could not find valid cipher")
}

// Listen on addr for encrypted packets and basically do UDP NAT.
func udpRemote(c net.PacketConn, ciphers map[string]shadowaead.Cipher) {
	defer c.Close()

	nm := newNATmap(config.UDPTimeout)
	cipherBuf := make([]byte, udpBufSize)
	textBuf := make([]byte, udpBufSize)

	for {
		func() {
			n, raddr, err := c.ReadFrom(cipherBuf)
			defer log.Printf("Done with %v", raddr.String())
			if err != nil {
				log.Printf("UDP remote read error: %v", err)
				return
			}
			log.Printf("Request from %v with %v bytes", raddr, n)
			buf, cipher, err := unpack(textBuf, cipherBuf[:n], ciphers)
			if err != nil {
				log.Printf("UDP remote read error: %v", err)
				return
			}

			tgtAddr := socks.SplitAddr(buf)
			if tgtAddr == nil {
				log.Printf("failed to split target address from packet: %q", buf[:n])
				return
			}

			tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
			if err != nil {
				log.Printf("failed to resolve target UDP address: %v", err)
				return
			}

			payload := buf[len(tgtAddr):n]

			pc := nm.Get(raddr.String())
			if pc == nil {
				pc, err = net.ListenPacket("udp", "")
				if err != nil {
					log.Printf("UDP remote listen error: %v", err)
					return
				}

				nm.Add(raddr, shadowaead.NewPacketConn(c, cipher), pc, remoteServer)
			}

			_, err = pc.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
			if err != nil {
				log.Printf("UDP remote write error: %v", err)
				return
			}
		}()
	}
}

// Packet NAT table
type natmap struct {
	sync.RWMutex
	m       map[string]net.PacketConn
	timeout time.Duration
}

func newNATmap(timeout time.Duration) *natmap {
	m := &natmap{}
	m.m = make(map[string]net.PacketConn)
	m.timeout = timeout
	return m
}

func (m *natmap) Get(key string) net.PacketConn {
	m.RLock()
	defer m.RUnlock()
	return m.m[key]
}

func (m *natmap) Set(key string, pc net.PacketConn) {
	m.Lock()
	defer m.Unlock()

	m.m[key] = pc
}

func (m *natmap) Del(key string) net.PacketConn {
	m.Lock()
	defer m.Unlock()

	pc, ok := m.m[key]
	if ok {
		delete(m.m, key)
		return pc
	}
	return nil
}

func (m *natmap) Add(peer net.Addr, dst, src net.PacketConn, role mode) {
	m.Set(peer.String(), src)

	go func() {
		timedCopy(dst, peer, src, m.timeout, role)
		if pc := m.Del(peer.String()); pc != nil {
			pc.Close()
		}
	}()
}

// copy from src to dst at target with read timeout
func timedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration, role mode) error {
	buf := make([]byte, udpBufSize)

	for {
		src.SetReadDeadline(time.Now().Add(timeout))
		n, raddr, err := src.ReadFrom(buf)
		if err != nil {
			return err
		}

		switch role {
		case remoteServer: // server -> client: add original packet source
			srcAddr := socks.ParseAddr(raddr.String())
			copy(buf[len(srcAddr):], buf[:n])
			copy(buf, srcAddr)
			_, err = dst.WriteTo(buf[:len(srcAddr)+n], target)
		case relayClient: // client -> user: strip original packet source
			srcAddr := socks.SplitAddr(buf[:n])
			_, err = dst.WriteTo(buf[len(srcAddr):n], target)
		case socksClient: // client -> socks5 program: just set RSV and FRAG = 0
			_, err = dst.WriteTo(append([]byte{0, 0, 0}, buf[:n]...), target)
		}

		if err != nil {
			return err
		}
	}
}
<|endoftext|>


<commit_before>package apigee

import (
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/gofrs/uuid"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/zambien/go-apigee-edge"
)

func resourceApiProxyDeployment() *schema.Resource {
	return &schema.Resource{
		Create: resourceApiProxyDeploymentCreate,
		Read:   resourceApiProxyDeploymentRead,
		Update: resourceApiProxyDeploymentUpdate,
		Delete: resourceApiProxyDeploymentDelete,
		Importer: &schema.ResourceImporter{
			State: resourceApiProxyDeploymentImport,
		},

		Schema: map[string]*schema.Schema{
			"proxy_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"org": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"env": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"revision": {
				Type:     schema.TypeString,
				Required: true,
			},
			"delay": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},
			"override": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
		},
	}
}

func resourceApiProxyDeploymentImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	log.Print("[DEBUG] resourceApiProxyDeploymentImport START")
	client := meta.(*apigee.EdgeClient)

	if len(strings.Split(d.Id(), "_")) != 3 {
		return []*schema.ResourceData{}, fmt.Errorf("[ERR] Wrong format of resource: %s. Please follow '{name}_{env}_deployment'", d.Id())
	}
	name := strings.Split(d.Id(), "_")[0]
	IDEnv := strings.Split(d.Id(), "_")[1]
	deployment, _, err := client.Proxies.GetDeployments(name)
	if err != nil {
		log.Printf("[DEBUG] resourceApiProxyDeploymentImport. Error getting deployment api: %v", err)
		return nil, nil
	}
	d.Set("org", deployment.Organization)
	d.Set("proxy_name", deployment.Name)
	d.Set("env", IDEnv)

	return []*schema.ResourceData{d}, nil
}

func resourceApiProxyDeploymentRead(d *schema.ResourceData, meta interface{}) (e error) {
	log.Print("[DEBUG] resourceApiProxyDeploymentRead START")
	log.Printf("[DEBUG] resourceApiProxyDeploymentRead proxy_name: %#v", d.Get("proxy_name").(string))

	client := meta.(*apigee.EdgeClient)

	found := false
	latestRevision := "0"

	if deployments, _, err := client.Proxies.GetDeployments(d.Get("proxy_name").(string)); err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentRead error getting deployments: %s", err.Error())
		if strings.Contains(err.Error(), "404 ") {
			log.Printf("[DEBUG] resourceApiProxyDeploymentRead 404 encountered.  Removing state for deployment proxy_name: %#v", d.Get("proxy_name").(string))
			d.SetId("")
			return nil
		} else {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentRead error reading deployments: %s", err.Error())
		}
	} else {
		log.Printf("[DEBUG] resourceApiProxyDeploymentRead deployments call fired for proxy_name: %#v", d.Get("proxy_name").(string))
		for _, environment := range deployments.Environments {
			log.Printf("[DEBUG] resourceApiProxyDeploymentRead checking revisions in deployed environment: %#v for expected environment: %#v\n", environment.Name, d.Get("env").(string))
			if environment.Name == d.Get("env").(string) {
				//We don't break.  Always get the last one if there are multiple deployments.
				for _, revision := range environment.Revision {
					log.Printf("[DEBUG] resourceApiProxyDeploymentRead checking deployed revision: %#v for expected revision: %#v\n", revision.Number.String(), d.Get("revision").(string))
					latestRevision = revision.Number.String()
					found = true
				}
			}
		}
	}

	if found {
		log.Printf("[DEBUG] resourceApiProxyDeploymentRead - deployment found. Revision is: %#v", latestRevision)
		d.Set("revision", latestRevision)
	} else {
		log.Print("[DEBUG] resourceApiProxyDeploymentRead - no deployment found")
		d.SetId("")
	}
	return nil
}

func resourceApiProxyDeploymentCreate(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentCreate START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)
	delay := int(d.Get("delay").(int))
	override := bool(d.Get("override").(bool))

	proxyDep, _, err := client.Proxies.Deploy(proxy_name, env, rev, delay, override)

	if err != nil {

		if strings.Contains(err.Error(), "conflicts with existing deployment path") {
			//create, fail, update
			log.Printf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
			log.Print("[DEBUG] resourceApiProxyDeploymentCreate something got out of sync... maybe someone messing around in apigee directly.  Terraform OVERRIDE!!!")
			resourceApiProxyDeploymentUpdate(d, meta)
		} else {
			log.Printf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
		}
	}

	id, _ := uuid.NewV4()
	d.SetId(id.String())
	d.Set("revision", proxyDep.Revision.String())

	return resourceApiProxyDeploymentRead(d, meta)
}

func resourceApiProxyDeploymentUpdate(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentUpdate START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	delay := int(d.Get("delay").(int))
	override := bool(d.Get("override").(bool))

	//We must set delay and override here if not set.
	if delay == 0 {
		delay = 15 //seconds
	}
	if override == false {
		override = true
	}

	if d.Get("revision").(string) == "latest" {
		// deploy latest
		rev, err := getLatestRevision(client, proxy_name)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error getting latest revision: %v", err)
		}
		_, _, err = client.Proxies.ReDeploy(proxy_name, env, apigee.Revision(rev), delay, override)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error deploying: %v", err)
		}
		log.Printf("[DEBUG] resourceApiProxyDeploymentUpdate Deployed revision %d of %s", rev, proxy_name)
		return resourceApiProxyDeploymentRead(d, meta)
	}

	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)
	_, _, err := client.Proxies.ReDeploy(proxy_name, env, rev, delay, override)

	if err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentUpdate error redeploying: %s", err.Error())
		if strings.Contains(err.Error(), " is already deployed into environment ") {
			return resourceApiProxyDeploymentRead(d, meta)
		}
		return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error redeploying: %s", err.Error())
	}

	return resourceApiProxyDeploymentRead(d, meta)
}

func resourceApiProxyDeploymentDelete(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentDelete START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)

	_, _, err := client.Proxies.Undeploy(proxy_name, env, rev)
	if err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentDelete error undeploying: %s", err.Error())
		return fmt.Errorf("[ERROR] resourceApiProxyDeploymentDelete error undeploying: %s", err.Error())
	}

	return nil
}

func getLatestRevision(client *apigee.EdgeClient, proxyName string) (int, error) {
	proxy, _, err := client.Proxies.Get(proxyName)
	if err != nil {
		return -1, fmt.Errorf("[ERROR] resourceApiProxyRead error reading proxies: %s", err.Error())
	}
	return len(proxy.Revisions), nil
}
<commit_msg>include latest option during create too<commit_after>package apigee

import (
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/gofrs/uuid"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/zambien/go-apigee-edge"
)

func resourceApiProxyDeployment() *schema.Resource {
	return &schema.Resource{
		Create: resourceApiProxyDeploymentCreate,
		Read:   resourceApiProxyDeploymentRead,
		Update: resourceApiProxyDeploymentUpdate,
		Delete: resourceApiProxyDeploymentDelete,
		Importer: &schema.ResourceImporter{
			State: resourceApiProxyDeploymentImport,
		},

		Schema: map[string]*schema.Schema{
			"proxy_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"org": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"env": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"revision": {
				Type:     schema.TypeString,
				Required: true,
			},
			"delay": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},
			"override": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
		},
	}
}

func resourceApiProxyDeploymentImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	log.Print("[DEBUG] resourceApiProxyDeploymentImport START")
	client := meta.(*apigee.EdgeClient)

	if len(strings.Split(d.Id(), "_")) != 3 {
		return []*schema.ResourceData{}, fmt.Errorf("[ERR] Wrong format of resource: %s. Please follow '{name}_{env}_deployment'", d.Id())
	}
	name := strings.Split(d.Id(), "_")[0]
	IDEnv := strings.Split(d.Id(), "_")[1]
	deployment, _, err := client.Proxies.GetDeployments(name)
	if err != nil {
		log.Printf("[DEBUG] resourceApiProxyDeploymentImport. Error getting deployment api: %v", err)
		return nil, nil
	}
	d.Set("org", deployment.Organization)
	d.Set("proxy_name", deployment.Name)
	d.Set("env", IDEnv)

	return []*schema.ResourceData{d}, nil
}

func resourceApiProxyDeploymentRead(d *schema.ResourceData, meta interface{}) (e error) {
	log.Print("[DEBUG] resourceApiProxyDeploymentRead START")
	log.Printf("[DEBUG] resourceApiProxyDeploymentRead proxy_name: %#v", d.Get("proxy_name").(string))

	client := meta.(*apigee.EdgeClient)

	found := false
	latestRevision := "0"

	if deployments, _, err := client.Proxies.GetDeployments(d.Get("proxy_name").(string)); err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentRead error getting deployments: %s", err.Error())
		if strings.Contains(err.Error(), "404 ") {
			log.Printf("[DEBUG] resourceApiProxyDeploymentRead 404 encountered.  Removing state for deployment proxy_name: %#v", d.Get("proxy_name").(string))
			d.SetId("")
			return nil
		} else {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentRead error reading deployments: %s", err.Error())
		}
	} else {
		log.Printf("[DEBUG] resourceApiProxyDeploymentRead deployments call fired for proxy_name: %#v", d.Get("proxy_name").(string))
		for _, environment := range deployments.Environments {
			log.Printf("[DEBUG] resourceApiProxyDeploymentRead checking revisions in deployed environment: %#v for expected environment: %#v\n", environment.Name, d.Get("env").(string))
			if environment.Name == d.Get("env").(string) {
				//We don't break.  Always get the last one if there are multiple deployments.
				for _, revision := range environment.Revision {
					log.Printf("[DEBUG] resourceApiProxyDeploymentRead checking deployed revision: %#v for expected revision: %#v\n", revision.Number.String(), d.Get("revision").(string))
					latestRevision = revision.Number.String()
					found = true
				}
			}
		}
	}

	if found {
		log.Printf("[DEBUG] resourceApiProxyDeploymentRead - deployment found. Revision is: %#v", latestRevision)
		d.Set("revision", latestRevision)
	} else {
		log.Print("[DEBUG] resourceApiProxyDeploymentRead - no deployment found")
		d.SetId("")
	}
	return nil
}

func resourceApiProxyDeploymentCreate(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentCreate START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)
	delay := int(d.Get("delay").(int))
	override := bool(d.Get("override").(bool))

	if d.Get("revision").(string) == "latest" {
		// deploy latest
		rev, err := getLatestRevision(client, proxy_name)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error getting latest revision: %v", err)
		}
		_, _, err = client.Proxies.Deploy(proxy_name, env, apigee.Revision(rev), delay, override)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error deploying: %v", err)
		}
		log.Printf("[DEBUG] resourceApiProxyDeploymentUpdate Deployed revision %d of %s", rev, proxy_name)
		return resourceApiProxyDeploymentRead(d, meta)
	}

	proxyDep, _, err := client.Proxies.Deploy(proxy_name, env, rev, delay, override)

	if err != nil {

		if strings.Contains(err.Error(), "conflicts with existing deployment path") {
			//create, fail, update
			log.Printf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
			log.Print("[DEBUG] resourceApiProxyDeploymentCreate something got out of sync... maybe someone messing around in apigee directly.  Terraform OVERRIDE!!!")
			resourceApiProxyDeploymentUpdate(d, meta)
		} else {
			log.Printf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentCreate error deploying: %s", err.Error())
		}
	}

	id, _ := uuid.NewV4()
	d.SetId(id.String())
	d.Set("revision", proxyDep.Revision.String())

	return resourceApiProxyDeploymentRead(d, meta)
}

func resourceApiProxyDeploymentUpdate(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentUpdate START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	delay := int(d.Get("delay").(int))
	override := bool(d.Get("override").(bool))

	//We must set delay and override here if not set.
	if delay == 0 {
		delay = 15 //seconds
	}
	if override == false {
		override = true
	}

	if d.Get("revision").(string) == "latest" {
		// deploy latest
		rev, err := getLatestRevision(client, proxy_name)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error getting latest revision: %v", err)
		}
		_, _, err = client.Proxies.ReDeploy(proxy_name, env, apigee.Revision(rev), delay, override)
		if err != nil {
			return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error deploying: %v", err)
		}
		log.Printf("[DEBUG] resourceApiProxyDeploymentUpdate Deployed revision %d of %s", rev, proxy_name)
		return resourceApiProxyDeploymentRead(d, meta)
	}

	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)
	_, _, err := client.Proxies.ReDeploy(proxy_name, env, rev, delay, override)

	if err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentUpdate error redeploying: %s", err.Error())
		if strings.Contains(err.Error(), " is already deployed into environment ") {
			return resourceApiProxyDeploymentRead(d, meta)
		}
		return fmt.Errorf("[ERROR] resourceApiProxyDeploymentUpdate error redeploying: %s", err.Error())
	}

	return resourceApiProxyDeploymentRead(d, meta)
}

func resourceApiProxyDeploymentDelete(d *schema.ResourceData, meta interface{}) error {

	log.Print("[DEBUG] resourceApiProxyDeploymentDelete START")

	client := meta.(*apigee.EdgeClient)

	proxy_name := d.Get("proxy_name").(string)
	env := d.Get("env").(string)
	rev_int, _ := strconv.Atoi(d.Get("revision").(string))
	rev := apigee.Revision(rev_int)

	_, _, err := client.Proxies.Undeploy(proxy_name, env, rev)
	if err != nil {
		log.Printf("[ERROR] resourceApiProxyDeploymentDelete error undeploying: %s", err.Error())
		return fmt.Errorf("[ERROR] resourceApiProxyDeploymentDelete error undeploying: %s", err.Error())
	}

	return nil
}

func getLatestRevision(client *apigee.EdgeClient, proxyName string) (int, error) {
	proxy, _, err := client.Proxies.Get(proxyName)
	if err != nil {
		return -1, fmt.Errorf("[ERROR] resourceApiProxyRead error reading proxies: %s", err.Error())
	}
	return len(proxy.Revisions), nil
}
<|endoftext|>


<commit_before>// route project route.go
package route

import (
	"net/http"
	"net/url"
	"path/filepath"
	"regexp"
	"strings"
)

const (
	CONNECT = "CONNECT"
	DELETE  = "DELETE"
	GET     = "GET"
	HEAD    = "HEAD"
	OPTIONS = "OPTIONS"
	PATCH   = "PATCH"
	POST    = "POST"
	PUT     = "PUT"
	TRACE   = "TRACE"
)

/*
//commonly used mime-types
const (
	applicationJson = "application/json"
	applicationXml  = "application/xml"
	textXml         = "text/xml"
)
*/

type route struct {
	method  string
	regex   *regexp.Regexp
	params  map[int]string
	handler http.HandlerFunc
}

type RouteMux struct {
	routes  []*route
	filters []http.HandlerFunc
}

func New() *RouteMux {
	return &RouteMux{}
}

// Get adds a new Route for GET requests.
// i.e Get("/user/{id1}/{id2:([A-Z]+)}", user)
func (m *RouteMux) Get(pattern string, handler http.HandlerFunc) {
	m.AddRoute(GET, pattern, handler)
}

// Put adds a new Route for PUT requests.
func (m *RouteMux) Put(pattern string, handler http.HandlerFunc) {
	m.AddRoute(PUT, pattern, handler)
}

// Del adds a new Route for DELETE requests.
func (m *RouteMux) Del(pattern string, handler http.HandlerFunc) {
	m.AddRoute(DELETE, pattern, handler)
}

// Patch adds a new Route for PATCH requests.
func (m *RouteMux) Patch(pattern string, handler http.HandlerFunc) {
	m.AddRoute(PATCH, pattern, handler)
}

// Post adds a new Route for POST requests.
func (m *RouteMux) Post(pattern string, handler http.HandlerFunc) {
	m.AddRoute(POST, pattern, handler)
}

// Adds a new Route for Static http requests. Serves
// static files from the specified directory
func (m *RouteMux) Static(pattern string, dir string) {
	//append a regex to the param to match everything
	// that comes after the prefix
	pattern = pattern
	//pattern = pattern + "(.+)"
	m.AddRoute(GET, pattern, func(w http.ResponseWriter, r *http.Request) {
		path := filepath.Clean(r.URL.Path)
		path = filepath.Join(dir, path)
		http.ServeFile(w, r, path)
	})
}

// Adds a new Route to the Handler
func (m *RouteMux) AddRoute(method string, pattern string, handler http.HandlerFunc) {
	//split the url into sections
	parts := strings.Split(pattern, "/")

	//find params that start with ":"
	//replace with regular expressions
	j := 0
	params := make(map[int]string)
	for i, part := range parts {
		if strings.HasPrefix(part, "{") {
			part = part[1 : len(part)-1]
			paris := strings.Split(part, ":")
			part = paris[0]
			expr := "([^/]+)"
			//a user may choose to override the defult expression
			// similar to expressjs: ‘/user/{id:([0-9]+)}’
			if len(paris) == 2 {
				expr = paris[1]
			}
			params[j] = part
			parts[i] = expr
			j++
		}
	}

	//recreate the url pattern, with parameters replaced
	//by regular expressions. then compile the regex
	pattern = strings.Join(parts, "/")
	regex, regexErr := regexp.Compile(pattern)
	if regexErr != nil {
		//TODO add error handling here to avoid panic
		panic(regexErr)
		return
	}

	//now create the Route
	route := &route{}
	route.method = method
	route.regex = regex
	route.handler = handler
	route.params = params

	//and finally append to the list of Routes
	m.routes = append(m.routes, route)
}

// Filter adds the middleware filter.
func (m *RouteMux) Filter(filter http.HandlerFunc) {
	m.filters = append(m.filters, filter)
}

// FilterParam adds the middleware filter iff the REST URL parameter exists.
func (m *RouteMux) FilterParam(param string, filter http.HandlerFunc) {
	if !strings.HasPrefix(param, ":") {
		param = ":" + param
	}

	m.Filter(func(w http.ResponseWriter, r *http.Request) {
		p := r.URL.Query().Get(param)
		if len(p) > 0 {
			filter(w, r)
		}
	})
}

// Required by http.Handler interface. This method is invoked by the
// http server and will handle all page routing
func (m *RouteMux) ServeHTTP(rw http.ResponseWriter, r *http.Request) {

	requestPath := r.URL.Path

	//wrap the response writer, in our custom interface
	w := &responseWriter{writer: rw}

	//find a matching Route
	for _, route := range m.routes {

		//if the methods don't match, skip this handler
		//i.e if request.Method is 'PUT' Route.Method must be 'PUT'
		if r.Method != route.method {
			continue
		}

		//check if Route pattern matches url
		if !route.regex.MatchString(requestPath) {
			continue
		}

		//get submatches (params)
		matches := route.regex.FindStringSubmatch(requestPath)
		//double check that the Route matches the URL pattern.
		if len(matches[0]) != len(requestPath) {
			continue
		}

		if len(route.params) > 0 {
			//add url parameters to the query param map
			values := r.URL.Query()
			for i, match := range matches[1:] {
				values.Add(route.params[i], match)
			}

			//reassemble query params and add to RawQuery
			r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
			//r.URL.RawQuery = url.Values(values).Encode()
		}

		//execute middleware filters
		for _, filter := range m.filters {
			filter(w, r)
			if w.started {
				return
			}
		}

		//Invoke the request handler
		route.handler(w, r)
		break
	}

	//if no matches to url, throw a not found exception
	if w.started == false {
		http.NotFound(w, r)
	}
}

// -----------------------------------------------------------------------------
// Simple wrapper around a ResponseWriter

// responseWriter is a wrapper for the http.ResponseWriter
// to track if response was written to. It also allows us
// to automatically set certain headers, such as Content-Type,
// Access-Control-Allow-Origin, etc.
type responseWriter struct {
	writer  http.ResponseWriter
	started bool
	status  int
}

// Header returns the header map that will be sent by WriteHeader.
func (w *responseWriter) Header() http.Header {
	return w.writer.Header()
}

// Write writes the data to the connection as part of an HTTP reply,
// and sets `started` to true
func (w *responseWriter) Write(p []byte) (int, error) {
	w.started = true
	return w.writer.Write(p)
}

// WriteHeader sends an HTTP response header with status code,
// and sets `started` to true
func (w *responseWriter) WriteHeader(code int) {
	w.status = code
	w.started = true
	w.writer.WriteHeader(code)
}

/*
// -----------------------------------------------------------------------------
// Below are helper functions to replace boilerplate
// code that serializes resources and writes to the
// http response.

// ServeJson replies to the request with a JSON
// representation of resource v.
func ServeJson(w http.ResponseWriter, v interface{}) {
	content, err := json.MarshalIndent(v, "", "  ")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Length", strconv.Itoa(len(content)))
	w.Header().Set("Content-Type", applicationJson)
	w.Write(content)
}

// ReadJson will parses the JSON-encoded data in the http
// Request object and stores the result in the value
// pointed to by v.
func ReadJson(r *http.Request, v interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return err
	}
	return json.Unmarshal(body, v)
}

// ServeXml replies to the request with an XML
// representation of resource v.
func ServeXml(w http.ResponseWriter, v interface{}) {
	content, err := xml.Marshal(v)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Length", strconv.Itoa(len(content)))
	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.Write(content)
}

// ReadXml will parses the XML-encoded data in the http
// Request object and stores the result in the value
// pointed to by v.
func ReadXml(r *http.Request, v interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return err
	}
	return xml.Unmarshal(body, v)
}

// ServeFormatted replies to the request with
// a formatted representation of resource v, in the
// format requested by the client specified in the
// Accept header.
func ServeFormatted(w http.ResponseWriter, r *http.Request, v interface{}) {
	accept := r.Header.Get("Accept")
	switch accept {
	case applicationJson:
		ServeJson(w, v)
	case applicationXml, textXml:
		ServeXml(w, v)
	default:
		ServeJson(w, v)
	}

	return
}

func Run(mux http.Handler, addr string, withTLS bool, crtPath, keyPath string) {
	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)
	srv := &http.Server{
		Addr:           addr,
		Handler:        mux,
		ReadTimeout:    5 * time.Second,
		WriteTimeout:   30 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}

	go func() {
		if withTLS {
			fmt.Println(srv.ListenAndServeTLS(crtPath, keyPath))
		} else {
			fmt.Println(srv.ListenAndServe())
		}
	}()

	<-stopChan
	fmt.Println("Shutting down server...")

	ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)
	srv.Shutdown(ctx)

	if nil != ctx.Err() {
		fmt.Println(ctx.Err().Error())
	}

}
*/
<commit_msg>fix bug<commit_after>// route project route.go
package route

import (
	"net/http"
	"net/url"
	"path/filepath"
	"regexp"
	"strings"
)

const (
	CONNECT = "CONNECT"
	DELETE  = "DELETE"
	GET     = "GET"
	HEAD    = "HEAD"
	OPTIONS = "OPTIONS"
	PATCH   = "PATCH"
	POST    = "POST"
	PUT     = "PUT"
	TRACE   = "TRACE"
)

/*
//commonly used mime-types
const (
	applicationJson = "application/json"
	applicationXml  = "application/xml"
	textXml         = "text/xml"
)
*/

type route struct {
	method  string
	regex   *regexp.Regexp
	params  map[int]string
	handler http.HandlerFunc
}

type RouteMux struct {
	routes  []*route
	filters []http.HandlerFunc
}

func New() *RouteMux {
	return &RouteMux{}
}

// Get adds a new Route for GET requests.
// Get("/user/{id1}/{id2:([A-Z]+)}", user)
func (m *RouteMux) Get(pattern string, handler http.HandlerFunc) {
	m.AddRoute(GET, pattern, handler)
}

// Put adds a new Route for PUT requests.
func (m *RouteMux) Put(pattern string, handler http.HandlerFunc) {
	m.AddRoute(PUT, pattern, handler)
}

// Del adds a new Route for DELETE requests.
func (m *RouteMux) Del(pattern string, handler http.HandlerFunc) {
	m.AddRoute(DELETE, pattern, handler)
}

// Patch adds a new Route for PATCH requests.
func (m *RouteMux) Patch(pattern string, handler http.HandlerFunc) {
	m.AddRoute(PATCH, pattern, handler)
}

// Post adds a new Route for POST requests.
func (m *RouteMux) Post(pattern string, handler http.HandlerFunc) {
	m.AddRoute(POST, pattern, handler)
}

// Adds a new Route for Static http requests. Serves
// static files from the specified directory
func (m *RouteMux) Static(pattern string, dir string) {
	//append a regex to the param to match everything
	// that comes after the prefix
	pattern = pattern
	//pattern = pattern + "(.+)"
	m.AddRoute(GET, pattern, func(w http.ResponseWriter, r *http.Request) {
		path := filepath.Clean(r.URL.Path)
		path = filepath.Join(dir, path)
		http.ServeFile(w, r, path)
	})
}

// Adds a new Route to the Handler
func (m *RouteMux) AddRoute(method string, pattern string, handler http.HandlerFunc) {
	//split the url into sections
	parts := strings.Split(pattern, "/")

	//find params that start with ":"
	//replace with regular expressions
	j := 0
	params := make(map[int]string)
	for i, part := range parts {
		if strings.HasPrefix(part, "{") {
			part = part[1 : len(part)-1]
			paris := strings.Split(part, ":")
			part = paris[0]
			expr := "([^/]+)"
			//a user may choose to override the defult expression
			// similar to expressjs: ‘/user/{id:([0-9]+)}’
			if len(paris) == 2 {
				expr = paris[1]
			}
			params[j] = part
			parts[i] = expr
			j++
		}
	}

	//recreate the url pattern, with parameters replaced
	//by regular expressions. then compile the regex
	pattern = strings.Join(parts, "/")
	regex, regexErr := regexp.Compile(pattern)
	if regexErr != nil {
		//TODO add error handling here to avoid panic
		panic(regexErr)
		return
	}

	//now create the Route
	route := &route{}
	route.method = method
	route.regex = regex
	route.handler = handler
	route.params = params

	//and finally append to the list of Routes
	m.routes = append(m.routes, route)
}

// Filter adds the middleware filter.
func (m *RouteMux) Filter(filter http.HandlerFunc) {
	m.filters = append(m.filters, filter)
}

// FilterParam adds the middleware filter iff the REST URL parameter exists.
func (m *RouteMux) FilterParam(param string, filter http.HandlerFunc) {
	m.Filter(func(w http.ResponseWriter, r *http.Request) {
		p := r.URL.Query().Get(param)
		if len(p) > 0 {
			filter(w, r)
		}
	})
}

// Required by http.Handler interface. This method is invoked by the
// http server and will handle all page routing
func (m *RouteMux) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	requestPath := r.URL.Path

	//wrap the response writer, in our custom interface
	w := &responseWriter{writer: rw}

	//find a matching Route
	for _, route := range m.routes {

		//if the methods don't match, skip this handler
		//i.e if request.Method is 'PUT' Route.Method must be 'PUT'
		if r.Method != route.method {
			continue
		}

		//check if Route pattern matches url
		if !route.regex.MatchString(requestPath) {
			continue
		}

		//get submatches (params)
		matches := route.regex.FindStringSubmatch(requestPath)
		//double check that the Route matches the URL pattern.
		if len(matches[0]) != len(requestPath) {
			continue
		}

		if len(route.params) > 0 {
			//add url parameters to the query param map
			values := r.URL.Query()
			for i, match := range matches[1:] {
				values.Add(route.params[i], match)
			}

			//reassemble query params and add to RawQuery
			r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
			//r.URL.RawQuery = url.Values(values).Encode()
		}

		//execute middleware filters
		for _, filter := range m.filters {
			filter(w, r)
			if w.started {
				return
			}
		}

		//Invoke the request handler
		route.handler(w, r)
		break
	}

	//if no matches to url, throw a not found exception
	if w.started == false {
		http.NotFound(w, r)
	}
}

// -----------------------------------------------------------------------------
// Simple wrapper around a ResponseWriter

// responseWriter is a wrapper for the http.ResponseWriter
// to track if response was written to. It also allows us
// to automatically set certain headers, such as Content-Type,
// Access-Control-Allow-Origin, etc.
type responseWriter struct {
	writer  http.ResponseWriter
	started bool
	status  int
}

// Header returns the header map that will be sent by WriteHeader.
func (w *responseWriter) Header() http.Header {
	return w.writer.Header()
}

// Write writes the data to the connection as part of an HTTP reply,
// and sets `started` to true
func (w *responseWriter) Write(p []byte) (int, error) {
	w.started = true
	return w.writer.Write(p)
}

// WriteHeader sends an HTTP response header with status code,
// and sets `started` to true
func (w *responseWriter) WriteHeader(code int) {
	w.status = code
	w.started = true
	w.writer.WriteHeader(code)
}

/*
// -----------------------------------------------------------------------------
// Below are helper functions to replace boilerplate
// code that serializes resources and writes to the
// http response.

// ServeJson replies to the request with a JSON
// representation of resource v.
func ServeJson(w http.ResponseWriter, v interface{}) {
	content, err := json.MarshalIndent(v, "", "  ")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Length", strconv.Itoa(len(content)))
	w.Header().Set("Content-Type", applicationJson)
	w.Write(content)
}

// ReadJson will parses the JSON-encoded data in the http
// Request object and stores the result in the value
// pointed to by v.
func ReadJson(r *http.Request, v interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return err
	}
	return json.Unmarshal(body, v)
}

// ServeXml replies to the request with an XML
// representation of resource v.
func ServeXml(w http.ResponseWriter, v interface{}) {
	content, err := xml.Marshal(v)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Length", strconv.Itoa(len(content)))
	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.Write(content)
}

// ReadXml will parses the XML-encoded data in the http
// Request object and stores the result in the value
// pointed to by v.
func ReadXml(r *http.Request, v interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return err
	}
	return xml.Unmarshal(body, v)
}

// ServeFormatted replies to the request with
// a formatted representation of resource v, in the
// format requested by the client specified in the
// Accept header.
func ServeFormatted(w http.ResponseWriter, r *http.Request, v interface{}) {
	accept := r.Header.Get("Accept")
	switch accept {
	case applicationJson:
		ServeJson(w, v)
	case applicationXml, textXml:
		ServeXml(w, v)
	default:
		ServeJson(w, v)
	}

	return
}

func Run(mux http.Handler, addr string, withTLS bool, crtPath, keyPath string) {
	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)
	srv := &http.Server{
		Addr:           addr,
		Handler:        mux,
		ReadTimeout:    5 * time.Second,
		WriteTimeout:   30 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}

	go func() {
		if withTLS {
			fmt.Println(srv.ListenAndServeTLS(crtPath, keyPath))
		} else {
			fmt.Println(srv.ListenAndServe())
		}
	}()

	<-stopChan
	fmt.Println("Shutting down server...")

	ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)
	srv.Shutdown(ctx)

	if nil != ctx.Err() {
		fmt.Println(ctx.Err().Error())
	}

}
*/
<|endoftext|>


<commit_before>package main

import (
	neural "./neural"
	problems "./problems"
	"fmt"
	sdl "github.com/veandco/go-sdl2/sdl"
	"math"
	"runtime"
	"sort"
	"time"
)

type FBird struct {
	bird  *problems.Bird
	brain *neural.Net
	bestX float64
	dead  bool
}

type Flock []FBird

func (birds Flock) Len() int {
	return len(birds)
}

func (birds Flock) Less(c, r int) bool {
	return birds[c].bestX > birds[r].bestX
}

func (birds Flock) Swap(c, r int) {
	birds[c], birds[r] = birds[r], birds[c]
}

// will check if going from pos to next will collide
func checkFlock(birds Flock, lvl *problems.Level) {

	collide := func(aX, bX, cX float64) bool {
		// c.X == d.X
		return aX-1 <= cX && bX+1 >= cX
	}

	hSize := float64(problems.PylonHole / 2)

	for c := range birds {
		if birds[c].bird.Pos.Y >= lvl.GetSize().Y || birds[c].bird.Pos.Y < 1 {
			// hit ceeling or floor
			birds[c].dead = true
			continue
		}

		pylon := lvl.ClosestPylon(&birds[c].bird.Pos)
		if birds[c].bird.Pos.Y >= pylon.Y-hSize && birds[c].bird.Pos.Y <= pylon.Y+hSize {
			// in the pylon hole
			continue
		}

		if birds[c].bird.Pos.Y > pylon.Y {
			// bottom pylon segment
			birds[c].dead = collide(birds[c].bird.Pos.X, birds[c].bird.NextPos.X, pylon.X)
		} else {
			// top pylon segment
			birds[c].dead = collide(birds[c].bird.Pos.X, birds[c].bird.NextPos.X, pylon.X)
		}
	}

}

func thnikFlock(birds Flock, lvl *problems.Level) {
	wg := make(chan struct{}, len(birds))

	thinkBird := func(c int) {
		next := lvl.FirstPylonAfter(&birds[c].bird.Pos)
		diffY := next.Y - birds[c].bird.Pos.Y
		diffX := next.X - birds[c].bird.Pos.X

		birds[c].brain.Stimulate(0, diffY)
		birds[c].brain.Stimulate(1, diffX)
		birds[c].brain.Stimulate(2, birds[c].bird.Vel.Y)

		birds[c].brain.Step()
		if birds[c].brain.ValueOf(7) > 0.75 {
			birds[c].bird.Vel.Y = -0.4
		}

		birds[c].brain.Clear()
		wg <- struct{}{}
	}

	for c := 0; c < len(birds); c++ {
		go thinkBird(c)
	}

	for c := 0; c < len(birds); c++ {
		<-wg
	}
}

func mutateFlock(birds Flock, lvl *problems.Level) {
	sort.Sort(birds)

	randNet := func() *neural.Net {
		return birds[int(neural.RandMax(float64(len(birds))))].brain
	}

	best := birds[0].brain

	for c := range birds {
		if birds[c].dead {
			birds[c].dead = false
			birds[c].bird.Pos = *lvl.NewBirdPos()
			birds[c].bird.Vel = *problems.NewVector(0.1, 0)

			birds[c].brain = neural.Cross(best, randNet())

			if neural.Chance(0.1) {
				// penalize best achievement due to mutation
				birds[c].bestX *= 0.99
				birds[c].brain.Mutate(0.33)
			}
		} else {
			birds[c].bird.Pos = birds[c].bird.NextPos
			birds[c].bestX = math.Max(birds[c].bird.Pos.X, birds[c].bestX)
		}
	}

}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	doDraw := true

	W := 1500
	H := 800
	LVL_W := W * 50
	fmt.Println(W, H)
	var FPS float64 = 60.0

	lvl := problems.NewLevel(LVL_W, H)

	sdl.Init(sdl.INIT_EVERYTHING)

	window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		int(W), int(H), sdl.WINDOW_SHOWN)
	if err != nil {
		panic(err)
	}
	defer window.Destroy()

	surface, err := window.GetSurface()
	if err != nil {
		panic(err)
	}

	rect := sdl.Rect{0, 0, 5, 5}
	clearRect := sdl.Rect{0, 0, int32(W), int32(H)}
	surface.FillRect(&clearRect, 0xffffffff)

	bcount := 10000

	nets := make([]*neural.Net, bcount, bcount)
	for c := range nets {
		nets[c] = neural.NewNet(8)

		// diffY- to hidden
		*nets[c].Synapse(0, 3) = 0.0
		*nets[c].Synapse(0, 4) = 0.0
		*nets[c].Synapse(0, 5) = 0.0
		*nets[c].Synapse(0, 6) = 0.0

		// diffX- to hidden
		*nets[c].Synapse(1, 3) = 0.0
		*nets[c].Synapse(1, 4) = 0.0
		*nets[c].Synapse(1, 5) = 0.0
		*nets[c].Synapse(1, 6) = 0.0

		// velY - to hidden
		*nets[c].Synapse(2, 3) = 0.0
		*nets[c].Synapse(2, 4) = 0.0
		*nets[c].Synapse(2, 5) = 0.0
		*nets[c].Synapse(2, 6) = 0.0

		// hidden to output
		*nets[c].Synapse(3, 7) = 0.0
		*nets[c].Synapse(4, 7) = 0.0
		*nets[c].Synapse(5, 7) = 0.0
		*nets[c].Synapse(6, 7) = 0.0

		nets[c].Randomize()
	}

	lvl.AddBirds(bcount)
	flock := make(Flock, bcount)
	for c := 0; c < bcount; c++ {
		flock[c].bird = (*lvl.GetBirds())[c]
		flock[c].brain = nets[c]
		flock[c].bestX = 0
	}

	offset := 0
	step := 65

	frame := 0
	var frameTime float64 = 1000 / FPS
	start := time.Now()
	for {

		frame++
		thnikFlock(flock, lvl)

		visible := func(x float64) bool {
			return x >= float64(offset) && x < float64(offset+W)
		}

		toScreen := func(x float64) float64 {
			return float64(x - float64(offset))
		}

		brds := *lvl.GetBirds()
		for _, brd := range brds {
			if !visible(brd.Pos.X) {
				continue
			}

			rect.X = int32(toScreen(brd.Pos.X))
			rect.Y = int32(brd.Pos.Y)
			rect.W = 5
			rect.H = 5
			if doDraw {
				surface.FillRect(&rect, 0xffff0000)
			}
		}

		hSize := float64(problems.PylonHole) / 2.0
		for _, pylon := range lvl.GetPylons() {
			if !visible(pylon.X) {
				continue
			}

			rect.X = int32(toScreen(pylon.X))
			rect.Y = int32(0)
			rect.W = 5

			// top part
			rect.H = int32(pylon.Y - hSize)
			if doDraw {
				surface.FillRect(&rect, 0xff00ff00)
			}

			// bottom part
			rect.Y = int32(pylon.Y + hSize)
			rect.H = int32(float64(H) - (pylon.Y + hSize))
			if doDraw {
				surface.FillRect(&rect, 0xff00ff00)
			}

			rect.Y = int32(pylon.Y)
			rect.W = 3
			rect.H = 3
			if doDraw {
				surface.FillRect(&rect, 0xff0000ff)
			}
		}

		elapsed := time.Since(start)

		if doDraw && frameTime < 1000.0/FPS {
			time.Sleep(time.Millisecond * time.Duration(1000.0/FPS-frameTime))
		}

		start = time.Now()

		frameTime = frameTime*0.9 + float64(elapsed.Nanoseconds())*0.1

		if frame > 60 {
			frame = 0
			fmt.Printf("fps last: %s\tfps average %f\tcompletion %f%%\n", elapsed, frameTime/1000000.0, flock[0].bestX/float64(LVL_W)*100.0)
		}

		window.UpdateSurface()
		lvl.Step(float64(elapsed.Nanoseconds()) / 1000000.0)
		checkFlock(flock, lvl)

		if doDraw {
			surface.FillRect(&clearRect, 0xffffffff)
		}

		stop := false
		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				stop = true
			case *sdl.KeyDownEvent:
				switch t.Keysym.Sym {
				case sdl.K_LEFT:
					offset = int(math.Max(0, float64(offset-step)))
				case sdl.K_RIGHT:
					offset = int(math.Min(float64(LVL_W-W), float64(offset+step)))
				case sdl.K_SPACE:
					doDraw = !doDraw
					surface.FillRect(&clearRect, 0xffaaaaaa)
				}
			}
		}

		if stop {
			break
		}

		mutateFlock(flock, lvl)
	}

	sdl.Quit()
}
<commit_msg>Change neurons to be named<commit_after>package main

import (
	neural "./neural"
	problems "./problems"
	"fmt"
	sdl "github.com/veandco/go-sdl2/sdl"
	"math"
	"runtime"
	"sort"
	"time"
)

type NeuronName int

const (
	diffY NeuronName = iota
	diffX NeuronName = iota
	velY  NeuronName = iota
	H1    NeuronName = iota
	H2    NeuronName = iota
	H3    NeuronName = iota
	H4    NeuronName = iota
	jump  NeuronName = iota
)

func nrn(name NeuronName) int {
	return int(name)
}

type FBird struct {
	bird  *problems.Bird
	brain *neural.Net
	bestX float64
	dead  bool
}

type Flock []FBird

func (birds Flock) Len() int {
	return len(birds)
}

func (birds Flock) Less(c, r int) bool {
	return birds[c].bestX > birds[r].bestX
}

func (birds Flock) Swap(c, r int) {
	birds[c], birds[r] = birds[r], birds[c]
}

// will check if going from pos to next will collide
func checkFlock(birds Flock, lvl *problems.Level) {

	collide := func(aX, bX, cX float64) bool {
		// c.X == d.X
		return aX-1 <= cX && bX+1 >= cX
	}

	hSize := float64(problems.PylonHole / 2)

	for c := range birds {
		if birds[c].bird.Pos.Y >= lvl.GetSize().Y || birds[c].bird.Pos.Y < 1 {
			// hit ceeling or floor
			birds[c].dead = true
			continue
		}

		pylon := lvl.ClosestPylon(&birds[c].bird.Pos)
		if birds[c].bird.Pos.Y >= pylon.Y-hSize && birds[c].bird.Pos.Y <= pylon.Y+hSize {
			// in the pylon hole
			continue
		}

		if birds[c].bird.Pos.Y > pylon.Y {
			// bottom pylon segment
			birds[c].dead = collide(birds[c].bird.Pos.X, birds[c].bird.NextPos.X, pylon.X)
		} else {
			// top pylon segment
			birds[c].dead = collide(birds[c].bird.Pos.X, birds[c].bird.NextPos.X, pylon.X)
		}
	}

}

func thnikFlock(birds Flock, lvl *problems.Level) {
	wg := make(chan struct{}, len(birds))

	thinkBird := func(c int) {
		next := lvl.FirstPylonAfter(&birds[c].bird.Pos)
		diffYval := next.Y - birds[c].bird.Pos.Y
		diffXval := next.X - birds[c].bird.Pos.X

		birds[c].brain.Stimulate(nrn(diffY), diffYval)
		birds[c].brain.Stimulate(nrn(diffX), diffXval)
		birds[c].brain.Stimulate(nrn(velY), birds[c].bird.Vel.Y)

		birds[c].brain.Step()
		if birds[c].brain.ValueOf(nrn(jump)) > 0.75 {
			birds[c].bird.Vel.Y = -0.4
		}

		birds[c].brain.Clear()
		wg <- struct{}{}
	}

	for c := 0; c < len(birds); c++ {
		go thinkBird(c)
	}

	for c := 0; c < len(birds); c++ {
		<-wg
	}
}

func mutateFlock(birds Flock, lvl *problems.Level) {
	sort.Sort(birds)

	randNet := func() *neural.Net {
		return birds[int(neural.RandMax(float64(len(birds))))].brain
	}

	best := birds[0].brain

	for c := range birds {
		if birds[c].dead {
			birds[c].dead = false
			birds[c].bird.Pos = *lvl.NewBirdPos()
			birds[c].bird.Vel = *problems.NewVector(0.1, 0)

			birds[c].brain = neural.Cross(best, randNet())

			if neural.Chance(0.1) {
				// penalize best achievement due to mutation
				birds[c].bestX *= 0.99
				birds[c].brain.Mutate(0.33)
			}
		} else {
			birds[c].bird.Pos = birds[c].bird.NextPos
			birds[c].bestX = math.Max(birds[c].bird.Pos.X, birds[c].bestX)
		}
	}

}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	doDraw := true

	W := 1500
	H := 800
	LVL_W := W * 50
	fmt.Println(W, H)
	var FPS float64 = 60.0

	lvl := problems.NewLevel(LVL_W, H)

	sdl.Init(sdl.INIT_EVERYTHING)

	window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		int(W), int(H), sdl.WINDOW_SHOWN)
	if err != nil {
		panic(err)
	}
	defer window.Destroy()

	surface, err := window.GetSurface()
	if err != nil {
		panic(err)
	}

	rect := sdl.Rect{0, 0, 5, 5}
	clearRect := sdl.Rect{0, 0, int32(W), int32(H)}
	surface.FillRect(&clearRect, 0xffffffff)

	bcount := 10000

	nets := make([]*neural.Net, bcount, bcount)
	for c := range nets {
		nets[c] = neural.NewNet(8)

		// diffY- to hidden
		*nets[c].Synapse(nrn(diffY), nrn(H1)) = 0.0
		*nets[c].Synapse(nrn(diffY), nrn(H2)) = 0.0
		*nets[c].Synapse(nrn(diffY), nrn(H3)) = 0.0
		*nets[c].Synapse(nrn(diffY), nrn(H4)) = 0.0

		// diffX- to hidden
		*nets[c].Synapse(nrn(diffX), nrn(H1)) = 0.0
		*nets[c].Synapse(nrn(diffX), nrn(H2)) = 0.0
		*nets[c].Synapse(nrn(diffX), nrn(H3)) = 0.0
		*nets[c].Synapse(nrn(diffX), nrn(H4)) = 0.0

		// velY - to hidden
		*nets[c].Synapse(nrn(velY), nrn(H1)) = 0.0
		*nets[c].Synapse(nrn(velY), nrn(H2)) = 0.0
		*nets[c].Synapse(nrn(velY), nrn(H3)) = 0.0
		*nets[c].Synapse(nrn(velY), nrn(H4)) = 0.0

		// hidden to output
		*nets[c].Synapse(nrn(H1), nrn(jump)) = 0.0
		*nets[c].Synapse(nrn(H2), nrn(jump)) = 0.0
		*nets[c].Synapse(nrn(H3), nrn(jump)) = 0.0
		*nets[c].Synapse(nrn(H4), nrn(jump)) = 0.0

		nets[c].Randomize()
	}

	lvl.AddBirds(bcount)
	flock := make(Flock, bcount)
	for c := 0; c < bcount; c++ {
		flock[c].bird = (*lvl.GetBirds())[c]
		flock[c].brain = nets[c]
		flock[c].bestX = 0
	}

	offset := 0
	step := 65

	frame := 0
	var frameTime float64 = 1000 / FPS
	start := time.Now()
	for {

		frame++
		thnikFlock(flock, lvl)

		visible := func(x float64) bool {
			return x >= float64(offset) && x < float64(offset+W)
		}

		toScreen := func(x float64) float64 {
			return float64(x - float64(offset))
		}

		brds := *lvl.GetBirds()
		for _, brd := range brds {
			if !visible(brd.Pos.X) {
				continue
			}

			rect.X = int32(toScreen(brd.Pos.X))
			rect.Y = int32(brd.Pos.Y)
			rect.W = 5
			rect.H = 5
			if doDraw {
				surface.FillRect(&rect, 0xffff0000)
			}
		}

		hSize := float64(problems.PylonHole) / 2.0
		for _, pylon := range lvl.GetPylons() {
			if !visible(pylon.X) {
				continue
			}

			rect.X = int32(toScreen(pylon.X))
			rect.Y = int32(0)
			rect.W = 5

			// top part
			rect.H = int32(pylon.Y - hSize)
			if doDraw {
				surface.FillRect(&rect, 0xff00ff00)
			}

			// bottom part
			rect.Y = int32(pylon.Y + hSize)
			rect.H = int32(float64(H) - (pylon.Y + hSize))
			if doDraw {
				surface.FillRect(&rect, 0xff00ff00)
			}

			rect.Y = int32(pylon.Y)
			rect.W = 3
			rect.H = 3
			if doDraw {
				surface.FillRect(&rect, 0xff0000ff)
			}
		}

		elapsed := time.Since(start)

		if doDraw && frameTime < 1000.0/FPS {
			time.Sleep(time.Millisecond * time.Duration(1000.0/FPS-frameTime))
		}

		start = time.Now()

		frameTime = frameTime*0.9 + float64(elapsed.Nanoseconds())*0.1

		if frame > 60 {
			frame = 0
			fmt.Printf("fps last: %s\tfps average %f\tcompletion %f%%\n", elapsed, frameTime/1000000.0, flock[0].bestX/float64(LVL_W)*100.0)
		}

		window.UpdateSurface()
		lvl.Step(float64(elapsed.Nanoseconds()) / 1000000.0)
		checkFlock(flock, lvl)

		if doDraw {
			surface.FillRect(&clearRect, 0xffffffff)
		}

		stop := false
		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				stop = true
			case *sdl.KeyDownEvent:
				switch t.Keysym.Sym {
				case sdl.K_LEFT:
					offset = int(math.Max(0, float64(offset-step)))
				case sdl.K_RIGHT:
					offset = int(math.Min(float64(LVL_W-W), float64(offset+step)))
				case sdl.K_SPACE:
					doDraw = !doDraw
					surface.FillRect(&clearRect, 0xffaaaaaa)
				}
			}
		}

		if stop {
			break
		}

		mutateFlock(flock, lvl)
	}

	sdl.Quit()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
	"sync"
)

type tinyCache struct {
	cache map[string]string
	l     sync.RWMutex
}

func newTinyCache() (sc tinyCache, err error) {
	sc = tinyCache{
		cache: make(map[string]string),
	}
	return sc, nil
}

func (sc *tinyCache) set(key string, value string) error {

	if strings.Trim(key, " ") == "" {
		return fmt.Errorf("simpleCache.set(key, value) needs a key different than an empty string")
	}

	sc.l.Lock()
	defer sc.l.Unlock()
	sc.cache[key] = value

	return nil
}

func (sc *tinyCache) get(key string) (value string, err error) {

	if strings.Trim(key, " ") == "" {
		return "", fmt.Errorf("simpleCache.get(key string) needs a key different than an empty string")
	}

	sc.l.RLock()
	defer sc.l.RUnlock()
	v, exists := sc.cache[key]

	if !exists {
		return "", nil
	}

	return v, nil
}

func main() {
	fmt.Println("Hello, playground")
}
<commit_msg>mend<commit_after><|endoftext|>


<commit_before>// main.go
package main

import (
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"time"
)

const (
	SLEEP_TIME          = 3 * time.Second
	KEYBOARD_BUFER_SIZE = 10000
)

func GetKeymapFromOutput(buf []byte) map[uint8]string {
	return make(map[uint8]string)
}

// Extract pressed keys from bufer buf
// It returns slice with key numbers in the same order
func GetKeyNumsFromOutput(buf []byte) []uint8 {
	const KEY_NUM_STRING_RE = "press[ ]+(\\d+)"
	re := regexp.MustCompile(KEY_NUM_STRING_RE)
	res_byte := re.FindAll(buf, -1)
	keyNums := make([]uint8, len(res_byte))
	re = regexp.MustCompile("\\d+")
	for i, line := range res_byte {
		num_byte := re.Find(line)
		if num, err := strconv.Atoi(string(num_byte)); err == nil {
			keyNums[i] = uint8(num)
		} else {
			log.Fatal(err)
		}
	}
	return keyNums
}

func main() {

	keyboard_id := 14
	cmd := exec.Command("xinput", "test", strconv.Itoa(keyboard_id))

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, KEYBOARD_BUFER_SIZE)
	for {
		n, err := stdout.Read(buf)
		if err != nil {
			log.Fatal(err)
		}
		// processing buf here
		fmt.Println(n)
		time.Sleep(SLEEP_TIME)
	}
}
<commit_msg>Added GetKeymap function, added docs for GetKeymapOutput and GetKeymapFromOutput<commit_after>// main.go
package main

import (
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"time"
)

const (
	SLEEP_TIME          = 3 * time.Second
	KEYBOARD_BUFER_SIZE = 10000
	KEYMAP_BUFFER_SIZE  = 32000
)

// Return map from key numbers to key names like "F1", "Tab", "d"
func GetKeymap() map[uint8]string {
	return GetKeymapFromOutput(GetKeymapOutput())
}

// Return output of utility that prints system keymap
func GetKeymapOutput() []byte {
	cmd := exec.Command("xmodmap", "-pke")
	out, err := cmd.Output()
	if err != nil {
		log.Fatal(err)
	}
	return out
}

// Return map with keymap from text
func GetKeymapFromOutput(buf []byte) map[uint8]string {
	return make(map[uint8]string)
}

// Extract pressed keys from bufer buf
// It returns slice with key numbers in the same order
func GetKeyNumsFromOutput(buf []byte) []uint8 {
	const KEY_NUM_STRING_RE = "press[ ]+(\\d+)"
	re := regexp.MustCompile(KEY_NUM_STRING_RE)
	res_byte := re.FindAll(buf, -1)
	keyNums := make([]uint8, len(res_byte))
	re = regexp.MustCompile("\\d+")
	for i, line := range res_byte {
		num_byte := re.Find(line)
		if num, err := strconv.Atoi(string(num_byte)); err == nil {
			keyNums[i] = uint8(num)
		} else {
			log.Fatal(err)
		}
	}
	return keyNums
}

func main() {

	keyboard_id := 14
	cmd := exec.Command("xinput", "test", strconv.Itoa(keyboard_id))

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, KEYBOARD_BUFER_SIZE)
	for {
		n, err := stdout.Read(buf)
		if err != nil {
			log.Fatal(err)
		}
		// processing buf here
		fmt.Println(n)
		time.Sleep(SLEEP_TIME)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"net/http"
	"net/url"
)

var sqlString string = "gimvic:GimVicServer@/gimvic"

func main() {
	http.HandleFunc("/chooserOptions", chooserOptions)
	http.HandleFunc("/data", data)
	http.ListenAndServe(":8080", nil)
}

func data(w http.ResponseWriter, r *http.Request) {
	queries := parseUrl(r)

	result := DataResponse{}
	if queries["type"][0] == "hybrid" {
		result.Days = pureScedule(queries)
	}

	jsonStr, err := json.Marshal(result)
	check(err)
	fmt.Fprint(w, string(jsonStr))
}

func pureScedule(queries map[string][]string) [5]Day {
	var days [5]Day
	con, err := sql.Open("mysql", sqlString)
	check(err)
	defer con.Close()

	where := ""
	for _, class := range queries["classes"] {
		if where != "" {
			where += " or "
		}
		where += "class='" + class + "'"
	}
	rows, err := con.Query("select class, teacher, subject, classroom, day, lesson from schedule where " + where + ";")
	check(err)
	var class, teacher, subject, classroom string
	var day, lesson int
	for rows.Next() {
		rows.Scan(&class, &teacher, &subject, &classroom, &day, &lesson)
		fmt.Println(lesson - 1)
		days[day-1].Lessons[lesson-1].Classes = append(days[day-1].Lessons[lesson-1].Classes, class)
		days[day-1].Lessons[lesson-1].Teachers = append(days[day-1].Lessons[lesson-1].Teachers, teacher)
		days[day-1].Lessons[lesson-1].Subjects = append(days[day-1].Lessons[lesson-1].Subjects, subject)
		days[day-1].Lessons[lesson-1].Classrooms = append(days[day-1].Lessons[lesson-1].Classrooms, classroom)
	}

	return days
}
func chooserOptions(w http.ResponseWriter, r *http.Request) {
	response := ChooserOptionsResponse{}
	con, err := sql.Open("mysql", sqlString)
	check(err)
	defer con.Close()

	//fill main classes
	rows, err := con.Query("select class from classes where main=1;")
	check(err)
	for rows.Next() {
		var temp string
		rows.Scan(&temp)
		response.MainClasses = append(response.MainClasses, temp)
	}

	//fill additional classes
	rows, err = con.Query("select class from classes where main=0;")
	check(err)
	for rows.Next() {
		var temp string
		rows.Scan(&temp)
		response.AdditionalClasses = append(response.AdditionalClasses, temp)
	}

	responseStr, err := json.Marshal(response)
	check(err)
	fmt.Fprint(w, string(responseStr))
}

func parseUrl(r *http.Request) map[string][]string {
	str := r.URL.String()
	u, err := url.Parse(str)
	check(err)
	m, err := url.ParseQuery(u.RawQuery)
	check(err)
	return m
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

type ChooserOptionsResponse struct {
	MainClasses       []string `json:"mainClasses,omitempty"`
	AdditionalClasses []string `json:"additionalClasses,omitempty"`
	ValidUntil        string   `json:"validUntil,omitempty"`
}

type DataResponse struct {
	Days [5]Day `json:"days,omitempty"`
	Hash string `json:"hash,omitempty"`
}

type Day struct {
	Lessons    [8]Lesson `json:"lessons,omitempty"`
	SnackLines []string  `json:"snackLines,omitempty"`
	LunchLines []string  `json:"lunchLines,omitempty"`
}

type Lesson struct {
	Subjects       []string `json:"subjects,omitempty"`
	Teachers       []string `json:"teachers,omitempty"`
	Classrooms     []string `json:"classrooms,omitempty"`
	Classes        []string `json:"classes,omitempty"`
	Note           string   `json:"note,omitempty"`
	Lesson         int      `json:"lesson,omitempty"`
	Day            int      `json:"day,omitempty"`
	IsSubstitution bool     `json:"substitution"`
}
<commit_msg>substitutions rendering added<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/now"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

var sqlString string = "gimvic:GimVicServer@/gimvic"
var oneDay time.Duration = time.Date(2015, 11, 30, 0, 0, 0, 0, time.UTC).Sub(time.Date(2015, 11, 29, 0, 0, 0, 0, time.UTC))

func main() {
	http.HandleFunc("/chooserOptions", chooserOptions)
	http.HandleFunc("/data", data)
	http.ListenAndServe(":8080", nil)
}

func data(w http.ResponseWriter, r *http.Request) {
	queries := parseUrl(r)
	addSubs, classes, _, _ := parseQueries(queries)
	result := DataResponse{}

	result.Days = pureScedule(classes)

	if addSubs {
		result.Days = addSubstitutions(result.Days, classes)
	}
	jsonStr, err := json.Marshal(result)
	check(err)
	fmt.Fprint(w, string(jsonStr))
}

func addSubstitutions(days [5]Day, classes []string) [5]Day {
	now.FirstDayMonday = true
	date := now.BeginningOfWeek()

	for i := 0; i < 5; i++ {
		where := "("
		for _, class := range classes {
			if where != "(" {
				where += " or "
			}
			where += "class='" + class + "'"
		}
		dateStr := strconv.Itoa(date.Year()) + "-" + strconv.Itoa(int(date.Month())) + "-" + strconv.Itoa(date.Day())
		where += ") and date='" + dateStr + "'"

		con, err := sql.Open("mysql", sqlString)
		check(err)
		defer con.Close()
		rows, err := con.Query("select class, teacher, subject, classroom, lesson, note from substitutions where " + where + ";")
		check(err)
		var class, teacher, subject, classroom, note string
		var lesson int
		for rows.Next() {
			rows.Scan(&class, &teacher, &subject, &classroom, &lesson, &note)

			days[i].Lessons[lesson-1].IsSubstitution = true

			days[i].Lessons[lesson-1].Classes = days[i].Lessons[lesson-1].Classes[:0]
			days[i].Lessons[lesson-1].Classes = append(days[i].Lessons[lesson-1].Classes, class)

			days[i].Lessons[lesson-1].Teachers = days[i].Lessons[lesson-1].Teachers[:0]
			days[i].Lessons[lesson-1].Teachers = append(days[i].Lessons[lesson-1].Teachers, teacher)

			days[i].Lessons[lesson-1].Subjects = days[i].Lessons[lesson-1].Subjects[:0]
			days[i].Lessons[lesson-1].Subjects = append(days[i].Lessons[lesson-1].Subjects, subject)

			days[i].Lessons[lesson-1].Classrooms = days[i].Lessons[lesson-1].Classrooms[:0]
			days[i].Lessons[lesson-1].Classrooms = append(days[i].Lessons[lesson-1].Classrooms, classroom)

			days[i].Lessons[lesson-1].Note = note
		}

		date = date.Add(oneDay)
	}

	return days
}

func parseQueries(q map[string][]string) (addSubstitutions bool, classes []string, snackType, lunchType string) {
	addSubs := false
	if q["addSubstitutions"][0] == "true" {
		addSubs = true
	}
	resultClasses := q["classes"]
	resSnackType := q["snackType"][0]
	resLunchType := q["lunchType"][0]

	return addSubs, resultClasses, resSnackType, resLunchType

}

func pureScedule(classes []string) [5]Day {
	var days [5]Day
	con, err := sql.Open("mysql", sqlString)
	check(err)
	defer con.Close()

	where := ""
	for _, class := range classes {
		if where != "" {
			where += " or "
		}
		where += "class='" + class + "'"
	}
	rows, err := con.Query("select class, teacher, subject, classroom, day, lesson from schedule where " + where + ";")
	check(err)
	var class, teacher, subject, classroom string
	var day, lesson int
	for rows.Next() {
		rows.Scan(&class, &teacher, &subject, &classroom, &day, &lesson)
		days[day-1].Lessons[lesson-1].Classes = append(days[day-1].Lessons[lesson-1].Classes, class)
		days[day-1].Lessons[lesson-1].Teachers = append(days[day-1].Lessons[lesson-1].Teachers, teacher)
		days[day-1].Lessons[lesson-1].Subjects = append(days[day-1].Lessons[lesson-1].Subjects, subject)
		days[day-1].Lessons[lesson-1].Classrooms = append(days[day-1].Lessons[lesson-1].Classrooms, classroom)
	}

	return days
}
func chooserOptions(w http.ResponseWriter, r *http.Request) {
	response := ChooserOptionsResponse{}
	con, err := sql.Open("mysql", sqlString)
	check(err)
	defer con.Close()

	//fill main classes
	rows, err := con.Query("select class from classes where main=1;")
	check(err)
	for rows.Next() {
		var temp string
		rows.Scan(&temp)
		response.MainClasses = append(response.MainClasses, temp)
	}

	//fill additional classes
	rows, err = con.Query("select class from classes where main=0;")
	check(err)
	for rows.Next() {
		var temp string
		rows.Scan(&temp)
		response.AdditionalClasses = append(response.AdditionalClasses, temp)
	}

	responseStr, err := json.Marshal(response)
	check(err)
	fmt.Fprint(w, string(responseStr))
}

func parseUrl(r *http.Request) map[string][]string {
	str := r.URL.String()
	u, err := url.Parse(str)
	check(err)
	m, err := url.ParseQuery(u.RawQuery)
	check(err)
	return m
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

type ChooserOptionsResponse struct {
	MainClasses       []string `json:"mainClasses,omitempty"`
	AdditionalClasses []string `json:"additionalClasses,omitempty"`
	ValidUntil        string   `json:"validUntil,omitempty"`
}

type DataResponse struct {
	Days [5]Day `json:"days,omitempty"`
	Hash string `json:"hash,omitempty"`
}

type Day struct {
	Lessons    [8]Lesson `json:"lessons,omitempty"`
	SnackLines []string  `json:"snackLines,omitempty"`
	LunchLines []string  `json:"lunchLines,omitempty"`
}

type Lesson struct {
	Subjects       []string `json:"subjects,omitempty"`
	Teachers       []string `json:"teachers,omitempty"`
	Classrooms     []string `json:"classrooms,omitempty"`
	Classes        []string `json:"classes,omitempty"`
	Note           string   `json:"note,omitempty"`
	Lesson         int      `json:"lesson,omitempty"`
	Day            int      `json:"day,omitempty"`
	IsSubstitution bool     `json:"substitution"`
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"os"
	"bytes"
	"strings"
	"json"
)

type message struct {
	message string
	channel chan *message
}

var reservationChannel = make(chan *message, 77)

func error(msg string, err os.Error) {
	fmt.Fprintf(os.Stderr, "error : %s%v\n", msg, err)
}

func readUntilCrLf(con *net.TCPConn) (line []byte, err os.Error) {

	buf := make([]byte, 1)
	var data []byte
	crSeen := false

	for {
		_, err := con.Read(buf)
		if err != nil {
			if err == os.EOF {
				break
			} else {
				return nil, err
			}
		}
		if crSeen {
			if buf[0] == 10 {
				break
			} else {
				crSeen = false
				data = bytes.Add(data, buf)
			}
		} else {
			if buf[0] == 13 {
				crSeen = true
			} else {
				data = bytes.Add(data, buf)
			}
		}
	}

	return data, nil
}

//func writeLine(con *net.TCPConn, line string) {
//	con.Write([]byte(line))
//	con.Write([]byte("\r\n"))
//}
func writeJson(con *net.TCPConn, data *interface{}) {
	bytes, _ := json.Marshal(data)
	con.Write(bytes)
	con.Write([]byte("\r\n"))
}
func writeJsonString(con *net.TCPConn, s string) {
	con.Write([]byte(fmt.Sprintf("\"%s\"\r\n", s)))
}

func doGet(con *net.TCPConn, args []string) {
	writeJsonString(con, args[0])
}
func doPut(con *net.TCPConn, args []string) {
	data, _ := readUntilCrLf(con)
	doc := new(map[string]interface{})
	json.Unmarshal(data, doc)
	//id, found := (*doc)["_id"]
	rev, found := (*doc)["_rev"]
	if !found {
		rev = 0
	}
	writeJson(con, &rev)
}

var commands = map[string]func(*net.TCPConn, []string){"get": doGet, "put": doPut}

func serve(con *net.TCPConn) {

	fmt.Fprintf(os.Stdout, "serving %s\n", con.RemoteAddr().String())

	for {

		line, err := readUntilCrLf(con)

		if err != nil {
			// TODO : pass error message
			con.Write([]byte("\"internal error\"\r\n"))
			continue
		}

		tokens := strings.Split(string(line), " ", -1)

		command := tokens[0]

		if command == "quit" {
			//writeLine(con, "\"bye.\"")
			writeJsonString(con, "bye.")
			con.Close()
			break
		}

		f, ok := commands[command]
		if ok {
			f(con, tokens[1:])
		} else {
			writeJsonString(con, fmt.Sprintf("unknown command '%s'", command))
		}
	}
}

func listen() {

	addr, err := net.ResolveTCPAddr("127.0.0.1:5555")
	if err != nil {
		panic("failed to resolve TCP address")
	}

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		panic("failed to listen on TCP address")
	}

	for {
		con, err := listener.AcceptTCP()
		if err != nil {
			error("problem with new connection", err)
		} else {
			go serve(con)
		}
	}
}

func manageReservations() {
	for {
		m := <-reservationChannel
		m.channel <- &message{m.message, nil}
	}
}

func main() {

	go manageReservations()
	listen()
}
<commit_msg>type document<commit_after>package main

import (
	"fmt"
	"net"
	"os"
	"bytes"
	"strings"
	"json"
)

type document map[string]interface{}

type reservation struct {
	typ string
	id  string
}

type request struct {
	typ     string
	id      string
	channel chan *reservation
}

func (r reservation) put(d *document) (doc *document, failure bool) {
	return nil, true
}
func (r reservation) delete(rev int64) (doc *document, failure bool) {
	return nil, true
}

var reservationChannel = make(chan *request, 77)

func error(msg string, err os.Error) {
	fmt.Fprintf(os.Stderr, "error : %s%v\n", msg, err)
}

func readUntilCrLf(con *net.TCPConn) (line []byte, err os.Error) {

	buf := make([]byte, 1)
	var data []byte
	crSeen := false

	for {
		_, err := con.Read(buf)
		if err != nil {
			if err == os.EOF {
				break
			} else {
				return nil, err
			}
		}
		if crSeen {
			if buf[0] == 10 {
				break
			} else {
				crSeen = false
				data = bytes.Add(data, buf)
			}
		} else {
			if buf[0] == 13 {
				crSeen = true
			} else {
				data = bytes.Add(data, buf)
			}
		}
	}

	return data, nil
}

//func writeLine(con *net.TCPConn, line string) {
//	con.Write([]byte(line))
//	con.Write([]byte("\r\n"))
//}
func writeJson(con *net.TCPConn, data *interface{}) {
	bytes, _ := json.Marshal(data)
	con.Write(bytes)
	con.Write([]byte("\r\n"))
}
func writeJsonString(con *net.TCPConn, s string) {
	con.Write([]byte(fmt.Sprintf("\"%s\"\r\n", s)))
}

//
// the commands

func doGet(con *net.TCPConn, args []string) {
	writeJsonString(con, args[0])
}
func doPut(con *net.TCPConn, args []string) {
	data, _ := readUntilCrLf(con)
	doc := new(document)
	json.Unmarshal(data, doc)
	//id, found := (*doc)["_id"]
	rev, found := (*doc)["_rev"]
	if !found {
		rev = 0
	}
	writeJson(con, &rev)
}

var commands = map[string]func(*net.TCPConn, []string){"get": doGet, "put": doPut}

//
// serving

func serve(con *net.TCPConn) {

	fmt.Fprintf(os.Stdout, "serving %s\n", con.RemoteAddr().String())

	for {

		line, err := readUntilCrLf(con)

		if err != nil {
			// TODO : pass error message
			con.Write([]byte("\"internal error\"\r\n"))
			continue
		}

		tokens := strings.Split(string(line), " ", -1)

		command := tokens[0]

		if command == "quit" {
			//writeLine(con, "\"bye.\"")
			writeJsonString(con, "bye.")
			con.Close()
			break
		}

		f, ok := commands[command]
		if ok {
			f(con, tokens[1:])
		} else {
			writeJsonString(con, fmt.Sprintf("unknown command '%s'", command))
		}
	}
}

func listen() {

	addr, err := net.ResolveTCPAddr("127.0.0.1:5555")
	if err != nil {
		panic("failed to resolve TCP address")
	}

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		panic("failed to listen on TCP address")
	}

	for {
		con, err := listener.AcceptTCP()
		if err != nil {
			error("problem with new connection", err)
		} else {
			go serve(con)
		}
	}
}

func manageReservations() {
	for {
		<-reservationChannel
		//m.channel <- &request{m.message, nil}
	}
}

func main() {

	go manageReservations()
	listen()
}
<|endoftext|>


<commit_before>package air

import "github.com/valyala/fasthttp"

type (
	// URI defines the interface for HTTP request uri.
	URI interface {
		// FullURI returns full uri in the form {Scheme}://{Host}{RequestURI}#{Hash}.
		FullURI() string

		// Path returns the request URI path.
		Path() string

		// SetPath sets the request URI path.
		SetPath(string)

		// QueryParam returns the query param for the provided name.
		QueryParam(string) string

		// QueryParam returns the query parameters as map.
		QueryParams() map[string][]string

		// QueryString returns the URI query string.
		QueryString() string
	}

	// FastURI implements `URI`.
	FastURI struct {
		*fasthttp.URI
	}
)

// FullURI implements `URI#FullURI` function.
func (u *FastURI) FullURI() string {
	return string(u.URI.FullURI())
}

// Path implements `URI#Path` function.
func (u *FastURI) Path() string {
	return string(u.URI.PathOriginal())
}

// SetPath implements `URI#SetPath` function.
func (u *FastURI) SetPath(path string) {
	u.URI.SetPath(path)
}

// QueryParam implements `URI#QueryParam` function.
func (u *FastURI) QueryParam(name string) string {
	return string(u.URI.QueryArgs().Peek(name))
}

// QueryParams implements `URI#QueryParams` function.
func (u *FastURI) QueryParams() (params map[string][]string) {
	params = make(map[string][]string)
	u.QueryArgs().VisitAll(func(k, v []byte) {
		_, ok := params[string(k)]
		if !ok {
			params[string(k)] = make([]string, 0)
		}
		params[string(k)] = append(params[string(k)], string(v))
	})
	return
}

// QueryString implements `URI#QueryString` function.
func (u *FastURI) QueryString() string {
	return string(u.URI.QueryString())
}

func (u *FastURI) reset(uri *fasthttp.URI) {
	u.URI = uri
}
<commit_msg>Format uri.go<commit_after>package air

import "github.com/valyala/fasthttp"

type (
	// URI defines the interface for HTTP request uri.
	URI interface {
		// FullURI returns full uri in the form {Scheme}://{Host}{RequestURI}#{Hash}.
		FullURI() string

		// Path returns the request URI path.
		Path() string

		// SetPath sets the request URI path.
		SetPath(string)

		// QueryParam returns the query param for the provided name.
		QueryParam(string) string

		// QueryParam returns the query parameters as map.
		QueryParams() map[string][]string

		// QueryString returns the URI query string.
		QueryString() string
	}

	// FastURI implements `URI`.
	FastURI struct {
		*fasthttp.URI
	}
)

// FullURI implements `URI#FullURI` function.
func (u *FastURI) FullURI() string {
	return string(u.URI.FullURI())
}

// Path implements `URI#Path` function.
func (u *FastURI) Path() string {
	return string(u.URI.PathOriginal())
}

// SetPath implements `URI#SetPath` function.
func (u *FastURI) SetPath(path string) {
	u.URI.SetPath(path)
}

// QueryParam implements `URI#QueryParam` function.
func (u *FastURI) QueryParam(name string) string {
	return string(u.URI.QueryArgs().Peek(name))
}

// QueryParams implements `URI#QueryParams` function.
func (u *FastURI) QueryParams() map[string][]string {
	params := make(map[string][]string)
	u.URI.QueryArgs().VisitAll(func(k, v []byte) {
		_, ok := params[string(k)]
		if !ok {
			params[string(k)] = make([]string, 0)
		}
		params[string(k)] = append(params[string(k)], string(v))
	})
	return
}

// QueryString implements `URI#QueryString` function.
func (u *FastURI) QueryString() string {
	return string(u.URI.QueryString())
}

func (u *FastURI) reset(uri *fasthttp.URI) {
	u.URI = uri
}
<|endoftext|>