<commit_before>package common

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"github.com/vishvananda/netlink"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"net"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"time"
)

var google net.IP = net.ParseIP("8.8.8.8")

// Config handles marshalling user supplied configuration data
type Config struct {
	InterfaceName string
	MachineID     string
	NumWorkers    int
	StatsWindow   time.Duration

	PrivateIP string
	PublicIP  string

	PublicAddress string

	PrivateKey []byte
	PublicKey  []byte

	ListenAddress string
	ListenPort    int

	Prefix   string
	ConfFile string
	DataDir  string
	LogDir   string

	SyncInterval    time.Duration
	RefreshInterval time.Duration

	TLSEnabled    bool
	TLSSkipVerify bool
	TLSCert       string
	TLSKey        string
	TLSCA         string

	Datastore   string
	endpoints   string
	Endpoints   []string
	AuthEnabled bool
	Username    string
	Password    string

	NetworkConfig *NetworkConfig
	notSet        map[string]bool
}

func (cfg *Config) handleDefaultString(name, def string) string {
	env := "QUANTUM_" + strings.ToUpper(strings.Replace(name, "-", "_", 10))
	output := os.Getenv(env)
	if output == "" {
		cfg.notSet[name] = true
		return def
	}
	return output
}

func (cfg *Config) handleDefaultInt(name string, def int) int {
	str := strconv.Itoa(def)
	output, err := strconv.Atoi(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleDefaultDuration(name string, def time.Duration) time.Duration {
	str := def.String()
	output, err := time.ParseDuration(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleDefaultBool(name string, def bool) bool {
	str := strconv.FormatBool(def)
	output, err := strconv.ParseBool(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleCli() {
	flag.StringVar(&cfg.ConfFile, "conf-file", cfg.handleDefaultString("conf-file", ""), "The json or yaml file to load configuration data from.")

	flag.StringVar(&cfg.InterfaceName, "interface-name", cfg.handleDefaultString("interface-name", "quantum%d"), "The name for the TUN interface that will be used for forwarding. Use %d to have the OS pick an available interface name.")
	flag.DurationVar(&cfg.StatsWindow, "stats-window", cfg.handleDefaultDuration("stats-window", 5), "The window of time to calculate bandwidth and packet per second information on.")

	flag.StringVar(&cfg.PrivateIP, "private-ip", cfg.handleDefaultString("private-ip", ""), "The private ip address of this node.")
	flag.StringVar(&cfg.PublicIP, "public-ip", cfg.handleDefaultString("public-ip", ""), "The public ip address of this node.")

	flag.StringVar(&cfg.ListenAddress, "listen-address", cfg.handleDefaultString("listen-address", "0.0.0.0"), "The ip address to listen on for forwarded packets.")
	flag.IntVar(&cfg.ListenPort, "listen-port", cfg.handleDefaultInt("listen-port", 1099), "The ip port to listen on for forwarded packets.")

	flag.StringVar(&cfg.Prefix, "prefix", cfg.handleDefaultString("prefix", "quantum"), "The etcd key that quantum information is stored under.")
	flag.StringVar(&cfg.DataDir, "data-dir", cfg.handleDefaultString("data-dir", "/var/lib/quantum"), "The data directory for quantum to use for persistent state.")
	flag.StringVar(&cfg.LogDir, "log-dir", cfg.handleDefaultString("log-dir", ""), "The log directory to write logs to, if this is ommited logs are written to stdout/stderr.")

	flag.DurationVar(&cfg.SyncInterval, "sync-interval", cfg.handleDefaultDuration("sync-interval", 30), "The backend sync interval")
	flag.DurationVar(&cfg.RefreshInterval, "refresh-interval", cfg.handleDefaultDuration("refresh-interval", 60), "The backend lease refresh interval.")

	flag.StringVar(&cfg.TLSCert, "tls-cert", cfg.handleDefaultString("tls-cert", ""), "The client certificate to use for authentication with the backend datastore.")
	flag.StringVar(&cfg.TLSKey, "tls-key", cfg.handleDefaultString("tls-key", ""), "The client key to use for authentication with the backend datastore.")
	flag.StringVar(&cfg.TLSCA, "tls-ca-cert", cfg.handleDefaultString("tls-ca-cert", ""), "The CA certificate to authenticate the backend datastore.")
	flag.BoolVar(&cfg.TLSSkipVerify, "tls-skip-verify", cfg.handleDefaultBool("tls-skip-verify", false), "The CA certificate to authenticate the backend datastore.")

	flag.StringVar(&cfg.Datastore, "datastore", cfg.handleDefaultString("datastore", "etcd"), "The datastore backend to use, either consul or etcd")
	flag.StringVar(&cfg.endpoints, "endpoints", cfg.handleDefaultString("endpoints", "127.0.0.1:2379"), "A comma delimited list of datastore endpoints to use.")
	flag.StringVar(&cfg.Username, "username", cfg.handleDefaultString("username", ""), "The datastore username to use for authentication.")
	flag.StringVar(&cfg.Password, "password", cfg.handleDefaultString("password", ""), "The datastore password to use for authentication.")

	flag.Parse()
}

func (cfg *Config) handleComputed() error {
	cfg.Endpoints = strings.Split(cfg.endpoints, ",")

	pubkey, privkey := GenerateECKeyPair()
	cfg.PublicKey = pubkey
	cfg.PrivateKey = privkey

	if (cfg.TLSCert != "" && cfg.TLSKey != "") || cfg.TLSCA != "" {
		cfg.TLSEnabled = true
	}

	if cfg.Username != "" {
		cfg.AuthEnabled = true
	}

	os.MkdirAll(cfg.DataDir, os.ModeDir)
	machineID := make([]byte, 32)
	machineIDPath := path.Join(cfg.DataDir, "machine-id")
	if _, err := os.Stat(machineIDPath); os.IsNotExist(err) {
		rand.Read(machineID)
		ioutil.WriteFile(machineIDPath, machineID, os.ModePerm)
	} else {
		buf, _ := ioutil.ReadFile(machineIDPath)
		machineID = buf
	}
	cfg.MachineID = hex.EncodeToString(machineID)

	if cfg.PublicIP == "" {
		routes, err := netlink.RouteGet(google)
		if err != nil {
			return err
		}

		cfg.PublicIP = routes[0].Src.String()
	}

	cfg.PublicAddress = cfg.PublicIP + ":" + strconv.Itoa(cfg.ListenPort)

	cores := runtime.NumCPU()
	runtime.GOMAXPROCS(cores * 2)

	cfg.NumWorkers = cores

	return nil
}

func (cfg *Config) parseFileData(data map[string]string) error {
	for k, v := range data {
		if _, ok := cfg.notSet[k]; ok {
			switch k {
			case "conf-file":
				cfg.ConfFile = v
			case "interface-name":
				cfg.InterfaceName = v
			case "private-ip":
				cfg.PrivateIP = v
			case "public-ip":
				cfg.PublicIP = v
			case "listen-address":
				cfg.ListenAddress = v
			case "listen-port":
				i, err := strconv.Atoi(v)
				if err != nil {
					return err
				}
				cfg.ListenPort = i
			case "prefix":
				cfg.Prefix = v
			case "data-dir":
				cfg.DataDir = v
			case "log-dir":
				cfg.LogDir = v
			case "stats-window":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.StatsWindow = dur
			case "sync-interval":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.SyncInterval = dur
			case "refresh-interval":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.RefreshInterval = dur
			case "tls-skip-verify":
				b, err := strconv.ParseBool(v)
				if err != nil {
					return err
				}
				cfg.TLSSkipVerify = b
			case "tls-cert":
				cfg.TLSCert = v
			case "tls-key":
				cfg.TLSKey = v
			case "tls-ca-cert":
				cfg.TLSCA = v
			case "datastore":
				cfg.Datastore = v
			case "endpoints":
				cfg.endpoints = v
			case "username":
				cfg.Username = v
			case "password":
				cfg.Password = v
			}
		}
	}
	return nil
}

func (cfg *Config) handleFile() error {
	if cfg.ConfFile != "" {
		buf, err := ioutil.ReadFile(cfg.ConfFile)
		if err != nil {
			return err
		}

		data := make(map[string]string)
		ext := path.Ext(cfg.ConfFile)
		switch {
		case ".json" == ext:
			err = json.Unmarshal(buf, &data)
		case ".yaml" == ext || ".yml" == ext:
			err = yaml.Unmarshal(buf, &data)
		default:
			return errors.New("The configuration file is not in a supported format.")
		}

		return cfg.parseFileData(data)
	}
	return nil
}

// NewConfig generates a new config object
func NewConfig() (*Config, error) {
	cfg := &Config{notSet: make(map[string]bool)}
	cfg.handleCli()

	err := cfg.handleFile()
	if err != nil {
		return nil, err
	}

	err = cfg.handleComputed()
	if err != nil {
		return nil, err
	}

	return cfg, nil
}
<commit_msg>Fixed go lint errors<commit_after>package common

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"github.com/vishvananda/netlink"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"net"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"time"
)

var google = net.ParseIP("8.8.8.8")

// Config handles marshalling user supplied configuration data
type Config struct {
	InterfaceName string
	MachineID     string
	NumWorkers    int
	StatsWindow   time.Duration

	PrivateIP string
	PublicIP  string

	PublicAddress string

	PrivateKey []byte
	PublicKey  []byte

	ListenAddress string
	ListenPort    int

	Prefix   string
	ConfFile string
	DataDir  string
	LogDir   string

	SyncInterval    time.Duration
	RefreshInterval time.Duration

	TLSEnabled    bool
	TLSSkipVerify bool
	TLSCert       string
	TLSKey        string
	TLSCA         string

	Datastore   string
	endpoints   string
	Endpoints   []string
	AuthEnabled bool
	Username    string
	Password    string

	NetworkConfig *NetworkConfig
	notSet        map[string]bool
}

func (cfg *Config) handleDefaultString(name, def string) string {
	env := "QUANTUM_" + strings.ToUpper(strings.Replace(name, "-", "_", 10))
	output := os.Getenv(env)
	if output == "" {
		cfg.notSet[name] = true
		return def
	}
	return output
}

func (cfg *Config) handleDefaultInt(name string, def int) int {
	str := strconv.Itoa(def)
	output, err := strconv.Atoi(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleDefaultDuration(name string, def time.Duration) time.Duration {
	str := def.String()
	output, err := time.ParseDuration(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleDefaultBool(name string, def bool) bool {
	str := strconv.FormatBool(def)
	output, err := strconv.ParseBool(cfg.handleDefaultString(name, str))
	if err != nil {
		panic(err)
	}
	return output
}

func (cfg *Config) handleCli() {
	flag.StringVar(&cfg.ConfFile, "conf-file", cfg.handleDefaultString("conf-file", ""), "The json or yaml file to load configuration data from.")

	flag.StringVar(&cfg.InterfaceName, "interface-name", cfg.handleDefaultString("interface-name", "quantum%d"), "The name for the TUN interface that will be used for forwarding. Use %d to have the OS pick an available interface name.")
	flag.DurationVar(&cfg.StatsWindow, "stats-window", cfg.handleDefaultDuration("stats-window", 5), "The window of time to calculate bandwidth and packet per second information on.")

	flag.StringVar(&cfg.PrivateIP, "private-ip", cfg.handleDefaultString("private-ip", ""), "The private ip address of this node.")
	flag.StringVar(&cfg.PublicIP, "public-ip", cfg.handleDefaultString("public-ip", ""), "The public ip address of this node.")

	flag.StringVar(&cfg.ListenAddress, "listen-address", cfg.handleDefaultString("listen-address", "0.0.0.0"), "The ip address to listen on for forwarded packets.")
	flag.IntVar(&cfg.ListenPort, "listen-port", cfg.handleDefaultInt("listen-port", 1099), "The ip port to listen on for forwarded packets.")

	flag.StringVar(&cfg.Prefix, "prefix", cfg.handleDefaultString("prefix", "quantum"), "The etcd key that quantum information is stored under.")
	flag.StringVar(&cfg.DataDir, "data-dir", cfg.handleDefaultString("data-dir", "/var/lib/quantum"), "The data directory for quantum to use for persistent state.")
	flag.StringVar(&cfg.LogDir, "log-dir", cfg.handleDefaultString("log-dir", ""), "The log directory to write logs to, if this is ommited logs are written to stdout/stderr.")

	flag.DurationVar(&cfg.SyncInterval, "sync-interval", cfg.handleDefaultDuration("sync-interval", 30), "The backend sync interval")
	flag.DurationVar(&cfg.RefreshInterval, "refresh-interval", cfg.handleDefaultDuration("refresh-interval", 60), "The backend lease refresh interval.")

	flag.StringVar(&cfg.TLSCert, "tls-cert", cfg.handleDefaultString("tls-cert", ""), "The client certificate to use for authentication with the backend datastore.")
	flag.StringVar(&cfg.TLSKey, "tls-key", cfg.handleDefaultString("tls-key", ""), "The client key to use for authentication with the backend datastore.")
	flag.StringVar(&cfg.TLSCA, "tls-ca-cert", cfg.handleDefaultString("tls-ca-cert", ""), "The CA certificate to authenticate the backend datastore.")
	flag.BoolVar(&cfg.TLSSkipVerify, "tls-skip-verify", cfg.handleDefaultBool("tls-skip-verify", false), "The CA certificate to authenticate the backend datastore.")

	flag.StringVar(&cfg.Datastore, "datastore", cfg.handleDefaultString("datastore", "etcd"), "The datastore backend to use, either consul or etcd")
	flag.StringVar(&cfg.endpoints, "endpoints", cfg.handleDefaultString("endpoints", "127.0.0.1:2379"), "A comma delimited list of datastore endpoints to use.")
	flag.StringVar(&cfg.Username, "username", cfg.handleDefaultString("username", ""), "The datastore username to use for authentication.")
	flag.StringVar(&cfg.Password, "password", cfg.handleDefaultString("password", ""), "The datastore password to use for authentication.")

	flag.Parse()
}

func (cfg *Config) handleComputed() error {
	cfg.Endpoints = strings.Split(cfg.endpoints, ",")

	pubkey, privkey := GenerateECKeyPair()
	cfg.PublicKey = pubkey
	cfg.PrivateKey = privkey

	if (cfg.TLSCert != "" && cfg.TLSKey != "") || cfg.TLSCA != "" {
		cfg.TLSEnabled = true
	}

	if cfg.Username != "" {
		cfg.AuthEnabled = true
	}

	os.MkdirAll(cfg.DataDir, os.ModeDir)
	machineID := make([]byte, 32)
	machineIDPath := path.Join(cfg.DataDir, "machine-id")
	if _, err := os.Stat(machineIDPath); os.IsNotExist(err) {
		rand.Read(machineID)
		ioutil.WriteFile(machineIDPath, machineID, os.ModePerm)
	} else {
		buf, _ := ioutil.ReadFile(machineIDPath)
		machineID = buf
	}
	cfg.MachineID = hex.EncodeToString(machineID)

	if cfg.PublicIP == "" {
		routes, err := netlink.RouteGet(google)
		if err != nil {
			return err
		}

		cfg.PublicIP = routes[0].Src.String()
	}

	cfg.PublicAddress = cfg.PublicIP + ":" + strconv.Itoa(cfg.ListenPort)

	cores := runtime.NumCPU()
	runtime.GOMAXPROCS(cores * 2)

	cfg.NumWorkers = cores

	return nil
}

func (cfg *Config) parseFileData(data map[string]string) error {
	for k, v := range data {
		if _, ok := cfg.notSet[k]; ok {
			switch k {
			case "conf-file":
				cfg.ConfFile = v
			case "interface-name":
				cfg.InterfaceName = v
			case "private-ip":
				cfg.PrivateIP = v
			case "public-ip":
				cfg.PublicIP = v
			case "listen-address":
				cfg.ListenAddress = v
			case "listen-port":
				i, err := strconv.Atoi(v)
				if err != nil {
					return err
				}
				cfg.ListenPort = i
			case "prefix":
				cfg.Prefix = v
			case "data-dir":
				cfg.DataDir = v
			case "log-dir":
				cfg.LogDir = v
			case "stats-window":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.StatsWindow = dur
			case "sync-interval":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.SyncInterval = dur
			case "refresh-interval":
				dur, err := time.ParseDuration(v)
				if err != nil {
					return err
				}
				cfg.RefreshInterval = dur
			case "tls-skip-verify":
				b, err := strconv.ParseBool(v)
				if err != nil {
					return err
				}
				cfg.TLSSkipVerify = b
			case "tls-cert":
				cfg.TLSCert = v
			case "tls-key":
				cfg.TLSKey = v
			case "tls-ca-cert":
				cfg.TLSCA = v
			case "datastore":
				cfg.Datastore = v
			case "endpoints":
				cfg.endpoints = v
			case "username":
				cfg.Username = v
			case "password":
				cfg.Password = v
			}
		}
	}
	return nil
}

func (cfg *Config) handleFile() error {
	if cfg.ConfFile != "" {
		buf, err := ioutil.ReadFile(cfg.ConfFile)
		if err != nil {
			return err
		}

		data := make(map[string]string)
		ext := path.Ext(cfg.ConfFile)
		switch {
		case ".json" == ext:
			err = json.Unmarshal(buf, &data)
		case ".yaml" == ext || ".yml" == ext:
			err = yaml.Unmarshal(buf, &data)
		default:
			return errors.New("The configuration file is not in a supported format.")
		}

		return cfg.parseFileData(data)
	}
	return nil
}

// NewConfig generates a new config object
func NewConfig() (*Config, error) {
	cfg := &Config{notSet: make(map[string]bool)}
	cfg.handleCli()

	err := cfg.handleFile()
	if err != nil {
		return nil, err
	}

	err = cfg.handleComputed()
	if err != nil {
		return nil, err
	}

	return cfg, nil
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/skeswa/gophr/common/dtos"
	"github.com/skeswa/gophr/common/models"
)

var (
	github_base_api_url     = "https://api.github.com"
	github_gophr_org_name   = "gophr-pm"
	commits_until_parameter = "until"
	commits_after_parameter = "after'"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

// TODO optimize this
func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(
	packageModel models.PackageModel,
) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGitHubRepoDataAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return nil, errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return nil, nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	responseBodyMap, err := parseGitHubRepoDataResponseBody(resp)
	if err != nil {
		return nil, err
	}

	return responseBodyMap, nil
}

func buildGitHubRepoDataAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	url := fmt.Sprintf("%s/repos/%s/%s?access_token=%s", github_base_api_url, author, repo, APIKeyModel.Key)
	return url
}

// TODO Optimize this with ffjson struct!
func parseGitHubRepoDataResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.New("Failed to parse response body")
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		return nil, errors.New("Failed to unmarshal response body")
	}

	return bodyMap, nil
}

func (gitHubRequestService *GitHubRequestService) CheckGitHubRepoExists(
	packageModel models.PackageModel,
) error {
	repoName := buildNewGitHubRepoName(packageModel)
	url := fmt.Sprintf("https://github.com/%s/%s", github_gophr_org_name, repoName)
	resp, err := http.Get(url)

	if err != nil {
		log.Println("Error, a repo with that name already exists")
		return err
	}

	if resp.StatusCode != 404 {
		log.Println("Error, a repo with that name already exists")
		return errors.New("Error, a repo with that name already exists.")
	}

	return nil
}

func (gitHubRequestService *GitHubRequestService) CreateNewGitHubRepo(
	packageModel models.PackageModel,
) error {
	err := gitHubRequestService.CheckGitHubRepoExists(packageModel)
	if err != nil {
		log.Println(err)
		return err
	}

	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	JSONBody := buildNewGitHubRepoJSONBody(packageModel)
	gitHubURL := buildNewGitHubRepoAPIURL(packageModel, APIKeyModel)

	req, err := http.Post(gitHubURL, "application/json", JSONBody)
	defer req.Body.Close()

	if err != nil {
		log.Printf("Error occured whilecreating new github repo %s", err)
		return err
	}
	if req.StatusCode != 201 {
		log.Printf("Error creating repo was not successful")
		return errors.New("Error creating repo was not successful")
	}

	return nil
}

func buildNewGitHubRepoAPIURL(
	packageModel models.PackageModel,
	APIKeyModel *GitHubAPIKeyModel,
) string {
	url := fmt.Sprintf("%s/orgs/%s/repos?access_token=%s",
		github_base_api_url,
		github_gophr_org_name,
		APIKeyModel.Key,
	)
	return url
}

func buildNewGitHubRepoJSONBody(
	packageModel models.PackageModel,
) *bytes.Buffer {
	author := *packageModel.Author
	repo := *packageModel.Repo
	newGitHubRepoName := buildNewGitHubRepoName(packageModel)
	description := fmt.Sprintf("Auto generated and versioned go package for %s/%s", author, repo)
	homepage := fmt.Sprintf("https://github.com/%s/%s", author, repo)

	JSONStruct := NewGitHubRepo{Name: newGitHubRepoName, Description: description, Homepage: homepage}
	JSONByteBuffer := new(bytes.Buffer)
	json.NewEncoder(JSONByteBuffer).Encode(JSONStruct)
	return JSONByteBuffer
}

func buildNewGitHubRepoName(packageModel models.PackageModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	newGitHubRepoName := fmt.Sprintf("%s-%s", author, repo)
	return newGitHubRepoName
}

func (gitHubRequestService *GitHubRequestService) FetchCommitSHA(
	packageModel models.PackageModel,
	timestamp time.Time,
) (string, error) {
	commitSHA, err := gitHubRequestService.fetchCommitSHAByTimeSelector(packageModel, timestamp, commits_until_parameter)
	if err == nil {
		return commitSHA, nil
	}

	log.Printf("%s \n", err)
	commitSHA, err = gitHubRequestService.fetchCommitSHAByTimeSelector(packageModel, timestamp, commits_after_parameter)
	if err == nil {
		return commitSHA, nil
	}

	log.Printf("%s \n", err)
	refs, err := FetchRefs(*packageModel.Author, *packageModel.Repo)
	if err != nil {
		return refs.MasterRefHash, nil
	}

	return "", err
}

func (gitHubRequestService *GitHubRequestService) fetchCommitSHAByTimeSelector(
	packageModel models.PackageModel,
	timestamp time.Time,
	timeSelector string,
) (string, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	githubURL := buildGitHubRepoCommitsFromTimestampAPIURL(packageModel, *APIKeyModel, timestamp, timeSelector)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return "", errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return "", nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	commitSHA, err := parseGitHubCommitLookUpResponseBody(resp)
	if err != nil {
		return "", err
	}

	return commitSHA, nil
}

func buildGitHubRepoCommitsFromTimestampAPIURL(
	packageModel models.PackageModel,
	APIKeyModel GitHubAPIKeyModel,
	timestamp time.Time,
	timeSelector string,
) string {
	author := *packageModel.Author
	repo := *packageModel.Repo

	url := fmt.Sprintf("%s/repos/%s/%s/commits?%s=%s&access_token=%s",
		github_base_api_url,
		author,
		repo,
		timeSelector,
		strings.Replace(timestamp.String(), " ", "", -1),
		APIKeyModel.Key,
	)
	return url
}

func parseGitHubCommitLookUpResponseBody(response *http.Response) (string, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", errors.New("Failed to parse response body")
	}

	var commitSHAArray []dtos.GitCommitDTO
	err = json.Unmarshal(body, &commitSHAArray)
	if err != nil {
		return "", errors.New("Failed to unmarshal response body")
	}

	if len(commitSHAArray) >= 1 {
		return commitSHAArray[0].SHA, nil
	}

	return "", errors.New("No commit SHAs available for timestamp given")
}

// ==== Misc ====

type NewGitHubRepo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Homepage    string `json:"homepage"`
}

// TODO Optimize this
type GitHubPackageModelDTO struct {
	Package      models.PackageModel
	ResponseBody map[string]interface{}
}

// TODO Won't need this after implementing FFJSON
func ParseStarCount(responseBody map[string]interface{}) int {
	starCount := responseBody["stargazers_count"]
	if starCount == nil {
		return 0
	}

	return int(starCount.(float64))
}
<commit_msg>update github.go<commit_after>package common

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/skeswa/gophr/common/dtos"
	"github.com/skeswa/gophr/common/models"
)

var (
	github_base_api_url     = "https://api.github.com"
	github_gophr_org_name   = "gophr-pm"
	commits_until_parameter = "until"
	commits_after_parameter = "after'"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

// TODO optimize this
func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(
	packageModel models.PackageModel,
) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGitHubRepoDataAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return nil, errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return nil, nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	responseBodyMap, err := parseGitHubRepoDataResponseBody(resp)
	if err != nil {
		return nil, err
	}

	return responseBodyMap, nil
}

func buildGitHubRepoDataAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	url := fmt.Sprintf("%s/repos/%s/%s?access_token=%s", github_base_api_url, author, repo, APIKeyModel.Key)
	return url
}

// TODO Optimize this with ffjson struct!
func parseGitHubRepoDataResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.New("Failed to parse response body")
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		return nil, errors.New("Failed to unmarshal response body")
	}

	return bodyMap, nil
}

