1
0

vault backup: 2025-12-21 17:17:55
Some checks failed
Deploy Quartz site to GitHub Pages / build (push) Has been cancelled

This commit is contained in:
2025-12-21 17:17:55 +01:00
parent 4b1f9082bf
commit cdfca356c3
220 changed files with 549 additions and 270 deletions

View File

@@ -0,0 +1,120 @@
#!/usr/bin/env bash
set -euo pipefail
# Classify old exam question markdown files and update YAML tags with:
# - exactly one of: anatomi | histologi
# - optionally: öra | öga when confidently detected
#
# Writes an apply_patch patch to STDOUT.
shopt -s nullglob
is_numeric_md() {
local base
base=$(basename "$1")
[[ $base =~ ^[0-9]+\.md$ ]]
}
lower_body() {
# Print lowercased body (after frontmatter) of a markdown file
awk 'BEGIN{infront=0}
/^---$/{c++; if(c==2){infront=0; next} if(c==1){infront=1; next}}
{if(infront==0) print tolower($0)}' "$1"
}
get_front_tags_line() {
sed -n '1,12p' "$1" | awk -F': ' '/^tags:/ {print $2}'
}
get_front_date_line() {
sed -n '1,12p' "$1" | awk '/^date:/{print}'
}
contains_re() {
local content="$1" regex="$2"
perl -0777 -ne "exit(!(/$regex/i))" <<< "$content"
}
append_tag_if_missing() {
local taglist="$1" tag="$2"
# If tag not present as a distinct item, append before closing bracket
if ! perl -e '$_=shift; $t=shift; exit(($_ =~ /(^|[,\[]\s*)\Q$t\E(,|\]|$)/) ? 0 : 1)' \
-- "$taglist" "$tag"; then
# Not present -> append
if [[ "$taglist" =~ ^\[.*\]$ ]]; then
# Ensure proper comma/space formatting
if [[ "$taglist" == "[]" ]]; then
taglist="[${tag}]"
else
if [[ "$taglist" == *"["*"," ]]; then
taglist="${taglist%]} ${tag}]"
else
taglist="${taglist%]} , ${tag}]"
fi
fi
else
# Fallback: create a list
taglist="[${tag}]"
fi
fi
printf '%s' "$taglist"
}
classify_file() {
local f="$1" body eye=0 ear=0 histo=0 unsure=0 anatomi=0
body=$(lower_body "$f")
# Eye keywords
if contains_re "$body" '\\b(retina|cornea|iris|pupill|lins|sclera|choroid|choroidea|ciliar|fovea|macula|syncentrum|n\\.?\\s*opticus|discus\\s+opticus|papilla\\s+opticus|glaskropp|konjunktiva|conjunctiva|muller|müller|tappar|stavar|zonula)\\b'; then eye=1; fi
# Ear keywords
if contains_re "$body" '\\b(öra|örat|öron|mellanörat|innerörat|trumhålan|hörsel|balans|vestibulo|cochle|scala|endolymf|perilymf|båggång|utrikel|saccul|otolit|stapes|malleus|incus|membrana\\s+tympani|auricul|tuba\\s+auditiva|hårcell|stria\\s+vascularis|corti|reissner|basilar)\\b'; then ear=1; fi
# Histology keywords
if contains_re "$body" '\\b(histologi|epitel|kubisk|cylindrisk|skivepitel|flerskiktat|bindväv|kollagen|vävnad|gliacell|astrocyt|oligodend|mikroglia|ependym|purkinje|granularis|molekularis|multiforme|pyramidalis|synaps|axon|dendrit|ganglie|ganglion|cellkärn|cellager|lamina)\\b'; then histo=1; fi
# Image-only uncertainty
if contains_re "$body" '!\\[\\['; then
if ! contains_re "$body" '\\b(thalamus|capsula|cortex|cerebell|nervus|putamen|lobus|ventrikel|pia|dura|arachnoid|ganglie|retina|cornea|iris|pupill|lins|sclera|ciliar|fovea|macula|opticus|cochle|scala|endolymf|perilymf|båggång|utrikel|saccul|otolit|stapes|malleus|incus)\\b'; then
unsure=1
fi
fi
if (( histo == 1 )); then anatomi=0; else anatomi=1; fi
echo "$eye $ear $histo $unsure $anatomi"
}
generate_patch() {
local root="Anatomi & Histologi 2/Gamla tentor" any_changes=0
echo "*** Begin Patch"
: > /tmp/unsure_files_list
while IFS= read -r f; do
is_numeric_md "$f" || continue
read -r eye ear histo unsure anatomi < <(classify_file "$f")
if (( unsure == 1 )); then
echo "$f" >> /tmp/unsure_files_list
continue
fi
oldtags=$(get_front_tags_line "$f")
[[ -z "$oldtags" ]] && continue
newtags="$oldtags"
if (( anatomi == 1 )); then newtags=$(append_tag_if_missing "$newtags" "anatomi"); else newtags=$(append_tag_if_missing "$newtags" "histologi"); fi
if (( ear == 1 )); then newtags=$(append_tag_if_missing "$newtags" "öra"); fi
if (( eye == 1 )); then newtags=$(append_tag_if_missing "$newtags" "öga"); fi
if [[ "$newtags" != "$oldtags" ]]; then
dateline=$(get_front_date_line "$f")
echo "*** Update File: $f"
echo "@@"
echo " ---"
echo "-tags: $oldtags"
echo "+tags: $newtags"
echo " $dateline"
echo " ---"
any_changes=1
fi
done < <(find "$root" -type f -name "*.md" | sort)
echo "*** End Patch"
return $any_changes
}
generate_patch

