<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/s3"

	"github.com/voxelbrain/goptions"
	"github.com/voxelbrain/kartoffelsack"
)

var (
	options = struct {
		Listen string        `goptions:"-l, --listen, description='Address to bind webserver to'"`
		Maps   []*Map        `goptions:"-m, --map, description='Map a path to a ressource', obligatory"`
		Help   goptions.Help `goptions:"-h, --help, description='Show this help'"`
	}{
		Listen: fmt.Sprintf(":%s", DefaultEnv("PORT", "8080")),
	}
)

func DefaultEnv(key, def string) string {
	if val := os.Getenv(key); val != "" {
		return val
	}
	return def
}

func main() {
	goptions.ParseAndFail(&options)

	for _, m := range options.Maps {
		if !strings.HasSuffix(m.Path, "/") {
			m.Path += "/"
		}
		var h http.Handler
		switch m.Ressource.Scheme {
		case "http", "https":
			h = kartoffelsack.NewSingleHostReverseProxy(m.Ressource)
		case "file":
			h = http.FileServer(http.Dir(m.Ressource.Path))
		case "s3":
			username := m.Ressource.User.Username()
			password, _ := m.Ressource.User.Password()
			region, err := regionByEndpoint(m.Ressource.Host)
			if err != nil {
				log.Fatalf("Could not connect to S3: %s", err)
			}
			auth := aws.Auth{
				AccessKey: username,
				SecretKey: password,
			}
			s3acc := s3.New(auth, region)
			h = &S3HTTP{s3acc.Bucket(m.Ressource.Path)}
		default:
			log.Fatalf("Unknown scheme: %s", m.Ressource.Scheme)
		}
		http.Handle(m.Path, http.StripPrefix(m.Path, h))
	}
	log.Printf("Starting webserver on %s...", options.Listen)
	err := http.ListenAndServe(options.Listen, nil)
	if err != nil {
		log.Fatalf("Could not start webserver: %s", err)
	}
}

func regionByEndpoint(endpoint string) (aws.Region, error) {
	for _, region := range aws.Regions {
		epURL, _ := url.Parse(region.S3Endpoint)
		if epURL.Host == endpoint {
			return region, nil
		}
	}
	return aws.Region{}, fmt.Errorf("No region with endpoint %s", endpoint)
}

type Map struct {
	Path      string
	Ressource *url.URL
}

func (m *Map) MarshalGoption(v string) error {
	maps := strings.Split(v, "=>")
	if len(maps) != 2 {
		return fmt.Errorf("Invalid mapping")
	}

	path := strings.TrimSpace(maps[0])
	rsrc, err := url.Parse(strings.TrimSpace(maps[1]))
	if err != nil {
		return fmt.Errorf("Invalid URI: %s", err)
	}

	m.Path = path
	m.Ressource = rsrc
	return nil
}

type S3HTTP struct {
	Bucket *s3.Bucket
}

func (s *S3HTTP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	f, err := s.Bucket.GetReader(r.URL.Path)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	defer f.Close()

	io.Copy(w, f)
}
<commit_msg>Add caching capabilities<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/s3"

	"github.com/voxelbrain/goptions"
	"github.com/voxelbrain/kartoffelsack"
)

var (
	options = struct {
		Listen        string        `goptions:"-l, --listen, description='Address to bind webserver to'"`
		CacheDuration time.Duration `goptions:"-c, --cache-duration, description='Duration to cache static content'"`
		Maps          []*Map        `goptions:"-m, --map, description='Map a path to a ressource', obligatory"`
		Help          goptions.Help `goptions:"-h, --help, description='Show this help'"`
	}{
		Listen:        fmt.Sprintf(":%s", DefaultEnv("PORT", "8080")),
		CacheDuration: 5 * time.Minute,
	}
)

func DefaultEnv(key, def string) string {
	if val := os.Getenv(key); val != "" {
		return val
	}
	return def
}

func main() {
	goptions.ParseAndFail(&options)

	for _, m := range options.Maps {
		if !strings.HasSuffix(m.Path, "/") {
			m.Path += "/"
		}
		var h http.Handler
		switch m.Ressource.Scheme {
		case "http", "https":
			h = kartoffelsack.NewSingleHostReverseProxy(m.Ressource)
		case "file":
			h = http.FileServer(http.Dir(m.Ressource.Path))
			h = kartoffelsack.NewCache(options.CacheDuration, h)
		case "s3":
			username := m.Ressource.User.Username()
			password, _ := m.Ressource.User.Password()
			region, err := regionByEndpoint(m.Ressource.Host)
			if err != nil {
				log.Fatalf("Could not connect to S3: %s", err)
			}
			auth := aws.Auth{
				AccessKey: username,
				SecretKey: password,
			}
			s3acc := s3.New(auth, region)
			h = &S3HTTP{s3acc.Bucket(m.Ressource.Path)}
			h = kartoffelsack.NewCache(options.CacheDuration, h)
		default:
			log.Fatalf("Unknown scheme: %s", m.Ressource.Scheme)
		}
		http.Handle(m.Path, http.StripPrefix(m.Path, h))
	}
	log.Printf("Starting webserver on %s...", options.Listen)
	err := http.ListenAndServe(options.Listen, nil)
	if err != nil {
		log.Fatalf("Could not start webserver: %s", err)
	}
}

func regionByEndpoint(endpoint string) (aws.Region, error) {
	for _, region := range aws.Regions {
		epURL, _ := url.Parse(region.S3Endpoint)
		if epURL.Host == endpoint {
			return region, nil
		}
	}
	return aws.Region{}, fmt.Errorf("No region with endpoint %s", endpoint)
}

type Map struct {
	Path      string
	Ressource *url.URL
}

func (m *Map) MarshalGoption(v string) error {
	maps := strings.Split(v, "=>")
	if len(maps) != 2 {
		return fmt.Errorf("Invalid mapping")
	}

	path := strings.TrimSpace(maps[0])
	rsrc, err := url.Parse(strings.TrimSpace(maps[1]))
	if err != nil {
		return fmt.Errorf("Invalid URI: %s", err)
	}

	m.Path = path
	m.Ressource = rsrc
	return nil
}

type S3HTTP struct {
	Bucket *s3.Bucket
}

func (s *S3HTTP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	key := r.URL.Path
	resp, err := s.Bucket.List(key, "", "", 2)
	if err != nil {
		log.Printf("Could not list bucket %s: %s", s.Bucket.Name, err)
		http.NotFound(w, r)
		return
	}
	if len(resp.Contents) != 1 {
		http.NotFound(w, r)
		return
	}

	w.Header().Set("Content-Length", fmt.Sprintf("%d", resp.Contents[0].Size))
	w.Header().Set("ETag", resp.Contents[0].ETag)
	f, _ := s.Bucket.GetReader(key)
	defer f.Close()

	io.Copy(w, f)
}
<|endoftext|>


<commit_before>package agent

import (
	"github.com/buildkite/agent/api"
	"github.com/buildkite/agent/logger"
)

type ArtifactBatchCreator struct {
	// The APIClient that will be used when uploading jobs
	APIClient *api.Client

	// The ID of the Job that these artifacts belong to
	JobID string

	// All the artifacts that need to be created
	Artifacts []*api.Artifact
}

func (a *ArtifactBatchCreator) Create() ([]*api.Artifact, error) {
	length := len(a.Artifacts)
	chunks := 10
	uploaded := []*api.Artifact{}

	// Split into the artifacts into chunks so we're not uploading a ton of
	// files at once.
	for i := 0; i < length; i += chunks {
		j := i + chunks
		if length < j {
			j = length
		}

		artifacts := a.Artifacts[i:j]

		logger.Info("Creating (%d-%d)/%d artifacts", i, j, length)

		u, _, err := a.APIClient.Artifacts.Create(a.JobID, artifacts)
		if err != nil {
			return nil, err
		}

		uploaded = append(uploaded, u...)
	}

	return uploaded, nil
}
<commit_msg>Retry batch artifact uploads.<commit_after>package agent

import (
	"github.com/buildkite/agent/api"
	"github.com/buildkite/agent/logger"
	"github.com/buildkite/agent/retry"
	"time"
)

type ArtifactBatchCreator struct {
	// The APIClient that will be used when uploading jobs
	APIClient *api.Client

	// The ID of the Job that these artifacts belong to
	JobID string

	// All the artifacts that need to be created
	Artifacts []*api.Artifact
}

func (a *ArtifactBatchCreator) Create() ([]*api.Artifact, error) {
	length := len(a.Artifacts)
	chunks := 10
	uploaded := []*api.Artifact{}

	// Split into the artifacts into chunks so we're not uploading a ton of
	// files at once.
	for i := 0; i < length; i += chunks {
		j := i + chunks
		if length < j {
			j = length
		}

		artifacts := a.Artifacts[i:j]

		logger.Info("Creating (%d-%d)/%d artifacts", i, j, length)

		var u []*api.Artifact
		var err error

		// Retry the batch upload a couple of times
		err = retry.Do(func(s *retry.Stats) error {
			u, _, err = a.APIClient.Artifacts.Create(a.JobID, artifacts)
			if err != nil {
				logger.Warn("%s (%s)", err, s)
			}

			return err
		}, &retry.Config{Maximum: 10, Interval: 1 * time.Second})
		if err != nil {
			return nil, err
		}

		uploaded = append(uploaded, u...)
	}

	return uploaded, nil
}
<|endoftext|>


<commit_before>package main

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

func (g *game) MonsterInLOS() *monster {
	for _, mons := range g.Monsters {
		if mons.Exists() && g.Player.LOS[mons.Pos] {
			return mons
		}
	}
	return nil
}

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

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

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

func (g *game) AttackMonster(mons *monster) {
	switch {
	case g.Player.Weapon.Cleave():
		var neighbors []position
		if g.Player.HasStatus(StatusConfusion) {
			neighbors = g.Dungeon.CardinalFreeNeighbors(g.Player.Pos)
		} else {
			neighbors = g.Dungeon.FreeNeighbors(g.Player.Pos)
		}
		for _, pos := range neighbors {
			mons, _ := g.MonsterAt(pos)
			if mons.Exists() {
				g.HitMonster(mons)
			}
		}
	case g.Player.Weapon.Pierce():
		g.HitMonster(mons)
		deltaX := mons.Pos.X - g.Player.Pos.X
		deltaY := mons.Pos.Y - g.Player.Pos.Y
		behind := position{g.Player.Pos.X + 2*deltaX, g.Player.Pos.Y + 2*deltaY}
		if g.Dungeon.Valid(behind) {
			mons, _ := g.MonsterAt(behind)
			if mons.Exists() {
				g.HitMonster(mons)
			}
		}
	default:
		g.HitMonster(mons)
		if (g.Player.Weapon == Sword || g.Player.Weapon == DoubleSword) && RandInt(4) == 0 {
			g.HitMonster(mons)
		}
	}
}