func (gitHubRequestService *GitHubRequestService) CheckGitHubRepoExists(
	packageModel models.PackageModel,
) error {
	repoName := BuildNewGitHubRepoName(packageModel)
	url := fmt.Sprintf("https://github.com/%s/%s", github_gophr_org_name, repoName)
	resp, err := http.Get(url)

	if err != nil {
		log.Println("Error occured during request")
		return err
	}

	if resp.StatusCode == 404 {
		return errors.New("Error, a repo with that name already exists.")
	}

	return nil
}

func (gitHubRequestService *GitHubRequestService) CreateNewGitHubRepo(
	packageModel models.PackageModel,
) error {
	err := gitHubRequestService.CheckGitHubRepoExists(packageModel)
	if err != nil {
		log.Println(err)
		return err
	}

	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	JSONBody := buildNewGitHubRepoJSONBody(packageModel)
	gitHubURL := buildNewGitHubRepoAPIURL(packageModel, APIKeyModel)

	req, err := http.Post(gitHubURL, "application/json", JSONBody)
	defer req.Body.Close()

	if err != nil {
		log.Printf("Error occured whilecreating new github repo %s", err)
		return err
	}
	if req.StatusCode != 201 {
		log.Printf("Error creating repo was not successful")
		return errors.New("Error creating repo was not successful")
	}

	return nil
}

