<commit_before>package manager

import (
	"container/heap"
	"fmt"
	"github.com/tiagofalcao/GoNotebook/log"
	"io"
	"os"
)

// GCJManager manage the io of each GCJ case
type GCJManager struct {
	cases      uint64  // Amount of Cases
	caseTask   GCJCase // case function
	nextCase   uint64  // The Next Case
	pq         outputQueue
	inputLock  chan bool
	caseOutput chan *googleCJCase
	caseNotify chan uint64
	endNotify  chan bool
	Input      io.Reader
	Output     io.Writer
}

// NewGCJManagerIO start the goroutine responsible by manage the io based on case
func NewGCJManagerIO(caseTask GCJCase, input io.Reader, output io.Writer) *GCJManager {
	log.Init(log.DefaultLevel)

	caseOutput := make(chan *googleCJCase, 100)
	caseNotify := make(chan uint64)
	endNotify := make(chan bool)
	inputLock := make(chan bool)

	manager := &GCJManager{
		caseTask:   caseTask,
		nextCase:   1,
		pq:         make(outputQueue, 0, 1),
		inputLock:  inputLock,
		caseOutput: caseOutput,
		caseNotify: caseNotify,
		endNotify:  endNotify,
		Input:      input,
		Output:     output,
	}

	heap.Init(&manager.pq)
	go manager.input()
	return manager
}

// NewGCJManager start the goroutine responsible by manage the io based on case
func NewGCJManager(caseTask GCJCase) *GCJManager {
	var err interface{}
	log.Init(log.DefaultLevel)

	var input *os.File
	if len(OptInput) > 0 {
		log.Debug.Printf("Opening input: %s\n", OptInput)
		input, err = os.Open(OptInput)
		if err != nil {
			panic(err)
		}
		//defer input.Close()
	} else {
		log.Debug.Println("Using stdin")
		input = os.Stdin
	}

	var output *os.File
	if len(OptOutput) > 0 {
		log.Debug.Printf("Opening output: %s\n", OptOutput)
		output, err = os.Create(OptOutput)
		if err != nil {
			panic(err)
		}
		//defer output.Close()
	} else {
		log.Debug.Println("Using stdout")
		output = os.Stdout
	}

	return NewGCJManagerIO(caseTask, input, output)
}

func (manager GCJManager) end() bool {
	return manager.nextCase > manager.cases
}

// Print send a request to print the return of a case
func (manager *GCJManager) Print(caseNum uint64, value string) {
	item := &googleCJCase{
		value:   value,
		caseNum: caseNum,
	}
	manager.caseOutput <- item
}

// WaitCaseEnd wait the end of one case and return the number of this case
func (manager *GCJManager) waitCaseEnd() uint64 {
	return <-manager.caseNotify
}

// WaitEnd wait the end of execution of all cases
func (manager *GCJManager) WaitEnd() {
	<-manager.endNotify
}

// InputUnlock free input to the next execution
func (manager *GCJManager) InputUnlock() {
	manager.inputLock <- true
}

// InputLock free input to the next execution
func (manager *GCJManager) InputLock() {
	<-manager.inputLock
}

func (manager GCJManager) notifyCaseEnd(caseNum uint64) {
	select {
	case manager.caseNotify <- caseNum:
	default:
	}
}

func (manager GCJManager) printCase(item *googleCJCase) {
	fmt.Fprintf(manager.Output, "Case #%d: %s\n", item.caseNum, item.value)
}

