Ty and Dan are joined by ESPN's Bill Barnwell for a special bonus show to rehash the online ecosystems that shaped their childhoods, from noisy baud modems and free America Online CDs to the early days of Napster, fantasy sports and Geocities. Instant Messenger. Plus, weird online encounters, Front Page fake punts, and the lasting effects of the Instant Messenger revolution.


text:
package github

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/go-github/v33/github"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/oauth2"

	"k8s.io/release/pkg/git"
	"k8s.io/release/pkg/github/internal"
	"k8s.io/release/pkg/util"
)

const (
	// TokenEnvKey is the default GitHub token environemt variable key
	TokenEnvKey = "GITHUB_TOKEN"
	// GitHubURL Prefix for github URLs
	GitHubURL = "https://github.com/"
)

// GitHub is a wrapper around GitHub related functionality
type GitHub struct {
	client Client
}

type githubClient struct {
	*github.Client
}

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
//counterfeiter:generate . Client
type Client interface {
	GetCommit(
		context.Context, string, string, string,
	) (*github.Commit, *github.Response, error)

	GetPullRequest(
		context.Context, string, string, int,
	) (*github.PullRequest, *github.Response, error)

	GetIssue(
		context.Context, string, string, int,
	) (*github.Issue, *github.Response, error)

	GetRepoCommit(
		context.Context, string, string, string,
	) (*github.RepositoryCommit, *github.Response, error)

	ListCommits(
		context.Context, string, string, *github.CommitsListOptions,
	) ([]*github.RepositoryCommit, *github.Response, error)

	ListPullRequestsWithCommit(
		context.Context, string, string, string, *github.PullRequestListOptions,
	) ([]*github.PullRequest, *github.Response, error)

	ListReleases(
		context.Context, string, string, *github.ListOptions,
	) ([]*github.RepositoryRelease, *github.Response, error)

	GetReleaseByTag(
		context.Context, string, string, string,
	) (*github.RepositoryRelease, *github.Response, error)

	DownloadReleaseAsset(
		context.Context, string, string, int64,
	) (io.ReadCloser, string, error)

	ListTags(
		context.Context, string, string, *github.ListOptions,
	) ([]*github.RepositoryTag, *github.Response, error)

	ListBranches(
		context.Context, string, string, *github.BranchListOptions,
	) ([]*github.Branch, *github.Response, error)

	CreatePullRequest(
		context.Context, string, string, string, string, string, string,
	) (*github.PullRequest, error)

	GetRepository(
		context.Context, string, string,
	) (*github.Repository, *github.Response, error)

	UpdateReleasePage(
		context.Context, string, string, int64, *github.RepositoryRelease,
	) (*github.RepositoryRelease, error)

	UploadReleaseAsset(
		context.Context, string, string, int64, *github.UploadOptions, *os.File,
	) (*github.ReleaseAsset, error)

	DeleteReleaseAsset(
		context.Context, string, string, int64,
	) error

	ListReleaseAssets(
		context.Context, string, string, int64,
	) ([]*github.ReleaseAsset, error)

	CreateComment(
		context.Context, string, string, int, string,
	) (*github.IssueComment, *github.Response, error)
}

// New creates a new default GitHub client. Tokens set via the $GITHUB_TOKEN
// environment variable will result in an authenticated client.
// If the $GITHUB_TOKEN is not set, then the client will do unauthenticated
// GitHub requests.
func New() *GitHub {
	ctx := context.Background()
	token := util.EnvDefault(TokenEnvKey, "")
	client := http.DefaultClient
	state := "unauthenticated"
	if token != "" {
		state = strings.TrimPrefix(state, "un")
		client = oauth2.NewClient(ctx, oauth2.StaticTokenSource(
			&oauth2.Token{AccessToken: token},
		))
	}
	logrus.Debugf("Using %s GitHub client", state)
	return &GitHub{&githubClient{github.NewClient(client)}}
}

// NewWithToken can be used to specify a GITHUB_TOKEN before retrieving the
// client to enforce authenticated GitHub requests
func NewWithToken(token string) (*GitHub, error) {
	if err := os.Setenv(TokenEnvKey, token); err != nil {
		return nil, errors.Wrapf(err, "unable to export %s", TokenEnvKey)
	}
	return New(), nil
}

func NewEnterprise(baseURL, uploadURL string) (*GitHub, error) {
	ctx := context.Background()
	token := util.EnvDefault(TokenEnvKey, "")
	client := http.DefaultClient
	state := "unauthenticated"
	if token != "" {
		state = strings.TrimPrefix(state, "un")
		client = oauth2.NewClient(ctx, oauth2.StaticTokenSource(
			&oauth2.Token{AccessToken: token},
		))
	}
	logrus.Debugf("Using %s Enterprise GitHub client", state)
	ghclient, err := github.NewEnterpriseClient(baseURL, uploadURL, client)
	if err != nil {
		return nil, fmt.Errorf("failed to new github client: %s", err)
	}
	return &GitHub{&githubClient{ghclient}}, nil
}

func NewEnterpriseWithToken(baseURL, uploadURL, token string) (*GitHub, error) {
	if err := os.Setenv(TokenEnvKey, token); err != nil {
		return nil, errors.Wrapf(err, "unable to export %s", TokenEnvKey)
	}
	return NewEnterprise(baseURL, uploadURL)
}

func (g *githubClient) GetCommit(
	ctx context.Context, owner, repo, sha string,
) (*github.Commit, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		commit, resp, err := g.Git.GetCommit(ctx, owner, repo, sha)
		if !shouldRetry(err) {
			return commit, resp, err
		}
	}
}

func (g *githubClient) GetPullRequest(
	ctx context.Context, owner, repo string, number int,
) (*github.PullRequest, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		pr, resp, err := g.PullRequests.Get(ctx, owner, repo, number)
		if !shouldRetry(err) {
			return pr, resp, err
		}
	}
}

func (g *githubClient) GetIssue(
	ctx context.Context, owner, repo string, number int,
) (*github.Issue, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		issue, resp, err := g.Issues.Get(ctx, owner, repo, number)
		if !shouldRetry(err) {
			return issue, resp, err
		}
	}
}

func (g *githubClient) GetRepoCommit(
	ctx context.Context, owner, repo, sha string,
) (*github.RepositoryCommit, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		commit, resp, err := g.Repositories.GetCommit(ctx, owner, repo, sha)
		if !shouldRetry(err) {
			return commit, resp, err
		}
	}
}

func (g *githubClient) ListCommits(
	ctx context.Context, owner, repo string, opt *github.CommitsListOptions,
) ([]*github.RepositoryCommit, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		commits, resp, err := g.Repositories.ListCommits(ctx, owner, repo, opt)
		if !shouldRetry(err) {
			return commits, resp, err
		}
	}
}

func (g *githubClient) ListPullRequestsWithCommit(
	ctx context.Context, owner, repo, sha string,
	opt *github.PullRequestListOptions,
) ([]*github.PullRequest, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		prs, resp, err := g.PullRequests.ListPullRequestsWithCommit(
			ctx, owner, repo, sha, opt,
		)
		if !shouldRetry(err) {
			return prs, resp, err
		}
	}
}

func (g *githubClient) ListReleases(
	ctx context.Context, owner, repo string, opt *github.ListOptions,
) ([]*github.RepositoryRelease, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		releases, resp, err := g.Repositories.ListReleases(
			ctx, owner, repo, opt,
		)
		if !shouldRetry(err) {
			return releases, resp, err
		}
	}
}

func (g *githubClient) GetReleaseByTag(
	ctx context.Context, owner, repo, tag string,
) (*github.RepositoryRelease, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		release, resp, err := g.Repositories.GetReleaseByTag(ctx, owner, repo, tag)
		if !shouldRetry(err) {
			return release, resp, err
		}
	}
}

func (g *githubClient) DownloadReleaseAsset(
	ctx context.Context, owner, repo string, assetID int64,
) (io.ReadCloser, string, error) {
	// TODO: Should we be getting this http client from somewhere else?
	httpClient := http.DefaultClient
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		assetBody, redirectURL, err := g.Repositories.DownloadReleaseAsset(ctx, owner, repo, assetID, httpClient)
		if !shouldRetry(err) {
			return assetBody, redirectURL, err
		}
	}
}

func (g *githubClient) ListTags(
	ctx context.Context, owner, repo string, opt *github.ListOptions,
) ([]*github.RepositoryTag, *github.Response, error) {
	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		tags, resp, err := g.Repositories.ListTags(ctx, owner, repo, opt)
		if !shouldRetry(err) {
			return tags, resp, err
		}
	}
}

func (g *githubClient) ListBranches(
	ctx context.Context, owner, repo string, opt *github.BranchListOptions,
) ([]*github.Branch, *github.Response, error) {
	branches, response, err := g.Repositories.ListBranches(ctx, owner, repo, opt)
	if err != nil {
		return nil, nil, errors.Wrap(err, "fetching brnaches from repo")
	}

	return branches, response, nil
}

func (g *githubClient) CreatePullRequest(
	ctx context.Context, owner, repo, baseBranchName, headBranchName, title, body string,
) (*github.PullRequest, error) {
	newPullRequest := &github.NewPullRequest{
		Title:               &title,
		Head:                &headBranchName,
		Base:                &baseBranchName,
		Body:                &body,
		MaintainerCanModify: github.Bool(true),
	}

	pr, _, err := g.PullRequests.Create(ctx, owner, repo, newPullRequest)
	if err != nil {
		return pr, errors.Wrap(err, "creating pull request")
	}

	logrus.Infof("Successfully created PR #%d", pr.GetNumber())
	return pr, nil
}

func (g *githubClient) GetRepository(
	ctx context.Context, owner, repo string,
) (*github.Repository, *github.Response, error) {
	pr, resp, err := g.Repositories.Get(ctx, owner, repo)
	if err != nil {
		return pr, resp, errors.Wrap(err, "getting repository")
	}

	return pr, resp, nil
}

func (g *githubClient) UpdateReleasePage(
	ctx context.Context, owner, repo string, releaseID int64,
	releaseData *github.RepositoryRelease,
) (release *github.RepositoryRelease, err error) {
	// If release is 0, we create a new Release
	if releaseID == 0 {
		release, _, err = g.Repositories.CreateRelease(ctx, owner, repo, releaseData)
	} else {
		release, _, err = g.Repositories.EditRelease(ctx, owner, repo, releaseID, releaseData)
	}

	if err != nil {
		return nil, errors.Wrap(err, "updating release pagin in github")
	}

	return release, nil
}

