typetui 0.1.0

A terminal-based typing test.
Documentation
package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

func RunWorkers(n int) {
	var wg sync.WaitGroup
	
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			fmt.Printf("Worker %d starting\n", id)
			time.Sleep(100 * time.Millisecond)
			fmt.Printf("Worker %d done\n", id)
		}(i)
	}
	
	wg.Wait()
}

func ProduceConsume() {
	ch := make(chan int, 10)
	go func() {
		for i := 0; i < 5; i++ {
			ch <- i
			fmt.Println("Produced:", i)
		}
		close(ch)
	}()
	
	for val := range ch {
		fmt.Println("Consumed:", val)
	}
}

func WorkerPool(jobs []int, workers int) []int {
	jobCh := make(chan int, len(jobs))
	resultCh := make(chan int, len(jobs))
	var wg sync.WaitGroup
	for w := 0; w < workers; w++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for job := range jobCh {
				result := job * job
				resultCh <- result
			}
		}()
	}
	
	go func() {
		for _, job := range jobs {
			jobCh <- job
		}
		close(jobCh)
	}()
	
	go func() {
		wg.Wait()
		close(resultCh)
	}()
	
	var results []int
	for r := range resultCh {
		results = append(results, r)
	}
	return results
}

func SelectDemo() {
	ch1 := make(chan string)
	ch2 := make(chan string)
	
	go func() {
		time.Sleep(100 * time.Millisecond)
		ch1 <- "from ch1"
	}()
	
	go func() {
		time.Sleep(200 * time.Millisecond)
		ch2 <- "from ch2"
	}()
	
	select {
	case msg1 := <-ch1:
		fmt.Println(msg1)
	case msg2 := <-ch2:
		fmt.Println(msg2)
	case <-time.After(300 * time.Millisecond):
		fmt.Println("timeout")
	}
}

type Result struct {
	Value int
	Error error
}

func ProcessWithTimeout(ctx context.Context, items []int) ([]Result, error) {
	results := make([]Result, len(items))
	for i, item := range items {
		select {
		case <-ctx.Done():
			return results, ctx.Err()
		default:
			time.Sleep(50 * time.Millisecond)
			results[i] = Result{Value: item * 2}
		}
	}
	return results, nil
}

func Generator(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

func Square(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}

func Merge(chans ...<-chan int) <-chan int {
	var wg sync.WaitGroup
	out := make(chan int)
	
	output := func(c <-chan int) {
		defer wg.Done()
		for n := range c {
			out <- n
		}
	}
	
	wg.Add(len(chans))
	for _, c := range chans {
		go output(c)
	}
	
	go func() {
		wg.Wait()
		close(out)
	}()
	
	return out
}

type SafeCounter struct {
	mu    sync.RWMutex
	count map[string]int
}

func NewSafeCounter() *SafeCounter {
	return &SafeCounter{
		count: make(map[string]int),
	}
}

func (c *SafeCounter) Inc(key string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.count[key]++
}

func (c *SafeCounter) Get(key string) int {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.count[key]
}

type Singleton struct {
	value string
}

var (
	instance *Singleton
	once     sync.Once
)

func GetInstance() *Singleton {
	once.Do(func() {
		instance = &Singleton{value: "initialized"}
	})
	return instance
}

func main() {
	jobs := []int{1, 2, 3, 4, 5}
	results := WorkerPool(jobs, 3)
	fmt.Println("Results:", results)
	nums := Generator(1, 2, 3, 4, 5)
	squares := Square(nums)
	for n := range squares {
		fmt.Println("Square:", n)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
	defer cancel()
	
	items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	res, err := ProcessWithTimeout(ctx, items)
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Println("Processed:", len(res))
}