func (manager *GCJManager) input() {

	fmt.Fscanf(manager.Input, "%d", &manager.cases)

	go manager.output()<commit_msg>Support newline cases at Code Jam<commit_after>package manager

import (
	"container/heap"
	"fmt"
	"github.com/tiagofalcao/GoNotebook/log"
	"io"
	"os"
	"unicode"
	"unicode/utf8"
)

// GCJManager manage the io of each GCJ case
type GCJManager struct {
	cases      uint64  // Amount of Cases
	caseTask   GCJCase // case function
	nextCase   uint64  // The Next Case
	pq         outputQueue
	inputLock  chan bool
	caseOutput chan *googleCJCase
	caseNotify chan uint64
	endNotify  chan bool
	Input      io.Reader
	Output     io.Writer
}

// NewGCJManagerIO start the goroutine responsible by manage the io based on case
func NewGCJManagerIO(caseTask GCJCase, input io.Reader, output io.Writer) *GCJManager {
	log.Init(log.DefaultLevel)

	caseOutput := make(chan *googleCJCase, 100)
	caseNotify := make(chan uint64)
	endNotify := make(chan bool)
	inputLock := make(chan bool)

	manager := &GCJManager{
		caseTask:   caseTask,
		nextCase:   1,
		pq:         make(outputQueue, 0, 1),
		inputLock:  inputLock,
		caseOutput: caseOutput,
		caseNotify: caseNotify,
		endNotify:  endNotify,
		Input:      input,
		Output:     output,
	}

	heap.Init(&manager.pq)
	go manager.input()
	return manager
}

// NewGCJManager start the goroutine responsible by manage the io based on case
func NewGCJManager(caseTask GCJCase) *GCJManager {
	var err interface{}
	log.Init(log.DefaultLevel)

	var input *os.File
	if len(OptInput) > 0 {
		log.Debug.Printf("Opening input: %s\n", OptInput)
		input, err = os.Open(OptInput)
		if err != nil {
			panic(err)
		}
		//defer input.Close()
	} else {
		log.Debug.Println("Using stdin")
		input = os.Stdin
	}

	var output *os.File
	if len(OptOutput) > 0 {
		log.Debug.Printf("Opening output: %s\n", OptOutput)
		output, err = os.Create(OptOutput)
		if err != nil {
			panic(err)
		}
		//defer output.Close()
	} else {
		log.Debug.Println("Using stdout")
		output = os.Stdout
	}

	return NewGCJManagerIO(caseTask, input, output)
}

func (manager GCJManager) end() bool {
	return manager.nextCase > manager.cases
}

// Print send a request to print the return of a case
func (manager *GCJManager) Print(caseNum uint64, value string) {
	item := &googleCJCase{
		value:   value,
		caseNum: caseNum,
	}
	manager.caseOutput <- item
}

// WaitCaseEnd wait the end of one case and return the number of this case
func (manager *GCJManager) waitCaseEnd() uint64 {
	return <-manager.caseNotify
}

// WaitEnd wait the end of execution of all cases
func (manager *GCJManager) WaitEnd() {
	<-manager.endNotify
}

// InputUnlock free input to the next execution
func (manager *GCJManager) InputUnlock() {
	manager.inputLock <- true
}

// InputLock free input to the next execution
func (manager *GCJManager) InputLock() {
	<-manager.inputLock
}

func (manager GCJManager) notifyCaseEnd(caseNum uint64) {
	select {
	case manager.caseNotify <- caseNum:
	default:
	}
}

func (manager GCJManager) printCase(item *googleCJCase) {
	first, size := utf8.DecodeRuneInString(item.value)
	if size == 0 {
		log.Error.Println("Non utf8 rune")
	}
	if unicode.IsSpace(first) {
		fmt.Fprintf(manager.Output, "Case #%d:%s\n", item.caseNum, item.value)
		return
	}
	fmt.Fprintf(manager.Output, "Case #%d: %s\n", item.caseNum, item.value)
}

func (manager *GCJManager) input() {

	fmt.Fscanf(manager.Input, "%d", &manager.cases)

	go manager.output()
{'fraction_non_alphanumeric': 0.11270908238236674, 'fraction_numerical': 0.0075035172737220575, 'mean_word_length': 3.7710663683818044, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 9, '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': '6508506', 'n_tokens_mistral': 2354, 'n_tokens_neox': 2220, 'n_words': 639}