func (g *githubClient) UploadReleaseAsset(
	ctx context.Context, owner, repo string, releaseID int64, opts *github.UploadOptions, file *os.File,
) (release *github.ReleaseAsset, err error) {
	logrus.Infof("Uploading %s to release %d", opts.Name, releaseID)
	asset, _, err := g.Repositories.UploadReleaseAsset(
		ctx, owner, repo, releaseID, opts, file,
	)
	if err != nil {
		return nil, errors.Wrap(err, "while uploading asset file")
	}

	return asset, nil
}

func (g *githubClient) DeleteReleaseAsset(
	ctx context.Context, owner string, repo string, assetID int64) error {
	_, err := g.Repositories.DeleteReleaseAsset(ctx, owner, repo, assetID)
	if err != nil {
		return errors.Wrapf(err, "deleting asset %d", assetID)
	}
	return nil
}

func (g *githubClient) ListReleaseAssets(
	ctx context.Context, owner, repo string, releaseID int64,
) ([]*github.ReleaseAsset, error) {
	assets, _, err := g.Repositories.ListReleaseAssets(ctx, owner, repo, releaseID, &github.ListOptions{})
	if err != nil {
		return nil, errors.Wrap(err, "getting release assets from GitHub")
	}
	return assets, nil
}

func (g *githubClient) CreateComment(
	ctx context.Context, owner, repo string, number int, message string,
) (*github.IssueComment, *github.Response, error) {
	comment := &github.IssueComment{
		Body: &message,
	}

	for shouldRetry := internal.DefaultGithubErrChecker(); ; {
		issueComment, resp, err := g.Issues.CreateComment(ctx, owner, repo, number, comment)
		if !shouldRetry(err) {
			return issueComment, resp, err
		}
	}
}

// SetClient can be used to manually set the internal GitHub client
func (g *GitHub) SetClient(client Client) {
	g.client = client
}

// Client can be used to retrieve the Client type
func (g *GitHub) Client() Client {
	return g.client
}

// TagsPerBranch is an abstraction over a simple branch to latest tag association
type TagsPerBranch map[string]string

// LatestGitHubTagsPerBranch returns the latest GitHub available tag for each
// branch. The logic how releases are associates with branches is motivated by
// the changelog generation and bound to the default Kubernetes release
// strategy, which is also the reason why we do not provide a repo and org
// parameter here.
//
// Releases are associated in the following way:
// - x.y.0-alpha.z releases are only associated with the main branch
// - x.y.0-beta.z releases are only associated with their release-x.y branch
// - x.y.0 final releases are associated with the main branch and the release-x.y branch
func (g *GitHub) LatestGitHubTagsPerBranch() (TagsPerBranch, error) {
	// List tags for all pages
	allTags := []*github.RepositoryTag{}
	opts := &github.ListOptions{PerPage: 100}
	for {
		tags, resp, err := g.client.ListTags(
			context.Background(), git.DefaultGithubOrg, git.DefaultGithubRepo,
			opts,
		)
		if err != nil {
			return nil, errors.Wrap(err, "unable to retrieve GitHub tags")
		}
		allTags = append(allTags, tags...)
		if resp.NextPage == 0 {
			break
		}
		opts.Page = resp.NextPage
	}

	releases := make(TagsPerBranch)
	for _, t := range allTags {
		tag := t.GetName()

		// alpha and beta releases are only available on the main branch
		if strings.Contains(tag, "beta") || strings.Contains(tag, "alpha") {
			releases.addIfNotExisting(git.DefaultBranch, tag)
			continue
		}

		// We skip non-semver tags because k/k contains tags like `v0.5` which
		// are not valid
		semverTag, err := util.TagStringToSemver(tag)
		if err != nil {
			logrus.Debugf("Skipping tag %s because it is not valid semver", tag)
			continue
		}

		// Latest vx.x.0 release are on both main and release branch
		if len(semverTag.Pre) == 0 {
			releases.addIfNotExisting(git.DefaultBranch, tag)
		}

		branch := fmt.Sprintf("release-%d.%d", semverTag.Major, semverTag.Minor)
		releases.addIfNotExisting(branch, tag)
	}

	return releases, nil
}

// addIfNotExisting adds a new `tag` for the `branch` if not already existing
// in the map `TagsForBranch`
func (t TagsPerBranch) addIfNotExisting(branch, tag string) {
	if _, ok := t[branch]; !ok {
		t[branch] = tag
	}
}

// Releases returns a list of GitHub releases for the provided `owner` and
// `repo`. If `includePrereleases` is `true`, then the resulting slice will
// also contain pre/drafted releases.
// TODO: Create a more descriptive method name and update references
func (g *GitHub) Releases(owner, repo string, includePrereleases bool) ([]*github.RepositoryRelease, error) {
	allReleases, _, err := g.client.ListReleases(
		context.Background(), owner, repo, nil,
	)
	if err != nil {
		return nil, errors.Wrap(err, "unable to retrieve GitHub releases")
	}

	releases := []*github.RepositoryRelease{}
	for _, release := range allReleases {
		if release.GetPrerelease() {
			if includePrereleases {
				releases = append(releases, release)
			}
		} else {
			releases = append(releases, release)
		}
	}

	return releases, nil
}

// GetReleaseTags returns a list of GitHub release tags for the provided
// `owner` and `repo`. If `includePrereleases` is `true`, then the resulting
// slice will also contain pre/drafted releases.
func (g *GitHub) GetReleaseTags(owner, repo string, includePrereleases bool) ([]string, error) {
	releases, err := g.Releases(owner, repo, includePrereleases)
	if err != nil {
		return nil, errors.Wrap(err, "getting releases")
	}

	releaseTags := []string{}
	for _, release := range releases {
		releaseTags = append(releaseTags, *release.TagName)
	}

	return releaseTags, nil
}

// DownloadReleaseAssets downloads a set of GitHub release assets to an
// `outputDir`. Assets to download are derived from the `releaseTags`.
func (g *GitHub) DownloadReleaseAssets(owner, repo string, releaseTags []string, outputDir string) (finalErr error) {
	var releases []*github.RepositoryRelease

	if len(releaseTags) > 0 {
		for _, tag := range releaseTags {
			release, _, err := g.client.GetReleaseByTag(context.Background(), owner, repo, tag)
			if err != nil {
				return errors.Wrapf(err, "getting release from tag %s", tag)
			}
			releases = append(releases, release)
		}
	} else {
		return errors.New("no release tags were populated")
	}

	errChan := make(chan error, len(releases))
	for i := range releases {
		release := releases[i]
		go func(f func() error) { errChan <- f() }(func() error {
			releaseTag := release.GetTagName()
			logrus.WithField("release", releaseTag).Infof("Download assets for %s/%s@%s", owner, repo, releaseTag)

			assets := release.Assets
			if len(assets) == 0 {
				logrus.Infof("Skipping download for %s/%s@%s as no release assets were found", owner, repo, releaseTag)
				return nil
			}

			releaseDir := filepath.Join(outputDir, owner, repo, releaseTag)
			if err := os.MkdirAll(releaseDir, os.FileMode(0o775)); err != nil {
				return errors.Wrap(err, "creating output directory for release assets")
			}

			logrus.WithField("release", releaseTag).Infof("Writing assets to %s", releaseDir)
			if err := g.downloadAssetsParallel(assets, owner, repo, releaseDir); err != nil {
				return errors.Wrapf(err, "downloading assets for %s", releaseTag)
			}
			return nil
		})
	}

	for i := 0; i < cap(errChan); i++ {
		if err := <-errChan; err != nil {
			if finalErr == nil {
				finalErr = err
				continue
			}
			finalErr = errors.Wrap(finalErr, err.Error())
		}
	}
	return finalErr
}

func (g *GitHub) downloadAssetsParallel(assets []*github.ReleaseAsset, owner, repo, releaseDir string) (finalErr error) {
	errChan := make(chan error, len(assets))
	for i := range assets {
		asset := assets[i]
		go func(f func() error) { errChan <- f() }(func() error {
			if asset.GetID() == 0 {
				return errors.New("asset ID should never be zero")
			}

			logrus.Infof("GitHub asset ID: %v, download URL: %s", *asset.ID, *asset.BrowserDownloadURL)
			assetBody, _, err := g.client.DownloadReleaseAsset(context.Background(), owner, repo, asset.GetID())
			if err != nil {
				return errors.Wrap(err, "downloading release assets")
			}

			absFile := filepath.Join(releaseDir, asset.GetName())
			defer assetBody.Close()
			assetFile, err := os.Create(absFile)
			if err != nil {
				return errors.Wrap(err, "creating release asset file")
			}

			defer assetFile.Close()
			if _, err := io.Copy(assetFile, assetBody); err != nil {
				return errors.Wrap(err, "copying release asset to file")
			}
			return nil
		})
	}

	for i := 0; i < cap(errChan); i++ {
		if err := <-errChan; err != nil {
			if finalErr == nil {
				finalErr = err
				continue
			}
			finalErr = errors.Wrap(finalErr, err.Error())
		}
	}
	return finalErr
}

// UploadReleaseAsset uploads a file onto the release assets
func (g *GitHub) UploadReleaseAsset(
	owner, repo string, releaseID int64, fileName string,
) (*github.ReleaseAsset, error) {
	fileLabel := ""
	// We can get a label for the asset by appeding it to the path with a colon
	if strings.Contains(fileName, ":") {
		p := strings.SplitN(fileName, ":", 2)
		if len(p) == 2 {
			fileName = p[0]
			fileLabel = p[1]
		}
	}

	// Check the file exists
	if !util.Exists(fileName) {
		return nil, errors.New("unable to upload asset, file not found")
	}

	f, err := os.Open(fileName)
	if err != nil {
		return nil, errors.Wrap(err, "opening the asset file for reading")
	}

	// Only the first 512 bytes are used to sniff the content type.
	buffer := make([]byte, 512)

	_, err = f.Read(buffer)
	if err != nil {
		return nil, errors.Wrap(err, "reading file to determine mimetype")
	}
	// Reset the pointer to reuse the filehandle
	_, err = f.Seek(0, 0)
	if err != nil {
		return nil, errors.Wrap(err, "rewinding the asset filepointer")
	}

	contentType := http.DetectContentType(buffer)
	logrus.Infof("Asset filetype will be %s", contentType)

	uopts := &github.UploadOptions{
		Name:      filepath.Base(fileName),
		Label:     fileLabel,
		MediaType: contentType,
	}

	asset, err := g.Client().UploadReleaseAsset(
		context.Background(), owner, repo, releaseID, uopts, f,
	)
	if err != nil {
		return nil, errors.Wrap(err, "uploading asset file to release")
	}

	return asset, nil
}