func buildNewGitHubRepoAPIURL(
	packageModel models.PackageModel,
	APIKeyModel *GitHubAPIKeyModel,
) string {
	url := fmt.Sprintf("%s/orgs/%s/repos?access_token=%s",
		github_base_api_url,
		github_gophr_org_name,
		APIKeyModel.Key,
	)
	return url
}

func buildNewGitHubRepoJSONBody(
	packageModel models.PackageModel,
) *bytes.Buffer {
	author := *packageModel.Author
	repo := *packageModel.Repo
	newGitHubRepoName := BuildNewGitHubRepoName(packageModel)
	description := fmt.Sprintf("Auto generated and versioned go package for %s/%s", author, repo)
	homepage := fmt.Sprintf("https://github.com/%s/%s", author, repo)

	JSONStruct := NewGitHubRepo{Name: newGitHubRepoName, Description: description, Homepage: homepage}
	JSONByteBuffer := new(bytes.Buffer)
	json.NewEncoder(JSONByteBuffer).Encode(JSONStruct)
	return JSONByteBuffer
}

func BuildNewGitHubRepoName(packageModel models.PackageModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	newGitHubRepoName := fmt.Sprintf("%s-%s", author, repo)
	return newGitHubRepoName
}

func (gitHubRequestService *GitHubRequestService) FetchCommitSHA(
	packageModel models.PackageModel,
	timestamp time.Time,
) (string, error) {
	commitSHA, err := gitHubRequestService.fetchCommitSHAByTimeSelector(packageModel, timestamp, commits_until_parameter)
	if err == nil {
		return commitSHA, nil
	}

	log.Printf("%s \n", err)
	commitSHA, err = gitHubRequestService.fetchCommitSHAByTimeSelector(packageModel, timestamp, commits_after_parameter)
	if err == nil {
		return commitSHA, nil
	}

	log.Printf("%s \n", err)
	refs, err := FetchRefs(*packageModel.Author, *packageModel.Repo)
	if err != nil {
		return refs.MasterRefHash, nil
	}

	return "", err
}

func (gitHubRequestService *GitHubRequestService) fetchCommitSHAByTimeSelector(
	packageModel models.PackageModel,
	timestamp time.Time,
	timeSelector string,
) (string, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	githubURL := buildGitHubRepoCommitsFromTimestampAPIURL(packageModel, *APIKeyModel, timestamp, timeSelector)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return "", errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return "", nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	commitSHA, err := parseGitHubCommitLookUpResponseBody(resp)
	if err != nil {
		return "", err
	}

	return commitSHA, nil
}