View File

@@ -0,0 +1,180 @@
#!/usr/bin/env bash
set -euo pipefail
# Classify old exam question markdown files and update YAML tags with:
# - exactly one of: anatomi | histologi
# - optionally: öra | öga when confidently detected
#
# Writes an apply_patch patch to STDOUT.
shopt -s nullglob
shopt -s extglob
is_numeric_md() {
local base
base=$(basename "$1")
[[ $base =~ ^[0-9]+\.md$ ]]
}
lower_body() {
# Print lowercased body (after frontmatter) of a markdown file
awk 'BEGIN{infront=0}
/^---$/{c++; if(c==2){infront=0; next} if(c==1){infront=1; next}}
{if(infront==0) print tolower($0)}' "$1"
}
get_front_tags_line() {
sed -n '1,12p' "$1" | awk -F': ' '/^tags:/ {print $2}'
}
get_front_date_line() {
sed -n '1,12p' "$1" | awk '/^date:/{print}'
}
contains_re() {
local content="$1" regex="$2"
# Use grep -E (ERE), case-insensitive
echo "$content" | grep -Eiq -- "$regex"
}
contains_lit() {
local content="$1" needle="$2"
grep -Fqi -- "$needle" <<< "$content"
}
# Trim leading/trailing spaces
trim() {
local s="$1"
s="${s##+([[:space:]])}"
s="${s%%+([[:space:]])}"
printf '%s' "$s"
}
# Parse YAML inline list like "[a, b, c]" into global array TAGS
parse_tags() {
local list="$1" inner
TAGS=()
inner="$list"
inner="${inner#'[']"; inner="${inner%']'}"
IFS=',' read -r -a raw <<< "$inner"
for tok in "${raw[@]}"; do
# trim spaces
t=$(echo "$tok" | sed -e 's/^\s\+//; s/\s\+$//')
[[ -z "$t" ]] && continue
# de-duplicate keeping order
local found=0
for ex in "${TAGS[@]}"; do [[ "$ex" == "$t" ]] && found=1 && break; done
(( found == 0 )) && TAGS+=("$t")
done
}
has_tag() {
local q="$1"
for ex in "${TAGS[@]}"; do [[ "$ex" == "$q" ]] && return 0; done
return 1
}
add_tag_unique() {
local q="$1"
has_tag "$q" || TAGS+=("$q")
}
remove_tag() {
local q="$1" out=()
for ex in "${TAGS[@]}"; do [[ "$ex" == "$q" ]] || out+=("$ex"); done
TAGS=("${out[@]}")
}
render_tags() {
local out="["
local first=1
for ex in "${TAGS[@]}"; do
if (( first )); then out+="$ex"; first=0; else out+=", $ex"; fi
done
out+="]"
printf '%s' "$out"
}
append_tag_if_missing() {
local taglist="$1" tag="$2"
if ! perl -e '$_=shift; $t=shift; exit(($_ =~ /(^|[,\[]\s*)\Q$t\E(,|\]|$)/) ? 0 : 1)' \
-- "$taglist" "$tag"; then
if [[ "$taglist" =~ ^\[(.*)\]$ ]]; then
local inner
inner=${BASH_REMATCH[1]}
if [[ -z "$inner" ]]; then
taglist="[${tag}]"
else
taglist="[${inner}, ${tag}]"
fi
else
taglist="[${tag}]"
fi
fi
printf '%s' "$taglist"
}
classify_file() {
local f="$1" body eye=0 ear=0 histo=0 unsure=0 anatomi=0
body=$(lower_body "$f")
# Eye keywords
if contains_re "$body" '(retina|cornea|iris|pupill|lins|sclera|choroid|choroidea|ciliar|fovea|macula|syncentrum|n\\.?[[:space:]]*opticus|discus[[:space:]]+opticus|papilla[[:space:]]+opticus|glaskropp|konjunktiva|conjunctiva|muller|müller|tappar|stavar|zonula)'; then eye=1; fi
# Ear keywords
if contains_re "$body" '(öra|örat|öron|mellanörat|innerörat|trumhålan|hörsel|balans|vestibulo|cochle|scala|endolymf|perilymf|båggång|utrikel|saccul|otolit|stapes|malleus|incus|membrana[[:space:]]+tympani|auricul|tuba[[:space:]]+auditiva|hårcell|stria[[:space:]]+vascularis|corti|reissner|basilar)'; then ear=1; fi
# Histology keywords
if contains_re "$body" '(histologi|epitel|kubisk|cylindrisk|skivepitel|flerskiktat|bindväv|kollagen|vävnad|gliacell|astrocyt|oligodend|mikroglia|ependym|purkinje|granularis|molekularis|multiforme|pyramidalis|synaps|axon|dendrit|ganglie|ganglion|cellkärn|cellager|lamina)'; then histo=1; fi
# Image-only uncertainty
if contains_lit "$body" '![['; then
if ! contains_re "$body" '(thalamus|capsula|cortex|cerebell|nervus|putamen|lobus|ventrikel|pia|dura|arachnoid|ganglie|retina|cornea|iris|pupill|lins|sclera|ciliar|fovea|macula|opticus|cochle|scala|endolymf|perilymf|båggång|utrikel|saccul|otolit|stapes|malleus|incus)'; then
unsure=1
fi
fi
if (( histo == 1 )); then anatomi=0; else anatomi=1; fi
echo "$eye $ear $histo $unsure $anatomi"
}
generate_patch() {
local root="Anatomi & Histologi 2/Gamla tentor" any_changes=0
echo "*** Begin Patch"
: > /tmp/unsure_files_list
while IFS= read -r f; do
is_numeric_md "$f" || continue
read -r eye ear histo unsure anatomi < <(classify_file "$f")
if (( unsure == 1 )); then
echo "$f" >> /tmp/unsure_files_list
continue
fi
oldtags=$(get_front_tags_line "$f")
[[ -z "$oldtags" ]] && continue
parse_tags "$oldtags"
# Ensure exactly one of anatomi|histologi
if (( histo == 1 )); then
remove_tag "anatomi"; add_tag_unique "histologi"
else
remove_tag "histologi"; add_tag_unique "anatomi"
fi
# Eye/Ear tags (add if detected)
(( ear == 1 )) && add_tag_unique "öra"
(( eye == 1 )) && add_tag_unique "öga"
newtags=$(render_tags)
if [[ "$newtags" != "$oldtags" ]]; then
dateline=$(get_front_date_line "$f")
echo "*** Update File: $f"
echo "@@"
echo " ---"
echo "-tags: $oldtags"
echo "+tags: $newtags"
echo " $dateline"
echo " ---"
any_changes=1
fi
done < <(find "$root" -type f -name "*.md" | sort)
echo "*** End Patch"
return $any_changes
}
generate_patch