// CreatePullRequest Creates a new pull request in owner/repo:baseBranch to merge changes from headBranchName
// which is a string containing a branch in the same repository or a user:branch pair
func (g *GitHub) CreatePullRequest(
	owner, repo, baseBranchName, headBranchName, title, body string,
) (*github.PullRequest, error) {
	// Use the client to create a new PR
	pr, err := g.Client().CreatePullRequest(context.Background(), owner, repo, baseBranchName, headBranchName, title, body)
	if err != nil {
		return pr, err
	}

	return pr, nil
}

// GetRepository gets a repository using the current client
func (g *GitHub) GetRepository(
	owner, repo string,
) (*github.Repository, error) {
	repository, _, err := g.Client().GetRepository(context.Background(), owner, repo)
	if err != nil {
		return repository, err
	}

	return repository, nil
}

// ListBranches gets a repository using the current client
func (g *GitHub) ListBranches(
	owner, repo string,
) ([]*github.Branch, error) {
	branches, _, err := g.Client().ListBranches(context.Background(), owner, repo, &github.BranchListOptions{})
	if err != nil {
		return branches, errors.Wrap(err, "getting branches from client")
	}

	return branches, nil
}

// RepoIsForkOf Function that checks if a repository is a fork of another
func (g *GitHub) RepoIsForkOf(
	forkOwner, forkRepo, parentOwner, parentRepo string,
) (bool, error) {
	repository, _, err := g.Client().GetRepository(context.Background(), forkOwner, forkRepo)
	if err != nil {
		return false, errors.Wrap(err, "checking if repository is a fork")
	}

	// First, repo has to be an actual fork
	if !repository.GetFork() {
		logrus.Infof("Repository %s/%s is not a fork", forkOwner, forkRepo)
		return false, nil
	}

	// Check if the parent repo matches the owner/repo string
	if repository.GetParent().GetFullName() == fmt.Sprintf("%s/%s", parentOwner, parentRepo) {
		logrus.Debugf("%s/%s is a fork of %s/%s", forkOwner, forkRepo, parentOwner, parentRepo)
		return true, nil
	}

	logrus.Infof("%s/%s is not a fork of %s/%s", forkOwner, forkRepo, parentOwner, parentRepo)
	return false, nil
}

// BranchExists checks if a branch exists in a given repo
func (g *GitHub) BranchExists(
	owner, repo, branchname string,
) (isBranch bool, err error) {
	branches, err := g.ListBranches(owner, repo)
	if err != nil {
		return false, errors.Wrap(err, "while listing repository branches")
	}

	for _, branch := range branches {
		if branch.GetName() == branchname {
			logrus.Debugf("Branch %s already exists in %s/%s", branchname, owner, repo)
			return true, nil
		}
	}

	logrus.Debugf("Repository %s/%s does not have a branch named %s", owner, repo, branchname)
	return false, nil
}

// UpdateReleasePage updates a release page in GitHub
func (g *GitHub) UpdateReleasePage(
	owner, repo string,
	releaseID int64,
	tag, commitish, name, body string,
	isDraft, isPrerelease bool,
) (release *github.RepositoryRelease, err error) {
	logrus.Infof("Updating release page for %s", tag)

	// Create the options for the
	releaseData := &github.RepositoryRelease{
		TagName:         &tag,
		TargetCommitish: &commitish,
		Name:            &name,
		Body:            &body,
		Draft:           &isDraft,
		Prerelease:      &isPrerelease,
	}

	// Call the client
	release, err = g.Client().UpdateReleasePage(
		context.Background(), owner, repo, releaseID, releaseData,
	)

	if err != nil {
		return nil, errors.Wrap(err, "updating the release page")
	}

	return release, nil
}

// DeleteReleaseAsset deletes an asset from a release
func (g *GitHub) DeleteReleaseAsset(owner, repo string, assetID int64) error {
	return errors.Wrap(g.Client().DeleteReleaseAsset(
		context.Background(), owner, repo, assetID,
	), "deleting asset from release")
}

// ListReleaseAssets gets the assets uploaded to a GitHub release
func (g *GitHub) ListReleaseAssets(
	owner, repo string, releaseID int64) ([]*github.ReleaseAsset, error) {
	// Get the assets from the client
	assets, err := g.Client().ListReleaseAssets(
		context.Background(), owner, repo, releaseID,
	)
	if err != nil {
		return nil, errors.Wrap(err, "getting release assets")
	}
	return assets, nil
}

// TagExists returns true is a specified tag exists in the repo
func (g *GitHub) TagExists(owner, repo, tag string) (exists bool, err error) {
	tags, _, err := g.Client().ListTags(
		context.Background(), owner, repo, &github.ListOptions{PerPage: 100},
	)
	if err != nil {
		return exists, errors.Wrap(err, "listing repository tags")
	}

	// List all tags and check if it exists
	for _, testTag := range tags {
		if testTag.GetName() == tag {
			return true, nil
		}
	}
	return false, nil
}

redpajama_set_name: RedPajamaGithub


The year was 1999, and our founder Nick Swinmurn was walking around a mall in San Francisco looking for a pair of shoes. One store had the right style, but not the right color. Another store had the right color, but not the right size.
Fixed Gear, Single-Speed, City Bikes, Road Bikes, Urban Commuter Bikes and Cruisers designed in Los Angeles. Starting at $279!
GIRL MEETS DRESS is an online boutique where you can borrow the latest designer dresses. London Showroom Appointments available.
Houthandel Woerden offers you the most beautiful and competitively priced table tops, stone slabs and other wood products. We have a very large stock in all sizes, so with us you will not easily miss out!


Budgeting for the Next Round of Bailouts?
May as well be prepared.
A chart of the various types of unemployment.
A former Reagan staffer explains why the tax on giant bailed-out banks is actually a fiscally conservative proposal.
Killer metaphor: sluggers and bankers dominated the last ten years.
This is a sick, sad group of data points and is exactly what you can expect in a country that makes virtually nothing and became overly reliant on the housing and real estate industry for jobs and income.
Street after street, town after town, state after state, everything's starting to look the same.
Gretchen Morgenson takes on one of the most crucial factors of our decennis horribilis in the stock market: the failure of corporate board culture.
One of the more perverse features of the bailout/ rescue/ stimulus plan is the fact that ultra-low rates are doing a great deal of damage to senior citizens and those who have been saving responsibly and coninue to attempt to do so.


text:
Power to require charity's...
42Power to require name to be changedE+W
(1)If this subsection applies to a charity, the Commission may give a direction requiring the name of the charity to be changed, within such period as is specified in the direction, to such other name as the charity trustees may determine with the approval of the Commission.
(2)Subsection (1) applies to a charity if—
(a)it is a registered charity and its name ("the registered name")—
(i)is the same as, or
(ii)is in the opinion of the Commission too like,
the name, at the time when the registered name was entered in the register in respect of the charity, of any other charity (whether registered or not),
(b)the name of the charity is in the opinion of the Commission likely to mislead the public as to the true nature of—
(i)the purposes of the charity as set out in its trusts, or
(ii)the activities which the charity carries on under its trusts in pursuit of those purposes,
(c)the name of the charity includes any word or expression for the time being specified in regulations made by the [F1Secretary of State] and the inclusion in its name of that word or expression is in the opinion of the Commission likely to mislead the public in any respect as to the status of the charity,
(d)the name of the charity is in the opinion of the Commission likely to give the impression that the charity is connected in some way with Her Majesty's Government or any local authority, or with any other body of persons or any individual, when it is not so connected, or
(e)the name of the charity is in the opinion of the Commission offensive.
(3)Any direction given by virtue of subsection (2)(a) must be given within 12 months of the time when the registered name was entered in the register in respect of the charity.
(4)In subsection (2) any reference to the name of a charity is, in relation to a registered charity, a reference to the name by which it is registered.
(5)Any direction given under this section with respect to a charity must be given to the charity trustees.
F1Words in s. 42(2)(c) substituted (9.11.2016) by The Transfer of Functions (Elections, Referendums, Third Sector and Information) Order 2016 (S.I. 2016/997), art. 1(2), Sch. 2 para. 25(2)(k) (with art. 12)

redpajama_set_name: RedPajamaCommonCrawl


text:
Indonesia prepared to welcome foreign universities
The Indonesia government has announced that it anticipates the first agreements between foreign education providers and local private-sector partners to be established later this year
Senior ministers have suggested that this long-delayed move will go ahead this year, resulting in five to ten new foreign campuses in the country
Indonesia has a long-running, on-again-off-again strategy to open up its higher education system to foreign providers. The legislation that provides for such foreign participation in higher education delivery in the country has been on the books since 2012, but the government has been reluctant in the years since to formally open the process.
It appears, however, that the tide is changing in recent months. In November, President Joko Widodo expressed his interest in having foreign institutions open new campuses in Indonesia in order to provide an important reference point for strengthening the country's own universities. And following on from this, Research, Technology and Higher Education Minister Muhammad Nasir held a press conference in January at which he announced Indonesia would indeed welcome foreign providers later this year.
Minister Nasir told the press conference that, "At least five or ten foreign universities are targeted to operate in the middle of this year." The Minister singled out the University of Cambridge, University of Melbourne, and CQUniversity Australia as institutions that had already expressed interest. The Minister also indicated science, technology, engineering, mathematics, business and management as priority subject areas.
Public pronouncements on this issue tend to be made cautiously in Indonesia, and any discussion of foreign unis setting up shop is always accompanied by two important qualifiers: the foreign institution will be expected to find a local private-sector partner and to prioritise the hiring of local faculty. All education institutions are also required to devote a portion of their curricula to teaching Indonesian culture, including religious and Islamic values.
In addition, the government is generally clear that any invitation to operate in Indonesia will only be extended to top-ranked institutions. "We give the chance for foreign higher learning institutions, especially world-class universities, to operate in Indonesia," said the Minister.
Arguments for and against
But if Indonesia's politicians have been cautious on this question, it has perhaps been with good reason as the prospect of opening up the country's higher education system has provoked a lively debate.
Proponents of the move argue that allowing foreign institutions to operate in Indonesia will not only boost local higher education capacity, but also encourage greater numbers of Indonesian students to study at home. Those in favour anticipate as well that highly ranked foreign providers will be an important spark for strengthening Indonesian institutions.
Those opposed argue that local institutions, public and private, will struggle to compete with foreign providers and that the end result will be a hollowing out of the domestic system.
With these questions still very much in play it seems likely that the government has set an overly ambitious schedule for the country's first partnerships with foreign providers. This is especially so as observers outside of Indonesia wonder over the details about such partnerships, including the need for top foreign institutions to form up with local private-sector partnerships, the legislated restrictions on for-profit operations in the country's education sector, and the requirements around Islamic cultural content.
As of today, Minister Nasir has not yet followed up on his January press conference with a formal decree concerning foreign university operations in Indonesia. But the timing of any further announcements may also be influenced by the progress of ongoing Australia-Indonesia free trade negotiation, which are ongoing at the moment and in which foreign educator operations in Indonesia have figured to date.
"Study finds that young Indonesians are highly motivated to study abroad"
"Southeast Asia trading and mobility bloc continues to take shape"
"Indonesia's growing middle class expected to drive outbound mobility"
This entry was posted in Agents, Asia, Higher Education, Indonesia, Regions and tagged education abroad, branch campus, higher education, postgraduate student recruitment, student mobility.
New study highlights global language travel trends and the role of agents
Reaching prospects by email and boosting open rates
Education agents continue to play a larger role in UK recruitment
How Canada's Bill C-35 affects education agents
Foreign graduate enrolment in the US dips for second year in a row
New report argues that international students in France should pay full fees
New insights on characteristics of US college students
Brazilian outbound grew in 2016
One thought on "Indonesia prepared to welcome foreign universities"
Pingback: Indonesian outbound continues to grow with emphasis on regional destinations - ICEF Monitor - Market intelligence for international student recruitment