func buildGitHubRepoCommitsFromTimestampAPIURL(
	packageModel models.PackageModel,
	APIKeyModel GitHubAPIKeyModel,
	timestamp time.Time,
	timeSelector string,
) string {
	author := *packageModel.Author
	repo := *packageModel.Repo

	url := fmt.Sprintf("%s/repos/%s/%s/commits?%s=%s&access_token=%s",
		github_base_api_url,
		author,
		repo,
		timeSelector,
		strings.Replace(timestamp.String(), " ", "", -1),
		APIKeyModel.Key,
	)
	return url
}

func parseGitHubCommitLookUpResponseBody(response *http.Response) (string, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", errors.New("Failed to parse response body")
	}

	var commitSHAArray []dtos.GitCommitDTO
	err = json.Unmarshal(body, &commitSHAArray)
	if err != nil {
		return "", errors.New("Failed to unmarshal response body")
	}

	if len(commitSHAArray) >= 1 {
		return commitSHAArray[0].SHA, nil
	}

	return "", errors.New("No commit SHAs available for timestamp given")
}

// ==== Misc ====

type NewGitHubRepo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Homepage    string `json:"homepage"`
}

// TODO Optimize this
type GitHubPackageModelDTO struct {
	Package      models.PackageModel
	ResponseBody map[string]interface{}
}

// TODO Won't need this after implementing FFJSON
func ParseStarCount(responseBody map[string]interface{}) int {
	starCount := responseBody["stargazers_count"]
	if starCount == nil {
		return 0
	}

	return int(starCount.(float64))
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"image/color"
	"sort"

	"sync"

	"engo.io/ecs"
	"engo.io/engo"
	"engo.io/gl"
)

const (
	// RenderSystemPriority is the priority of the RenderSystem
	RenderSystemPriority = -1000
)

type renderChangeMessage struct{}

func (renderChangeMessage) Type() string {
	return "renderChangeMessage"
}

// Drawable is that which can be rendered to OpenGL.
type Drawable interface {
	Texture() *gl.Texture
	Width() float32
	Height() float32
	View() (float32, float32, float32, float32)
	Close()
}

// TextureRepeating is the method used to repeat a texture in OpenGL.
type TextureRepeating uint8

const (
	// NoRepeat does not repeat the texture.
	NoRepeat TextureRepeating = iota
	// ClampToEdge stretches the texture to the edge of the viewport.
	ClampToEdge
	// ClampToBorder stretches the texture to the border of the viewpport.
	ClampToBorder
	// Repeat repeats the texture until the border of the viewport.
	Repeat
	// MirroredRepeat repeats a mirror image of the texture until the border of the viewport.
	MirroredRepeat
)

// ZoomFilter is a filter used when zooming in or out of a texture.
type ZoomFilter uint8

const (
	// FilterNearest is a simple nearest neighbor algorithm
	FilterNearest ZoomFilter = iota
	// FilterLinear is a bilinear interpolation algorithm
	FilterLinear
)

// RenderComponent is the component needed to render an entity.
type RenderComponent struct {
	// Hidden is used to prevent drawing by OpenGL
	Hidden bool
	// Scale is the scale at which to render, in the X and Y axis. Not defining Scale, will default to engo.Point{1, 1}
	Scale engo.Point
	// Color defines how much of the color-components of the texture get used
	Color color.Color
	// Drawable refers to the Texture that should be drawn
	Drawable Drawable
	// Repeat defines how to repeat the Texture if the SpaceComponent of the entity
	// is larger than the texture itself, after applying scale. Defaults to NoRepeat
	// which allows the texture to draw entirely without regard to th SpaceComponent
	// Do not set to anything other than NoRepeat for textures in a sprite sheet.
	// This does not yet work with sprite sheets.
	Repeat TextureRepeating
	// Buffer represents the buffer object itself
	// Avoid using it unless your are writing a custom shader
	Buffer *gl.Buffer
	// BufferContent contains the buffer data
	// Avoid using it unless your are writing a custom shader
	BufferContent []float32

	magFilter, minFilter ZoomFilter

	shader Shader
	zIndex float32
}

// SetShader sets the shader used by the RenderComponent.
func (r *RenderComponent) SetShader(s Shader) {
	r.shader = s
	engo.Mailbox.Dispatch(&renderChangeMessage{})
}

// SetZIndex sets the order that the RenderComponent is drawn to the screen. Higher z-indices are drawn on top of
// lower ones if they overlap.
func (r *RenderComponent) SetZIndex(index float32) {
	r.zIndex = index
	engo.Mailbox.Dispatch(&renderChangeMessage{})
}

// SetMinFilter sets the ZoomFilter used for minimizing the RenderComponent
func (r *RenderComponent) SetMinFilter(z ZoomFilter) {
	r.minFilter = z
	engo.Mailbox.Dispatch(renderChangeMessage{})
}

// SetMagFilter sets the ZoomFilter used for magnifying the RenderComponent
func (r *RenderComponent) SetMagFilter(z ZoomFilter) {
	r.magFilter = z
	engo.Mailbox.Dispatch(renderChangeMessage{})
}

type renderEntity struct {
	*ecs.BasicEntity
	*RenderComponent
	*SpaceComponent
}

type renderEntityList []renderEntity

func (r renderEntityList) Len() int {
	return len(r)
}

func (r renderEntityList) Less(i, j int) bool {
	// Sort by shader-pointer if they have the same zIndex
	if r[i].RenderComponent.zIndex == r[j].RenderComponent.zIndex {
		// // TODO: optimize this for performance
		p1 := fmt.Sprintf("%p", r[i].RenderComponent.shader)
		p2 := fmt.Sprintf("%p", r[j].RenderComponent.shader)
		// Sort by texture if shader is the same
		// fmt.Println(p1, p2)
		if p1 == p2 {
			t1 := fmt.Sprintf("%p", r[i].RenderComponent.Drawable.Texture())
			t2 := fmt.Sprintf("%p", r[j].RenderComponent.Drawable.Texture())
			// Sort by magFilter if they're the same texture
			if t1 == t2 {
				mag1 := r[i].RenderComponent.magFilter
				mag2 := r[j].RenderComponent.magFilter
				// Sort by minFilter if they're the same magFilter
				if mag1 == mag2 {
					return r[i].RenderComponent.minFilter < r[j].RenderComponent.minFilter
				}
				return mag1 < mag2
			}
			return t1 < t2
		}
		return p1 < p2
	}

	return r[i].RenderComponent.zIndex < r[j].RenderComponent.zIndex
}

func (r renderEntityList) Swap(i, j int) {
	r[i], r[j] = r[j], r[i]
}

// RenderSystem is the system that draws entities on the OpenGL surface. It requires
// a CameraSystem to work. If a CameraSystem is not in the World when you add RenderSystem
// one is automatically added to the world.
type RenderSystem struct {
	entities renderEntityList
	world    *ecs.World

	sortingNeeded, newCamera bool
	currentShader            Shader
}

// Priority implements the ecs.Prioritizer interface.
func (*RenderSystem) Priority() int { return RenderSystemPriority }

// New initializes the RenderSystem
func (rs *RenderSystem) New(w *ecs.World) {
	rs.world = w

	engo.Mailbox.Listen("NewCameraMessage", func(engo.Message) {
		rs.newCamera = true
	})

	addCameraSystemOnce(w)

	if !engo.Headless() {
		if err := initShaders(w); err != nil {
			panic(err)
		}
		engo.Gl.Enable(engo.Gl.MULTISAMPLE)
	}

	engo.Mailbox.Listen("renderChangeMessage", func(engo.Message) {
		rs.sortingNeeded = true
	})
}

var cameraInitMutex sync.Mutex

func addCameraSystemOnce(w *ecs.World) {
	cameraInitMutex.Lock()
	defer cameraInitMutex.Unlock()

	camSystemAlreadyAdded := false
	for _, system := range w.Systems() {
		switch system.(type) {
		case *CameraSystem:
			camSystemAlreadyAdded = true
		}
	}
	if !camSystemAlreadyAdded {
		w.AddSystem(&CameraSystem{})
	}
}

// Add adds an entity to the RenderSystem. The entity needs a basic, render, and space component to be added to the system.
func (rs *RenderSystem) Add(basic *ecs.BasicEntity, render *RenderComponent, space *SpaceComponent) {
	// Do nothing if entity already exists
	if rs.EntityExists(basic) >= 0 {
		return
	}

	// Setting default shader
	if render.shader == nil {
		switch render.Drawable.(type) {
		case Triangle:
			render.shader = LegacyShader
		case Circle:
			render.shader = LegacyShader
		case Rectangle:
			render.shader = LegacyShader
		case ComplexTriangles:
			render.shader = LegacyShader
		case Text:
			render.shader = TextShader
		default:
			render.shader = DefaultShader
		}
	}

	// This is to prevent users from using the wrong one
	if render.shader == HUDShader {
		switch render.Drawable.(type) {
		case Triangle:
			render.shader = LegacyHUDShader
		case Circle:
			render.shader = LegacyHUDShader
		case Rectangle:
			render.shader = LegacyHUDShader
		case ComplexTriangles:
			render.shader = LegacyHUDShader
		case Text:
			render.shader = TextHUDShader
		default:
			render.shader = HUDShader
		}
	}

	rs.entities = append(rs.entities, renderEntity{basic, render, space})
	rs.sortingNeeded = true
}