func (g *game) HitMonster(mons *monster) {
	acc := RandInt(g.Player.Accuracy())
	ev := RandInt(mons.Evasion)
	if acc > ev {
		g.MakeNoise(12, mons.Pos)
		bonus := 0
		if g.Player.HasStatus(StatusBerserk) {
			bonus += RandInt(5)
		}
		attack := g.HitDamage(g.Player.Attack()+bonus, mons.Armor)
		if mons.State == Resting {
			if g.Player.Weapon == Dagger {
				attack *= 5
			} else {
				attack *= 2
			}
		}
		mons.HP -= attack
		if mons.HP > 0 {
			g.Printf("You hit the %v (%d damage).", mons.Kind, attack)
		} else {
			g.Printf("You kill the %v (%d damage).", mons.Kind, attack)
			g.Killed++
		}
		mons.MakeHuntIfHurt(g)
	} else {
		g.Printf("You miss the %v.", mons.Kind)
	}
}

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

func (g *game) MPRegen(ev event) {
	if g.Player.MP < g.Player.MPMax() {
		g.Player.MP++
	}
	delay := 100
	ev.Renew(g, delay)
}
<commit_msg>make the noise only in the explosion case<commit_after>package main

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

func (g *game) MonsterInLOS() *monster {
	for _, mons := range g.Monsters {
		if mons.Exists() && g.Player.LOS[mons.Pos] {
			return mons
		}
	}
	return nil
}

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

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

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

func (g *game) AttackMonster(mons *monster) {
	switch {
	case g.Player.Weapon.Cleave():
		var neighbors []position
		if g.Player.HasStatus(StatusConfusion) {
			neighbors = g.Dungeon.CardinalFreeNeighbors(g.Player.Pos)
		} else {
			neighbors = g.Dungeon.FreeNeighbors(g.Player.Pos)
		}
		for _, pos := range neighbors {
			mons, _ := g.MonsterAt(pos)
			if mons.Exists() {
				g.HitMonster(mons)
			}
		}
	case g.Player.Weapon.Pierce():
		g.HitMonster(mons)
		deltaX := mons.Pos.X - g.Player.Pos.X
		deltaY := mons.Pos.Y - g.Player.Pos.Y
		behind := position{g.Player.Pos.X + 2*deltaX, g.Player.Pos.Y + 2*deltaY}
		if g.Dungeon.Valid(behind) {
			mons, _ := g.MonsterAt(behind)
			if mons.Exists() {
				g.HitMonster(mons)
			}
		}
	default:
		g.HitMonster(mons)
		if (g.Player.Weapon == Sword || g.Player.Weapon == DoubleSword) && RandInt(4) == 0 {
			g.HitMonster(mons)
		}
	}
}

func (g *game) HitMonster(mons *monster) {
	acc := RandInt(g.Player.Accuracy())
	ev := RandInt(mons.Evasion)
	if acc > ev {
		g.MakeNoise(12, mons.Pos)
		bonus := 0
		if g.Player.HasStatus(StatusBerserk) {
			bonus += RandInt(5)
		}
		attack := g.HitDamage(g.Player.Attack()+bonus, mons.Armor)
		if mons.State == Resting {
			if g.Player.Weapon == Dagger {
				attack *= 5
			} else {
				attack *= 2
			}
		}
		mons.HP -= attack
		if mons.HP > 0 {
			g.Printf("You hit the %v (%d damage).", mons.Kind, attack)
		} else {
			g.Printf("You kill the %v (%d damage).", mons.Kind, attack)
			g.Killed++
		}
		mons.MakeHuntIfHurt(g)
	} else {
		g.Printf("You miss the %v.", mons.Kind)
	}
}

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

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


<commit_before>package roaring

import (
	"container/heap"
)

// Or function that requires repairAfterLazy
func lazyOR(x1, x2 *Bitmap) *Bitmap {
	answer := NewBitmap()
	pos1 := 0
	pos2 := 0
	length1 := x1.highlowcontainer.size()
	length2 := x2.highlowcontainer.size()
main:
	for (pos1 < length1) && (pos2 < length2) {
		s1 := x1.highlowcontainer.getKeyAtIndex(pos1)
		s2 := x2.highlowcontainer.getKeyAtIndex(pos2)

		for {
			if s1 < s2 {
				answer.highlowcontainer.appendCopy(x1.highlowcontainer, pos1)
				pos1++
				if pos1 == length1 {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
			} else if s1 > s2 {
				answer.highlowcontainer.appendCopy(x2.highlowcontainer, pos2)
				pos2++
				if pos2 == length2 {
					break main
				}
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			} else {
				c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
				switch t := c1.(type) {
				case *arrayContainer:
					c1 = t.toBitmapContainer()
				case *runContainer16:
					if !t.isFull() {
						c1 = t.toBitmapContainer()
					}
				}

				answer.highlowcontainer.appendContainer(s1, c1.lazyOR(x2.highlowcontainer.getContainerAtIndex(pos2)), false)
				pos1++
				pos2++
				if (pos1 == length1) || (pos2 == length2) {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			}
		}
	}
	if pos1 == length1 {
		answer.highlowcontainer.appendCopyMany(x2.highlowcontainer, pos2, length2)
	} else if pos2 == length2 {
		answer.highlowcontainer.appendCopyMany(x1.highlowcontainer, pos1, length1)
	}
	return answer
}

// In-place Or function that requires repairAfterLazy
func (x1 *Bitmap) lazyOR(x2 *Bitmap) *Bitmap {
	pos1 := 0
	pos2 := 0
	length1 := x1.highlowcontainer.size()
	length2 := x2.highlowcontainer.size()
main:
	for (pos1 < length1) && (pos2 < length2) {
		s1 := x1.highlowcontainer.getKeyAtIndex(pos1)
		s2 := x2.highlowcontainer.getKeyAtIndex(pos2)

		for {
			if s1 < s2 {
				pos1++
				if pos1 == length1 {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
			} else if s1 > s2 {
				x1.highlowcontainer.insertNewKeyValueAt(pos1, s2, x2.highlowcontainer.getContainerAtIndex(pos2).clone())
				pos2++
				pos1++
				length1++
				if pos2 == length2 {
					break main
				}
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			} else {
				c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
				switch t := c1.(type) {
				case *arrayContainer:
					c1 = t.toBitmapContainer()
				case *runContainer16:
					if !t.isFull() {
						c1 = t.toBitmapContainer()
					}
				case *bitmapContainer:
					c1 = x1.highlowcontainer.getWritableContainerAtIndex(pos1)
				}

				x1.highlowcontainer.containers[pos1] = c1.lazyIOR(x2.highlowcontainer.getContainerAtIndex(pos2))
				x1.highlowcontainer.needCopyOnWrite[pos1] = false
				pos1++
				pos2++
				if (pos1 == length1) || (pos2 == length2) {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			}
		}
	}
	if pos1 == length1 {
		x1.highlowcontainer.appendCopyMany(x2.highlowcontainer, pos2, length2)
	}
	return x1
}

// to be called after lazy aggregates
func (x1 *Bitmap) repairAfterLazy() {
	for pos := 0; pos < x1.highlowcontainer.size(); pos++ {
		c := x1.highlowcontainer.getContainerAtIndex(pos)
		switch c.(type) {
		case *bitmapContainer:
			if c.(*bitmapContainer).cardinality == invalidCardinality {
				c = x1.highlowcontainer.getWritableContainerAtIndex(pos)
				c.(*bitmapContainer).computeCardinality()
				if c.(*bitmapContainer).getCardinality() <= arrayDefaultMaxSize {
					x1.highlowcontainer.setContainerAtIndex(pos, c.(*bitmapContainer).toArrayContainer())
				} else if c.(*bitmapContainer).isFull() {
					x1.highlowcontainer.setContainerAtIndex(pos, newRunContainer16Range(0, MaxUint16))
				}
			}
		}
	}
}

// FastAnd computes the intersection between many bitmaps quickly
// Compared to the And function, it can take many bitmaps as input, thus saving the trouble
// of manually calling "And" many times.
func FastAnd(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	} else if len(bitmaps) == 1 {
		return bitmaps[0].Clone()
	}
	answer := And(bitmaps[0], bitmaps[1])
	for _, bm := range bitmaps[2:] {
		answer.And(bm)
	}
	return answer
}

// FastOr computes the union between many bitmaps quickly, as opposed to having to call Or repeatedly.
// It might also be faster than calling Or repeatedly.
func FastOr(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	} else if len(bitmaps) == 1 {
		return bitmaps[0].Clone()
	}
	answer := lazyOR(bitmaps[0], bitmaps[1])
	for _, bm := range bitmaps[2:] {
		answer = answer.lazyOR(bm)
	}
	// here is where repairAfterLazy is called.
	answer.repairAfterLazy()
	return answer
}

// HeapOr computes the union between many bitmaps quickly using a heap.
// It might be faster than calling Or repeatedly.
func HeapOr(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	}
	// TODO:  for better speed, we could do the operation lazily, see Java implementation
	pq := make(priorityQueue, len(bitmaps))
	for i, bm := range bitmaps {
		pq[i] = &item{bm, i}
	}
	heap.Init(&pq)

	for pq.Len() > 1 {
		x1 := heap.Pop(&pq).(*item)
		x2 := heap.Pop(&pq).(*item)
		heap.Push(&pq, &item{Or(x1.value, x2.value), 0})
	}
	return heap.Pop(&pq).(*item).value
}

// HeapXor computes the symmetric difference between many bitmaps quickly (as opposed to calling Xor repeated).
// Internally, this function uses a heap.
// It might be faster than calling Xor repeatedly.
func HeapXor(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	}

	pq := make(priorityQueue, len(bitmaps))
	for i, bm := range bitmaps {
		pq[i] = &item{bm, i}
	}
	heap.Init(&pq)

	for pq.Len() > 1 {
		x1 := heap.Pop(&pq).(*item)
		x2 := heap.Pop(&pq).(*item)
		heap.Push(&pq, &item{Xor(x1.value, x2.value), 0})
	}
	return heap.Pop(&pq).(*item).value
}

