# Semana 15: caminos mínimos. 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      antes de empezar: su MinHeap de la semana 13
#   make test-map       paso 1: cargar el mapa
#   make test-dijkstra  paso 2: Dijkstra y la ruta
#   make test-routes    paso 3: BFS frente a Dijkstra
#   make test-stop      paso 4: detenerse al sacar el destino
#   make test-queues    paso 5: std::priority_queue y el arreglo
#   make test-lab     prueba los pasos 1 a 5; falla hasta que los terminen
#   make test-trie    paso 6, opcional: el trie
#   make test-bloom   paso 6, opcional: el filtro de Bloom
#   make compare      paso 3: la tabla para su informe
#   make savings      paso 4: la tabla para su informe
#   make measure      paso 5: la tabla para su informe, con -O2
#   make measure-bloom  paso 6: falsos positivos sobre palabras.txt, con -O2
#   make trie-sizes     paso 6: nodos de un trie, con -O2
#   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
PROGRAMS = dijkstra_trace route_demo distance_range test_structures
BENCHES = dijkstra_counts
COMMON_HEADERS = graph.h traversals.h shortest_paths.h sample_graphs.h map_file.h bench.h
GIVEN_HEADERS = lab/graph.h lab/traversals.h lab/map_file.h lab/not_implemented.h
ROUTE_HEADERS = $(LAB_DIR)/routes.h $(LAB_DIR)/min_heap.h $(GIVEN_HEADERS)
OPTIONAL_HEADERS = $(LAB_DIR)/trie.h $(LAB_DIR)/bloom.h lab/map_file.h
LAB_FLAGS = -I$(LAB_DIR) -Ilab
LAB_BUILD = $(BUILD)/$(LAB_DIR)
LAB_PROGRAMS = lab_tests compare_routes savings
LAB_BENCH = bench_routes
OPTIONAL_PROGRAMS = optional_tests places
OPTIONAL_BENCHES = bloom_measure trie_sizes

.PHONY: all lab optional test test-heap test-map test-dijkstra test-routes test-stop test-queues test-lab \
	test-trie test-bloom compare savings measure measure-bloom trie-sizes 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í los programas toman los archivos de esa carpeta.
$(LAB_PROGRAMS:%=$(LAB_BUILD)/%): $(LAB_BUILD)/%: lab/tests/%.cpp $(ROUTE_HEADERS) | $(LAB_BUILD)
	$(CXX) $(CXXFLAGS) $(LAB_FLAGS) $< -o $@

$(LAB_BENCH:%=$(LAB_BUILD)/%): $(LAB_BUILD)/%: lab/tests/%.cpp bench.h $(ROUTE_HEADERS) | $(LAB_BUILD)
	$(CXX) $(BENCHFLAGS) $(LAB_FLAGS) -I. $< -o $@

$(OPTIONAL_PROGRAMS:%=$(LAB_BUILD)/%): $(LAB_BUILD)/%: lab/tests/%.cpp $(OPTIONAL_HEADERS) | $(LAB_BUILD)
	$(CXX) $(CXXFLAGS) $(LAB_FLAGS) $< -o $@

$(OPTIONAL_BENCHES:%=$(LAB_BUILD)/%): $(LAB_BUILD)/%: lab/tests/%.cpp $(OPTIONAL_HEADERS) | $(LAB_BUILD)
	$(CXX) $(BENCHFLAGS) $(LAB_FLAGS) $< -o $@

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

lab: $(LAB_PROGRAMS:%=$(LAB_BUILD)/%) $(LAB_BENCH:%=$(LAB_BUILD)/%)

optional: $(OPTIONAL_PROGRAMS:%=$(LAB_BUILD)/%) $(OPTIONAL_BENCHES:%=$(LAB_BUILD)/%)

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

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

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

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

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

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

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

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

test-trie: optional
	LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_optional.TestTrie

test-bloom: optional
	LAB_DIR=$(LAB_DIR) python3 -m unittest -v test_optional.TestBloom

compare: $(LAB_BUILD)/compare_routes
	$< $(DATA)/mapas/lima-sur.txt $(DATA)/mapas/lima-sur-calles.tsv lab/tests/fixtures/pares-lima-sur.tsv

savings: $(LAB_BUILD)/savings
	$< $(DATA)/mapas/lima-sur.txt $(DATA)/mapas/lima-sur-calles.tsv "Avenida José Larco"

measure: $(LAB_BUILD)/bench_routes
	$< $(DATA)/mapas/miraflores.txt $(DATA)/mapas/lima-sur.txt $(DATA)/mapas/lima.txt

measure-bloom: $(LAB_BUILD)/bloom_measure
	$< $(DATA)/palabras.txt

trie-sizes: $(LAB_BUILD)/trie_sizes
	$< $(DATA)/mapas/lima-calles.tsv $(DATA)/terminos.tsv $(DATA)/palabras.txt

clean:
	rm -rf $(BUILD) __pycache__