// EntityExists looks if the entity is already into the System's entities. It will return the index >= 0 of the object into de rs.entities or -1 if it could not be found.
func (rs *RenderSystem) EntityExists(basic *ecs.BasicEntity) int {
	for index, entity := range rs.entities {
		if entity.ID() == basic.ID() {
			return index
		}
	}

	return -1
}

// AddByInterface adds any Renderable to the render system. Any Entity containing a BasicEntity,RenderComponent, and SpaceComponent anonymously does this automatically
func (rs *RenderSystem) AddByInterface(i ecs.Identifier) {
	o, _ := i.(Renderable)
	rs.Add(o.GetBasicEntity(), o.GetRenderComponent(), o.GetSpaceComponent())
}

// Remove removes an entity from the RenderSystem
func (rs *RenderSystem) Remove(basic ecs.BasicEntity) {
	var delete = rs.EntityExists(&basic)
	if delete >= 0 {
		rs.entities = append(rs.entities[:delete], rs.entities[delete+1:]...)
		rs.sortingNeeded = true
	}
}

// Update draws the entities in the RenderSystem to the OpenGL Surface.
func (rs *RenderSystem) Update(dt float32) {
	if engo.Headless() {
		return
	}

	if rs.sortingNeeded {
		sort.Sort(rs.entities)
		rs.sortingNeeded = false
	}

	if rs.newCamera {
		newCamera(rs.world)
		rs.newCamera = false
	}

	engo.Gl.Clear(engo.Gl.COLOR_BUFFER_BIT)

	// TODO: it's linear for now, but that might very well be a bad idea
	for _, e := range rs.entities {
		if e.RenderComponent.Hidden {
			continue // with other entities
		}

		// Retrieve a shader, may be the default one -- then use it if we aren't already using it
		shader := e.RenderComponent.shader

		// Change Shader if we have to
		if shader != rs.currentShader {
			if rs.currentShader != nil {
				rs.currentShader.Post()
			}
			shader.Pre()
			rs.currentShader = shader
		}

		// Setting default scale to 1
		if e.RenderComponent.Scale.X == 0 && e.RenderComponent.Scale.Y == 0 {
			e.RenderComponent.Scale = engo.Point{X: 1, Y: 1}
		}

		// Setting default to white
		if e.RenderComponent.Color == nil {
			e.RenderComponent.Color = color.White
		}

		rs.currentShader.Draw(e.RenderComponent, e.SpaceComponent)
	}

	if rs.currentShader != nil {
		rs.currentShader.Post()
		rs.currentShader = nil
	}
}

// SetBackground sets the OpenGL ClearColor to the provided color.
func SetBackground(c color.Color) {
	if !engo.Headless() {
		r, g, b, a := c.RGBA()

		engo.Gl.ClearColor(float32(r)/0xffff, float32(g)/0xffff, float32(b)/0xffff, float32(a)/0xffff)
	}
}
<commit_msg>change render check to map of IDs<commit_after>package common

import (
	"fmt"
	"image/color"
	"sort"

	"sync"

	"engo.io/ecs"
	"engo.io/engo"
	"engo.io/gl"
)

const (
	// RenderSystemPriority is the priority of the RenderSystem
	RenderSystemPriority = -1000
)

type renderChangeMessage struct{}

func (renderChangeMessage) Type() string {
	return "renderChangeMessage"
}

// Drawable is that which can be rendered to OpenGL.
type Drawable interface {
	Texture() *gl.Texture
	Width() float32
	Height() float32
	View() (float32, float32, float32, float32)
	Close()
}

// TextureRepeating is the method used to repeat a texture in OpenGL.
type TextureRepeating uint8

const (
	// NoRepeat does not repeat the texture.
	NoRepeat TextureRepeating = iota
	// ClampToEdge stretches the texture to the edge of the viewport.
	ClampToEdge
	// ClampToBorder stretches the texture to the border of the viewpport.
	ClampToBorder
	// Repeat repeats the texture until the border of the viewport.
	Repeat
	// MirroredRepeat repeats a mirror image of the texture until the border of the viewport.
	MirroredRepeat
)

// ZoomFilter is a filter used when zooming in or out of a texture.
type ZoomFilter uint8

const (
	// FilterNearest is a simple nearest neighbor algorithm
	FilterNearest ZoomFilter = iota
	// FilterLinear is a bilinear interpolation algorithm
	FilterLinear
)

// RenderComponent is the component needed to render an entity.
type RenderComponent struct {
	// Hidden is used to prevent drawing by OpenGL
	Hidden bool
	// Scale is the scale at which to render, in the X and Y axis. Not defining Scale, will default to engo.Point{1, 1}
	Scale engo.Point
	// Color defines how much of the color-components of the texture get used
	Color color.Color
	// Drawable refers to the Texture that should be drawn
	Drawable Drawable
	// Repeat defines how to repeat the Texture if the SpaceComponent of the entity
	// is larger than the texture itself, after applying scale. Defaults to NoRepeat
	// which allows the texture to draw entirely without regard to th SpaceComponent
	// Do not set to anything other than NoRepeat for textures in a sprite sheet.
	// This does not yet work with sprite sheets.
	Repeat TextureRepeating
	// Buffer represents the buffer object itself
	// Avoid using it unless your are writing a custom shader
	Buffer *gl.Buffer
	// BufferContent contains the buffer data
	// Avoid using it unless your are writing a custom shader
	BufferContent []float32

	magFilter, minFilter ZoomFilter

	shader Shader
	zIndex float32
}

// SetShader sets the shader used by the RenderComponent.
func (r *RenderComponent) SetShader(s Shader) {
	r.shader = s
	engo.Mailbox.Dispatch(&renderChangeMessage{})
}

// SetZIndex sets the order that the RenderComponent is drawn to the screen. Higher z-indices are drawn on top of
// lower ones if they overlap.
func (r *RenderComponent) SetZIndex(index float32) {
	r.zIndex = index
	engo.Mailbox.Dispatch(&renderChangeMessage{})
}

// SetMinFilter sets the ZoomFilter used for minimizing the RenderComponent
func (r *RenderComponent) SetMinFilter(z ZoomFilter) {
	r.minFilter = z
	engo.Mailbox.Dispatch(renderChangeMessage{})
}

// SetMagFilter sets the ZoomFilter used for magnifying the RenderComponent
func (r *RenderComponent) SetMagFilter(z ZoomFilter) {
	r.magFilter = z
	engo.Mailbox.Dispatch(renderChangeMessage{})
}

type renderEntity struct {
	*ecs.BasicEntity
	*RenderComponent
	*SpaceComponent
}

type renderEntityList []renderEntity

func (r renderEntityList) Len() int {
	return len(r)
}

func (r renderEntityList) Less(i, j int) bool {
	// Sort by shader-pointer if they have the same zIndex
	if r[i].RenderComponent.zIndex == r[j].RenderComponent.zIndex {
		// // TODO: optimize this for performance
		p1 := fmt.Sprintf("%p", r[i].RenderComponent.shader)
		p2 := fmt.Sprintf("%p", r[j].RenderComponent.shader)
		// Sort by texture if shader is the same
		// fmt.Println(p1, p2)
		if p1 == p2 {
			t1 := fmt.Sprintf("%p", r[i].RenderComponent.Drawable.Texture())
			t2 := fmt.Sprintf("%p", r[j].RenderComponent.Drawable.Texture())
			// Sort by magFilter if they're the same texture
			if t1 == t2 {
				mag1 := r[i].RenderComponent.magFilter
				mag2 := r[j].RenderComponent.magFilter
				// Sort by minFilter if they're the same magFilter
				if mag1 == mag2 {
					return r[i].RenderComponent.minFilter < r[j].RenderComponent.minFilter
				}
				return mag1 < mag2
			}
			return t1 < t2
		}
		return p1 < p2
	}

	return r[i].RenderComponent.zIndex < r[j].RenderComponent.zIndex
}

func (r renderEntityList) Swap(i, j int) {
	r[i], r[j] = r[j], r[i]
}

// RenderSystem is the system that draws entities on the OpenGL surface. It requires
// a CameraSystem to work. If a CameraSystem is not in the World when you add RenderSystem
// one is automatically added to the world.
type RenderSystem struct {
	entities renderEntityList
	ids      map[uint64]struct{}
	world    *ecs.World

	sortingNeeded, newCamera bool
	currentShader            Shader
}

// Priority implements the ecs.Prioritizer interface.
func (*RenderSystem) Priority() int { return RenderSystemPriority }

// New initializes the RenderSystem
func (rs *RenderSystem) New(w *ecs.World) {
	rs.world = w
	rs.ids = make(map[uint64]struct{})

	engo.Mailbox.Listen("NewCameraMessage", func(engo.Message) {
		rs.newCamera = true
	})

	addCameraSystemOnce(w)

	if !engo.Headless() {
		if err := initShaders(w); err != nil {
			panic(err)
		}
		engo.Gl.Enable(engo.Gl.MULTISAMPLE)
	}

	engo.Mailbox.Listen("renderChangeMessage", func(engo.Message) {
		rs.sortingNeeded = true
	})
}

var cameraInitMutex sync.Mutex

func addCameraSystemOnce(w *ecs.World) {
	cameraInitMutex.Lock()
	defer cameraInitMutex.Unlock()

	camSystemAlreadyAdded := false
	for _, system := range w.Systems() {
		switch system.(type) {
		case *CameraSystem:
			camSystemAlreadyAdded = true
		}
	}
	if !camSystemAlreadyAdded {
		w.AddSystem(&CameraSystem{})
	}
}