// AndAny provides a result equivalent to x1.And(FastOr(bitmaps)).
// It's optimized to minimize allocations. It also might be faster than separate calls.
func (x1 *Bitmap) AndAny(bitmaps ...*Bitmap) {
	if len(bitmaps) == 0 {
		return
	} else if len(bitmaps) == 1 {
		x1.And(bitmaps[0])
		return
	}

	type withPos struct {
		bitmap *roaringArray
		pos    int
		key    uint16
	}
	filters := make([]withPos, 0, len(bitmaps))

	for _, b := range bitmaps {
		if b.highlowcontainer.size() > 0 {
			filters = append(filters, withPos{
				bitmap: &b.highlowcontainer,
				pos:    0,
				key:    b.highlowcontainer.getKeyAtIndex(0),
			})
		}
	}

	basePos := 0
	intersections := 0
	keyContainers := make([]container, 0, len(filters))
	var (
		tmpArray   *arrayContainer
		tmpBitmap  *bitmapContainer
		minNextKey uint16
	)

	for basePos < x1.highlowcontainer.size() && len(filters) > 0 {
		baseKey := x1.highlowcontainer.getKeyAtIndex(basePos)

		// accumulate containers for current key, find next minimal key in filters
		// and exclude filters that do not have related values anymore
		i := 0
		maxPossibleOr := 0
		minNextKey = MaxUint16
		for _, f := range filters {
			if f.key < baseKey {
				f.pos = f.bitmap.advanceUntil(baseKey, f.pos)
				if f.pos == f.bitmap.size() {
					continue
				}
				f.key = f.bitmap.getKeyAtIndex(f.pos)
			}

			if f.key == baseKey {
				cont := f.bitmap.getContainerAtIndex(f.pos)
				keyContainers = append(keyContainers, cont)
				maxPossibleOr += cont.getCardinality()

				f.pos++
				if f.pos == f.bitmap.size() {
					continue
				}
				f.key = f.bitmap.getKeyAtIndex(f.pos)
			}

			minNextKey = minOfUint16(minNextKey, f.key)
			filters[i] = f
			i++
		}
		filters = filters[:i]

		if len(keyContainers) == 0 {
			basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
			continue
		}

		var ored container

		if len(keyContainers) == 1 {
			ored = keyContainers[0]
		} else {
			//TODO: special case for run containers?
			if maxPossibleOr > arrayDefaultMaxSize {
				if tmpBitmap == nil {
					tmpBitmap = newBitmapContainer()
				}
				tmpBitmap.resetTo(keyContainers[0])
				for _, c := range keyContainers[1:] {
					tmpBitmap.ior(c)
				}
				ored = tmpBitmap
			} else {
				if tmpArray == nil {
					tmpArray = newArrayContainerCapacity(maxPossibleOr)
				}
				tmpArray.realloc(maxPossibleOr)
				tmpArray.resetTo(keyContainers[0])
				for _, c := range keyContainers[1:] {
					tmpArray.ior(c)
				}
				ored = tmpArray
			}
		}

		result := x1.highlowcontainer.getWritableContainerAtIndex(basePos).iand(ored)
		if !result.isEmpty() {
			x1.highlowcontainer.replaceKeyAndContainerAtIndex(intersections, baseKey, result, false)
			intersections++
		}

		keyContainers = keyContainers[:0]
		basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
	}

	x1.highlowcontainer.resize(intersections)
}
<commit_msg>Stop assuming ior is in-place for AndAny.<commit_after>package roaring

import (
	"container/heap"
)

// Or function that requires repairAfterLazy
func lazyOR(x1, x2 *Bitmap) *Bitmap {
	answer := NewBitmap()
	pos1 := 0
	pos2 := 0
	length1 := x1.highlowcontainer.size()
	length2 := x2.highlowcontainer.size()
main:
	for (pos1 < length1) && (pos2 < length2) {
		s1 := x1.highlowcontainer.getKeyAtIndex(pos1)
		s2 := x2.highlowcontainer.getKeyAtIndex(pos2)

		for {
			if s1 < s2 {
				answer.highlowcontainer.appendCopy(x1.highlowcontainer, pos1)
				pos1++
				if pos1 == length1 {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
			} else if s1 > s2 {
				answer.highlowcontainer.appendCopy(x2.highlowcontainer, pos2)
				pos2++
				if pos2 == length2 {
					break main
				}
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			} else {
				c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
				switch t := c1.(type) {
				case *arrayContainer:
					c1 = t.toBitmapContainer()
				case *runContainer16:
					if !t.isFull() {
						c1 = t.toBitmapContainer()
					}
				}

				answer.highlowcontainer.appendContainer(s1, c1.lazyOR(x2.highlowcontainer.getContainerAtIndex(pos2)), false)
				pos1++
				pos2++
				if (pos1 == length1) || (pos2 == length2) {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			}
		}
	}
	if pos1 == length1 {
		answer.highlowcontainer.appendCopyMany(x2.highlowcontainer, pos2, length2)
	} else if pos2 == length2 {
		answer.highlowcontainer.appendCopyMany(x1.highlowcontainer, pos1, length1)
	}
	return answer
}

// In-place Or function that requires repairAfterLazy
func (x1 *Bitmap) lazyOR(x2 *Bitmap) *Bitmap {
	pos1 := 0
	pos2 := 0
	length1 := x1.highlowcontainer.size()
	length2 := x2.highlowcontainer.size()
main:
	for (pos1 < length1) && (pos2 < length2) {
		s1 := x1.highlowcontainer.getKeyAtIndex(pos1)
		s2 := x2.highlowcontainer.getKeyAtIndex(pos2)

		for {
			if s1 < s2 {
				pos1++
				if pos1 == length1 {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
			} else if s1 > s2 {
				x1.highlowcontainer.insertNewKeyValueAt(pos1, s2, x2.highlowcontainer.getContainerAtIndex(pos2).clone())
				pos2++
				pos1++
				length1++
				if pos2 == length2 {
					break main
				}
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			} else {
				c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
				switch t := c1.(type) {
				case *arrayContainer:
					c1 = t.toBitmapContainer()
				case *runContainer16:
					if !t.isFull() {
						c1 = t.toBitmapContainer()
					}
				case *bitmapContainer:
					c1 = x1.highlowcontainer.getWritableContainerAtIndex(pos1)
				}

				x1.highlowcontainer.containers[pos1] = c1.lazyIOR(x2.highlowcontainer.getContainerAtIndex(pos2))
				x1.highlowcontainer.needCopyOnWrite[pos1] = false
				pos1++
				pos2++
				if (pos1 == length1) || (pos2 == length2) {
					break main
				}
				s1 = x1.highlowcontainer.getKeyAtIndex(pos1)
				s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
			}
		}
	}
	if pos1 == length1 {
		x1.highlowcontainer.appendCopyMany(x2.highlowcontainer, pos2, length2)
	}
	return x1
}

// to be called after lazy aggregates
func (x1 *Bitmap) repairAfterLazy() {
	for pos := 0; pos < x1.highlowcontainer.size(); pos++ {
		c := x1.highlowcontainer.getContainerAtIndex(pos)
		switch c.(type) {
		case *bitmapContainer:
			if c.(*bitmapContainer).cardinality == invalidCardinality {
				c = x1.highlowcontainer.getWritableContainerAtIndex(pos)
				c.(*bitmapContainer).computeCardinality()
				if c.(*bitmapContainer).getCardinality() <= arrayDefaultMaxSize {
					x1.highlowcontainer.setContainerAtIndex(pos, c.(*bitmapContainer).toArrayContainer())
				} else if c.(*bitmapContainer).isFull() {
					x1.highlowcontainer.setContainerAtIndex(pos, newRunContainer16Range(0, MaxUint16))
				}
			}
		}
	}
}

// FastAnd computes the intersection between many bitmaps quickly
// Compared to the And function, it can take many bitmaps as input, thus saving the trouble
// of manually calling "And" many times.
func FastAnd(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	} else if len(bitmaps) == 1 {
		return bitmaps[0].Clone()
	}
	answer := And(bitmaps[0], bitmaps[1])
	for _, bm := range bitmaps[2:] {
		answer.And(bm)
	}
	return answer
}

// FastOr computes the union between many bitmaps quickly, as opposed to having to call Or repeatedly.
// It might also be faster than calling Or repeatedly.
func FastOr(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	} else if len(bitmaps) == 1 {
		return bitmaps[0].Clone()
	}
	answer := lazyOR(bitmaps[0], bitmaps[1])
	for _, bm := range bitmaps[2:] {
		answer = answer.lazyOR(bm)
	}
	// here is where repairAfterLazy is called.
	answer.repairAfterLazy()
	return answer
}

// HeapOr computes the union between many bitmaps quickly using a heap.
// It might be faster than calling Or repeatedly.
func HeapOr(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	}
	// TODO:  for better speed, we could do the operation lazily, see Java implementation
	pq := make(priorityQueue, len(bitmaps))
	for i, bm := range bitmaps {
		pq[i] = &item{bm, i}
	}
	heap.Init(&pq)

	for pq.Len() > 1 {
		x1 := heap.Pop(&pq).(*item)
		x2 := heap.Pop(&pq).(*item)
		heap.Push(&pq, &item{Or(x1.value, x2.value), 0})
	}
	return heap.Pop(&pq).(*item).value
}

// HeapXor computes the symmetric difference between many bitmaps quickly (as opposed to calling Xor repeated).
// Internally, this function uses a heap.
// It might be faster than calling Xor repeatedly.
func HeapXor(bitmaps ...*Bitmap) *Bitmap {
	if len(bitmaps) == 0 {
		return NewBitmap()
	}

	pq := make(priorityQueue, len(bitmaps))
	for i, bm := range bitmaps {
		pq[i] = &item{bm, i}
	}
	heap.Init(&pq)

	for pq.Len() > 1 {
		x1 := heap.Pop(&pq).(*item)
		x2 := heap.Pop(&pq).(*item)
		heap.Push(&pq, &item{Xor(x1.value, x2.value), 0})
	}
	return heap.Pop(&pq).(*item).value
}

// AndAny provides a result equivalent to x1.And(FastOr(bitmaps)).
// It's optimized to minimize allocations. It also might be faster than separate calls.
func (x1 *Bitmap) AndAny(bitmaps ...*Bitmap) {
	if len(bitmaps) == 0 {
		return
	} else if len(bitmaps) == 1 {
		x1.And(bitmaps[0])
		return
	}

	type withPos struct {
		bitmap *roaringArray
		pos    int
		key    uint16
	}
	filters := make([]withPos, 0, len(bitmaps))

	for _, b := range bitmaps {
		if b.highlowcontainer.size() > 0 {
			filters = append(filters, withPos{
				bitmap: &b.highlowcontainer,
				pos:    0,
				key:    b.highlowcontainer.getKeyAtIndex(0),
			})
		}
	}

	basePos := 0
	intersections := 0
	keyContainers := make([]container, 0, len(filters))
	var (
		tmpArray   *arrayContainer
		tmpBitmap  *bitmapContainer
		minNextKey uint16
	)

	for basePos < x1.highlowcontainer.size() && len(filters) > 0 {
		baseKey := x1.highlowcontainer.getKeyAtIndex(basePos)

		// accumulate containers for current key, find next minimal key in filters
		// and exclude filters that do not have related values anymore
		i := 0
		maxPossibleOr := 0
		minNextKey = MaxUint16
		for _, f := range filters {
			if f.key < baseKey {
				f.pos = f.bitmap.advanceUntil(baseKey, f.pos)
				if f.pos == f.bitmap.size() {
					continue
				}
				f.key = f.bitmap.getKeyAtIndex(f.pos)
			}

			if f.key == baseKey {
				cont := f.bitmap.getContainerAtIndex(f.pos)
				keyContainers = append(keyContainers, cont)
				maxPossibleOr += cont.getCardinality()

				f.pos++
				if f.pos == f.bitmap.size() {
					continue
				}
				f.key = f.bitmap.getKeyAtIndex(f.pos)
			}

			minNextKey = minOfUint16(minNextKey, f.key)
			filters[i] = f
			i++
		}
		filters = filters[:i]

		if len(keyContainers) == 0 {
			basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
			continue
		}

		var ored container

		if len(keyContainers) == 1 {
			ored = keyContainers[0]
		} else {
			//TODO: special case for run containers?
			if maxPossibleOr > arrayDefaultMaxSize {
				if tmpBitmap == nil {
					tmpBitmap = newBitmapContainer()
				}
				tmpBitmap.resetTo(keyContainers[0])
				ored = tmpBitmap
			} else {
				if tmpArray == nil {
					tmpArray = newArrayContainerCapacity(maxPossibleOr)
				}
				tmpArray.realloc(maxPossibleOr)
				tmpArray.resetTo(keyContainers[0])
				ored = tmpArray
			}
			for _, c := range keyContainers[1:] {
				ored = ored.ior(c)
			}
		}

		result := x1.highlowcontainer.getWritableContainerAtIndex(basePos).iand(ored)
		if !result.isEmpty() {
			x1.highlowcontainer.replaceKeyAndContainerAtIndex(intersections, baseKey, result, false)
			intersections++
		}

		keyContainers = keyContainers[:0]
		basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
	}

	x1.highlowcontainer.resize(intersections)
}
<|endoftext|>


