2026-02-13 22:08:22 +01:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
#
|
2026-02-16 14:25:45 +01:00
|
|
|
# print_questions.sh — Convert and print exam questions from questions/ folder
|
2026-02-13 22:08:22 +01:00
|
|
|
#
|
|
|
|
|
# Usage:
|
|
|
|
|
# ./print_questions.sh [OPTIONS] [QUESTION_NUMBERS...]
|
|
|
|
|
#
|
|
|
|
|
# Examples:
|
|
|
|
|
# ./print_questions.sh # Generate PDF of ALL questions
|
|
|
|
|
# ./print_questions.sh 1 # Generate PDF of question 1
|
|
|
|
|
# ./print_questions.sh 1 3 7 # Generate PDF of questions 1, 3, 7
|
|
|
|
|
# ./print_questions.sh 1-5 # Generate PDF of questions 1 through 5
|
|
|
|
|
# ./print_questions.sh 1 3-5 8 # Mix of individual and ranges
|
|
|
|
|
# ./print_questions.sh --print 1 3 # Generate PDF AND print questions 1, 3
|
|
|
|
|
# ./print_questions.sh --print # Generate PDF AND print ALL questions
|
|
|
|
|
# ./print_questions.sh --list # List available questions
|
|
|
|
|
#
|
|
|
|
|
# Options:
|
|
|
|
|
# --print, -p Send to printer after generating PDF
|
|
|
|
|
# --printer NAME Printer name (default: Brother_HL-1110_series)
|
|
|
|
|
# --list, -l List available questions and exit
|
|
|
|
|
# --output, -o FILE Output PDF path (default: auto-generated in /tmp)
|
|
|
|
|
# --keep, -k Keep intermediate files (for debugging)
|
|
|
|
|
# --help, -h Show this help
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
# ── Configuration ──────────────────────────────────────────────────────────────
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
2026-02-16 14:25:45 +01:00
|
|
|
QUESTIONS_DIR="${SCRIPT_DIR}/questions"
|
2026-02-13 22:08:22 +01:00
|
|
|
PRINTER="Brother_HL-1110_series"
|
|
|
|
|
DO_PRINT=false
|
|
|
|
|
LIST_ONLY=false
|
|
|
|
|
KEEP_TMP=false
|
|
|
|
|
OUTPUT_PDF=""
|
|
|
|
|
QUESTIONS=()
|
|
|
|
|
|
|
|
|
|
# ── Parse arguments ───────────────────────────────────────────────────────────
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
|
case "$1" in
|
|
|
|
|
--print|-p)
|
|
|
|
|
DO_PRINT=true
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--printer)
|
|
|
|
|
PRINTER="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--list|-l)
|
|
|
|
|
LIST_ONLY=true
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--output|-o)
|
|
|
|
|
OUTPUT_PDF="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--keep|-k)
|
|
|
|
|
KEEP_TMP=true
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--help|-h)
|
|
|
|
|
head -28 "$0" | tail -26
|
|
|
|
|
exit 0
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
# Parse question numbers and ranges (e.g., "1", "3-5", "13/27")
|
|
|
|
|
if [[ "$1" =~ ^[0-9]+(\/[0-9]+)?(-[0-9]+(\/[0-9]+)?)?$ ]]; then
|
|
|
|
|
if [[ "$1" == *-* ]]; then
|
|
|
|
|
# Range: extract start-end
|
|
|
|
|
range_start="${1%%-*}"
|
|
|
|
|
range_end="${1##*-}"
|
|
|
|
|
for ((i=range_start; i<=range_end; i++)); do
|
|
|
|
|
QUESTIONS+=("$i")
|
|
|
|
|
done
|
|
|
|
|
else
|
|
|
|
|
QUESTIONS+=("$1")
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
echo "Error: Unknown argument '$1'. Use --help for usage." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
# ── Verify questions directory ────────────────────────────────────────────────
|
|
|
|
|
if [[ ! -d "$QUESTIONS_DIR" ]]; then
|
|
|
|
|
echo "Error: Questions directory not found: $QUESTIONS_DIR" >&2
|
|
|
|
|
echo "Run split_questions.py first to generate per-question files." >&2
|
2026-02-13 22:08:22 +01:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
# ── Helper: find question file by number ──────────────────────────────────────
|
|
|
|
|
# Matches question number against filenames like pytanie_01.md, pytanie_13_27.md
|
|
|
|
|
find_question_file() {
|
|
|
|
|
local num="$1"
|
|
|
|
|
local padded
|
|
|
|
|
padded=$(printf "%02d" "$num")
|
|
|
|
|
|
|
|
|
|
# Try exact match: pytanie_NN.md
|
|
|
|
|
local exact="${QUESTIONS_DIR}/pytanie_${padded}.md"
|
|
|
|
|
if [[ -f "$exact" ]]; then
|
|
|
|
|
echo "$exact"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Try dual-numbered: pytanie_NN_MM.md (match either side)
|
|
|
|
|
for f in "${QUESTIONS_DIR}"/pytanie_*_*.md; do
|
|
|
|
|
[[ -f "$f" ]] || continue
|
|
|
|
|
local base
|
|
|
|
|
base=$(basename "$f" .md)
|
|
|
|
|
# Extract numbers from pytanie_NN_MM
|
|
|
|
|
local nums="${base#pytanie_}"
|
|
|
|
|
local left="${nums%%_*}"
|
|
|
|
|
local right="${nums##*_}"
|
|
|
|
|
if [[ "$padded" == "$left" || "$padded" == "$right" ]]; then
|
|
|
|
|
echo "$f"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 22:08:22 +01:00
|
|
|
# ── List questions ────────────────────────────────────────────────────────────
|
|
|
|
|
list_questions() {
|
2026-02-16 14:25:45 +01:00
|
|
|
echo "Available questions in ${QUESTIONS_DIR}/"
|
2026-02-13 22:08:22 +01:00
|
|
|
echo ""
|
2026-02-16 14:25:45 +01:00
|
|
|
for f in "${QUESTIONS_DIR}"/pytanie_*.md; do
|
|
|
|
|
[[ -f "$f" ]] || continue
|
|
|
|
|
# Read first line to get the header
|
|
|
|
|
local header
|
|
|
|
|
header=$(head -1 "$f")
|
|
|
|
|
local num title
|
|
|
|
|
num=$(echo "$header" | sed 's/^## PYTANIE \([0-9/]*\):.*/\1/')
|
|
|
|
|
title=$(echo "$header" | sed 's/^## PYTANIE [0-9/]*: //')
|
2026-02-13 22:08:22 +01:00
|
|
|
printf " %6s %s\n" "$num" "$title"
|
|
|
|
|
done
|
|
|
|
|
echo ""
|
2026-02-16 14:25:45 +01:00
|
|
|
echo "Total: $(ls -1 "${QUESTIONS_DIR}"/pytanie_*.md 2>/dev/null | wc -l) questions"
|
2026-02-13 22:08:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if $LIST_ONLY; then
|
|
|
|
|
list_questions
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
# ── Assemble selected questions ───────────────────────────────────────────────
|
|
|
|
|
assemble_questions() {
|
2026-02-13 22:08:22 +01:00
|
|
|
local selected=("$@")
|
|
|
|
|
|
|
|
|
|
if [[ ${#selected[@]} -eq 0 ]]; then
|
2026-02-16 14:25:45 +01:00
|
|
|
# All questions — concatenate all files in order
|
|
|
|
|
local first=true
|
|
|
|
|
for f in "${QUESTIONS_DIR}"/pytanie_*.md; do
|
|
|
|
|
[[ -f "$f" ]] || continue
|
|
|
|
|
if ! $first; then
|
|
|
|
|
echo ""
|
|
|
|
|
echo "\\newpage"
|
|
|
|
|
echo ""
|
|
|
|
|
fi
|
|
|
|
|
first=false
|
|
|
|
|
cat "$f"
|
|
|
|
|
done
|
2026-02-13 22:08:22 +01:00
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
# Selected questions
|
2026-02-13 22:08:22 +01:00
|
|
|
local first=true
|
2026-02-16 14:25:45 +01:00
|
|
|
local found_any=false
|
2026-02-13 22:08:22 +01:00
|
|
|
for sel in "${selected[@]}"; do
|
2026-02-16 14:25:45 +01:00
|
|
|
local qfile
|
|
|
|
|
if qfile=$(find_question_file "$sel"); then
|
|
|
|
|
found_any=true
|
|
|
|
|
if ! $first; then
|
|
|
|
|
echo ""
|
|
|
|
|
echo "\\newpage"
|
|
|
|
|
echo ""
|
2026-02-13 22:08:22 +01:00
|
|
|
fi
|
2026-02-16 14:25:45 +01:00
|
|
|
first=false
|
|
|
|
|
cat "$qfile"
|
|
|
|
|
else
|
|
|
|
|
echo "Warning: Question $sel not found, skipping." >&2
|
|
|
|
|
fi
|
2026-02-13 22:08:22 +01:00
|
|
|
done
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
if ! $found_any; then
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
2026-02-13 22:08:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ── Generate output filename ─────────────────────────────────────────────────
|
|
|
|
|
if [[ -z "$OUTPUT_PDF" ]]; then
|
|
|
|
|
if [[ ${#QUESTIONS[@]} -eq 0 ]]; then
|
|
|
|
|
OUTPUT_PDF="/tmp/obrona_all_questions.pdf"
|
|
|
|
|
elif [[ ${#QUESTIONS[@]} -eq 1 ]]; then
|
|
|
|
|
OUTPUT_PDF="/tmp/obrona_q${QUESTIONS[0]}.pdf"
|
|
|
|
|
else
|
|
|
|
|
joined=$(IFS=_; echo "${QUESTIONS[*]}")
|
2026-02-16 12:41:12 +01:00
|
|
|
joined="${joined//\//-}" # Replace / with - for safe filenames
|
2026-02-13 22:08:22 +01:00
|
|
|
OUTPUT_PDF="/tmp/obrona_q${joined}.pdf"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ── Create temporary markdown ────────────────────────────────────────────────
|
|
|
|
|
TMP_DIR=$(mktemp -d)
|
|
|
|
|
TMP_MD="${TMP_DIR}/questions.md"
|
|
|
|
|
|
2026-02-16 14:25:45 +01:00
|
|
|
if ! assemble_questions "${QUESTIONS[@]}" > "$TMP_MD"; then
|
|
|
|
|
echo "Error: No matching questions found for: ${QUESTIONS[*]}" >&2
|
|
|
|
|
echo "Use --list to see available questions." >&2
|
|
|
|
|
rm -rf "$TMP_DIR"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2026-02-13 22:08:22 +01:00
|
|
|
|
|
|
|
|
# Count extracted questions
|
|
|
|
|
extracted=$(grep -c "^## PYTANIE" "$TMP_MD" || echo "0")
|
|
|
|
|
if [[ "$extracted" -eq 0 ]]; then
|
|
|
|
|
echo "Error: No matching questions found for: ${QUESTIONS[*]}" >&2
|
|
|
|
|
echo "Use --list to see available questions." >&2
|
|
|
|
|
rm -rf "$TMP_DIR"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ── Convert to PDF via pandoc + xelatex ───────────────────────────────────────
|
|
|
|
|
echo "Converting $extracted question(s) to PDF..."
|
|
|
|
|
|
|
|
|
|
pandoc "$TMP_MD" \
|
|
|
|
|
-o "$OUTPUT_PDF" \
|
|
|
|
|
--pdf-engine=xelatex \
|
2026-02-16 14:25:45 +01:00
|
|
|
--resource-path="${SCRIPT_DIR}" \
|
2026-02-13 22:08:22 +01:00
|
|
|
-V geometry:a4paper \
|
|
|
|
|
-V geometry:margin=1.8cm \
|
|
|
|
|
-V fontsize=12pt \
|
|
|
|
|
-V mainfont="DejaVu Sans" \
|
|
|
|
|
-V sansfont="DejaVu Sans" \
|
|
|
|
|
-V monofont="DejaVu Sans Mono" \
|
|
|
|
|
-V linestretch=1.15 \
|
|
|
|
|
-V colorlinks=false \
|
|
|
|
|
--highlight-style=monochrome \
|
|
|
|
|
-V header-includes='\usepackage{fancyhdr}\pagestyle{fancy}\fancyhead[L]{\small Obrona magisterska}\fancyhead[R]{\small\thepage}\fancyfoot{}' \
|
|
|
|
|
-V header-includes='\usepackage{enumitem}\setlist{nosep,leftmargin=*}' \
|
|
|
|
|
-V header-includes='\renewcommand{\arraystretch}{1.3}' \
|
|
|
|
|
-V header-includes='\usepackage{booktabs}' \
|
|
|
|
|
2>/dev/null
|
|
|
|
|
|
|
|
|
|
echo "PDF generated: $OUTPUT_PDF"
|
|
|
|
|
echo " Pages: $(pdfinfo "$OUTPUT_PDF" 2>/dev/null | grep Pages | awk '{print $2}' || echo "?")"
|
|
|
|
|
|
|
|
|
|
# ── Print ─────────────────────────────────────────────────────────────────────
|
|
|
|
|
if $DO_PRINT; then
|
|
|
|
|
if ! lpstat -p "$PRINTER" &>/dev/null; then
|
|
|
|
|
echo "Error: Printer '$PRINTER' not found." >&2
|
|
|
|
|
echo "Available printers:" >&2
|
|
|
|
|
lpstat -p 2>/dev/null | awk '{print " " $2}' >&2
|
|
|
|
|
rm -rf "$TMP_DIR"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "Printing to $PRINTER..."
|
|
|
|
|
lp -d "$PRINTER" \
|
|
|
|
|
-o media=A4 \
|
|
|
|
|
-o sides=one-sided \
|
|
|
|
|
-o fit-to-page \
|
|
|
|
|
"$OUTPUT_PDF"
|
|
|
|
|
echo "Print job submitted."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ── Cleanup ───────────────────────────────────────────────────────────────────
|
|
|
|
|
if $KEEP_TMP; then
|
|
|
|
|
echo "Temporary files kept in: $TMP_DIR"
|
|
|
|
|
else
|
|
|
|
|
rm -rf "$TMP_DIR"
|
|
|
|
|
fi
|