// Add adds an entity to the RenderSystem. The entity needs a basic, render, and space component to be added to the system.
func (rs *RenderSystem) Add(basic *ecs.BasicEntity, render *RenderComponent, space *SpaceComponent) {
	// Do nothing if entity already exists
	if _, ok := rs.ids[basic.ID()]; ok {
		return
	}

	rs.ids[basic.ID()] = struct{}{}

	// Setting default shader
	if render.shader == nil {
		switch render.Drawable.(type) {
		case Triangle:
			render.shader = LegacyShader
		case Circle:
			render.shader = LegacyShader
		case Rectangle:
			render.shader = LegacyShader
		case ComplexTriangles:
			render.shader = LegacyShader
		case Text:
			render.shader = TextShader
		default:
			render.shader = DefaultShader
		}
	}

	// This is to prevent users from using the wrong one
	if render.shader == HUDShader {
		switch render.Drawable.(type) {
		case Triangle:
			render.shader = LegacyHUDShader
		case Circle:
			render.shader = LegacyHUDShader
		case Rectangle:
			render.shader = LegacyHUDShader
		case ComplexTriangles:
			render.shader = LegacyHUDShader
		case Text:
			render.shader = TextHUDShader
		default:
			render.shader = HUDShader
		}
	}

	rs.entities = append(rs.entities, renderEntity{basic, render, space})
	rs.sortingNeeded = true
}

// EntityExists looks if the entity is already into the System's entities. It will return the index >= 0 of the object into de rs.entities or -1 if it could not be found.
func (rs *RenderSystem) EntityExists(basic *ecs.BasicEntity) int {
	for index, entity := range rs.entities {
		if entity.ID() == basic.ID() {
			return index
		}
	}

	return -1
}

// AddByInterface adds any Renderable to the render system. Any Entity containing a BasicEntity,RenderComponent, and SpaceComponent anonymously does this automatically
func (rs *RenderSystem) AddByInterface(i ecs.Identifier) {
	o, _ := i.(Renderable)
	rs.Add(o.GetBasicEntity(), o.GetRenderComponent(), o.GetSpaceComponent())
}

// Remove removes an entity from the RenderSystem
func (rs *RenderSystem) Remove(basic ecs.BasicEntity) {
	var d = rs.EntityExists(&basic)
	if d >= 0 {
		rs.entities = append(rs.entities[:d], rs.entities[d+1:]...)
		rs.sortingNeeded = true
	}
	delete(rs.ids, basic.ID())
}

// Update draws the entities in the RenderSystem to the OpenGL Surface.
func (rs *RenderSystem) Update(dt float32) {
	if engo.Headless() {
		return
	}

	if rs.sortingNeeded {
		sort.Sort(rs.entities)
		rs.sortingNeeded = false
	}

	if rs.newCamera {
		newCamera(rs.world)
		rs.newCamera = false
	}

	engo.Gl.Clear(engo.Gl.COLOR_BUFFER_BIT)

	// TODO: it's linear for now, but that might very well be a bad idea
	for _, e := range rs.entities {
		if e.RenderComponent.Hidden {
			continue // with other entities
		}

		// Retrieve a shader, may be the default one -- then use it if we aren't already using it
		shader := e.RenderComponent.shader

		// Change Shader if we have to
		if shader != rs.currentShader {
			if rs.currentShader != nil {
				rs.currentShader.Post()
			}
			shader.Pre()
			rs.currentShader = shader
		}

		// Setting default scale to 1
		if e.RenderComponent.Scale.X == 0 && e.RenderComponent.Scale.Y == 0 {
			e.RenderComponent.Scale = engo.Point{X: 1, Y: 1}
		}

		// Setting default to white
		if e.RenderComponent.Color == nil {
			e.RenderComponent.Color = color.White
		}

		rs.currentShader.Draw(e.RenderComponent, e.SpaceComponent)
	}

	if rs.currentShader != nil {
		rs.currentShader.Post()
		rs.currentShader = nil
	}
}

// SetBackground sets the OpenGL ClearColor to the provided color.
func SetBackground(c color.Color) {
	if !engo.Headless() {
		r, g, b, a := c.RGBA()

		engo.Gl.ClearColor(float32(r)/0xffff, float32(g)/0xffff, float32(b)/0xffff, float32(a)/0xffff)
	}
}
<|endoftext|>


<commit_before>/*
Package riseset calculates the rise and set times for the Sun, Moon and twilight.

Copyright 2015 James McHugh

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.

GO Program by James McHugh, converted from QBASIC version developed by
Keith Burnett keith@xylem.demon.co.uk
http://www.stargazing.net/kepler/moonrise.html

Original QBASIC program adapted and modified from Montenbruck and Pfleger,
'Astronomy on the personal Computer' 3rd Edition, Springer section 3.8

Accuracy of detection of 'always below' and 'always above' situations depends
on the approximate routines used for Sun and Moon. For instance, 1999 Dec 25th,
at 0 long, 67.43 lat this program will give an 8 minute long day between sunrise
and sunset. More accurate programs say the Sun is always below the horizon on
this day.

*/
package github.com/exploded/riseset

import (
	"testing"
	"time"
)

