# Semana 13: heaps y colas de prioridad, heapsort, Huffman. Se usa dentro del entorno del curso.
#
#   make                  compila los programas de la clase en build/
#   make lab              compila el laboratorio en build/lab/
#   make test             corre las pruebas de los ejemplos y de los apuntes
#   make test-heap        prueba MinHeap (paso 1)
#   make test-top         prueba top_k y top_words (paso 3)
#   make test-tree        prueba frecuencias, árbol y códigos (pasos 4 y 5)
#   make test-compress    prueba compress y decompress, con cmp (pasos 5 y 6)
#   make test-lab         prueba todo su laboratorio; falla hasta que lo terminen
#   make bench            construir frente a insertar, con -O2 y sin sanitizers (paso 2)
#   make bench-top        heap de tamaño k frente a ordenar (paso 3)
#   make samples          crea los archivos de prueba en build/samples (paso 6)
#   make roundtrip        comprime, descomprime y compara con cmp cada archivo (paso 6)
#   make bench-compress   cuánto comprime cada archivo (paso 6)
#   make clean            borra lo generado
#
# Los programas de errors/ tienen errores a propósito. No se compilan con make:
# los compilan las pruebas, y ustedes, con los comandos de los apuntes.

CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++20 -g -fsanitize=address,undefined
BENCHFLAGS = -Wall -Wextra -std=c++20 -O2
DATA ?= ../../data
LAB_DIR ?= lab
BUILD = build
LAB_BUILD = $(BUILD)/$(LAB_DIR)
PROGRAMS = heap_demo where_is_max heapsort_demo pq_demo huffman_demo test_structures
BENCHES = build_counts heapsort_counts heapsort_cache heapsort_times top_k_bench
COMMON_HEADERS = int_heap.h heapsort.h bench.h
GIVEN = lab/bit_io.h lab/byte_file.h lab/word_count.h lab/words.h lab/not_implemented.h
LAB_HEADERS = $(LAB_DIR)/min_heap.h $(LAB_DIR)/top_k.h $(LAB_DIR)/huffman.h $(GIVEN)
LAB_INCLUDES = -I$(LAB_DIR) -Ilab
LAB_PROGRAMS = heap_tests huffman_tests top_words compress decompress
LAB_BENCHES = bench_heap bench_top bench_compress
SAMPLES = empty one_byte single_symbol all_bytes random special
SAMPLE_FILES = $(SAMPLES:%=$(BUILD)/samples/%.bin)

.PHONY: all lab samples test test-heap test-top test-tree test-compress test-lab bench bench-top roundtrip bench-compress clean

all: $(PROGRAMS:%=$(BUILD)/%) $(BENCHES:%=$(BUILD)/%)

$(PROGRAMS:%=$(BUILD)/%): $(BUILD)/%: %.cpp $(COMMON_HEADERS) | $(BUILD)
	$(CXX) $(CXXFLAGS) $< -o $@

# Las mediciones van con -O2 y sin sanitizers.
$(BENCHES:%=$(BUILD)/%): $(BUILD)/%: %.cpp $(COMMON_HEADERS) | $(BUILD)
	$(CXX) $(BENCHFLAGS) $< -o $@

# LAB_DIR va primero: así las pruebas toman el código de esa carpeta.
$(LAB_BUILD)/heap_tests: lab/tests/heap_tests.cpp $(LAB_HEADERS) | $(LAB_BUILD)
	$(CXX) $(CXXFLAGS) $(LAB_INCLUDES) $< -o $@

$(LAB_BUILD)/huffman_tests: lab/tests/huffman_tests.cpp $(LAB_HEADERS) | $(LAB_BUILD)
	$(CXX) $(CXXFLAGS) $(LAB_INCLUDES) $< -o $@

$(LAB_BUILD)/top_words $(LAB_BUILD)/compress $(LAB_BUILD)/decompress: $(LAB_BUILD)/%: $(LAB_DIR)/%.cpp $(LAB_HEADERS) | $(LAB_BUILD)
	$(CXX) $(CXXFLAGS) $(LAB_INCLUDES) $< -o $@

$(LAB_BENCHES:%=$(LAB_BUILD)/%): $(LAB_BUILD)/%: lab/tests/%.cpp $(LAB_HEADERS) bench.h | $(LAB_BUILD)
	$(CXX) $(BENCHFLAGS) $(LAB_INCLUDES) -I. $< -o $@

$(BUILD)/make_samples: lab/tests/make_samples.cpp | $(BUILD)
	$(CXX) $(BENCHFLAGS) $< -o $@

$(SAMPLE_FILES) &: $(BUILD)/make_samples
	mkdir -p $(BUILD)/samples
	$(BUILD)/make_samples $(BUILD)/samples

samples: $(SAMPLE_FILES)

$(BUILD) $(LAB_BUILD):
	mkdir -p $@

lab: $(LAB_PROGRAMS:%=$(LAB_BUILD)/%) $(LAB_BENCHES:%=$(LAB_BUILD)/%) samples

# Si existe solution/, también se comprueba la solución del laboratorio.
test: all samples
	@if [ -d solution ]; then $(MAKE) --no-print-directory LAB_DIR=solution lab; fi
	DATA=$(DATA) python3 -m unittest discover -p 'test_*.py'

test-heap: lab
	DATA=$(DATA) LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_lab.TestHeap

test-top: lab
	DATA=$(DATA) LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_lab.TestTop

test-tree: lab
	DATA=$(DATA) LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_lab.TestTree

test-compress: lab
	DATA=$(DATA) LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_lab.TestCompress

test-lab: all lab
	DATA=$(DATA) LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_lab

bench: $(LAB_BUILD)/bench_heap
	$<

bench-top: $(LAB_BUILD)/bench_top
	$< $(DATA)/tradiciones.txt

roundtrip: $(LAB_BUILD)/compress $(LAB_BUILD)/decompress samples
	lab/tests/roundtrip.sh $(LAB_BUILD) $(SAMPLE_FILES) lab/tests/fixture.txt $(DATA)/tradiciones.txt

bench-compress: $(LAB_BUILD)/bench_compress samples
	$< $(SAMPLE_FILES) $(DATA)/tradiciones.txt $(DATA)/terminos.tsv $(DATA)/palabras.txt

clean:
	rm -rf $(BUILD) __pycache__
