package main

import (
	"fmt"
	"slices"
	"sync"
	"time"
)

type Hasil struct {
	ID      int
	Kuadrat int
}

func main() {
	const jumlahPekerja = 3
	daftarTugas := []int{1, 2, 3, 4, 5}

	tugas := make(chan int)
	// Buffer seukuran jumlah tugas: pekerja bisa menulis hasil
	// meskipun main masih sibuk mengirim tugas (menghindari deadlock).
	hasil := make(chan Hasil, len(daftarTugas))

	var wg sync.WaitGroup
	for pekerja := 1; pekerja <= jumlahPekerja; pekerja++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for id := range tugas {
				time.Sleep(10 * time.Millisecond) // simulasi kerja
				hasil <- Hasil{ID: id, Kuadrat: id * id}
			}
		}()
	}

	// Sebarkan semua tugas lalu tutup channel tugas agar pekerja berhenti.
	for _, id := range daftarTugas {
		tugas <- id
	}
	close(tugas)

	// Tutup channel hasil setelah semua pekerja selesai.
	go func() {
		wg.Wait()
		close(hasil)
	}()

	// Kumpulkan hasil, lalu urutkan berdasarkan ID agar output deterministik.
	terkumpul := []Hasil{}
	for h := range hasil {
		terkumpul = append(terkumpul, h)
	}
	slices.SortFunc(terkumpul, func(a, b Hasil) int {
		return a.ID - b.ID
	})

	fmt.Println("hasil pekerjaan (terurut berdasarkan ID):")
	for _, h := range terkumpul {
		fmt.Printf("tugas %d → kuadrat %d\n", h.ID, h.Kuadrat)
	}
}