func TestRiseset(t *testing.T) {

	var rstests = []struct {
		year  int
		month int
		day   int
		zone  float64
		lon   float64
		lat   float64
		mrise string
		mset  string
		srise string
		sset  string
		nrise string
		nset  string
	}{
		{2000, 01, 03, 0, -1.91667, 52.50, "05:01", "14:09", "08:18", "16:06", "06:53", "17:31"},
		{1999, 12, 25, 0, 00.00000, 67.43, "17:47", "12:06", "11:56", "12:04", "07:47", "16:13"},
		{2000, 01, 03, 1, 17.42000, 68.43, "06:29", "11:57", "-", "-", "07:43", "16:07"},
	}

	// Only using the date part so GMT is okay
	mytime, _ := time.LoadLocation("GMT")

	for _, tt := range rstests {

		//Moon
		got := Riseset(1, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.mrise || got.Set != tt.mset {
			t.Errorf("Riseset(1,%v) == %v, want rise=%v set=%v", tt, got, tt.mrise, tt.mset)
		}

		//Sun
		got = Riseset(2, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.srise || got.Set != tt.sset {
			t.Errorf("Riseset(2,%v) == %v, want rise=%v set=%v", tt, got, tt.srise, tt.sset)
		}

		//Twilight
		got = Riseset(3, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.nrise || got.Set != tt.nset {
			t.Errorf("Riseset(3,%v) == %v, want rise=%v set=%v", tt, got, tt.nrise, tt.nset)
		}

	}
}
<commit_msg>Fix package<commit_after>/*
Package riseset calculates the rise and set times for the Sun, Moon and twilight.

Copyright 2015 James McHugh

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.

GO Program by James McHugh, converted from QBASIC version developed by
Keith Burnett keith@xylem.demon.co.uk
http://www.stargazing.net/kepler/moonrise.html

Original QBASIC program adapted and modified from Montenbruck and Pfleger,
'Astronomy on the personal Computer' 3rd Edition, Springer section 3.8

Accuracy of detection of 'always below' and 'always above' situations depends
on the approximate routines used for Sun and Moon. For instance, 1999 Dec 25th,
at 0 long, 67.43 lat this program will give an 8 minute long day between sunrise
and sunset. More accurate programs say the Sun is always below the horizon on
this day.

*/
package riseset

import (
	"testing"
	"time"
)

func TestRiseset(t *testing.T) {

	var rstests = []struct {
		year  int
		month int
		day   int
		zone  float64
		lon   float64
		lat   float64
		mrise string
		mset  string
		srise string
		sset  string
		nrise string
		nset  string
	}{
		{2000, 01, 03, 0, -1.91667, 52.50, "05:01", "14:09", "08:18", "16:06", "06:53", "17:31"},
		{1999, 12, 25, 0, 00.00000, 67.43, "17:47", "12:06", "11:56", "12:04", "07:47", "16:13"},
		{2000, 01, 03, 1, 17.42000, 68.43, "06:29", "11:57", "-", "-", "07:43", "16:07"},
	}

	// Only using the date part so GMT is okay
	mytime, _ := time.LoadLocation("GMT")

	for _, tt := range rstests {

		//Moon
		got := Riseset(1, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.mrise || got.Set != tt.mset {
			t.Errorf("Riseset(1,%v) == %v, want rise=%v set=%v", tt, got, tt.mrise, tt.mset)
		}

		//Sun
		got = Riseset(2, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.srise || got.Set != tt.sset {
			t.Errorf("Riseset(2,%v) == %v, want rise=%v set=%v", tt, got, tt.srise, tt.sset)
		}

		//Twilight
		got = Riseset(3, time.Date(tt.year, time.Month(tt.month), tt.day, 0, 0, 0, 0, mytime), tt.lon,tt.lat,tt.zone)
		if got.Rise != tt.nrise || got.Set != tt.nset {
			t.Errorf("Riseset(3,%v) == %v, want rise=%v set=%v", tt, got, tt.nrise, tt.nset)
		}

	}
}
<|endoftext|>


<commit_before>// Title：全局容器组件
//
// Description: 是一个view的根元素，是必需的，所有的元素都要建立在该容器之下
//
// Author:black
//
// Createtime:2013-08-08 09:27
//
// Version:1.0
//
// 修改历史:版本号 修改日期 修改人 修改说明
//
// 1.0 2013-08-08 09:27 black 创建文档
package lessgo

import (
	"bytes"
	"encoding/xml"
	"net/http"
	"text/template"
)

//当viewport下面可以放置其他元素的时候，就扩展Viewport结构体
type viewport struct {
	XMLName          xml.Name          `xml:"viewport"`
	GridPanels       []gridPanel       `xml:"gridpanel"`
	FormPanels       []formPanel       `xml:"formpanel"`
	MutiFormPanels   []mutiFormPanel   `xml:"mutiformpanel"`
	CustomGridPanels []customGridPanel `xml:"customgridpanel"`
	CustomFormPanels []customFormPanel `xml:"customformpanel"`
	Crumbs           crumbs            `xml:"crumbs"`
}

//面包屑
type crumbs struct {
	Crumbs []crumb `xml:"crumb"`
}

type crumb struct {
	Url         string `xml:"url,attr"`
	Text        string `xml:"text,attr"`
	CurrentPage string `xml:"currentPage,attr"`
}

//扩展viewport的同时，记得同时扩展container
func (viewport viewport) generateViewport(terminal, packageName string, r *http.Request, employee Employee) []byte {

	content := ""

	for _, gridpanel := range viewport.GridPanels {
		content += string(gridpanel.generate(getEntity(gridpanel.Entity), terminal, packageName))
	}

	for _, formpanel := range viewport.FormPanels {
		content += string(formpanel.generate(getEntity(formpanel.Entity), terminal, packageName, r))
	}

	for _, mutiformpanel := range viewport.MutiFormPanels {
		content += string(mutiformpanel.generate(terminal, packageName, r))
	}

	for _, customgridpanel := range viewport.CustomGridPanels {
		content += string(customgridpanel.generate(terminal, packageName))
	}

	for _, customformpanel := range viewport.CustomFormPanels {
		content += string(customformpanel.generate(terminal, packageName))
	}

	var t *template.Template

	var buf bytes.Buffer

	t = template.New("viewport.html")

	t = t.Funcs(template.FuncMap{
		"compareString": CompareString,
	})

	t, err := t.ParseFiles("../lessgo/template/component/" + terminal + "/viewport.html")

	if err != nil {
		Log.Error(err.Error())
		return []byte{}
	}

	data := make(map[string]interface{})
	data["Content"] = content
	data["Crumbs"] = viewport.Crumbs
	data["Employee"] = employee

	err = t.Execute(&buf, data)

	if err != nil {
		Log.Error(err.Error())
		return []byte{}
	}

	return buf.Bytes()
}
<commit_msg>调整一下组件的渲染顺序，这个属于没有做的，应该是要由用户自己去指定顺序<commit_after>// Title：全局容器组件
//
// Description: 是一个view的根元素，是必需的，所有的元素都要建立在该容器之下
//
// Author:black
//
// Createtime:2013-08-08 09:27
//
// Version:1.0
//
// 修改历史:版本号 修改日期 修改人 修改说明
//
// 1.0 2013-08-08 09:27 black 创建文档
package lessgo

import (
	"bytes"
	"encoding/xml"
	"net/http"
	"text/template"
)

//当viewport下面可以放置其他元素的时候，就扩展Viewport结构体
type viewport struct {
	XMLName          xml.Name          `xml:"viewport"`
	GridPanels       []gridPanel       `xml:"gridpanel"`
	FormPanels       []formPanel       `xml:"formpanel"`
	MutiFormPanels   []mutiFormPanel   `xml:"mutiformpanel"`
	CustomGridPanels []customGridPanel `xml:"customgridpanel"`
	CustomFormPanels []customFormPanel `xml:"customformpanel"`
	Crumbs           crumbs            `xml:"crumbs"`
}

//面包屑
type crumbs struct {
	Crumbs []crumb `xml:"crumb"`
}

type crumb struct {
	Url         string `xml:"url,attr"`
	Text        string `xml:"text,attr"`
	CurrentPage string `xml:"currentPage,attr"`
}

//扩展viewport的同时，记得同时扩展container
func (viewport viewport) generateViewport(terminal, packageName string, r *http.Request, employee Employee) []byte {

	content := ""

	for _, formpanel := range viewport.FormPanels {
		content += string(formpanel.generate(getEntity(formpanel.Entity), terminal, packageName, r))
	}

	for _, mutiformpanel := range viewport.MutiFormPanels {
		content += string(mutiformpanel.generate(terminal, packageName, r))
	}

	for _, gridpanel := range viewport.GridPanels {
		content += string(gridpanel.generate(getEntity(gridpanel.Entity), terminal, packageName))
	}

	for _, customgridpanel := range viewport.CustomGridPanels {
		content += string(customgridpanel.generate(terminal, packageName))
	}

	for _, customformpanel := range viewport.CustomFormPanels {
		content += string(customformpanel.generate(terminal, packageName))
	}

	var t *template.Template

	var buf bytes.Buffer

	t = template.New("viewport.html")

	t = t.Funcs(template.FuncMap{
		"compareString": CompareString,
	})

	t, err := t.ParseFiles("../lessgo/template/component/" + terminal + "/viewport.html")

	if err != nil {
		Log.Error(err.Error())
		return []byte{}
	}

	data := make(map[string]interface{})
	data["Content"] = content
	data["Crumbs"] = viewport.Crumbs
	data["Employee"] = employee

	err = t.Execute(&buf, data)

	if err != nil {
		Log.Error(err.Error())
		return []byte{}
	}

	return buf.Bytes()
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func GetSourceRepoRepositoryCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//sourcerepo.googleapis.com/projects/{{project}}/repos/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetSourceRepoRepositoryApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "sourcerepo.googleapis.com/Repository",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/sourcerepo/v1/rest",
				DiscoveryName:        "Repository",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetSourceRepoRepositoryApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandSourceRepoRepositoryName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	pubsubConfigsProp, err := expandSourceRepoRepositoryPubsubConfigs(d.Get("pubsub_configs"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("pubsub_configs"); !isEmptyValue(reflect.ValueOf(pubsubConfigsProp)) && (ok || !reflect.DeepEqual(v, pubsubConfigsProp)) {
		obj["pubsubConfigs"] = pubsubConfigsProp
	}

	return obj, nil
}

func expandSourceRepoRepositoryName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return replaceVars(d, config, "projects/{{project}}/repos/{{name}}")
}

func expandSourceRepoRepositoryPubsubConfigs(v interface{}, d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	if v == nil {
		return map[string]interface{}{}, nil
	}
	m := make(map[string]interface{})
	for _, raw := range v.(*schema.Set).List() {
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedMessageFormat, err := expandSourceRepoRepositoryPubsubConfigsMessageFormat(original["message_format"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedMessageFormat); val.IsValid() && !isEmptyValue(val) {
			transformed["messageFormat"] = transformedMessageFormat
		}

		transformedServiceAccountEmail, err := expandSourceRepoRepositoryPubsubConfigsServiceAccountEmail(original["service_account_email"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedServiceAccountEmail); val.IsValid() && !isEmptyValue(val) {
			transformed["serviceAccountEmail"] = transformedServiceAccountEmail
		}

		transformedTopic, err := expandSourceRepoRepositoryPubsubConfigsTopic(original["topic"], d, config)
		if err != nil {
			return nil, err
		}
		m[transformedTopic] = transformed
	}
	return m, nil
}

func expandSourceRepoRepositoryPubsubConfigsMessageFormat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandSourceRepoRepositoryPubsubConfigsServiceAccountEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}
<commit_msg>Fix bug: diff being detected for source_repo_repository even when there are no changes (#3786) (#487)<commit_after>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"bytes"
	"fmt"
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func resourceSourceRepoRepositoryPubSubConfigsHash(v interface{}) int {
	if v == nil {
		return 0
	}

	var buf bytes.Buffer
	m := v.(map[string]interface{})

	buf.WriteString(fmt.Sprintf("%s-", GetResourceNameFromSelfLink(m["topic"].(string))))
	buf.WriteString(fmt.Sprintf("%s-", m["message_format"].(string)))
	if v, ok := m["service_account_email"]; ok {
		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
	}

	return hashcode.String(buf.String())
}

func GetSourceRepoRepositoryCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//sourcerepo.googleapis.com/projects/{{project}}/repos/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetSourceRepoRepositoryApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "sourcerepo.googleapis.com/Repository",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/sourcerepo/v1/rest",
				DiscoveryName:        "Repository",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetSourceRepoRepositoryApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandSourceRepoRepositoryName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	pubsubConfigsProp, err := expandSourceRepoRepositoryPubsubConfigs(d.Get("pubsub_configs"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("pubsub_configs"); !isEmptyValue(reflect.ValueOf(pubsubConfigsProp)) && (ok || !reflect.DeepEqual(v, pubsubConfigsProp)) {
		obj["pubsubConfigs"] = pubsubConfigsProp
	}

	return obj, nil
}

func expandSourceRepoRepositoryName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return replaceVars(d, config, "projects/{{project}}/repos/{{name}}")
}

func expandSourceRepoRepositoryPubsubConfigs(v interface{}, d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	if v == nil {
		return map[string]interface{}{}, nil
	}
	m := make(map[string]interface{})
	for _, raw := range v.(*schema.Set).List() {
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedMessageFormat, err := expandSourceRepoRepositoryPubsubConfigsMessageFormat(original["message_format"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedMessageFormat); val.IsValid() && !isEmptyValue(val) {
			transformed["messageFormat"] = transformedMessageFormat
		}

		transformedServiceAccountEmail, err := expandSourceRepoRepositoryPubsubConfigsServiceAccountEmail(original["service_account_email"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedServiceAccountEmail); val.IsValid() && !isEmptyValue(val) {
			transformed["serviceAccountEmail"] = transformedServiceAccountEmail
		}

		transformedTopic, err := expandSourceRepoRepositoryPubsubConfigsTopic(original["topic"], d, config)
		if err != nil {
			return nil, err
		}
		m[transformedTopic] = transformed
	}
	return m, nil
}

func expandSourceRepoRepositoryPubsubConfigsMessageFormat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandSourceRepoRepositoryPubsubConfigsServiceAccountEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}
<|endoftext|>


<commit_before>// Package ethwire provides low level access to the Ethereum network and allows
// you to broadcast data over the network.
package ethwire

import (
	"bytes"
	"fmt"
	"net"
	"time"

	"github.com/ethereum/eth-go/ethutil"
)

// Connection interface describing the methods required to implement the wire protocol.
type Conn interface {
	Write(typ MsgType, v ...interface{}) error
	Read() *Msg
}

// The magic token which should be the first 4 bytes of every message and can be used as separator between messages.
var MagicToken = []byte{34, 64, 8, 145}

type MsgType byte

const (
	// Values are given explicitly instead of by iota because these values are
	// defined by the wire protocol spec; it is easier for humans to ensure
	// correctness when values are explicit.
	MsgHandshakeTy = 0x00
	MsgDiscTy      = 0x01
	MsgPingTy      = 0x02
	MsgPongTy      = 0x03
	MsgGetPeersTy  = 0x04
	MsgPeersTy     = 0x05

	MsgStatusTy         = 0x10
	MsgGetTxsTy         = 0x11
	MsgTxTy             = 0x12
	MsgGetBlockHashesTy = 0x13
	MsgBlockHashesTy    = 0x14
	MsgGetBlocksTy      = 0x15
	MsgBlockTy          = 0x16
)

var msgTypeToString = map[MsgType]string{
	MsgHandshakeTy:      "Handshake",
	MsgDiscTy:           "Disconnect",
	MsgPingTy:           "Ping",
	MsgPongTy:           "Pong",
	MsgGetPeersTy:       "Get peers",
	MsgStatusTy:         "Status",
	MsgPeersTy:          "Peers",
	MsgTxTy:             "Transactions",
	MsgBlockTy:          "Blocks",
	MsgGetTxsTy:         "Get Txs",
	MsgGetBlockHashesTy: "Get block hashes",
	MsgBlockHashesTy:    "Block hashes",
	MsgGetBlocksTy:      "Get blocks",
}

func (mt MsgType) String() string {
	return msgTypeToString[mt]
}

type Msg struct {
	Type MsgType // Specifies how the encoded data should be interpreted
	//Data []byte
	Data *ethutil.Value
}

func NewMessage(msgType MsgType, data interface{}) *Msg {
	return &Msg{
		Type: msgType,
		Data: ethutil.NewValue(data),
	}
}

type Messages []*Msg

// The basic message reader waits for data on the given connection, decoding
// and doing a few sanity checks such as if there's a data type and
// unmarhals the given data
func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
	// The recovering function in case anything goes horribly wrong
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ethwire.ReadMessage error: %v", r)
		}
	}()

	var (
		buff      []byte
		messages  [][]byte
		msgLength int
	)

	for {
		// Give buffering some time
		conn.SetReadDeadline(time.Now().Add(5 * time.Millisecond))
		// Create a new temporarily buffer
		b := make([]byte, 1440)
		n, _ := conn.Read(b)
		if err != nil && n == 0 {
			if err.Error() != "EOF" {
				fmt.Println("err now", err)
				return nil, err
			} else {
				break
			}
		}

		if n == 0 && len(buff) == 0 {
			// If there's nothing on the wire wait for a bit
			time.Sleep(200)

			continue
		}

		buff = append(buff, b[:n]...)
		if msgLength == 0 {
			// Check if the received 4 first bytes are the magic token
			if bytes.Compare(MagicToken, buff[:4]) != 0 {
				return nil, fmt.Errorf("MagicToken mismatch. Received %v", buff[:4])
			}

			// Read the length of the message
			msgLength = int(ethutil.BytesToNumber(buff[4:8]))

			// Remove the token and length
			buff = buff[8:]
		}

		if len(buff) >= msgLength {
			messages = append(messages, buff[:msgLength])
			buff = buff[msgLength:]
			msgLength = 0

			if len(buff) == 0 {
				break
			}
		}
	}

	for _, m := range messages {
		decoder := ethutil.NewValueFromBytes(m)
		// Type of message
		t := decoder.Get(0).Uint()
		// Actual data
		d := decoder.SliceFrom(1)

		msgs = append(msgs, &Msg{Type: MsgType(t), Data: d})
	}

	return
}

// The basic message writer takes care of writing data over the given
// connection and does some basic error checking
func WriteMessage(conn net.Conn, msg *Msg) error {
	var pack []byte

	// Encode the type and the (RLP encoded) data for sending over the wire
	encoded := ethutil.NewValue(append([]interface{}{byte(msg.Type)}, msg.Data.Slice()...)).Encode()
	payloadLength := ethutil.NumberToBytes(uint32(len(encoded)), 32)

	// Write magic token and payload length (first 8 bytes)
	pack = append(MagicToken, payloadLength...)
	pack = append(pack, encoded...)
	//fmt.Printf("payload %v (%v) %q\n", msg.Type, conn.RemoteAddr(), encoded)

	// Write to the connection
	_, err := conn.Write(pack)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Increased from 200 nano to milliseconds<commit_after>// Package ethwire provides low level access to the Ethereum network and allows
// you to broadcast data over the network.
package ethwire

import (
	"bytes"
	"fmt"
	"net"
	"time"

	"github.com/ethereum/eth-go/ethutil"
)

// Connection interface describing the methods required to implement the wire protocol.
type Conn interface {
	Write(typ MsgType, v ...interface{}) error
	Read() *Msg
}

// The magic token which should be the first 4 bytes of every message and can be used as separator between messages.
var MagicToken = []byte{34, 64, 8, 145}

type MsgType byte

const (
	// Values are given explicitly instead of by iota because these values are
	// defined by the wire protocol spec; it is easier for humans to ensure
	// correctness when values are explicit.
	MsgHandshakeTy = 0x00
	MsgDiscTy      = 0x01
	MsgPingTy      = 0x02
	MsgPongTy      = 0x03
	MsgGetPeersTy  = 0x04
	MsgPeersTy     = 0x05

	MsgStatusTy         = 0x10
	MsgGetTxsTy         = 0x11
	MsgTxTy             = 0x12
	MsgGetBlockHashesTy = 0x13
	MsgBlockHashesTy    = 0x14
	MsgGetBlocksTy      = 0x15
	MsgBlockTy          = 0x16
)

var msgTypeToString = map[MsgType]string{
	MsgHandshakeTy:      "Handshake",
	MsgDiscTy:           "Disconnect",
	MsgPingTy:           "Ping",
	MsgPongTy:           "Pong",
	MsgGetPeersTy:       "Get peers",
	MsgStatusTy:         "Status",
	MsgPeersTy:          "Peers",
	MsgTxTy:             "Transactions",
	MsgBlockTy:          "Blocks",
	MsgGetTxsTy:         "Get Txs",
	MsgGetBlockHashesTy: "Get block hashes",
	MsgBlockHashesTy:    "Block hashes",
	MsgGetBlocksTy:      "Get blocks",
}

func (mt MsgType) String() string {
	return msgTypeToString[mt]
}

type Msg struct {
	Type MsgType // Specifies how the encoded data should be interpreted
	//Data []byte
	Data *ethutil.Value
}

func NewMessage(msgType MsgType, data interface{}) *Msg {
	return &Msg{
		Type: msgType,
		Data: ethutil.NewValue(data),
	}
}

type Messages []*Msg

// The basic message reader waits for data on the given connection, decoding
// and doing a few sanity checks such as if there's a data type and
// unmarhals the given data
func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
	// The recovering function in case anything goes horribly wrong
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ethwire.ReadMessage error: %v", r)
		}
	}()

	var (
		buff      []byte
		messages  [][]byte
		msgLength int
	)

	for {
		// Give buffering some time
		conn.SetReadDeadline(time.Now().Add(5 * time.Millisecond))
		// Create a new temporarily buffer
		b := make([]byte, 1440)
		n, _ := conn.Read(b)
		if err != nil && n == 0 {
			if err.Error() != "EOF" {
				fmt.Println("err now", err)
				return nil, err
			} else {
				break
			}
		}

		fmt.Println(n, len(buff))
		if n == 0 && len(buff) == 0 {
			// If there's nothing on the wire wait for a bit
			time.Sleep(200 * time.Millisecond)

			continue
		}

		buff = append(buff, b[:n]...)
		if msgLength == 0 {
			// Check if the received 4 first bytes are the magic token
			if bytes.Compare(MagicToken, buff[:4]) != 0 {
				return nil, fmt.Errorf("MagicToken mismatch. Received %v", buff[:4])
			}

			// Read the length of the message
			msgLength = int(ethutil.BytesToNumber(buff[4:8]))

			// Remove the token and length
			buff = buff[8:]
		}

		if len(buff) >= msgLength {
			messages = append(messages, buff[:msgLength])
			buff = buff[msgLength:]
			msgLength = 0

			if len(buff) == 0 {
				break
			}
		}
	}

	for _, m := range messages {
		decoder := ethutil.NewValueFromBytes(m)
		// Type of message
		t := decoder.Get(0).Uint()
		// Actual data
		d := decoder.SliceFrom(1)

		msgs = append(msgs, &Msg{Type: MsgType(t), Data: d})
	}

	return
}

// The basic message writer takes care of writing data over the given
// connection and does some basic error checking
func WriteMessage(conn net.Conn, msg *Msg) error {
	var pack []byte

	// Encode the type and the (RLP encoded) data for sending over the wire
	encoded := ethutil.NewValue(append([]interface{}{byte(msg.Type)}, msg.Data.Slice()...)).Encode()
	payloadLength := ethutil.NumberToBytes(uint32(len(encoded)), 32)

	// Write magic token and payload length (first 8 bytes)
	pack = append(MagicToken, payloadLength...)
	pack = append(pack, encoded...)
	//fmt.Printf("payload %v (%v) %q\n", msg.Type, conn.RemoteAddr(), encoded)

	// Write to the connection
	_, err := conn.Write(pack)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>