<commit_before>package fastly

import (
	"fmt"
)

// BigQuery represents a BigQuery logging response from the Fastly API.
type BigQuery struct {
	ServiceID         string `mapstructure:"service_id"`
	Name              string `mapstructure:"name"`
	Format            string `mapstructure:"format"`
	User              string `mapstructure:"user"`
	ProjectID         string `mapstructure:"project_id"`
	Dataset           string `mapstructure:"dataset"`
	Table             string `mapstructure:"table"`
	SecretKey         string `mapstructure:"secret_key"`
	CreatedAt         string `mapstructure:"created_at"`
	UpdatedAt         string `mapstructure:"updated_at"`
	DeletedAt         string `mapstructure:"deleted_at"`
	ResponseCondition string `mapstructure:"response_condition"`
}

// GetBigQueryInput is used as input to the GetBigQuery function.
type GetBigQueryInput struct {
	// Service is the ID of the service. Version is the specific configuration
	// version. Both fields are required.
	Service string
	Version int
}

// GetBigQuery lists all BigQuerys associated with a service version.
func (c *Client) GetBigQuery(i *GetBigQueryInput) ([]*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery", i.Service, i.Version)
	resp, err := c.Get(path, nil)
	if err != nil {
		return nil, err
	}

	var bs []*BigQuery
	if err := decodeJSON(&bs, resp.Body); err != nil {
		return nil, err
	}
	return bs, nil
}

// CreateBigQueryInput is used as input to the CreateBigQuery function.
// All fields are required.
type CreateBigQueryInput struct {
	// Service is the ID of the service.
	Service string

	//Version is the specific configuration version.
	Version int

	// Name is the name if your bigquery logging endpoint.
	Name string

	// Project ID your GCP project ID.
	ProjectID string

	// Dataset is your BigQuery dataset.
	Dataset string

	// Table is your BigQuery table.
	Table string

	// User is the user with access to write to your BigQuery dataset.
	User string

	// Secret key is the user's secret key.
	SecretKey string
}