When it comes to the weekend, it has become a routine for me to ask Daddy & Mummy where we will be going on Saturday. And for last Saturday, I was given the all important task to make the decision.
A decision that pleased di-di as well.
Di-di & I quickly got down to building our sandcastle, with me the chief engineer donning the important supervisory role.
Can see that di-di was really hard at work huh?
I had even wanted to go for a dip in the sea, but too bad Daddy didn't bring his change of clothing... so we could only get our legs wet. Darn.
What we really did throw was Frisbee!


The first thing you notice when you enter the residency space at the Mattress Factory Art Museum is a sign posted with a list of rules, such as: treat yo' self, practice reckless optimism, check your privilege, and don't forget to take your meds. At any other art museum, these rules would seem out of place, but they fit right in at the Mattress Factory.
This summer, the Mattress Factory Art Museum is hosting The Summer Art Cooperative – a free summer program that gives teens the opportunity to curate and install exhibits, plan events, meet with local artists, and explore contemporary art. For the duration of the program, participants work towards their final exhibition on August 7th. In addition to planning that event, they also learn how to do everything from pickling to mud dancing. The program has been a great success.
In a lot of art museums, it's easy to forget about the people behind the scenes, but the Mattress Factory values its installers and curators, including those who specialize in different forms of art. Kathryn is one of the few participants who isn't a self proclaimed visual artist. Instead, she's interested in the publication and magazine industries. "I'm here because I know that I love art even though I'm not a visual artist," Kathryn says. "I would love to maybe start my own magazine with positive messages… We spoke with the head of marketing for the museum, so this program is putting us in contact with people who have been where we want to go." Kathryn is a great example that you don't need to be a traditional artist to make an impact in the art world.
Another topic explored in the Co-Op is marketing. The Mattress Factory uses installation art to explore relevant and diverse topics. But despite their international acclaim, few people in Pittsburgh know about the museum. Ada, another participant, wants to change that and attract more locals. She explains: "Most of the museum's visitors are white which I found was surprising because we're in the North Side which is a hub of people of color. But then I realized the admission price is like $20 which is probably why." Ada's individual project for the exhibition examines white privilege and stereotypes surrounding black culture. She hopes that using an instillation piece will make the viewer think about the meaning behind the piece, and not just what's in front of them. "I want to hopefully do a critique on how white people consume black culture, but they don't appreciate black people." Another one of her goals is to market the museum's discounted ticket rates. The Mattress Factory offers half off admission prices on Tuesdays and for residents of the North Side in the 15212 and 15213 zip codes. Ada is working closely with museum staff to raise awareness of these deals to locals in an attempt to bring in a more diverse group of patrons.
One of the most well known pieces at the Mattress Factory, Word Balloons by John Pena, reads "Sometimes I just don't know how to be in the world." It seems like the participants in the Summer Art Cooperative do know how to be in the world. They've all found their artistic niches, and those happen to be at the Mattress Factory.


text:
#if !defined CUDA_DISABLER

#include "TestHypothesesGrow.h"
#include "NCVHaarObjectDetection.hpp"

TestHypothesesGrow::TestHypothesesGrow(std::string testName_, NCVTestSourceProvider<Ncv32u> &src_,
                                       Ncv32u rectWidth_, Ncv32u rectHeight_, Ncv32f rectScale_,
                                       Ncv32u maxLenSrc_, Ncv32u lenSrc_, Ncv32u maxLenDst_, Ncv32u lenDst_)
    :
    NCVTestProvider(testName_),
    src(src_),
    rectWidth(rectWidth_),
    rectHeight(rectHeight_),
    rectScale(rectScale_),
    maxLenSrc(maxLenSrc_),
    lenSrc(lenSrc_),
    maxLenDst(maxLenDst_),
    lenDst(lenDst_)
{
}

bool TestHypothesesGrow::toString(std::ofstream &strOut)
{
    strOut << "rectWidth=" << rectWidth << std::endl;
    strOut << "rectHeight=" << rectHeight << std::endl;
    strOut << "rectScale=" << rectScale << std::endl;
    strOut << "maxLenSrc=" << maxLenSrc << std::endl;
    strOut << "lenSrc=" << lenSrc << std::endl;
    strOut << "maxLenDst=" << maxLenDst << std::endl;
    strOut << "lenDst=" << lenDst << std::endl;
    return true;
}

bool TestHypothesesGrow::init()
{
    return true;
}

bool TestHypothesesGrow::process()
{
    NCVStatus ncvStat;
    bool rcode = false;

    NCVVectorAlloc<Ncv32u> h_vecSrc(*this->allocatorCPU.get(), this->maxLenSrc);
    ncvAssertReturn(h_vecSrc.isMemAllocated(), false);
    NCVVectorAlloc<Ncv32u> d_vecSrc(*this->allocatorGPU.get(), this->maxLenSrc);
    ncvAssertReturn(d_vecSrc.isMemAllocated(), false);

    NCVVectorAlloc<NcvRect32u> h_vecDst(*this->allocatorCPU.get(), this->maxLenDst);
    ncvAssertReturn(h_vecDst.isMemAllocated(), false);
    NCVVectorAlloc<NcvRect32u> d_vecDst(*this->allocatorGPU.get(), this->maxLenDst);
    ncvAssertReturn(d_vecDst.isMemAllocated(), false);
    NCVVectorAlloc<NcvRect32u> h_vecDst_d(*this->allocatorCPU.get(), this->maxLenDst);
    ncvAssertReturn(h_vecDst_d.isMemAllocated(), false);

    NCV_SET_SKIP_COND(this->allocatorGPU.get()->isCounting());

    NCV_SKIP_COND_BEGIN
    ncvAssertReturn(this->src.fill(h_vecSrc), false);
    memset(h_vecDst.ptr(), 0, h_vecDst.length() * sizeof(NcvRect32u));
    NCVVectorReuse<Ncv32u> h_vecDst_as32u(h_vecDst.getSegment(), lenDst * sizeof(NcvRect32u) / sizeof(Ncv32u));
    ncvAssertReturn(h_vecDst_as32u.isMemReused(), false);
    ncvAssertReturn(this->src.fill(h_vecDst_as32u), false);
    memcpy(h_vecDst_d.ptr(), h_vecDst.ptr(), h_vecDst.length() * sizeof(NcvRect32u));
    NCV_SKIP_COND_END

    ncvStat = h_vecSrc.copySolid(d_vecSrc, 0);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);
    ncvStat = h_vecDst.copySolid(d_vecDst, 0);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);
    ncvAssertCUDAReturn(cudaStreamSynchronize(0), false);

    Ncv32u h_outElemNum_d = 0;
    Ncv32u h_outElemNum_h = 0;
    NCV_SKIP_COND_BEGIN
    h_outElemNum_d = this->lenDst;
    ncvStat = ncvGrowDetectionsVector_device(d_vecSrc, this->lenSrc,
                                             d_vecDst, h_outElemNum_d, this->maxLenDst,
                                             this->rectWidth, this->rectHeight, this->rectScale, 0);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);
    ncvStat = d_vecDst.copySolid(h_vecDst_d, 0);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);
    ncvAssertCUDAReturn(cudaStreamSynchronize(0), false);

    h_outElemNum_h = this->lenDst;
    ncvStat = ncvGrowDetectionsVector_host(h_vecSrc, this->lenSrc,
                                           h_vecDst, h_outElemNum_h, this->maxLenDst,
                                           this->rectWidth, this->rectHeight, this->rectScale);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);
    NCV_SKIP_COND_END

    //bit-to-bit check
    bool bLoopVirgin = true;

    NCV_SKIP_COND_BEGIN
    if (h_outElemNum_d != h_outElemNum_h)
    {
        bLoopVirgin = false;
    }
    else
    {
        if (memcmp(h_vecDst.ptr(), h_vecDst_d.ptr(), this->maxLenDst * sizeof(NcvRect32u)))
        {
            bLoopVirgin = false;
        }
    }
    NCV_SKIP_COND_END

    if (bLoopVirgin)
    {
        rcode = true;
    }

    return rcode;
}

bool TestHypothesesGrow::deinit()
{
    return true;
}

#endif /* CUDA_DISABLER */


At Metal Cutting, we have the proven skills and experience to work with virtually any metal our customers need, offering a complete portfolio of solid metal parts, machined parts, and small metal tubes cut to tight tolerances and finished according to your specifications.
For solids made from all types of metal, parts can be cut to exceptionally tight tolerances and high Cpk/Ppk. For machined parts, our capabilities in Swiss-style automatic machining, 4-axis CNC milling and turning, CNC lathes, and multi-axis CNC wire EDM enable us to handle very complex and difficult small diameter components. For small metal tubes, our expertise in working with thin walls, small diameters, and virtually any metal allows us to cut tubes to precise lengths and achieve a wide range of customized features.


