<commit_before>package captcha

import (
	"bytes"
	"crypto/rand"
	"github.com/dchest/uniuri"
	"io"
	"os"
)

// Standard number of digits in captcha.
const StdLength = 6

var globalStore = newStore()

// RandomDigits returns a byte slice of the given length containing random
// digits in range 0-9.
func RandomDigits(length int) []byte {
	d := make([]byte, length)
	if _, err := io.ReadFull(rand.Reader, d); err != nil {
		panic(err)
	}
	for i := range d {
		d[i] %= 10
	}
	return d
}

// New creates a new captcha of the given length, saves it in the internal
// storage, and returns its id.
func New(length int) (id string) {
	id = uniuri.New()
	globalStore.saveCaptcha(id, RandomDigits(length))
	return
}

// Reload generates and remembers new digits for the given captcha id.  This
// function returns false if there is no captcha with the given id.
//
// After calling this function, the image or audio presented to a user must be
// refreshed to show the new captcha representation (WriteImage and WriteAudio
// will write the new one).
func Reload(id string) bool {
	old := globalStore.getDigits(id)
	if old == nil {
		return false
	}
	globalStore.saveCaptcha(id, RandomDigits(len(old)))
	return true
}

// WriteImage writes PNG-encoded image representation of the captcha with the
// given id. The image will have the given width and height.
func WriteImage(w io.Writer, id string, width, height int) os.Error {
	d := globalStore.getDigits(id)
	if d == nil {
		return os.NewError("captcha id not found")
	}
	_, err := NewImage(d, width, height).WriteTo(w)
	return err
}

// WriteAudio writes WAV-encoded audio representation of the captcha with the
// given id.
func WriteAudio(w io.Writer, id string) os.Error {
	d := globalStore.getDigits(id)
	if d == nil {
		return os.NewError("captcha id not found")
	}<commit_msg>Add ErrNotFound, return it from WriteAudio/Image.<commit_after>package captcha

import (
	"bytes"
	"crypto/rand"
	"github.com/dchest/uniuri"
	"io"
	"os"
)

// Standard number of digits in captcha.
const StdLength = 6

var ErrNotFound = os.NewError("captcha with the given id not found")

var globalStore = newStore()

// RandomDigits returns a byte slice of the given length containing random
// digits in range 0-9.
func RandomDigits(length int) []byte {
	d := make([]byte, length)
	if _, err := io.ReadFull(rand.Reader, d); err != nil {
		panic(err)
	}
	for i := range d {
		d[i] %= 10
	}
	return d
}

// New creates a new captcha of the given length, saves it in the internal
// storage, and returns its id.
func New(length int) (id string) {
	id = uniuri.New()
	globalStore.saveCaptcha(id, RandomDigits(length))
	return
}

// Reload generates and remembers new digits for the given captcha id.  This
// function returns false if there is no captcha with the given id.
//
// After calling this function, the image or audio presented to a user must be
// refreshed to show the new captcha representation (WriteImage and WriteAudio
// will write the new one).
func Reload(id string) bool {
	old := globalStore.getDigits(id)
	if old == nil {
		return false
	}
	globalStore.saveCaptcha(id, RandomDigits(len(old)))
	return true
}

// WriteImage writes PNG-encoded image representation of the captcha with the
// given id. The image will have the given width and height.
func WriteImage(w io.Writer, id string, width, height int) os.Error {
	d := globalStore.getDigits(id)
	if d == nil {
		return ErrNotFound
	}
	_, err := NewImage(d, width, height).WriteTo(w)
	return err
}

// WriteAudio writes WAV-encoded audio representation of the captcha with the
// given id.
func WriteAudio(w io.Writer, id string) os.Error {
	d := globalStore.getDigits(id)
	if d == nil {
		return ErrNotFound
	}
{'fraction_non_alphanumeric': 0.10533405172413793, 'fraction_numerical': 0.0026939655172413795, 'mean_word_length': 3.723918575063613, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3332036', 'n_tokens_mistral': 1222, 'n_tokens_neox': 1187, 'n_words': 464}