// CreateBigQuery creates a new Fastly BigQuery logging endpoint.
func (c *Client) CreateBigQuery(i *CreateBigQueryInput) (*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	if i.Name == "" {
		return nil, ErrMissingName
	}

	if i.ProjectID == "" {
		return nil, ErrMissingProjectID
	}

	if i.Dataset == "" {
		return nil, ErrMissingDataset
	}

	if i.Table == "" {
		return nil, ErrMissingTable
	}

	if i.User == "" {
		return nil, ErrMissingUser
	}

	if i.SecretKey == "" {
		return nil, ErrMissingSecretKey
	}

	params := make(map[string]string)
	params["name"] = i.Name
	params["project_id"] = i.ProjectID
	params["dataset"] = i.Dataset
	params["table"] = i.Table
	params["user"] = i.User
	params["secret_key"] = i.SecretKey

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery", i.Service, i.Version)
	resp, err := c.PostForm(path, i, &RequestOptions{
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	var b *BigQuery
	if err := decodeJSON(&b, resp.Body); err != nil {
		return nil, err
	}
	return b, nil
}

// UpdateBigQueryInput is used as input to the UpdateBigQuery function.
// All fields are required.
type UpdateBigQueryInput struct {
	// Service is the ID of the service.
	Service string

	//Version is the specific configuration version.
	Version int

	// Name is the old name if your bigquery logging endpoint.
	// Used to identify the correct BigQuery logging endpoint if there
	// is a name change.
	Name string

	// NewName is the new name of your BigQuery logging endpoint.
	NewName string
}

// UpdateBigQuery updates a BigQuery logging endpoint.
func (c *Client) UpdateBigQuery(i *UpdateBigQueryInput) (*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	if i.Name == "" {
		return nil, ErrMissingName
	}

	if i.NewName == "" {
		return nil, ErrMissingNewName
	}

	params := make(map[string]string)
	params["name"] = i.NewName

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery/%s", i.Service, i.Version, i.Name)
	resp, err := c.PutForm(path, i, &RequestOptions{
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	var b *BigQuery
	if err := decodeJSON(&b, resp.Body); err != nil {
		return nil, err
	}
	return b, nil
}

// DeleteBigQueryInput is the input parameter to DeleteBigQuery.
// All fields are required.
type DeleteBigQueryInput struct {
	// Service is the ID of the service.
	Service string

	// Version is the specific configuration.
	Version int

	// Name is the name of the BigQuery logging endpoint to delete.
	Name string
}

// DeleteBigQuery deletes the given BigQuery logging endpoint.
func (c *Client) DeleteBigQuery(i *DeleteBigQueryInput) error {
	if i.Service == "" {
		return ErrMissingService
	}

	if i.Version == 0 {
		return ErrMissingVersion
	}

	if i.Name == "" {
		return ErrMissingName
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery/%s", i.Service, i.Version, i.Name)
	resp, err := c.Delete(path, nil)
	if err != nil {
		return err
	}

	var r *statusResp
	if err := decodeJSON(&r, resp.Body); err != nil {
		return err
	}
	if !r.Ok() {
		return fmt.Errorf("Not Ok")
	}
	return nil
}
<commit_msg>adding additional fields<commit_after>package fastly

import (
	"fmt"
)

// BigQuery represents a BigQuery logging response from the Fastly API.
type BigQuery struct {
	ServiceID         string `mapstructure:"service_id"`
	Name              string `mapstructure:"name"`
	Format            string `mapstructure:"format"`
	User              string `mapstructure:"user"`
	ProjectID         string `mapstructure:"project_id"`
	Dataset           string `mapstructure:"dataset"`
	Table             string `mapstructure:"table"`
	SecretKey         string `mapstructure:"secret_key"`
	CreatedAt         string `mapstructure:"created_at"`
	UpdatedAt         string `mapstructure:"updated_at"`
	DeletedAt         string `mapstructure:"deleted_at"`
	ResponseCondition string `mapstructure:"response_condition"`
}

// GetBigQueryInput is used as input to the GetBigQuery function.
type GetBigQueryInput struct {
	// Service is the ID of the service. Version is the specific configuration
	// version. Both fields are required.
	Service string
	Version int
}

// GetBigQuery lists all BigQuerys associated with a service version.
func (c *Client) GetBigQuery(i *GetBigQueryInput) ([]*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery", i.Service, i.Version)
	resp, err := c.Get(path, nil)
	if err != nil {
		return nil, err
	}

	var bs []*BigQuery
	if err := decodeJSON(&bs, resp.Body); err != nil {
		return nil, err
	}
	return bs, nil
}

// CreateBigQueryInput is used as input to the CreateBigQuery function.
type CreateBigQueryInput struct {
	// All fields other than format are required.
	// Service is the ID of the service.
	Service string

	//Version is the specific configuration version.
	Version int

	// Name is the name if your bigquery logging endpoint.
	Name string

	// Project ID your GCP project ID.
	ProjectID string

	// Dataset is your BigQuery dataset.
	Dataset string

	// Table is your BigQuery table.
	Table string

	// User is the user with access to write to your BigQuery dataset.
	User string

	// Secret key is the user's secret key.
	SecretKey string

	// Format is the log formatting desired for your BigQuery dataset.
	// Optional.
	Format string
}

// CreateBigQuery creates a new Fastly BigQuery logging endpoint.
func (c *Client) CreateBigQuery(i *CreateBigQueryInput) (*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	if i.Name == "" {
		return nil, ErrMissingName
	}

	if i.ProjectID == "" {
		return nil, ErrMissingProjectID
	}

	if i.Dataset == "" {
		return nil, ErrMissingDataset
	}

	if i.Table == "" {
		return nil, ErrMissingTable
	}

	if i.User == "" {
		return nil, ErrMissingUser
	}

	if i.SecretKey == "" {
		return nil, ErrMissingSecretKey
	}

	params := make(map[string]string)
	params["name"] = i.Name
	params["project_id"] = i.ProjectID
	params["dataset"] = i.Dataset
	params["table"] = i.Table
	params["user"] = i.User
	params["secret_key"] = i.SecretKey
	if i.Format != "" {
		params["format"] = i.Format
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery", i.Service, i.Version)
	resp, err := c.PostForm(path, i, &RequestOptions{
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	var b *BigQuery
	if err := decodeJSON(&b, resp.Body); err != nil {
		return nil, err
	}
	return b, nil
}

// UpdateBigQueryInput is used as input to the UpdateBigQuery function.
type UpdateBigQueryInput struct {
	// Service is the ID of the service.
	// This field is required.
	Service string

	//Version is the specific configuration version.
	// This field is required.
	Version int

	// Name is the old name if your bigquery logging endpoint.
	// Used to identify the correct BigQuery logging endpoint if there
	// is a name change.
	// This field is required.
	Name string

	// NewName is the new name of your BigQuery logging endpoint.
	// This field is required.
	NewName string

	// Project ID your GCP project ID.
	ProjectID string

	// Dataset is your BigQuery dataset.
	Dataset string

	// Table is your BigQuery table.
	Table string

	// User is the user with access to write to your BigQuery dataset.
	User string

	// Secret key is the user's secret key.
	SecretKey string

	// Format is the log formatting desired for your BigQuery dataset.
	// Optional.
	Format string
}

// UpdateBigQuery updates a BigQuery logging endpoint.
func (c *Client) UpdateBigQuery(i *UpdateBigQueryInput) (*BigQuery, error) {
	if i.Service == "" {
		return nil, ErrMissingService
	}

	if i.Version == 0 {
		return nil, ErrMissingVersion
	}

	if i.Name == "" {
		return nil, ErrMissingName
	}

	if i.NewName == "" {
		return nil, ErrMissingNewName
	}

	params := make(map[string]string)
	params["name"] = i.NewName
	if i.ProjectID != "" {
		params["project_id"] = i.ProjectID
	}
	if i.Dataset != "" {
		params["dataset"] = i.Dataset
	}
	if i.Table != "" {
		params["table"] = i.Table
	}
	if i.User != "" {
		params["user"] = i.User
	}
	if i.SecretKey != "" {
		params["secret_key"] = i.SecretKey
	}
	if i.Format != "" {
		params["format"] = i.Format
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery/%s", i.Service, i.Version, i.Name)
	resp, err := c.PutForm(path, i, &RequestOptions{
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	var b *BigQuery
	if err := decodeJSON(&b, resp.Body); err != nil {
		return nil, err
	}
	return b, nil
}

// DeleteBigQueryInput is the input parameter to DeleteBigQuery.
// All fields are required.
type DeleteBigQueryInput struct {
	// Service is the ID of the service.
	Service string

	// Version is the specific configuration.
	Version int

	// Name is the name of the BigQuery logging endpoint to delete.
	Name string
}

// DeleteBigQuery deletes the given BigQuery logging endpoint.
func (c *Client) DeleteBigQuery(i *DeleteBigQueryInput) error {
	if i.Service == "" {
		return ErrMissingService
	}

	if i.Version == 0 {
		return ErrMissingVersion
	}

	if i.Name == "" {
		return ErrMissingName
	}

	path := fmt.Sprintf("/service/%s/version/%d/logging/bigquery/%s", i.Service, i.Version, i.Name)
	resp, err := c.Delete(path, nil)
	if err != nil {
		return err
	}

	var r *statusResp
	if err := decodeJSON(&r, resp.Body); err != nil {
		return err
	}
	if !r.Ok() {
		return fmt.Errorf("Not Ok")
	}
	return nil
}
<|endoftext|>


<commit_before>/* https://leetcode.com/problems/third-maximum-number/#/description
Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).

Example 1:
    Input: [3, 2, 1]
    Output: 1

Explanation: The third maximum is 1.

Example 2:
    Input: [1, 2]
    Output: 2

Explanation: The third maximum does not exist, so the maximum (2) is returned instead.

Example 3:
    Input: [2, 2, 3, 1]
    Output: 1

Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.

*/

package leetcode

const MaxUint = ^uint(0)
const MaxInt = int(MaxUint >> 1)
const MinInt = -MaxInt - 1

func thirdMax(nums []int) int {
	max, second, third := nums[0], MinInt, MinInt
	c := 1
	for i := 1; i < len(nums); i++ {
		if nums[i] == max || nums[i] == second || nums[i] <= third {
			continue
		}
		if nums[i] > max {
			tempAgoMax, tempAgoSecond := max, second
			max, second, third = nums[i], tempAgoMax, tempAgoSecond
		} else if nums[i] > second {
			second, third = nums[i], second
		} else if nums[i] > third {
			third = nums[i]
		}
		c++
	}
	if c > 2 {
		return third
	}
	return max
}
<commit_msg>enhance code<commit_after>/* https://leetcode.com/problems/third-maximum-number/#/description
Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).

Example 1:
    Input: [3, 2, 1]
    Output: 1

Explanation: The third maximum is 1.

Example 2:
    Input: [1, 2]
    Output: 2

Explanation: The third maximum does not exist, so the maximum (2) is returned instead.

Example 3:
    Input: [2, 2, 3, 1]
    Output: 1

Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.

*/

package leetcode

const MaxUint = ^uint(0)
const MaxInt = int(MaxUint >> 1)
const MinInt = -MaxInt - 1

func thirdMax(nums []int) int {
	max, second, third := MinInt, MinInt, MinInt
	c := 0
	for _, num := range nums {
		if num == max || num == second || num <= third {
			continue
		}
		if num > max {
			tempAgoMax, tempAgoSecond := max, second
			max, second, third = num, tempAgoMax, tempAgoSecond
		} else if num > second {
			second, third = num, second
		} else if num > third {
			third = num
		}
		c++
	}
	if c > 2 {
		return third
	}
	return max
}
<|endoftext|>


<commit_before>package fetcher

import (
	"os"
	"sync"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry/noaa"
)

type Fetcher interface {
	Fetch() (Data, error)
}

type fetcher struct {
	bbsClient  bbs.Client
	noaaClient *noaa.Consumer
}

type Data struct {
	Domains []string
	Tasks   []*models.Task
	LRPs    LRPs
}

func NewFetcher(bbsClient bbs.Client, noaaClient *noaa.Consumer) Fetcher {
	return &fetcher{
		bbsClient:  bbsClient,
		noaaClient: noaaClient,
	}
}

func (f *fetcher) Fetch() (Data, error) {
	domains, err := f.bbsClient.Domains()
	if err != nil {
		return Data{}, err
	}

	tasks, err := f.bbsClient.Tasks()
	if err != nil {
		return Data{}, err
	}

	lrps, err := f.fetchLRPs()
	if err != nil {
		return Data{}, err
	}

	return Data{
		Domains: domains,
		Tasks:   tasks,
		LRPs:    lrps,
	}, nil
}

func (f *fetcher) fetchLRPs() (map[string]*LRP, error) {
	lrps := map[string]*LRP{}

	desiredLRPs, err := f.bbsClient.DesiredLRPs(models.DesiredLRPFilter{})
	if err != nil {
		return nil, err
	}

	for _, desiredLRP := range desiredLRPs {
		lrps[desiredLRP.ProcessGuid] = &LRP{Desired: desiredLRP}
	}

	actualLRPGroups, err := f.bbsClient.ActualLRPGroups(models.ActualLRPFilter{})
	if err != nil {
		return nil, err
	}

	for _, actualLRPGroup := range actualLRPGroups {
		actualLRP, evacuating := actualLRPGroup.Resolve()

		lrp, ok := lrps[actualLRP.ProcessGuid]
		if !ok {
			continue
		}

		actual := Actual{ActualLRP: actualLRP, Evacuating: evacuating}
		lrp.Actuals = append(lrp.Actuals, &actual)
	}

	wg := sync.WaitGroup{}
	authToken := os.Getenv("OAUTH_TOKEN")
	for _, lrp := range lrps {
		lrp := lrp
		wg.Add(1)
		go func() {
			defer wg.Done()
			containerMetrics, err := f.noaaClient.ContainerMetrics(lrp.Desired.LogGuid, authToken)
			if err != nil {
				return
			}

			for _, metrics := range containerMetrics {
				for _, actual := range lrp.Actuals {
					if actual.ActualLRP.Index == metrics.GetInstanceIndex() {
						containerMetrics := ContainerMetrics{
							CPU:    metrics.GetCpuPercentage(),
							Memory: metrics.GetMemoryBytes(),
							Disk:   metrics.GetDiskBytes(),
						}

						actual.Metrics = containerMetrics
					}
				}
			}
		}()
	}
	wg.Wait()

	return lrps, nil
}
<commit_msg>Cell States<commit_after>package fetcher

import (
	"os"
	"sync"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry/noaa"
)

type Fetcher interface {
	Fetch() (Data, error)
}

type fetcher struct {
	bbsClient  bbs.Client
	noaaClient *noaa.Consumer
}

type Data struct {
	Domains []string
	Tasks   []*models.Task
	LRPs    LRPs
}

func NewFetcher(bbsClient bbs.Client, noaaClient *noaa.Consumer) Fetcher {
	return &fetcher{
		bbsClient:  bbsClient,
		noaaClient: noaaClient,
	}
}

func (f *fetcher) Fetch() (Data, error) {
	domains, err := f.bbsClient.Domains()
	if err != nil {
		return Data{}, err
	}

	tasks, err := f.bbsClient.Tasks()
	if err != nil {
		return Data{}, err
	}

	lrps, err := f.fetchLRPs()
	if err != nil {
		return Data{}, err
	}

	return Data{
		Domains: domains,
		Tasks:   tasks,
		LRPs:    lrps,
	}, nil
}

func (f *fetcher) fetchLRPs() (map[string]*LRP, error) {
	lrps := map[string]*LRP{}

	desiredLRPs, err := f.bbsClient.DesiredLRPs(models.DesiredLRPFilter{})
	if err != nil {
		return nil, err
	}

	for _, desiredLRP := range desiredLRPs {
		lrps[desiredLRP.ProcessGuid] = &LRP{Desired: desiredLRP}
	}

	actualLRPGroups, err := f.bbsClient.ActualLRPGroups(models.ActualLRPFilter{})
	if err != nil {
		return nil, err
	}

	for _, actualLRPGroup := range actualLRPGroups {
		actualLRP, evacuating := actualLRPGroup.Resolve()

		lrp, ok := lrps[actualLRP.ProcessGuid]
		if !ok {
			continue
		}

		actual := Actual{ActualLRP: actualLRP, Evacuating: evacuating}
		lrp.Actuals = append(lrp.Actuals, &actual)
	}

	wg := sync.WaitGroup{}
	authToken := os.Getenv("OAUTH_TOKEN")
	for _, lrp := range lrps {
		lrp := lrp
		wg.Add(1)
		go func() {
			defer wg.Done()
			containerMetrics, err := f.noaaClient.ContainerMetrics(lrp.Desired.LogGuid, authToken)
			if err != nil {
				return
			}

			for _, metrics := range containerMetrics {
				for _, actual := range lrp.Actuals {
					if actual.ActualLRP.Index == metrics.GetInstanceIndex() {
						containerMetrics := ContainerMetrics{
							CPU:    metrics.GetCpuPercentage(),
							Memory: metrics.GetMemoryBytes(),
							Disk:   metrics.GetDiskBytes(),
						}

						actual.Metrics = containerMetrics
					}
				}
			}
		}()
	}
	wg.Wait()

	return lrps, nil
}

type CellState struct {
	MemoryUsed     uint64
	MemoryReserved uint64

	DiskUsed     uint64
	DiskReserved uint64

	CPUPercentage float64

	NumLRPs  uint64
	NumTasks uint64
}

func (d *Data) GetCellState() map[string]*CellState {
	cellStates := map[string]*CellState{}
	for _, lrp := range d.LRPs {
		for _, actual := range lrp.Actuals {
			cellState, ok := cellStates[actual.ActualLRP.CellId]
			if !ok {
				cellState = &CellState{}
			}

			cellState.NumLRPs++
			cellState.CPUPercentage += actual.Metrics.CPU
			cellState.MemoryUsed += actual.Metrics.Memory
			cellState.DiskReserved += uint64(lrp.Desired.MemoryMb * 1024 * 1024)
			cellState.DiskUsed += actual.Metrics.Disk
			cellState.DiskReserved += uint64(lrp.Desired.DiskMb * 1024 * 1024)
		}
	}

	return cellStates
}
<|endoftext|>


<commit_before>package buffer

import (
	"strings"
	"testing"

	testifyAssert "github.com/stretchr/testify/assert"
	lua "github.com/yuin/gopher-lua"

	ulua "github.com/zyedidia/micro/internal/lua"
)

type operation struct {
	start Loc
	end   Loc
	text  []string
}

type asserter interface {
	Equal(interface{}, interface{}, ...interface{}) bool
	NotEqual(interface{}, interface{}, ...interface{}) bool
}

type noOpAsserter struct {
}

func (a *noOpAsserter) Equal(interface{}, interface{}, ...interface{}) bool {
	return true
}

func (a *noOpAsserter) NotEqual(interface{}, interface{}, ...interface{}) bool {
	return true
}

func init() {
	ulua.L = lua.NewState()
}

func check(t *testing.T, before []string, operations []operation, after []string) {
	var assert asserter
	if t == nil {
		// Benchmark mode; don't perform assertions
		assert = &noOpAsserter{}
	} else {
		assert = testifyAssert.New(t)
	}

	b := NewBufferFromString(strings.Join(before, "\n"), "", BTDefault)

	assert.NotEqual("", b.GetName())
	assert.Equal(false, b.ExternallyModified())
	assert.Equal(false, b.Modified())
	assert.Equal(1, b.NumCursors())

	checkText := func(lines []string) {
		assert.Equal([]byte(strings.Join(lines, "\n")), b.Bytes())
		assert.Equal(len(lines), b.LinesNum())
		for i, s := range lines {
			assert.Equal(s, b.Line(i))
			assert.Equal([]byte(s), b.LineBytes(i))
		}
	}

	checkText(before)

	var cursors []*Cursor

	for _, op := range operations {
		cursor := NewCursor(b, op.start)
		cursor.SetSelectionStart(op.start)
		cursor.SetSelectionEnd(op.end)
		b.AddCursor(cursor)
		cursors = append(cursors, cursor)
	}

	assert.Equal(1+len(operations), b.NumCursors())

	for i, op := range operations {
		cursor := cursors[i]
		b.SetCurCursor(cursor.Num)
		cursor.DeleteSelection()
		cursor.ResetSelection()
		b.Insert(cursor.Loc, strings.Join(op.text, "\n"))
	}

	checkText(after)

	// must have exactly two events per operation (delete and insert)
	for range operations {
		b.UndoOneEvent()
		b.UndoOneEvent()
	}

	checkText(before)

	for i, op := range operations {
		cursor := cursors[i]
		if !cursor.HasSelection() {
			assert.Equal(op.start, cursor.Loc)
		} else {
			assert.Equal(op.start, cursor.CurSelection[0])
			assert.Equal(op.end, cursor.CurSelection[1])
		}
	}

	for range operations {
		b.RedoOneEvent()
		b.RedoOneEvent()
	}

	checkText(after)

	b.Close()
}
<commit_msg>Improve buffer test<commit_after>package buffer

import (
	"strings"
	"testing"

	testifyAssert "github.com/stretchr/testify/assert"
	lua "github.com/yuin/gopher-lua"

	ulua "github.com/zyedidia/micro/internal/lua"
)

type operation struct {
	start Loc
	end   Loc
	text  []string
}

type asserter interface {
	Equal(interface{}, interface{}, ...interface{}) bool
	NotEqual(interface{}, interface{}, ...interface{}) bool
}

type noOpAsserter struct {
}

func (a *noOpAsserter) Equal(interface{}, interface{}, ...interface{}) bool {
	return true
}

func (a *noOpAsserter) NotEqual(interface{}, interface{}, ...interface{}) bool {
	return true
}

func init() {
	ulua.L = lua.NewState()
}

func check(t *testing.T, before []string, operations []operation, after []string) {
	var assert asserter
	if t == nil {
		// Benchmark mode; don't perform assertions
		assert = &noOpAsserter{}
	} else {
		assert = testifyAssert.New(t)
	}

	b := NewBufferFromString(strings.Join(before, "\n"), "", BTDefault)

	assert.NotEqual("", b.GetName())
	assert.Equal(false, b.ExternallyModified())
	assert.Equal(false, b.Modified())
	assert.Equal(1, b.NumCursors())

	checkText := func(lines []string) {
		assert.Equal([]byte(strings.Join(lines, "\n")), b.Bytes())
		assert.Equal(len(lines), b.LinesNum())
		for i, s := range lines {
			assert.Equal(s, b.Line(i))
			assert.Equal([]byte(s), b.LineBytes(i))
		}
	}

	checkText(before)

	var cursors []*Cursor

	for _, op := range operations {
		cursor := NewCursor(b, op.start)
		cursor.SetSelectionStart(op.start)
		cursor.SetSelectionEnd(op.end)
		b.AddCursor(cursor)
		cursors = append(cursors, cursor)
	}

	assert.Equal(1+len(operations), b.NumCursors())

	for i, op := range operations {
		cursor := cursors[i]
		b.SetCurCursor(cursor.Num)
		cursor.DeleteSelection()
		b.Insert(cursor.Loc, strings.Join(op.text, "\n"))
	}

	checkText(after)

	// must have exactly two events per operation (delete and insert)
	for range operations {
		b.UndoOneEvent()
		b.UndoOneEvent()
	}

	checkText(before)

	for i, op := range operations {
		cursor := cursors[i]
		if op.start == op.end {
			assert.Equal(op.start, cursor.Loc)
		} else {
			assert.Equal(op.start, cursor.CurSelection[0])
			assert.Equal(op.end, cursor.CurSelection[1])
		}
	}

	for range operations {
		b.RedoOneEvent()
		b.RedoOneEvent()
	}

	checkText(after)

	b.Close()
}
<|endoftext|>


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

package source

import (
	"context"
	"fmt"
	"go/ast"
	"go/types"

	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/telemetry/trace"
)

func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.DocumentSymbol, error) {
	ctx, done := trace.StartSpan(ctx, "source.DocumentSymbols")
	defer done()

	pkg, pgh, err := getParsedFile(ctx, snapshot, fh, NarrowestPackageHandle)
	if err != nil {
		return nil, fmt.Errorf("getting file for DocumentSymbols: %v", err)
	}
	file, _, _, err := pgh.Cached()
	if err != nil {
		return nil, err
	}

	info := pkg.GetTypesInfo()
	q := qualifier(file, pkg.GetTypes(), info)

	methodsToReceiver := make(map[types.Type][]protocol.DocumentSymbol)
	symbolsToReceiver := make(map[types.Type]int)
	var symbols []protocol.DocumentSymbol
	for _, decl := range file.Decls {
		switch decl := decl.(type) {
		case *ast.FuncDecl:
			if obj := info.ObjectOf(decl.Name); obj != nil {
				fs, err := funcSymbol(ctx, snapshot.View(), pkg, decl, obj, q)
				if err != nil {
					return nil, err
				}
				// Store methods separately, as we want them to appear as children
				// of the corresponding type (which we may not have seen yet).
				if fs.Kind == protocol.Method {
					rtype := obj.Type().(*types.Signature).Recv().Type()
					methodsToReceiver[rtype] = append(methodsToReceiver[rtype], fs)
				} else {
					symbols = append(symbols, fs)
				}
			}
		case *ast.GenDecl:
			for _, spec := range decl.Specs {
				switch spec := spec.(type) {
				case *ast.TypeSpec:
					if obj := info.ObjectOf(spec.Name); obj != nil {
						ts, err := typeSymbol(ctx, snapshot.View(), pkg, info, spec, obj, q)
						if err != nil {
							return nil, err
						}
						symbols = append(symbols, ts)
						symbolsToReceiver[obj.Type()] = len(symbols) - 1
					}
				case *ast.ValueSpec:
					for _, name := range spec.Names {
						if obj := info.ObjectOf(name); obj != nil {
							vs, err := varSymbol(ctx, snapshot.View(), pkg, decl, name, obj, q)
							if err != nil {
								return nil, err
							}
							symbols = append(symbols, vs)
						}
					}
				}
			}
		}
	}

	// Attempt to associate methods to the corresponding type symbol.
	for typ, methods := range methodsToReceiver {
		if ptr, ok := typ.(*types.Pointer); ok {
			typ = ptr.Elem()
		}

		if i, ok := symbolsToReceiver[typ]; ok {
			symbols[i].Children = append(symbols[i].Children, methods...)
		} else {
			// The type definition for the receiver of these methods was not in the document.
			symbols = append(symbols, methods...)
		}
	}
	return symbols, nil
}

func funcSymbol(ctx context.Context, view View, pkg Package, decl *ast.FuncDecl, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Function,
	}
	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, decl.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	sig, _ := obj.Type().(*types.Signature)
	if sig != nil {
		if sig.Recv() != nil {
			s.Kind = protocol.Method
		}
		s.Detail += "("
		for i := 0; i < sig.Params().Len(); i++ {
			if i > 0 {
				s.Detail += ", "
			}
			param := sig.Params().At(i)
			label := types.TypeString(param.Type(), q)
			if param.Name() != "" {
				label = fmt.Sprintf("%s %s", param.Name(), label)
			}
			s.Detail += label
		}
		s.Detail += ")"
	}
	return s, nil
}

func setKind(s *protocol.DocumentSymbol, typ types.Type, q types.Qualifier) {
	switch typ := typ.Underlying().(type) {
	case *types.Interface:
		s.Kind = protocol.Interface
	case *types.Struct:
		s.Kind = protocol.Struct
	case *types.Signature:
		s.Kind = protocol.Function
		if typ.Recv() != nil {
			s.Kind = protocol.Method
		}
	case *types.Named:
		setKind(s, typ.Underlying(), q)
	case *types.Basic:
		i := typ.Info()
		switch {
		case i&types.IsNumeric != 0:
			s.Kind = protocol.Number
		case i&types.IsBoolean != 0:
			s.Kind = protocol.Boolean
		case i&types.IsString != 0:
			s.Kind = protocol.String
		}
	default:
		s.Kind = protocol.Variable
	}
}

func typeSymbol(ctx context.Context, view View, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
	}
	s.Detail, _ = formatType(obj.Type(), q)
	setKind(&s, obj.Type(), q)

	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, spec)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, spec.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	t, objIsStruct := obj.Type().Underlying().(*types.Struct)
	st, specIsStruct := spec.Type.(*ast.StructType)
	if objIsStruct && specIsStruct {
		for i := 0; i < t.NumFields(); i++ {
			f := t.Field(i)
			child := protocol.DocumentSymbol{
				Name: f.Name(),
				Kind: protocol.Field,
			}
			child.Detail, _ = formatType(f.Type(), q)

			spanNode, selectionNode := nodesForStructField(i, st)
			if span, err := nodeToProtocolRange(view, pkg, spanNode); err == nil {
				child.Range = span
			}
			if span, err := nodeToProtocolRange(view, pkg, selectionNode); err == nil {
				child.SelectionRange = span
			}
			s.Children = append(s.Children, child)
		}
	}

	ti, objIsInterface := obj.Type().Underlying().(*types.Interface)
	ai, specIsInterface := spec.Type.(*ast.InterfaceType)
	if objIsInterface && specIsInterface {
		for i := 0; i < ti.NumExplicitMethods(); i++ {
			method := ti.ExplicitMethod(i)
			child := protocol.DocumentSymbol{
				Name: method.Name(),
				Kind: protocol.Method,
			}

			var spanNode, selectionNode ast.Node
		Methods:
			for _, f := range ai.Methods.List {
				for _, id := range f.Names {
					if id.Name == method.Name() {
						spanNode, selectionNode = f, id
						break Methods
					}
				}
			}
			child.Range, err = nodeToProtocolRange(view, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(view, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}

		for i := 0; i < ti.NumEmbeddeds(); i++ {
			embedded := ti.EmbeddedType(i)
			nt, isNamed := embedded.(*types.Named)
			if !isNamed {
				continue
			}

			child := protocol.DocumentSymbol{
				Name: types.TypeString(embedded, q),
			}
			setKind(&child, embedded, q)
			var spanNode, selectionNode ast.Node
		Embeddeds:
			for _, f := range ai.Methods.List {
				if len(f.Names) > 0 {
					continue
				}

				if t := info.TypeOf(f.Type); types.Identical(nt, t) {
					spanNode, selectionNode = f, f.Type
					break Embeddeds
				}
			}
			child.Range, err = nodeToProtocolRange(view, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(view, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}
	}
	return s, nil
}

func nodesForStructField(i int, st *ast.StructType) (span, selection ast.Node) {
	j := 0
	for _, field := range st.Fields.List {
		if len(field.Names) == 0 {
			if i == j {
				return field, field.Type
			}
			j++
			continue
		}
		for _, name := range field.Names {
			if i == j {
				return field, name
			}
			j++
		}
	}
	return nil, nil
}

func varSymbol(ctx context.Context, view View, pkg Package, decl ast.Node, name *ast.Ident, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Variable,
	}
	if _, ok := obj.(*types.Const); ok {
		s.Kind = protocol.Constant
	}
	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.Detail = types.TypeString(obj.Type(), q)
	return s, nil
}
<commit_msg>internal/lsp/source: eliminate setKind<commit_after>// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package source

import (
	"context"
	"fmt"
	"go/ast"
	"go/types"

	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/telemetry/trace"
)

func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.DocumentSymbol, error) {
	ctx, done := trace.StartSpan(ctx, "source.DocumentSymbols")
	defer done()

	pkg, pgh, err := getParsedFile(ctx, snapshot, fh, NarrowestPackageHandle)
	if err != nil {
		return nil, fmt.Errorf("getting file for DocumentSymbols: %v", err)
	}
	file, _, _, err := pgh.Cached()
	if err != nil {
		return nil, err
	}

	info := pkg.GetTypesInfo()
	q := qualifier(file, pkg.GetTypes(), info)

	methodsToReceiver := make(map[types.Type][]protocol.DocumentSymbol)
	symbolsToReceiver := make(map[types.Type]int)
	var symbols []protocol.DocumentSymbol
	for _, decl := range file.Decls {
		switch decl := decl.(type) {
		case *ast.FuncDecl:
			if obj := info.ObjectOf(decl.Name); obj != nil {
				fs, err := funcSymbol(ctx, snapshot.View(), pkg, decl, obj, q)
				if err != nil {
					return nil, err
				}
				// Store methods separately, as we want them to appear as children
				// of the corresponding type (which we may not have seen yet).
				if fs.Kind == protocol.Method {
					rtype := obj.Type().(*types.Signature).Recv().Type()
					methodsToReceiver[rtype] = append(methodsToReceiver[rtype], fs)
				} else {
					symbols = append(symbols, fs)
				}
			}
		case *ast.GenDecl:
			for _, spec := range decl.Specs {
				switch spec := spec.(type) {
				case *ast.TypeSpec:
					if obj := info.ObjectOf(spec.Name); obj != nil {
						ts, err := typeSymbol(ctx, snapshot.View(), pkg, info, spec, obj, q)
						if err != nil {
							return nil, err
						}
						symbols = append(symbols, ts)
						symbolsToReceiver[obj.Type()] = len(symbols) - 1
					}
				case *ast.ValueSpec:
					for _, name := range spec.Names {
						if obj := info.ObjectOf(name); obj != nil {
							vs, err := varSymbol(ctx, snapshot.View(), pkg, decl, name, obj, q)
							if err != nil {
								return nil, err
							}
							symbols = append(symbols, vs)
						}
					}
				}
			}
		}
	}

	// Attempt to associate methods to the corresponding type symbol.
	for typ, methods := range methodsToReceiver {
		if ptr, ok := typ.(*types.Pointer); ok {
			typ = ptr.Elem()
		}

		if i, ok := symbolsToReceiver[typ]; ok {
			symbols[i].Children = append(symbols[i].Children, methods...)
		} else {
			// The type definition for the receiver of these methods was not in the document.
			symbols = append(symbols, methods...)
		}
	}
	return symbols, nil
}

func funcSymbol(ctx context.Context, view View, pkg Package, decl *ast.FuncDecl, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Function,
	}
	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, decl.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	sig, _ := obj.Type().(*types.Signature)
	if sig != nil {
		if sig.Recv() != nil {
			s.Kind = protocol.Method
		}
		s.Detail += "("
		for i := 0; i < sig.Params().Len(); i++ {
			if i > 0 {
				s.Detail += ", "
			}
			param := sig.Params().At(i)
			label := types.TypeString(param.Type(), q)
			if param.Name() != "" {
				label = fmt.Sprintf("%s %s", param.Name(), label)
			}
			s.Detail += label
		}
		s.Detail += ")"
	}
	return s, nil
}

func typeSymbol(ctx context.Context, view View, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
	}
	s.Detail, _ = formatType(obj.Type(), q)
	s.Kind = typeToKind(obj.Type())

	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, spec)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, spec.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	t, objIsStruct := obj.Type().Underlying().(*types.Struct)
	st, specIsStruct := spec.Type.(*ast.StructType)
	if objIsStruct && specIsStruct {
		for i := 0; i < t.NumFields(); i++ {
			f := t.Field(i)
			child := protocol.DocumentSymbol{
				Name: f.Name(),
				Kind: protocol.Field,
			}
			child.Detail, _ = formatType(f.Type(), q)

			spanNode, selectionNode := nodesForStructField(i, st)
			if span, err := nodeToProtocolRange(view, pkg, spanNode); err == nil {
				child.Range = span
			}
			if span, err := nodeToProtocolRange(view, pkg, selectionNode); err == nil {
				child.SelectionRange = span
			}
			s.Children = append(s.Children, child)
		}
	}

	ti, objIsInterface := obj.Type().Underlying().(*types.Interface)
	ai, specIsInterface := spec.Type.(*ast.InterfaceType)
	if objIsInterface && specIsInterface {
		for i := 0; i < ti.NumExplicitMethods(); i++ {
			method := ti.ExplicitMethod(i)
			child := protocol.DocumentSymbol{
				Name: method.Name(),
				Kind: protocol.Method,
			}

			var spanNode, selectionNode ast.Node
		Methods:
			for _, f := range ai.Methods.List {
				for _, id := range f.Names {
					if id.Name == method.Name() {
						spanNode, selectionNode = f, id
						break Methods
					}
				}
			}
			child.Range, err = nodeToProtocolRange(view, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(view, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}

		for i := 0; i < ti.NumEmbeddeds(); i++ {
			embedded := ti.EmbeddedType(i)
			nt, isNamed := embedded.(*types.Named)
			if !isNamed {
				continue
			}

			child := protocol.DocumentSymbol{
				Name: types.TypeString(embedded, q),
			}
			child.Kind = typeToKind(embedded)
			var spanNode, selectionNode ast.Node
		Embeddeds:
			for _, f := range ai.Methods.List {
				if len(f.Names) > 0 {
					continue
				}

				if t := info.TypeOf(f.Type); types.Identical(nt, t) {
					spanNode, selectionNode = f, f.Type
					break Embeddeds
				}
			}
			child.Range, err = nodeToProtocolRange(view, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(view, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}
	}
	return s, nil
}

func nodesForStructField(i int, st *ast.StructType) (span, selection ast.Node) {
	j := 0
	for _, field := range st.Fields.List {
		if len(field.Names) == 0 {
			if i == j {
				return field, field.Type
			}
			j++
			continue
		}
		for _, name := range field.Names {
			if i == j {
				return field, name
			}
			j++
		}
	}
	return nil, nil
}

func varSymbol(ctx context.Context, view View, pkg Package, decl ast.Node, name *ast.Ident, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Variable,
	}
	if _, ok := obj.(*types.Const); ok {
		s.Kind = protocol.Constant
	}
	var err error
	s.Range, err = nodeToProtocolRange(view, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(view, pkg, name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.Detail = types.TypeString(obj.Type(), q)
	return s, nil
}
<|endoftext|>


<commit_before>// Copyright 2020 The Ebiten Authors
//
// 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
//
//     http://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 shader_test

import (
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/shader"
)

func TestDump(t *testing.T) {
	tests := []struct {
		Name string
		Src  string
		VS   string
		FS   string
	}{
		{
			Name: "uniforms",
			Src: `package main

var (
	Foo vec2
	Boo vec4
)`,
			VS: `uniform vec2 U0;
uniform vec4 U1;`,
		},
		{
			Name: "func",
			Src: `package main

func Foo(foo vec2) vec4 {
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
}`,
		},
		{
			Name: "func body",
			Src: `package main

func Foo(foo vec2) vec4 {
	return vec4(foo, 0, 1)
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	l1 = vec4(l0, 0.0, 1.0);
	return;
}`,
		},
		{
			Name: "multiple out params",
			Src: `package main

func Foo(foo vec4) (float, float, float, float) {
	return foo.x, foo.y, foo.z, foo.w
}`,
			VS: `void F0(in vec4 l0, out float l1, out float l2, out float l3, out float l4) {
	l1 = (l0).x;
	l2 = (l0).y;
	l3 = (l0).z;
	l4 = (l0).w;
	return;
}`,
		},
		{
			Name: "blocks",
			Src: `package main

func Foo(foo vec2) vec4 {
	var r vec4
	{
		r.x = foo.x
		var foo vec3
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
	}
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	{
		vec3 l3 = vec3(0.0);
		(l2).x = (l0).x;
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
	}
	l1 = l2;
	return;
}`,
		},
		{
			Name: "define",
			Src: `package main

func Foo(foo vec2) vec4 {
	r := vec4(foo, 0, 1)
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	l2 = vec4(l0, 0.0, 1.0);
	l1 = l2;
	return;
}`,
		},
		{
			Name: "vertex",
			Src: `package main

func Vertex(position vec2, texCoord vec2, color vec4) (position vec4, texCoord vec2, color vec4) {
	projectionMatrix := mat4(
		2 / ScreenSize.x, 0, 0, 0,
		0, 2 / ScreenSize.y, 0, 0,
		0, 0, 1, 0,
		-1, -1, 0, 1,
	)
	return projectionMatrix * vec4(position, 0, 1), texCoord, color
}

var ScreenSize vec2`,
			VS: `uniform vec2 U0;
attribute vec2 A0;
attribute vec2 A1;
attribute vec4 A2;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	mat4 l0 = mat4(0.0);
	l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -(1.0), -(1.0), 0.0, 1.0);
	gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
	V0 = A1;
	V1 = A2;
	return;
}`,
			FS: `uniform vec2 U0;
varying vec2 V0;
varying vec4 V1;`,
		},
		{
			Name: "vertex and fragment",
			Src: `package main

func Vertex(position vec2, texCoord vec2, color vec4) (position vec4, texCoord vec2, color vec4) {
	projectionMatrix := mat4(
		2 / ScreenSize.x, 0, 0, 0,
		0, 2 / ScreenSize.y, 0, 0,
		0, 0, 1, 0,
		-1, -1, 0, 1,
	)
	return projectionMatrix * vec4(position, 0, 1), texCoord, color
}

func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	return vec4(1, 0, 0, 1)
}

var ScreenSize vec2`,
			VS: `uniform vec2 U0;
attribute vec2 A0;
attribute vec2 A1;
attribute vec4 A2;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	mat4 l0 = mat4(0.0);
	l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -(1.0), -(1.0), 0.0, 1.0);
	gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
	V0 = A1;
	V1 = A2;
	return;
}`,
			FS: `uniform vec2 U0;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
	return;
}`,
		},
	}
	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			s, err := Compile([]byte(tc.Src), "Vertex", "Fragment")
			if err != nil {
				t.Error(err)
				return
			}
			vs, fs := s.Glsl()
			if got, want := vs, tc.VS+"\n"; got != want {
				t.Errorf("got: %v, want: %v", got, want)
			}
			if tc.FS != "" {
				if got, want := fs, tc.FS+"\n"; got != want {
					t.Errorf("got: %v, want: %v", got, want)
				}
			}
		})
	}
}
<commit_msg>shader: Bug fix: Test compile error<commit_after>// Copyright 2020 The Ebiten Authors
//
// 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
//
//     http://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 shader_test

import (
	"go/parser"
	"go/token"
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/shader"
)

func TestDump(t *testing.T) {
	tests := []struct {
		Name string
		Src  string
		VS   string
		FS   string
	}{
		{
			Name: "uniforms",
			Src: `package main

var (
	Foo vec2
	Boo vec4
)`,
			VS: `uniform vec2 U0;
uniform vec4 U1;`,
		},
		{
			Name: "func",
			Src: `package main

func Foo(foo vec2) vec4 {
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
}`,
		},
		{
			Name: "func body",
			Src: `package main

func Foo(foo vec2) vec4 {
	return vec4(foo, 0, 1)
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	l1 = vec4(l0, 0.0, 1.0);
	return;
}`,
		},
		{
			Name: "multiple out params",
			Src: `package main

func Foo(foo vec4) (float, float, float, float) {
	return foo.x, foo.y, foo.z, foo.w
}`,
			VS: `void F0(in vec4 l0, out float l1, out float l2, out float l3, out float l4) {
	l1 = (l0).x;
	l2 = (l0).y;
	l3 = (l0).z;
	l4 = (l0).w;
	return;
}`,
		},
		{
			Name: "blocks",
			Src: `package main

func Foo(foo vec2) vec4 {
	var r vec4
	{
		r.x = foo.x
		var foo vec3
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
	}
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	{
		vec3 l3 = vec3(0.0);
		(l2).x = (l0).x;
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
	}
	l1 = l2;
	return;
}`,
		},
		{
			Name: "define",
			Src: `package main

func Foo(foo vec2) vec4 {
	r := vec4(foo, 0, 1)
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	l2 = vec4(l0, 0.0, 1.0);
	l1 = l2;
	return;
}`,
		},
		{
			Name: "vertex",
			Src: `package main

func Vertex(position vec2, texCoord vec2, color vec4) (position vec4, texCoord vec2, color vec4) {
	projectionMatrix := mat4(
		2 / ScreenSize.x, 0, 0, 0,
		0, 2 / ScreenSize.y, 0, 0,
		0, 0, 1, 0,
		-1, -1, 0, 1,
	)
	return projectionMatrix * vec4(position, 0, 1), texCoord, color
}

var ScreenSize vec2`,
			VS: `uniform vec2 U0;
attribute vec2 A0;
attribute vec2 A1;
attribute vec4 A2;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	mat4 l0 = mat4(0.0);
	l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -(1.0), -(1.0), 0.0, 1.0);
	gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
	V0 = A1;
	V1 = A2;
	return;
}`,
			FS: `uniform vec2 U0;
varying vec2 V0;
varying vec4 V1;`,
		},
		{
			Name: "vertex and fragment",
			Src: `package main

func Vertex(position vec2, texCoord vec2, color vec4) (position vec4, texCoord vec2, color vec4) {
	projectionMatrix := mat4(
		2 / ScreenSize.x, 0, 0, 0,
		0, 2 / ScreenSize.y, 0, 0,
		0, 0, 1, 0,
		-1, -1, 0, 1,
	)
	return projectionMatrix * vec4(position, 0, 1), texCoord, color
}

func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	return vec4(1, 0, 0, 1)
}

var ScreenSize vec2`,
			VS: `uniform vec2 U0;
attribute vec2 A0;
attribute vec2 A1;
attribute vec4 A2;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	mat4 l0 = mat4(0.0);
	l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -(1.0), -(1.0), 0.0, 1.0);
	gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
	V0 = A1;
	V1 = A2;
	return;
}`,
			FS: `uniform vec2 U0;
varying vec2 V0;
varying vec4 V1;

void main(void) {
	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
	return;
}`,
		},
	}
	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			fset := token.NewFileSet()
			f, err := parser.ParseFile(fset, "", []byte(tc.Src), parser.AllErrors)
			if err != nil {
				t.Fatal(err)
				return
			}

			s, err := Compile(fset, f, "Vertex", "Fragment")
			if err != nil {
				t.Error(err)
				return
			}
			vs, fs := s.Glsl()
			if got, want := vs, tc.VS+"\n"; got != want {
				t.Errorf("got: %v, want: %v", got, want)
			}
			if tc.FS != "" {
				if got, want := fs, tc.FS+"\n"; got != want {
					t.Errorf("got: %v, want: %v", got, want)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 The Ebiten Authors
//
// 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
//
//     http://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 shader_test

import (
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/shader"
)

func TestDump(t *testing.T) {
	tests := []struct {
		Name string
		Src  string
		VS   string
		FS   string
	}{
		{
			Name: "uniforms",
			Src: `package main

var (
	Foo vec2
	Boo vec4
)`,
			VS: `uniform vec2 U0;
uniform vec4 U1;`,
		},
		{
			Name: "func",
			Src: `package main

func Foo(foo vec2) vec4 {
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
}`,
		},
		{
			Name: "func body",
			Src: `package main

func Foo(foo vec2) vec4 {
	return vec4(foo, 0, 1)
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	l1 = vec4(l0, 0, 1);
	return;
}`,
		},
		{
			Name: "multiple out params",
			Src: `package main

func Foo(foo vec4) (float, float, float, float) {
	return foo.x, foo.y, foo.z, foo.w
}`,
			VS: `void F0(in vec4 l0, out float l1, out float l2, out float l3, out float l4) {
	l1 = (l0).x;
	l2 = (l0).y;
	l3 = (l0).z;
	l4 = (l0).w;
	return;
}`,
		},
		{
			Name: "blocks",
			Src: `package main

func Foo(foo vec2) vec4 {
	var r vec4
	{
		r.x = foo.x
		var foo vec3
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
	}
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	{
		vec3 l3 = vec3(0.0);
		(l2).x = (l0).x;
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
	}
	l1 = l2;
	return;
}`,
		},
		{
			Name: "define",
			Src: `package main

func Foo(foo vec2) vec4 {
	r := vec4(foo, 0, 1)
	return r
}`,
			// TODO: number literals must be floats.
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	l2 = vec4(l0, 0, 1);
	l1 = l2;
	return;
}`,
		},
	}
	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			s, err := Compile([]byte(tc.Src))
			if err != nil {
				t.Error(err)
				return
			}
			vs, fs := s.Glsl()
			if got, want := vs, tc.VS+"\n"; got != want {
				t.Errorf("got: %v, want: %v", got, want)
			}
			if tc.FS != "" {
				if got, want := fs, tc.FS+"\n"; got != want {
					t.Errorf("got: %v, want: %v", got, want)
				}
			}
		})
	}
}
<commit_msg>shader: Add more shadowing tests<commit_after>// Copyright 2020 The Ebiten Authors
//
// 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
//
//     http://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 shader_test

import (
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/shader"
)

func TestDump(t *testing.T) {
	tests := []struct {
		Name string
		Src  string
		VS   string
		FS   string
	}{
		{
			Name: "uniforms",
			Src: `package main

var (
	Foo vec2
	Boo vec4
)`,
			VS: `uniform vec2 U0;
uniform vec4 U1;`,
		},
		{
			Name: "func",
			Src: `package main

func Foo(foo vec2) vec4 {
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
}`,
		},
		{
			Name: "func body",
			Src: `package main

func Foo(foo vec2) vec4 {
	return vec4(foo, 0, 1)
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	l1 = vec4(l0, 0, 1);
	return;
}`,
		},
		{
			Name: "multiple out params",
			Src: `package main

func Foo(foo vec4) (float, float, float, float) {
	return foo.x, foo.y, foo.z, foo.w
}`,
			VS: `void F0(in vec4 l0, out float l1, out float l2, out float l3, out float l4) {
	l1 = (l0).x;
	l2 = (l0).y;
	l3 = (l0).z;
	l4 = (l0).w;
	return;
}`,
		},
		{
			Name: "blocks",
			Src: `package main

func Foo(foo vec2) vec4 {
	var r vec4
	{
		r.x = foo.x
		var foo vec3
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
		{
			r.y = foo.y
			var foo vec4
			r.z = foo.z
		}
	}
	return r
}`,
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	{
		vec3 l3 = vec3(0.0);
		(l2).x = (l0).x;
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
		{
			vec4 l4 = vec4(0.0);
			(l2).y = (l3).y;
			(l2).z = (l4).z;
		}
	}
	l1 = l2;
	return;
}`,
		},
		{
			Name: "define",
			Src: `package main

func Foo(foo vec2) vec4 {
	r := vec4(foo, 0, 1)
	return r
}`,
			// TODO: number literals must be floats.
			VS: `void F0(in vec2 l0, out vec4 l1) {
	vec4 l2 = vec4(0.0);
	l2 = vec4(l0, 0, 1);
	l1 = l2;
	return;
}`,
		},
	}
	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			s, err := Compile([]byte(tc.Src))
			if err != nil {
				t.Error(err)
				return
			}
			vs, fs := s.Glsl()
			if got, want := vs, tc.VS+"\n"; got != want {
				t.Errorf("got: %v, want: %v", got, want)
			}
			if tc.FS != "" {
				if got, want := fs, tc.FS+"\n"; got != want {
					t.Errorf("got: %v, want: %v", got, want)
				}
			}
		})
	}
}
<|endoftext|>