The 1981-83 drug interdiction program devolved into a program to illegally arm the Nicaraguan right-wing rebel group in their efforts to overthrow the newly elected Sandinista government. U.S. military weapons, in an effort to conceal their origins, were shipped to Honduras ostensibly for U.S. Army 101st Airborne Division's staged maneuvers to ward off and invasion by neighboring Nicaragua– an extremely far fetched scenario In reality, the weapons were being 'laundered' According to Plumlee, although the military told the Government Accounting Office that the weapons were a total loss, the equipment was in fact transported back to the U.S. and retrofitted before being flown back to Central America and into the hands of the CIA's Contra army.
The weapons were taken to the El Toro Marine Corps Air Station and the U.S. Army Proving Grounds near Yuma, Arizona, because they needed to be repaired, Plumlee remembers making three trips into El Toro, including one that may have involved bringing drugs into the military airstrip.
Plumlee became concerned that the drugs he and other CIA contract pilots were bringing into the United States were not actually being interdicted, but were being used for other matters. The record being clear, neither the U.S. nor Mexico was moving to shut down the Mexican and Central American airstrips and staging facilities being used for the cocaine and drug shipments into the United States. it appeared to Plumlee that the U.S. Government was not really interested in shutting down those drug routes, nor shutting down the cartels of South America. The flow of drugs in American cities increased as time went on.
It appeared to many who were associated with government, "Black Ops" and the so-called drug interdiction program was a cover to illegally supply weapons to the right-wing Contras in their attempts to overthrow the government of Nicaragua. The weapons transportation into southern Mexico and Central America continued unabated and was in total violation of the U.S. Congressional mandate designed to prevent weapon shipments to those countries. That Congressional resolution to stop such activities was known as the Boland Amendment.
Soon federal authorities began indicting some of the U.S. CIA contract pilots for drug trafficking despite the fact that they were flying government-sanctioned operations. To protect himself for prosecution as a drug trafficker, Plumlee, in 1983, contacted staffers for U.S. Senator Gary Hart, Democrat of Colorado, and told them everything he knew about the phony drug interdiction program and how it had been used by the CIA as a cover for the agency's secret – and illegal – -shipment of arms for the Nicaraguan Contras he provided to Senator Hart maps, names, and other supporting evidence to the Senator. Plumlee took the measure to go on record before the fact – before they could arrest him on weapons charges and drug running. On May 5th, 1987. The joint congressional hearings on the Iran – Contra fiasco began – four years after Plumlee's discussions with Senator Hart and his staff. These hearings would become known as the Iran – Contra hearings. Senator John Kerry chaired those hearings on Narcotics.
Robert Plumlee's direct involvement in this complex web of drugs and arms trafficking made him a valuable resource to a number of congressional committees. Plumlee provided first-hand accounts of the intricacies of the phony drug interdiction program as well as the methods wherein arms were secured and provided to the illegal armed group, known as the Contras.
Plumlee and other pilots were secretly working for the Arizona based Tri-State Drug Task Force. His contact was the Phoenix organized crime detail. The federal agents didn't know of his existence. Plumlee flew under and assigned fake name: William H. Pearson. "All of us ops guys used alias", he says. When Plumlee first started flying drugs into the Unites States he was certain the information he collected—flight routes, drop points and cargo loads—was being passed onto the federal drug agents, along with the tons of cocaine he was ferrying. The whole operation was a set up to be used as an interdiction program operating through Mexico. The pilots were transporting weapons and drugs on C-130 aircraft. Plumlee and the other pilots were flying drugs into the United States and weapons back into Central America via Mexico. The pilots were working undercover to log and record the aircraft ID numbers and landing strip location. The covert operation was to log staging points and flyways.
Iran-Contra, a covert operation Plumlee had stumbled into would later be known ("Iran" being a reference to the Reagan administration's secret missile-for- hostages exchange with the Iranian government), began as a way to circumvent the congressional ban on arming the Nicaraguan Contras. The Contras were the right-wing army partly created by the CIA to topple the countries Sandinista Government, which had taken over the country during a popular uprising in 1979. When the U.S. congress banned any aid to the Contras, Oliver North, then a lieutenant Colonel in the Marine Corps working for Reagan-era National Security Council, secretly continued arms shipments. In 1986, the crash of a C-123 Aircraft in Nicaragua that was owned by Southern Air Transport and piloted by a friend of Plumlee's, Bill Cooper, exposed the covert operation.
TODAY, DECEMBER 2016, INTERNATIONAL GUNRUNNING IS STILL ALIVE AND WELL…. JUST ASK THE CLINTON FOUNDATION.


New York: Farrar Straus & Giroux, 2002. New York: Farrar, Straus & Giroux, 2002. First Edition first printing. 8vo. Trade Paperback, 368 pp. Peggy Kaye, the author and illustrator of the "Games for" series, shows parents and teachers how to engange young children in amusing yet slyly educatonal games based on 28 classic children's books. Bumping on corners of covers. Very Good.. First Edition. Trade Paperback. Very Good. Illus. by Kaye, Peggy. 8vo - over 7¾" - 9¾" tall.


text:
Q: Migrate java web project IBM RAD to Intellij We have a project that developed in IBM RAD 8.5 and using WebSphere Server.
I want to migrate the project to Intellij idea and use tomcat to jBos for server.
When I try to add the dependencies jars, still I got this error.
"Error:(14, 36) java: unmappable character (0xE7) for encoding UTF-8"
I think I am missing something huge. Could you please explain me what is the trick under the hood of migrating. I have .classpath, .project web.xml, build.xml. How to edit them to get completely free from RAD.
regards

redpajama_set_name: RedPajamaStackExchange


text:
Gear Spotlight - Fender Custom Shop Electric Guitars
Gear SpotlightBuddy Beaudoin Apr 15, 2022
In the mid '80s, the Fender Custom Shop opened its doors with the express mission of making custom, top shelf, instruments available to the public. Built by a select few world renown builders, Fender Custom Shop guitars set a standard of excellence, and are some of the most sought-after guitars available on the market. Here at Parkway, we're happy to carry a broad selection of these beautiful instruments, and we just so happen to have quite a few available. Let's take a look!
First up, we have a gorgeous Limited Edition '56 Strat with color-over-color Super Faded Aged Candy Apple Red over a classic 2-Tone Sunburst finish. The heavy relic on this one is just enough to let that 2-Tone burst peak through the otherwise super vibrant two piece alder body on front and back. If you're a fan of the '50s look and sound, you'll appreciate the off-center "V" neck profile and hand-wound Custom Shop Fat '50s pickups.
If red is not your color, but you're after all of the specs that the '56 Strat has to offer, we have a similar Strat up for grabs in a striking Aged Seafoam Green over 2-Tone Sunburst. In keeping with the '56 theme, we have a Strat on offer in Aged Sherwood Green Metallic finish with some different spec and pickup options and a much lighter relic'd body. Both are great players, and most importantly, both look damn cool.
If it's '60 Strat vibe you're after, don't worry, we've got you well covered. We have a handful of Custom Shop '60s Strats on the floor right now in a variety of finishes, relic jobs, and specs, but if you're a fan of Shell Pink, you'll be happy with our selection. For me, the S20 LTD '60 Strat in Super Faded Aged Shell Pink and Journeyman relic is where it's at. Paired with a class mint pick guard, the Journeyman relic on the Shell Pink here is not so over the top that it loses any of it's vibe or charm. Featuring a quarter-sawn maple neck, AAA rosewood fingerboard, and a '60s "C" neck profile, this beast is an absolute player.
Of course it's not all about the Strats here. We have some killer Custom Shop telecasters here as well. If you were feeling the Candy Apple Red of that Strat, our first Tele in line is for you. It's got the same glowing red finish, but with a much lighter Journeyman relic so you retain all of the classic color. It's got a two-piece ash body, '57 softy-style "V" neck profile, and handwound 55/56 Tele pickups that pack a punch.
If you're a Fender historian, this next one is for you. The S20 LTD '50s Pine Esquire features a super heavy relic over the beloved Nocaster Blonde finish, Eastern White Pine body, maple rift-sawn neck and fingerboard, and an inspiring 1950 Blackguard neck profile. It's loaded with a hand-wound 50-50 Blackguard single bridge pickup for true Esquire tone and feel, and at just over 7lbs, it's by no means a backbreaker.
We have these, and so many more in stock and ready for you to play right now, but I should definitely note that we have plenty more on the way. If you haven't found what you're looking for today, keep your eyes peeled. We've got some truly special Custom Shop offerings coming up. Also, if we didn't highlight the one for you, you can take a look at our entire stock of Custom Shops below.
Thanks for hanging,
Tags: Gear spotlight


Internašunála Sámi Filbmainstituhtta galgá nannet sámi filbma buvttadeami. - The International Sami Film Institute aims to support sami film production.
SAMY'S DOSAKALL Restaurant was founded by the SAMY in 1980, which eventually opened at Spectrum Mall in Chennai. SAMY'S DOSAKALL is well-known for its varieties of Dosa and many creative concepts, which made the restaurant extremely famous.
Shop Samy's Camera (in-store and online) for all your photography needs.
SDG – Sami Dáiddaguovddáš/Samisk Senter for Samtidskunst/Sami Center for Contemporary Art– lea guovddáš sámi govvadáidaga várás ja profilejuvvon arena dálááiggi ovdanbuktinvugiide.
Bye Sami es un banda de rock de Tijuana, México que se formó en el 2000.


This webpage provides information and resources to anyone intending to conduct metal mining operations in Oregon's streams or rivers. DEQ's fact sheet, Water Quality Permits for Metal Mining Activities, describes all water quality permits required for metal mining/prospecting and ore processing operations that discharge wastewater to the land and state waters on private or public land. This fact sheet includes contact information for local, state and federal agencies in Oregon that may also have requirements related to mining.
DEQ regulates the discharge of wastewater from suction dredge and in-water, non-motorized mining operations that recover precious metals or minerals from streambed sediments via the 700-PM NPDES general permit. This permit modification, effective May 7, 2018, updates the permit issued in 2015 to include current requirements.
discharges from highbanker and combination highbanker/suction dredge equipment (you may convert the combination highbanker/suction dredge to a suction dredge, but it must meet definition 19 in the permit.
There may be additional requirements by other local (city, county), state, and federal (BLM, Forest Service, Army Corps) mining and land use authorities (not listed above) that have more stringent requirements than conditions specified in the 700-PM. You must abide by the most stringent requirement and the 700-PM does not exempt your operation from a more stringent requirement.
NOTE: Registration under the 700-PM general permit does not authorize suction dredge mining in areas where mining is prohibited.
A copy of the 700-PM general permit and resource materials are available at any DEQ office or by using the links provided below.
Please refer to the application form for registration fees.
In December 2018, the U.S. Environmental Protection Agency approved Oregon's 2012 Clean Water Act Section 303(d) list of impaired waterbodies and added new waterbodies to the 303(d) list. This new list is not on the Interactive Location Mapping Tool at this time. Please also check this new list of waterbodies added to the 303(d) list to determine if permit coverage can be provided for a mining site location. This new 303(d) list of impaired water is available on DEQ's Water Quality Assessment web page.
Permit holders may not operate a gravity or siphon suction dredge with a suction hose larger than four inches in essential salmon habitat. Outside essential salmon habitat, they may not operate a gravity or siphon suction dredge with a suction hose larger than six inches. In addition to only operating during daylight hours (from sunrise to sunset) suction dredging is allowed only during the in-water work schedule (Timing of In-Water Work to Protect Fish and Wildlife Resources) as set by the Oregon Department of Fish and Wildlife. The 700PM permit does not allow suction dredge mining outside of Oregon Department of Fish and Wildlife's in-water work period.
Wastewater discharges are not allowed where the visible turbidity plume affects the intake of a drinking water source from any placer mining operation. Measures must be taken to prevent the spreading of invasive species.
Suction dredges must operate at a distance 500 feet upstream from any stream segment listed as water quality limited for sedimentation, turbidity or toxics other than chlorine. The 303(d) list that applies is list that is in effect January 1 of each year.
Suction dredge operations are required to keep records and submit a report to DEQ annually.
The 700PM general permit does not allow suction dredge mining operations to discharge to surface waters on tribal lands. Oregon does not have jurisdiction to regulate surface water discharges on tribal lands; that authority lies with either the tribe or the U. S. Environmental Protection Agency.
In addition, the 700PM general permit does not authorize discharges from mining operations into waterways that border a tribal reservation. Mining in these waters would require an individual discharge permit from DEQ to ensure that tribal water quality standards are protected.
Applicants should submit an application at least 30 days in advance of the date to start a suction dredging operation.
(10) 12 wilderness areas with limited discharge (no visible turbidity allowed) for mining site locations and prevent applications from being returned due to incomplete or inaccurate information.
Also for mining site locations, you can provide the mining claim name if you have one. This is not required. The Interactive Location Mapping Tool may not help determine who owns the land. You may need to determine from other sources whether the land is public or private, and, if it is public, determine what type of public land.
Follow the links below to find useful information to help you fill out an application to register under the 700PM general permit and comply with permit conditions.
DSL's Recreational and Small-Scale Placer Mining web page has information on permitting and Essential Salmon Habitat and Scenic Waterways.
In addition to needing a DEQ permit for mining, activities on federal lands must comply with the DEQ permit and with any additional terms or conditions established by a federal agency. Before undertaking mining activities on federal lands in Oregon, miners should contact the appropriate federal district office to see if there are any restrictions or conditions regarding mining activities or access to areas where mining will take place. Requirements may differ from one district to another.
U.S. Forest Service - Region 6, or call the district ranger for the national forest where you want to mine.
An individual permit only applies to a specific operation and location or mining claim.
Applicants should apply for a new permit at least six months before they plan to begin operating. Those applying for a renewal should also allow six months for permit processing. In addition to the application fee and first year annual fee (when required), applicants must submit a complete individual NPDES permit application at least 180 days in advance of the date to start operating. DEQ will not process incomplete applications.
DEQ's permit administration process requires a public comment period of 35 days and will likely require a public hearing with a minimum of 30 days advance notice. If DEQ determines that additional information or measures are needed, there will be an additional 90 days or more added to the process.
Oregon Administrative Rule 340-075-0075 Permit Fee Schedule - Please see Table 70A for NPDES application fees and Mining Operations in Table 70B for NPDES annual fees due with an application submittal.
This general permit is for small-scale mining operations and non-chemical ore processors that dispose of wastewater by evaporation and/or seepage. Operations are off-stream and above ordinary high-water levels. Discharge to water is prohibited.
Note: This general permit expired on Jan. 31, 2017 but is administratively continued and will remain in effect for permit holders until a new permit is issued. Permit holders operating under the administratively continued permit are expected to comply with the terms and conditions of that permit. DEQ does not currently have a schedule for renewing or revising this permit. This permit cannot be assigned to new applicants.
DEQ requires an individual water pollution control facility permit for wastewater management if an owner or operator proposes a metal mining activity that processes more than 10,000 cubic yards of ore per year with no discharge to Oregon waters.
This individual permit only applies to a specific operation and location or mining claim.
Applicants should plan on at least six months for permit processing in advance of operating under a new permit. In addition to the application fee and first year annual fee (when required), applicants must submit an individual NPDES permit application at least 60 days before operations are scheduled to start. In addition to a comprehensive application (returned if incomplete), DEQ's permit administration process requires a public comment period of 35 days and will likely require a public hearing with a minimum of 30 days advance notice. If DEQ determines that additional information or measures are needed, there will be an additional 90 days or more added to the process period.
Oregon Administrative Rule 340-075-0075 Permit Fee Schedule - Please see Table 70A for WPCF application fees and Mining Operations in Table 70B for WPCF annual fees due with an application submittal.
Metal mining activity owners or operators may need to also register for permit coverage under additional general stormwater discharge permits.
For off-stream activities, miners often utilize all local water resources including stormwater to fill off-stream ponds (engineered impoundments, excavated pits or natural land depressions) to operate the high bank machine, trommel or powered sluice box. Stormwater may be diverted from mining activities to prevent contact or minimize the volume of contaminated stormwater to manage. Stormwater contacting any mining activity must be managed on site (seepage and evaporation) or an industrial stormwater discharge permit is required.
Program topics and current news is on the NPDES Stormwater Discharge Permits webpage.
Industrial Stormwater General NPDES 1200-Z Permit: DEQ requires an application for this permit. The permit covers potential industrial stormwater discharges to Oregon waters from Standard Industrial Classification Code 10 (SIC 10) metal mining operations if the stormwater will contact mining materials and/or waste (such as overburden, raw material, intermediate product or waste products). DEQ requires a stormwater pollution prevention and control plan with applications for 1200-Z permit coverage.
For information, forms and the general permit for industrial stormwater discharges, visit DEQ's NPDES Stormwater Discharge Permits Industrial Activities webpage.
Construction Stormwater General NPDES 1200-C Permit: DEQ requires a general NPDES 1200-C permit application for potential stormwater discharges from construction activities that will disturb one or more acres with potential stormwater runoff to Oregon waters or conveyance systems (such as a catch basin, storm drain, ditch, pipe, culvert, etc.) leading to state surface waters. Construction activities include clearing, grading, excavation and stockpiling. DEQ also requires an erosion and sediment control plan with this permit application.
For information, forms and the general permit for construction stormwater discharges, visit DEQ's NPDES Stormwater Discharge Permits Construction Activities webpage.


Teams | Bayonne Hockey Association Inc.
In the 2014-2015 season, the BYHA is fielding 9 teams. They are the Bayonne Ranger 2 Mites, 1 Squirt teams, 1 Peewee, 2 Bantam, Midget 16A & Midget 18A travel hockey teams, as well as a Girls beginner team. For further information about these teams, including schedule, roster, and game results, hit the "Team" tab above our banner.


text:
What's Next For Avengers Academy – More Guardians, Inhumans And…X-Men?
by Joe Glass
So the current event (the fifth? Sixth? Of 2017) in mobile casual game Avengers Academy, Legends Assemble, is coming to an end this week, and for players who have managed to unlock Nick Fury, they got some hints at what is to come.
In game, Pepper Potts discusses messages received at the Academy for Fury while he was captured by the evil rival schools. One was hefty mention of messages of outer space, and implications throughout the event have implied that, yes, there will be another Guardians of the Galaxy event allowing players the chance to get new cosmic heroes. What ones those would be hasn't been revealed, but one imagines that new characters appearing in the movie released next week are likely to be around.
Secondly, the is mention of 'Attilan Academy' – so that means Inhumans. So far, the game has only strayed into Inhuman territory as far as NuHuman characters, like Ms. Marvel. It's kind of been surprising given Marvel's heavy push to make Inhumans happen as a property, especially in other media, but this year sees the Inhumans Royals making it to screens big and small, so I guess it's finally time.
Lastly, Potts in game mentions 'hearing a strange voice in my head saying they're ready' to be revealed. And later, in another story interaction, Fury seems alarmed that something from inside one of the Academy's mysterious vaults is trying to get out. When asked what could be stronger than the vibranium they've been using for the doors and repairs, Fury simply replies 'Anything that isn't metal'.
That's not just me? This can only mean Magneto, and X-Men, are finally coming to Avengers Academy.
It's kind of surprising, but for interesting reasons. Previously, Marvel had seemed to eschew using mutants and the X-Men in marketing and promotional materials, seeing mutant characters removed from images used for clothing etc. More recently, and tying into a rebirth of the restrengthening of the X-Men franchise in the comics, X-Men have seen a slowly building return in these other mediums.
However, in some of the various mobile games Marvel has, such as Contest of Champions, X-Men characters have actually regularly been a part of those games since pretty much their inception, from the obvious Wolverine and Deadpool, to characters like Phoenix and Colossus. But despite this little quirk in Marvel's cross-media plans in this platform, mutants had yet to appear in Avengers Academy. Numerous characters that weren't Avengers made it into the game, but never an X-Man.
Well, if these clues are any indication, that may be about to change. And while I am not holding my breath that my absolute fave, Chamber, will make it into the game, it may just be time to start getting excited in this game again.
Posted in: Games, Movies | Tagged: android, avengers, avengers academy, chamber, colossus, deadpool, games, gotg, guardians of the galaxy, inhumans, ios, nick fury, pepper potts, phoenix, rescue, royals, video games, wolverine, x-men
Enjoyed this? Please share on social media!
About Joe Glass
Joe Glass has been contributing to Bleeding Cool for about four years. He's been a roaming reporter at shows like SDCC and NYCC, and also has a keen LGBTQ focus, with his occasional LGBTQ focus articles, Tales from the Four Color Closet. He is also now Bleeding Cool's Senior Mutant Correspondent thanks to his obsession with Marvel's merry mutants. Joe is also a comics creator, writer of LGBTQ superhero team series, The Pride, the first issue of which was one of the Top 25 ComiXology Submit Titles of 2014. He is also a co-writer on Stiffs, a horror comedy series set in South Wales about call centre workers who hunt the undead by night. One happens to be a monkey. Just because.
Comments will load 8 seconds after page. Click here to load them now.
Latest by Joe Glass
2017 Television Countdown #4: The Steven Universe Accidental Racism Apology
This was a curious one. Steven Universe is a hugely popular show with a very dedicated fan base, who are themselves pretty diverse. Much of this comes
Doomsday Clock Speculation: Is Doctor Manhattan Posing as a DC Superhero?
Doomsday Clock #2 from DC Comics by Geoff Johns, Gary Frank, and Brad Anderson comes out and continues the ongoing mystery of just what is the connection of the Watchmen world and the DC Universe — and what is Doctor Manhattan doing. Well, Johns may have added another wrinkle to this mystery with this issue.
Eugenic #3 Review: The Horror Ends with a Look at the Horrors of Ignorance
Review of Eugenic #3 from BOOM! Studios by James Tynion IV, Eryk Donovan, Dee Cunniffe, and Jim Campbell, presenting us with a very real horror more horrifying than blood, guts and murder.
Well, Does Anyone Like the 'Jubilee is a Vampire' Idea?
With today's X-Men Blue, we might just get a hint that it really is the case that absolutely no one likes the 'Jubilee is a vampire' character development.
A Major Unexpected Return in Today's Spider-Men II #5
Spider-Men II #5 comes out from Marvel today, and Brian Michael Bendis and guest artist, longtime collaborator Mark Bagley, mark a surprising return to the Marvel Universe in this issue.
The Controversial Fate of Miles Morales in Spider-Men II Revealed
The final issue of Spider-Men II answers the question of just where Miles Morales will end off, and it may cause a bit of surprise for some readers and fans of the teenage Spider-hero.
Latest in Games
The incredible artists who made Silver Tempest, the final main series Pokémon TCG: Sword & Shield-era set, shine get the spotlight today.
Dragon Ball Super CG Value Watch: Mythic Booster In January 2023
Dragon Ball Super CG Value Watch: Mythic Booster in January 2023 sees this Alt Art/reprint set remain somewhat steady in value.
WWE's Zelina Vega Joins Street Fighter 6 As In-Game Commentator
Thea Trinidad will be joining Street Fighter 6, adding her voice to the commentary team in the game to talk about the fights.
Risen Makes Its Way To All Three Major Consoles
THQ Nordic has officially given Risen a console port as you can play it right now for Xbox, PlayStation, and Switch.
The Pegasus Expedition Announces New Free Content Update
Fulqrum Publishing has dropped a new expansion for The Pegasus Expedition as players can download Scattered Empires right now.
Scorchlands Receives February Early Access Release Date
Scorchlands will be coming to Steam's Early Access on February 7th, giving you a city builder title with a touch of magic.
Latest in Movies
With details soon on James Gunn & Peter Safran's DCU plans, a possible "Amanda Waller" clue feeds our dumpster fires of random speculation.
Avatar: the Way Of Water Becomes #4 All-Time, Passing Force Awakens
Avatar: The Way Of Water is now the fourth highest grossing film ever worldwide, meaning James Cameron owns 3/4 spots in the top 4 himself.
Mia Goth spoke out about the lack of horror nominations at the Academy Awards yet again this year: "A change is necessary"
TMNT Soundtracks Back On Vinyl At Waxwork Records
TMNT fans will want to head over to Waxwork Records and snag the three soundtracks to the live action films before they sell out again.
Kaguya-sama: Love Is War Movie Gets US Theatrical Release Date
Kaguya-sama: Love Is War -The First Kiss That Never Ends-, the feature film spinoff of the popular romantic comedy anime, is getting a Valentine's Day theatrical release in North America.
It's Time To Face The Facts; It Is Way Past Time To Retire The Razzies
After nominating a 12-year-old for no other reason than to be mean, it is time to retire the tired joke that is The Razzies.


Costume Contest – Dress as your favorite Harry Potter character and help your team win the House Cup!
Bring canned goods to donate to the Gringotts Wizarding "Food" Bank. Donations will benefit the Round Rock Serving Center.
Big thanks to our sponsor Friends of Round Rock Public Library for making this program available to the families of Round Rock! The Friends will be joining us at Flourish & Blotts Book Shop in Diagon Ally (located in Meeting Room C). They will be accepting donations of new or gently used children's books to benefit all the muggle children who take part in our Summer Reading Program.


Originally published in the November/December 2014 issue of Life Learning Magazine.
I made a chocolate pudding with a whipped cream topping this past week. Using just coconut milk and semi-sweet chocolate, with some vanilla and rum for added flavour, the pudding tasted and felt more like a mousse than anything--rich and dark and creamy--and was in fact rich enough that none of my family could eat much at a time.
In other words, it would be classified by some as "not good for you," though I think it was an ideal treat, fun to make and eat.
My sister and I, both adults now, have grown into adulthood with remarkably few issues around food. Neither of us have ever dieted, we've never counted calories or gone out of our way to avoid "bad" foods. I care whether the food I'm eating is healthy for me (which is why I tend to avoid soy, which messes with hormone levels), but I also feel strongly that health, when it comes to food and other areas of life, is about our emotional health as well as our physical health, which means that when I get a craving for noodles with fried tofu, the next time I'm at the grocery store I buy a big block of the stuff.
In short, my approach to food is one of listening to my body and mind, and approaching both cooking and eating with an attitude of excitement, fun, and enjoyment.
Guilt or limiting has nothing to do with it.
The fact that my sister has a similar attitude kind of amazes me. Two women from the same house, and both of us have a healthy and joyous relationship with food? In the world we live in, which places a whole lot of pressure and guilt on women especially when it comes to food, I don't think there is a magical set of steps that guarantees children will grow up with a good relationship to food (I certainly have my own set of issues when it comes to other aspects of life, regardless of my upbringing). Some of the reasons are probably as diverse as genetics, the communities we've been a part of, our personalities, and pure chance. However, I feel like some of the ways I was raised created an environment that was conducive to that positive relationship.
Life learning wasn't the sole contributor, for sure. But, I can't help but think that my upbringing did have an impact… We weren't radical unschoolers, we didn't have unlimited access to sweets, and we were generally only allowed to have dessert after supper. I can't really say whether that was a harm or a help, though I have felt that certain foods being "treats" meant that I only really discovered I wasn't so fond of them later in life. Mostly, though, I don't really care about what limits were or weren't placed on food when I was young, since at this point in my life food is such a marvelously positive thing.
I was never told I had to finish what's on my plate. It was okay to stop eating when I was full.
I didn't have to eat if I wasn't hungry. We had regular mealtimes because it was important to my father that he get to eat at certain times, but I didn't have to eat then if I didn't want to.
My mother felt very strongly about never trying to trick us into eating "healthy" food. I never had to look at my meal suspiciously, wondering if something I hated was mixed in there. Any discussions we had about healthy eating were open and honest, and not a matter of manipulation.
My parents never commented about our weight. It just wasn't mentioned. There was no "you need to exercise more, you're getting chubby" or comments about food being too fattening. While my mother might have frequently had insecurities about her own weight, that was never transferred to me or my sister.
My parents very clearly and vocally valued us for things other than our looks. While my grandmother focused very much on prettiness and looks and activities that she deemed appropriately girly (in a well-intentioned though very misguided way), I always had the strong feeling that she was wrong to do so, a feeling that my mother very much validated.
My mother always had great excitement for trying new things. That doesn't mean my sister and I always felt the same. Children especially can be good at being very picky! But both of us did eventually develop a similar love for new flavours, cuisines, and dishes, as well as a love of making exciting new dishes ourselves.
When I started to become really into food, my parents supported that passion. They didn't discourage me from pursuing something so un-academic, or feel that I was wasting my time. Instead they just found me cookbooks, acted as very happy tasters, and encouraged me to pursue more food-related opportunities. They liked seeing me so happy about something, and I don't think it much mattered to them what that something was.
I'm a cook, and I've done some cooking professionally, and I've spent many more hours in my own kitchen. I can tell just how passionate I am about creating tasty food by how exciting a thought it is that no matter how many new dishes I make, there will always be more to try! Food holds a large and important place in my life. I love reading cookbooks and watching cooking shows, talking about food with friends and thinking up new dishes. Cooking is a main artistic outlet for me, and just generally causes a whole bunch of warm and fuzzy feelings.
I'm drawn to the philosophy of "intuitive eating," as it just seems really right to me that most people, if they're never taught to distrust their own bodies, can figure out quite well what and how much is best for them to eat. We're all different, and will all require slightly different fuels in different proportions, guided by personal tastes and preferences and availability. Instead of fighting against an individual's naturally developing relationship with food and eating, telling them that certain foods are bad or "unclean," and introducing a whole bunch of guilt and body shaming into the picture, it seems we would be much better served by always treating food with the respect it deserves. Food is about our physical and emotional health, it's about our cultures and community, it's personal and it's social and it holds and expresses so much history and creativity and innovation. No matter how you look at it, food is important. And if we can embrace it with a sense of joy and discovery from a young age, hopefully it can remain something deeply positive throughout our lives.
My upbringing wasn't perfect. And no matter how good my upbringing was (because it really was pretty good), there are still a lot of negative messages and pressures to be found in our current culture. However, I do think that my parents got some things really right when it came to food, and I'm so grateful for the place it now holds in my life.
I have a beautiful relationship with food, and I think that life learning helped me to develop it.
I'm seeing a tag going around, proclaiming today to be National Start Homeschooling Day. In honour of that, I figured I'd share my top reasons to start unschooling. I understand that, for any number of reasons, unschooling just might not to be doable in your life. If that's the case, I hope you can still glean inspiration for doing your best to devalue standardized assessments and instead place value on passion lead, self directed learning, no matter where it takes place. If, however, you are considering leaving school or taking your kids out of school, I hope these reasons will prove so inspiring that you actually do it!
Forget teachers and standardized curriculum dictating what and how and when you should learn. Instead, learn about whatever really interests you, what you feel is truly important and relevant. Your learning then becomes truly personalized, unique to you and based on what you want and need. You get to spend as much time as you want doing whatever it is that you wished you could be doing instead of sitting in a classroom, bored by the current lecture.
When you control your own learning, timelines of when certain things "should" be learned become irrelevant. Your child isn't a "late" reader, and you're not "behind" in math when you're no longer comparing yourself or your kids to others, based on what the school system thinks you should be learning. Instead, you can learn and grow at your own pace, and in your own way. We all learn differently, and unschooling allows us to truly embrace that.
In school, there are teachers there to impart knowledge, and students attending in order to have knowledge imparted to them. Outside of school, you start to recognize that everyone can fill both of those roles at different times, and that the relationship between those who are teaching and those who are learning can be a cooperative, collaborative, and respectful one.
Parent-child relationships, especially parent-teen relationships, can often be contentious. Fights often revolve around issues of homework, bed time (early school days seem to require one), and other school-related things. When you remove school from the equation, and when parents start striving to trust, respect, and truly listen to their children, relationships can change dramatically, and "teenage rebellion" can become a thing of the past.
The forced socialization of schools, complete with bullies (both other children and sometimes even teachers), a lack of freedom of choice and movement, and an inability to choose more or less socializing based on each individual's needs, does not exactly promote the development of a healthy social life. As an unschooler, socializing can be based on the emotional needs of each child, and you can build a social life that truly feels good to you.
Instead of learning in a single, age segregated building, unschoolers learn in the real world. You can learn at home, in nature, at the library, at museums and community centers and yes, in classes. The world opens up, and you start to see all the myriad opportunities that are all around you for learning that feels relevant and important in your life.
For many students--including LGBTQ people, disabled students, and students with mental illnesses--schools can feel anything but safe or supportive. People learn best and are most creative in their learning when they're not stressed and afraid, so if family life is nurturing and loving, home can make a much better base for learning.
Instead of being pushed to focus constantly, school-free learning leaves plenty of time for relaxing, processing, daydreaming, playing, and quiet introspection. As an unschooler you can reject ideas of "laziness" and choose to value the whole learning process, including boredom, not only the parts that look most active and productive.
When you're not simply studying for a test or producing a project or paper that will never be seen outside of a single classroom, you can instead focus on work and creation that actually feels real. You can volunteer doing important work in your community, get a job or apprentice in a field that fascinates you, write blog posts and articles for an actual audience, create visual art for a community exhibition, and otherwise share yourself with the world. You have the time to do things that feel genuinely meaningful, and that make a real impact on the lives of others.
All of these are compelling reasons why many of us have chosen unschooling for ourselves or our families. I hope that they encourage you to choose a freer, more personalized, more exciting way of approaching learning in your own lives, as well.


text:
L'avion Fiat G.212 est un avion de transport trimoteur à aile basse produit par le constructeur aéronautique italien Fiat Aviazione à la fin des années 1940.

Conçu à l'origine ,au début des années 1940 ,comme version plus grande et plus puissante du Fiat G.12, avec le déclenchement de la Seconde Guerre mondiale, le développement s'arrêta pour redémarrer  seulement à la fin du conflit et son utilisation reprit dans le transport civil avec la compagnie nationale Avio Linee Italiane.

Conception

Le contexte
Au début des années 1940 la direction de Fiat confia à son ingénieur spécialiste en aviation Giuseppe Gabrielli le développement d'un nouvel avion pouvant  transporter  jusqu'à  34 passagers par rapport aux 14 du G.12, tout en cherchant de maintenir  bas les couts de développement ainsi, l'ingénieur lance l'étude du Fiat G.212 en 1943, en tenant compte de l'expérience acquise avec  le Fiat G.12.

Le concept
Le premier prototype du Fiat G.212 nommé G.212 CA était motorisé par trois moteurs Alfa Romeo 128 développant 860 cv

Description technique
Comme son prédécesseur G.12, le Fiat G.212 est, à l'origine, un avion de ligne trimoteur à structure métallique capable de voler à haute altitude. Il se distingue de la production étrangère par son fuselage fin et une aile de grande surface, lui assurant une grande stabilité. Le fuselage, de section rectangulaire et arrondie aux angles supérieurs, est construit en duralumin réunis par des lisses sur lesquelles le revêtement aussi en duralumin est fixé. La cabine de pilotage comprend deux sièges côte-à-côte pour les pilotes, avec double commande. La planche de bord recevait des instruments pour le vol sans visibilité, à savoir un goniomètre et un conservateur de cap. Le mécanicien et le radio sont placés derrière les pilotes. La porte d'accès au fuselage est de forme pentagonale. Les flancs du fuselage du G.212 comprennent 8 hublots rectangulaires, la cabine passagers pouvant accueillir 34 personnes.

Le Fiat G.212 après-guerre
Au printemps 1948, la compagnie Avio Linee Italiane continue ses liaisons Milan-Rome avec les Fiat G.212, après avoir opéré ces liaisons avec les Fiat G.12 CA.

Le , un avion transportant l'équipe du Torino Football Club s'écrase contre la basilique de Superga tuant les 31 occupants.

Utilisateurs

Civils

SAIDE - Services Aériens Internationaux d'Egypte

 Compagnie Air Transport

 Ali Flotte Riunite
 Avio Linee Italiane

 Arabian Desert Airlines

Militaires

 Armée de l'air égyptienne

 Aeronautica Militare

Notes et références

Voir aussi

Bibliographie

Liens externes

Avion trimoteur
Avion construit en Italie
G212
Avion à hélices
Avion de ligne
Avion des années 1940
Moyen-courrier
Premier vol en 1947

redpajama_set_name: RedPajamaWikipedia


A cargo ship collision with a chartered party boat on the River Nile leaves 40 dead. Kemplon Engineering takes a closer look at this tragic news.
On the River Nile, festivities quickly turned into tragedy for a party of about 50 people celebrating a young couple's engagement on a chartered boat. A cargo ship had collided with it during the night, causing the passenger boat to capsize. Initial rescue efforts were made especially difficult by darkness, but continued through to first light and in the succeeding days. As bodies were recovered from the river, the death toll rose to 40. Among the fatalities are young children, including four babies.
It is reported that traffic on the Nile had been heavy at the time of the accident, amidst celebrations of the end of the Ramadan holy month.
In the wake of the accident, the captain and crew from the cargo ship have been detained under suspicion of manslaughter. President Abdel Fattah al-Sissi had also ordered compensation of 80,000 Egyptian pounds ($10,000) to be paid out to aggrieved family members for each victim killed in the accident. Each injured person is also expected to get 10,000 EGP. Furthermore, safety measures have been strengthened and promptly acted upon on the River; a committee has been created to review appropriate legislation, the head of the River Transport Authority has been suspended, and police forces seized boats for a miscellany of river traffic offenses including overloading, operating without appropriate licenses, and for missing vital safety equipment. The crackdown resulted in 134 vessels seized over the span of just 24 hours.
Following an initial investigation, it has been revealed that the party boat was operating with a fake license plate, and had exceeded its maximum passenger capacity. The 90-metre cargo ship that had caused its downfall, on the other hand, had incompatible parts assembled without proper approvals, on top of missing lights and horns, and operating with only three of its required six-man crew. Officials deemed to share in the responsibility for the incident have also been called in by Egyptian General Prosecution.
We at Kemplon Engineering sympathize with those affected by this disaster, and hope for justice for those lost and injured.
For more articles on passenger safety and other topics relating to the maritime industry, explore our blog. If you would like to work on a project with Kemplon Engineering, check out our website for details on the services we can do for marine and industrial customers. We have been in the business of providing engineering solutions – on time and on budget – since 2005, and would love to have the chance to work with you. From welding and fabrication, precision machining, pipe fitting, laser cutting, and more, we have a wide range of capabilities and a great team dedicated to customer satisfaction. Contact us for queries and quotes at info@kemplon.com, or by phone at (877) 522-6526.


Over recent years Charleston Academy pupils and staff have been fortunate to have been able to go on an exciting and diverse range of school trips, exchanges or visits. So much so, that in order to keep track of all the visits our pupils and staff have been on we have created a trips wall map in the foyer that includes all the exciting destinations that we have been to.
Recent trips abroad have seen pupils head off to Belgium, France, the USA, China, India, South Africa, Botswana and Sweden to name but a few.
There also many regular trips closer to home that include Hampden for Football and Murrayfield for Rugby. In 2012 a group of pupils visited the Olympic Stadium.
The dedication and commitment of hard working staff at Charleston Academy and their willingness to give up holiday time as well as class time means that these trips continue.
Please see our News Blog for up to date information on trips and visits.


text:
Windows 10 Free Upgrade Offer Does Not Apply to Pirates
Subject: Windows 10 Free Upgrade Offer Does Not Apply to Pirates Sat May 16, 2015 2:12 pm
http://www.gamespot.com/articles/actually-windows-10-free-upgrade-offer-does-not-ap/1100-6427384/
Earlier this year, Windows executive Terry Myerson said in an interview that all Windows users--even people with pirated copies of the operating system--would be eligible to take advantage of Microsoft Windows 10 free upgrade offer. But as it turns out, this was a misunderstanding. Pirates are out of luck.
"While our free offer to upgrade to Windows 10 will not apply to non-genuine Windows devices, as we've always done, we will continue to offer Windows 10 to customers running devices in a non-genuine state." Myerson said in a blog post published today.
"Non-genuine Windows has a high risk of malware, fraud, public exposure of your personal information, and a higher risk for poor performance or feature malfunctions," he added. "Non-genuine Windows is not supported by Microsoft or a trusted partner."
Myerson did, however, tease that Microsoft is preparing some kind of incentive to get people with non-genuine Windows copies to switch over to a legitimate copy of Windows 10.
"In partnership with some of our valued OEM partners, we are planning very attractive Windows 10 upgrade offers for their customers running one of their older devices in a non-genuine state," he said. "Please stay tuned to learn more from our partners on the specifics of their offers."
As Mary J. Foley of GameSpot sister site Zdnet points out: "Non-genuine Windows copies are not always pirated copies. Sometimes users unknowingly purchase Windows copies that certain resellers or retailers are passing off as legal, which are counterfeit and/or tampered with. Sometimes there are false positives, via which legal copies of Windows show up as illegally licensed."
Per the terms of Microsoft's free Windows 10 upgrade offer, all PCs running Windows 7 and 8 will be eligible for a free upgrade to the new OS for the first twelve months following Windows 10's launch. Microsoft has not yet announced how much Windows 10 will cost after this period.
TJ Ω
#TeamRomie
Location : Where I Shouldn't Be
Subject: Re: Windows 10 Free Upgrade Offer Does Not Apply to Pirates Sat May 16, 2015 3:00 pm


Our general purpose plastic pumps are available in a polypropylene or PVDF housing. Polypropylene is suitable for use with a wide variety of chemical applications. PVDF offers stronger chemical resistance to both acids and bases, while offering a higher temperature and abrasion protection than polypropylene.