diff --git a/bin/bamc b/bin/bamc index 35b32c9..4871d39 100755 --- a/bin/bamc +++ b/bin/bamc @@ -1,34 +1,38 @@ #!/bin/bash # Set SNAME, SDIR and SPATH if [ -h $0 ]; then SNAME=$(readlink $0); else SNAME=$0; fi SDIR=$(dirname $SNAME) if [[ "$SDIR" =~ ^/ ]]; then SPATH=$SDIR; else SPATH=$(realpath $(pwd)/$SDIR); fi # Set DIR_LIB DIR_LIB=$(realpath $SPATH/../lib/bash) # Source libs source $DIR_LIB/tools.sh source $DIR_LIB/colors.sh source $DIR_LIB/io.sh source $DIR_LIB/debugging.sh source $DIR_LIB/cmdline_parser.sh source $DIR_LIB/bamc_configuration.sh source $DIR_LIB/bamc_sanity.sh source $DIR_LIB/bamc_help.sh source $DIR_LIB/bamc_workspace.sh +source $DIR_LIB/bamc_questions.sh source $DIR_LIB/bamc_exams.sh source $DIR_LIB/bamc_templates.sh source $DIR_LIB/bamc_projects.sh source $DIR_LIB/bamc_amc-commands.sh +# Set some variables DEFAULT_ITEMS=$(get_exam_list) DEFAULT_ACTIONS="help" CALLBACK_PREFIX="action_" +# Run! run $@ -RC=$? -debug "Return code: $RC" -exit $RC +# RIP +exit $? + +#EOF diff --git a/conf/bamc.conf b/conf/bamc.conf index 9362ef2..1fcddd7 100644 --- a/conf/bamc.conf +++ b/conf/bamc.conf @@ -1,55 +1,56 @@ #!/bin/bash # Worspace DIR_QUESTIONS='questions' DIR_EXAMS='exams' DIR_PROJECTS='projects' FILE_WORKSPACE_ROOT=".workspace_root" # Configuration dirs DIR_DATA=$(realpath $SPATH/../data) DIR_WORKSPACE_TEMPLATE=$DIR_DATA/workspace DIR_EXAM_TEMPLATES=$DIR_DATA/templates # Template DEFAULT_EXAM_TEMPLATE="default" FILE_PROJECT_BUILD="project_build_script.sh" # Configuration files FILE_AMC_OPTIONS='options.xml' # Output dirs DIR_PROJECTS='projects' DIR_SAMPLES='pdf-samples' +DIR_CATALOGS='pdf-catalogs' DIR_BLANKS='pdf-blanks' DIR_PDFS='pdf-exams' DIR_LISTS='pdf-lists' # Intput files FILE_SECTIONS='sections.conf' FILE_EXAM='exam.conf' FILE_STUDENTS='students.csv' # Variables EXTRA_STUDENTS=9 PDFLATEX_RUNS=1 return 0 FILE_SAMPLE_CSV='sample.csv' FILE_EXTRA_CSV='extra.csv' FILE_BLANK_CSV='blank.csv' FILE_AMC_MAILING='mailing.xml' FILE_LIST_MAIN='list.tex' FILE_LIST_TSTART='start_tab.tex' FILE_LIST_TEND='end_tab.tex' # OUTPUT FILES FILE_RESULTS='raw' FILE_EMAILS_SCRIPT='send_emails.sh' FILE_LIST_ROWS='rows.tex' # VARIABLES DEFAULT_EMAIL='pierre-olivier.valles@epfl.ch' LIST_ROWS_PER_PAGE=50 LIST_MAX_CHAR=30 diff --git a/data/templates/maths/project_build_script.sh b/data/templates/maths/project_build_script.sh index 35e182f..ad2b79e 100644 --- a/data/templates/maths/project_build_script.sh +++ b/data/templates/maths/project_build_script.sh @@ -1,225 +1,217 @@ #!/bin/bash # This part is specific to the template. # Entry point from bamc: build_project $exam # $exam: name of the exam to build # # Useful variable # --------------- # DIR_WORKSPACE [current workspace dir (absolute)] # DIR_PROJECTS [projects target directory] # DIR_EXAMS [exams'directory in workspace] e.g. $DIR_WORKSPACE/$DIR_EXAMS/$exam # DIR_PROJECTS [projects's directory in workspace] # DIR_EXAM_TEMPLATE [directory of the exam template in use] # FILE_STUDENTS # ... # see 'conf/bamc.conf' for full reference # # Useful functions # ---------------- # verbose "text" # debug "text" # get_lang $exam # ... # see 'lib/bash/*.sh' files for full reference function build_project() { local exam=$1 lang=$(get_lang $exam) assert_exam $exam verbose "Project '$exam' uses '$lang' language" if [ $? -eq 1 ]; then return 1; fi verbose "Building AMC project for '$exam' in workspace '$DIR_WORKSPACE'..." # Project structure build_amc_project $exam if [ $? -ne 0 ]; then error "Could not build AMC project :("; return 1; fi # Build LaTeX sections build_sections $exam $lang if [ $? -ne 0 ]; then error "Could not build project sections :("; return 1; fi # Import LaTeX files import_tex_files $exam $lang if [ $? -ne 0 ]; then error "Could not import LaTeX files :("; return 1; fi # Import local LaTeX files override_tex_files $exam if [ $? -ne 0 ]; then error "Could not override LaTeX files :("; return 1; fi # Customize LaTeX file customize_tex_files $exam $lang if [ $? -ne 0 ]; then error "Could not customize LaTeX files :("; return 1; fi # Import media files add_media_files $exam if [ $? -ne 0 ]; then error "Could not import media files :("; return 1; fi # Build student list file import_student_file $exam if [ $? -ne 0 ]; then error "Could not create student list :("; return 1; fi return 0 } function import_student_file() { - verbose "Customizing LaTeX files" + verbose "Customizing student files" local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local exam=$DIR_WORKSPACE/$DIR_EXAMS/$1 local lang=$2 local FILE=$exam/$FILE_STUDENTS check_file_exists $FILE if [ $? -ne 0 ]; then return 1; fi cp $FILE $project/$FILE_STUDENTS # Add extra students local nb IFS=$'\n' local id=$(tail -n 1 $project/$FILE_STUDENTS | cut -d ',' -f 1) local sample=$(head -n 1 $DIR_EXAM_TEMPLATE/csv/extra.csv) nb=0 while [ $nb -lt $EXTRA_STUDENTS ]; do ((nb++)) ((id++)) echo $sample |\ sed "s/#NB#/$nb/g" |\ sed "s/#ID#/$id/g" |\ sed "s/#SCIPER#/FAKE-$nb/g" |\ sed "s/#EMAIL#/$DEFAULT_EMAIL/g" |\ sed "s/#SEMESTER#/$SEMESTER/g" >> $project/$FILE_STUDENTS done return 0 } function add_media_files() { verbose "Importing media files" local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 cp $DIR_EXAM_TEMPLATE/media/* $project/media/ } function replace_in_file() { local pattern=$1 string=$2 filename=$3 - sed "s/$pattern/$string/g" $filename > /tmp/sed.tmp.$$ + sed "s?$pattern?$string?g" $filename > /tmp/sed.tmp.$$ mv /tmp/sed.tmp.$$ $filename return 0 } function customize_tex_files() { verbose "Customizing LaTeX files" local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local exam=$DIR_WORKSPACE/$DIR_EXAMS/$1 local lang=$2 local replace IFS=$'\n' local FILE=$exam/$FILE_EXAM check_file_exists $FILE if [ $? -ne 0 ]; then return 1; fi # professor.tex local prof_file=$project/professor.tex check_file_exists $prof_file if [ $? -ne 0 ]; then return 1; fi for replace in $(cat $FILE); do replace_in_file "#$(echo $replace | cut -d ':' -f 1)#" "$(echo $replace | cut -d ':' -f 2-)" $prof_file done # exam.tex replace_in_file "#LANG#" $(echo $lang | tr '[a-z]' '[A-Z]') $project/exam.tex # Add extra_section.tex file if [ -r $exam/extra_section.tex ]; then - sed -i 's?% #EXTRA_SECTION#?\\input{./extra_section.tex}?g' $project/exam.tex + replace_in_file '% #EXTRA_SECTION#' '\\input{./extra_section.tex}' $project/exam.tex fi # Add extra_packages.tex file if [ -r $exam/extra_packages.tex ]; then - sed -i 's?% #EXTRA_PACKAGES#?\\input{./extra_packages.tex}?g' $project/exam.tex + replace_in_file '% #EXTRA_PACKAGES#' '\\input{./extra_packages.tex}' $project/exam.tex fi return 0 } function override_tex_files() { verbose "Overriding LaTeX files (if needed)" local exam=$DIR_WORKSPACE/$DIR_EXAMS/$1 local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local f for f in $(find $exam/ -type f -name '*.tex'); do verbose "- LaTeX override file found: $f" done find $exam/ -type f -name '*.tex' -exec cp {} $project/ \; } function import_tex_files() { verbose "Importing LaTeX files" local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local lang=$2 cp $DIR_EXAM_TEMPLATE/base/* $project/ cp $DIR_EXAM_TEMPLATE/$lang/* $project/ return 0 } function build_amc_project() { local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 verbose "Creating AMC project structure" mkdir -p $project/cr/corrections/jpg mkdir -p $project/cr/corrections/pdf mkdir -p $project/cr/diagnostic mkdir -p $project/cr/zooms mkdir -p $project/data mkdir -p $project/exports mkdir -p $project/scans mkdir -p $project/copies mkdir -p $project/media cp $DIR_EXAM_TEMPLATE/config/$FILE_AMC_OPTIONS $project/$FILE_AMC_OPTIONS return $? } -function get_exam_parameter() { - cat $DIR_WORKSPACE/$DIR_EXAMS/$1/$FILE_EXAM | grep "^$2:" | cut -d ':' -f 2- -} - -function get_lang() { - get_exam_parameter $1 'LANG' -} - function build_sections() { local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local exam=$DIR_WORKSPACE/$DIR_EXAMS/$1 local lang=$2 local question_file question section_file section local IFS=$'\n' FILE=$exam/$FILE_SECTIONS verbose "Importing questions" check_file_exists $FILE if [ $? -ne 0 ]; then return 1; fi local section_num=0 rm -f $project/sections.tex $project/random-sections.tex for section in $(cat $FILE); do ((section_num++)) section_file=$project/section_${section_num}.tex rm -f $section_file for question in $(echo $section | tr ',' '\n'); do verbose "Adding $question to section $section_file..."; question_file=$DIR_WORKSPACE/$DIR_QUESTIONS/$lang/$question check_file_exists $question_file if [ $? -ne 0 ]; then return 1; fi echo "%% From $lang/$question =======================================" >> $section_file echo '\element{section'$section_num'}{' >> $section_file cat $question_file >> $section_file echo '}' >> $section_file done echo "\input{./section_${section_num}.tex}" >> $project/sections.tex echo "\input{./header_${section_num}.tex} \melangegroupe{section${section_num}} \restituegroupe{section${section_num}} " >> $project/random-sections.tex done return 0 } # EOF diff --git a/lib/bash/bamc_amc-commands.sh b/lib/bash/bamc_amc-commands.sh index 661de6b..e2e9d26 100644 --- a/lib/bash/bamc_amc-commands.sh +++ b/lib/bash/bamc_amc-commands.sh @@ -1,128 +1,168 @@ #!/bin/bash +function action_exam() { + local rc=0 + while [ $# -gt 0 ]; do + local item=$1 + local project=$DIR_WORKSPACE/$DIR_PROJECTS/$item + local lang=$(get_lang $item) + amc_prepare $item "exam" + if [ $? -eq 0 ]; then + mkdir -p $DIR_WORKSPACE/$DIR_PDFS + mv $project/EXAM-exam.pdf $DIR_WORKSPACE/$DIR_PDFS/EXAM-${lang}-${item}.pdf + mv $project/EXAM-correction.pdf $DIR_WORKSPACE/$DIR_PDFS/EXAM-CORRECTION-${lang}-${item}.pdf + amc_clean $item + else + ((rc++)) + fi + shift + done + return $rc; +} + + function action_blank() { local rc=0 while [ $# -gt 0 ]; do local item=$1 local project=$DIR_WORKSPACE/$DIR_PROJECTS/$item local lang=$(get_lang $item) amc_prepare $item "blank" if [ $? -eq 0 ]; then mkdir -p $DIR_WORKSPACE/$DIR_BLANKS mv $project/BLANK-exam.pdf $DIR_WORKSPACE/$DIR_BLANKS/BLANK-${lang}-${item}.pdf amc_clean $item else ((rc++)) fi shift done return $rc; } +function action_catalog() { + local rc=0 + while [ $# -gt 0 ]; do + local item=$1 + local project=$DIR_WORKSPACE/$DIR_PROJECTS/$item + local lang=$(get_lang $item) + amc_prepare $item "catalog" + if [ $? -eq 0 ]; then + mkdir -p $DIR_WORKSPACE/$DIR_CATALOGS + mv $project/catalog.pdf $DIR_WORKSPACE/$DIR_CATALOGS/CATALOG-${lang}-${item}.pdf + amc_clean $item + else + ((rc++)) + fi + shift + done + return $rc; +} + function action_sample() { local rc=0 while [ $# -gt 0 ]; do local item=$1 local project=$DIR_WORKSPACE/$DIR_PROJECTS/$item local lang=$(get_lang $item) amc_prepare $item "sample" if [ $? -eq 0 ]; then mkdir -p $DIR_WORKSPACE/$DIR_SAMPLES mv $project/SAMPLE-exam.pdf $DIR_WORKSPACE/$DIR_SAMPLES/SAMPLE-${lang}-${item}.pdf mv $project/SAMPLE-correction.pdf $DIR_WORKSPACE/$DIR_SAMPLES/SAMPLE-CORRECTION-${lang}-${item}.pdf amc_clean $item else ((rc++)) fi shift done return $rc; } function action_check() { local rc=0 while [ $# -gt 0 ]; do local item=$1 local project=$DIR_WORKSPACE/$DIR_PROJECTS/$item local lang=$(get_lang $item) amc_prepare $item "check" if [ $? -ne 0 ]; then ((rc++)); else amc_clean $item; fi shift done return $rc; } function amc_clean() { local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 rm -f $project/*-exam.pdf $project/*-correction.pdf $project/amc-compiled.* } function amc_prepare() { assert_exam $1; if [ $? -ne 0 ]; then return 1; fi assert_template; if [ $? -ne 0 ]; then return 1; fi local project=$DIR_WORKSPACE/$DIR_PROJECTS/$1 local runs=$PDFLATEX_RUNS ok=0 local mode=$2 prefix + perma "Running AMC/$mode on project '$1'" + case $mode in - "blank"|"sample") - verbose "Building $mode exam '$1'" + "blank"|"sample"|"catalog"|"exam") if [ -r $project/INVALID ]; then error "This AMC project is marked as invalid. Please correct project and run the 'check' action again." return 1 fi prefix=$(echo $mode | tr '[a-z]' '[A-Z]');; "check") - verbose "Checking exam '$1'" prefix=BLANK;; esac # Save real students.csv file case $mode in - "blank"|"check") + "blank"|"check"|"catalog") mv $project/$FILE_STUDENTS $project/${FILE_STUDENTS}.sav cp $DIR_EXAM_TEMPLATE/csv/blank.csv $project/$FILE_STUDENTS ;; "sample") mv $project/$FILE_STUDENTS $project/${FILE_STUDENTS}.sav cp $DIR_EXAM_TEMPLATE/csv/sample.csv $project/$FILE_STUDENTS ;; esac # Clean before compiling project amc_clean $1 while [ $runs -gt 0 ]; do auto-multiple-choice prepare \ --mode s \ --with pdflatex \ --filter latex \ - --prefix $project \ + --prefix $project/ \ --out-sujet ${prefix}-exam.pdf \ --out-corrige ${prefix}-correction.pdf \ $project/exam.tex > /dev/null 2>&1 if [ ! -r $project/${prefix}-exam.pdf ]; then runs=0; else ok=1; fi; if [ ! -r $project/${prefix}-correction.pdf ]; then runs=0; else ok=1; fi; ((runs--)) done # Restore students.csv case $mode in - "blank"|"check"|"sample") + "blank"|"check"|"sample"|"catalog"|"sample") mv $project/${FILE_STUDENTS}.sav $project/$FILE_STUDENTS ;; esac if [ $ok -eq 0 ]; then error "This AMC/LaTeX project does not compile with AMC." touch $project/INVALID return 1 else rm -f $project/INVALID fi return 0 } # EOF diff --git a/lib/bash/bamc_exams.sh b/lib/bash/bamc_exams.sh index dc77a34..1d6b2cf 100644 --- a/lib/bash/bamc_exams.sh +++ b/lib/bash/bamc_exams.sh @@ -1,70 +1,78 @@ #/bin/bash function action_list() { # Check workspace assert_workspace; if [ $? -eq 1 ]; then return 1; fi # List exams verbose "List of exams in current workspace:" for exam in $(find $DIR_WORKSPACE/$DIR_EXAMS -mindepth 1 -maxdepth 1 -type d -exec basename {} \;); do color_echo "- \"$exam\"" done # Done return 0 } function get_exam_list() { assert_workspace "quiet"; if [ $? -eq 1 ]; then return 1; fi find $DIR_WORKSPACE/$DIR_EXAMS -mindepth 1 -maxdepth 1 -type d -exec basename {} \; } function action_add-exam() { # Check workspace assert_workspace; if [ $? -eq 1 ]; then return 1; fi # Set source DIR_EXAM=$DIR_WORKSPACE_TEMPLATE/$DIR_EXAMS/skel if [ ! -d $DIR_EXAM ]; then error_echo "Directory '$DIR_EXAM' not found." return 1 fi is_set 'exam' if [ $? -eq 1 ]; then DESTINATION=$(get_parameter 'exam'); fi is_set 'e' if [ $? -eq 1 ]; then DESTINATION=$(get_parameter 'e'); fi if [ -z "$DESTINATION" ]; then error_echo "No exam name provided. Add parameter 'exam=exam-name' to your command line"; return 1; fi # Set destination DESTINATION=$DIR_WORKSPACE/$DIR_EXAMS/$DESTINATION if [ -d $DESTINATION ]; then warn "This exam already exists!" confirm "Do you want to write in existing exam '$(basename $DESTINATION)' ?" if [ $? -eq 0 ]; then return 1; fi fi # Copy color_echo_n "Creating new exam '$(basename $DESTINATION)' from '$DIR_EXAM'... " cp -rp $DIR_EXAM $DESTINATION check_rc_echo $? return $? } function assert_exam() { # Check workspace assert_workspace; if [ $? -eq 1 ]; then return 1; fi local exam=$1 local mode=$2 if [ ! -d $DIR_WORKSPACE/$DIR_EXAMS/$exam ]; then if [ "$mode" != "quiet" ]; then error_echo "This exam does not exists: '$exam'. Please check the list of exams in this workspace using the 'list' action."; fi return 1 fi return 0 } +function get_exam_parameter() { + cat $DIR_WORKSPACE/$DIR_EXAMS/$1/$FILE_EXAM | grep "^$2:" | cut -d ':' -f 2- +} + +function get_lang() { + get_exam_parameter $1 'LANG' +} + # EOF diff --git a/lib/bash/bamc_help.sh b/lib/bash/bamc_help.sh index 3ff4b20..3558368 100644 --- a/lib/bash/bamc_help.sh +++ b/lib/bash/bamc_help.sh @@ -1,44 +1,50 @@ #!/bin/bash +function action_implemented() { + perma "Implemented functions:" + grep 'function action_' $DIR_LIB/* | grep -v grep | cut -d ' ' -f 2 | cut -d '(' -f 1 | cut -d '_' -f 2 | sort + return 0 +} + function action_help() { local item=$1 # Useless... echo -e "${DarkGreen}USAGE:${NoColor} "$(basename $0)" [-p|--params p1=v1,p2-v2,...] [-o|--only item1,item2,...] action1 [action2 ...] e.g.: $(basename $0) --params workspace=~/AMC_Workspace init e.g.: $(basename $0) show Parameters: ----------- ${DarkGreen}debug${NoColor} (GENERAL) print debugging messages ${DarkGreen}force${NoColor} (GENERAL) do not ask for user confirmation ${DarkGreen}workspace|w${NoColor} (GENERAL) name a specific workspace ${DarkGreen}exam|e${NoColor} (GENERAL) name a specific exam within the workspace Items: ----------- ${DarkGreen}item1${NoColor} (GENERAL) items are the existing exams (as printed by the 'list' action) Actions: -------- ${DarkGreen}sanity-checks${NoColor} (GENERAL) check system ${DarkGreen}init${NoColor} (WORKSPACE) create a new workspace in the current directory ${DarkGreen}add-exam${NoColor} (EXAMS) add a new exam in the current workspace ${DarkGreen}list${NoColor} (EXAMS) print list of exams in the current workspace ${DarkGreen}clean${NoColor} (PROJECTS) remove project and output directories ${DarkGreen}project${NoColor} (PROJECTS) (re)build the AMC project(s) ${DarkGreen}check-latex${NoColor} (PROJECTS) check LaTeX syntax ${DarkGreen}check-cvs${NoColor} (PROJECTS) check CSV files syntax ${DarkGreen}check-amc${NoColor} (PROJECTS) check AMC specific syntax ${DarkGreen}check${NoColor} (PROJECTS) do all checks ${DarkGreen}blank${NoColor} (PDF) build a blank (anonymous) exam ${DarkGreen}catalog${NoColor} (PDF) build a catalog of questions ${DarkGreen}sample${NoColor} (PDF) build a sample (4 exams) exam ${DarkGreen}exam${NoColor} (PDF) build PDF exam" return 0 } diff --git a/lib/bash/bamc_projects.sh b/lib/bash/bamc_projects.sh index ce90946..04b6ae8 100644 --- a/lib/bash/bamc_projects.sh +++ b/lib/bash/bamc_projects.sh @@ -1,61 +1,61 @@ #!/bin/bash function action_clean() { local exams=$@ local exam for exam in $(echo $exams); do assert_exam $exam if [ $? -eq 1 ]; then return 1; fi perma "Cleaning '$exam'" confirm "Clean project and outputs for exam '$exam' ?" if [ $? -eq 0 ]; then return 0; fi - for dir in $(echo $DIR_WORKSPACE/$DIR_PROJECTS $DIR_WORKSPACE/$DIR_SAMPLES $DIR_WORKSPACE/$DIR_BLANKS $DIR_WORKSPACE/$DIR_PDFS $DIR_WORKSPACE/$DIR_LISTS); do + for dir in $(echo $DIR_WORKSPACE/$DIR_PROJECTS $DIR_WORKSPACE/$DIR_SAMPLES $DIR_WORKSPACE/$DIR_BLANKS $DIR_WORKSPACE/$DIR_PDFS $DIR_WORKSPACE/$DIR_LISTS $DIR_WORKSPACE/$DIR_CATALOGS $DIR_WORKSPACE/$DIR_PDFS); do if [ -d "$dir/$exam" ]; then verbose "Removing directory: '$dir/$exam'" rm -rf "$dir/$exam/" else verbose "Removing files: '$dir/$exam*'" rm -rf $dir/$exam-* rm -rf $dir/*-$exam* fi if [ -d "$dir" ]; then if [ $(ls -1A $dir/ | wc -l) -eq 0 ]; then verbose "Removing now empty directory: '$dir'" rmdir $dir/ fi fi done done return 0 } function action_project() { # Get exam template to use assert_template if [ $? -ne 0 ]; then return 1; fi # Check we have a build script for this template check_file_exists $DIR_EXAM_TEMPLATE/$FILE_PROJECT_BUILD if [ $? -ne 0 ]; then return 1; fi # Source it ! source $DIR_EXAM_TEMPLATE/$FILE_PROJECT_BUILD # Check we now have a 'build_project' function function_exists 'build_project' if [ $? -ne 0 ]; then error "This template's build script ($DIR_EXAM_TEMPLATE/$FILE_PROJECT_BUILD) is not valid (no 'build_project' function)." ; return 1; fi # Good. Proceed. verbose "Building projects using script '$DIR_EXAM_TEMPLATE/$FILE_PROJECT_BUILD'" local exams=$@ exam lang rc=0 for exam in $(echo $exams); do perma "Building project for exam '$exam'" build_project $exam; rc=$((rc+$?)) done return $rc } # EOF diff --git a/lib/bash/bamc_questions.sh b/lib/bash/bamc_questions.sh new file mode 100644 index 0000000..0406595 --- /dev/null +++ b/lib/bash/bamc_questions.sh @@ -0,0 +1,110 @@ +#!/bin/bash + + + +function action_check-questions() { + assert_workspace; if [ $? -eq 1 ]; then return 1; fi + + perma "Checking questions (LaTeX syntax)" + local cwd=$(pwd) + local TMP="/tmp/bamc" + local SRC=$DIR_WORKSPACE/$DIR_QUESTIONS + local TEX=$TMP/question.tex + local rc=0 + + # Create tmp dir + mkdir -p $TMP + + # Import question resources (media file, etc.) + for stuff in $(find $SRC -type f -not -name '*.tex' | grep -v '\.ignore' | sort); do + verbose "Copying resource: $stuff ..." + cp $stuff $TMP + done + + # Compile questions + for q in $(find $SRC -type f -name '*.tex' | grep -v '\.ignore' | sort); do + + q_short=$(echo $q | sed "s?$DIR_QUESTIONS/?|?" | cut -d '|' -f 2) + + # Check EOL mode + verbose "Checking EOL mode of question '$q_short'" + dos2unix < $q | cmp -s - $q + if [ $? -ne 0 ]; then warn "Some lines are in DOS mode."; fi + mac2unix < $q | cmp -s - $q + if [ $? -ne 0 ]; then warn "Some lines are in Mac mode."; fi + + # Check encoding + verbose "Checking encoding of question '$q_short'" + if [ "$(get_file_encoding $q)" != "unicode" ]; then + warn "Incorrect file encoding: $(get_file_encoding $q)" + fi + + # Compile + rm -f $TMP/question.* + verbose "Compiling question '$q_short'" + echo_header_part > $TEX + cat $q >> $TEX + echo_footer_part >> $TEX + cd $TMP + pdflatex -interaction=nonstopmode question.tex > /dev/null + rc=$? + if [ $rc -ne 0 ]; then + error "Question '$q_short' does not compile :("; + ((rc++)) + fi + cd $cwd + done + + # Done + return $rc +} + +function echo_header_part() { + cat << EOF +\documentclass[a4paper]{article} +\usepackage[utf8x]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{multicol} +\usepackage[francais,bloc,catalog]{automultiplechoice} + + +%% =============== +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{fancyhdr} +\usepackage{tikz} + +\newcommand{\fracpd}[2]{\frac{\partial #1}{\partial #2}} % partielle Ableitung +\newcommand{\dfracpd}[2]{\dfrac{\partial #1}{\partial #2}} % partielle Ableitung +%% =============== + +\newcommand{\TRUE}{ + \bareme{b=1,m=-1} + \begin{choiceshoriz}[o] + \bonne{VRAI} + \mauvaise{FAUX} + \end{choiceshoriz} +} + +\newcommand{\FALSE}{ + \bareme{b=1,m=-1} + \begin{choiceshoriz}[o] + \mauvaise{VRAI} + \bonne{FAUX} + \end{choiceshoriz} +} + +\begin{document} +EOF + +} + +function echo_footer_part() { + cat << EOF +\end{document} +EOF +} + +# EOF diff --git a/lib/bash/cmdline_parser.sh b/lib/bash/cmdline_parser.sh index 3d5f146..05f2769 100644 --- a/lib/bash/cmdline_parser.sh +++ b/lib/bash/cmdline_parser.sh @@ -1,129 +1,133 @@ #!/bin/bash # Reusable command line parser # USAGE: [in the calling script] # 1) set the global variables: $DEFAULT_ITEMS, $DEFAULT_PARAMS and $DEFAULT_ACTIONS # 2) set the global variable: $CALLBACK_PREFIX (default: cb_ ) # 3) implement each the callback: e.g. function cb_list() { ... } to implement the list action # 4) call: run $@ ACTIONS='' PARAMS='' ITEMS='' CALLBACK_PREFIX=${CALLBACK_PREFIX:-cb_} function parse_args() { while [ $# -gt 0 ]; do case $1 in "-o"|"--only") shift ITEMS=$1 shift continue ;; "-p"|"--params") shift PARAMS=$1 shift continue ;; *) if [ -z "$ACTIONS" ]; then ACTIONS=$1; else ACTIONS="$ACTIONS $1"; fi shift ;; esac done # Source local configuration (if any) source_workspace_configuration # Compute final ITEMS if [ -z "$ITEMS" ]; then ITEMS=$(get_default_items); fi if [ -z "$ITEMS" ]; then ITEMS='~no~items~'; fi # Compute final ACTIONS if [ -z "$ACTIONS" ]; then ACTIONS=$(get_default_actions); fi if [ -z "$ACTIONS" ]; then ACTIONS='help'; fi # Compute final PARAMS PARAMS=$(echo $PARAMS,$(get_default_params) | tr "," "\n" | sort -u | grep -v '^$' | tr "\n" "," | sed 's/,$//') debug "End of command line parsing. ACTIONS: '$ACTIONS' | ITEMS: '$ITEMS' | PARAMS: '$PARAMS'" } function get_items() { echo "$ITEMS" | sed "s/,/\n/g" } function get_actions() { echo "$ACTIONS" | sed "s/ /\n/g" } function get_params() { echo "$PARAMS" | sed "s/,/\n/g" } function get_parameter() { key=$1 # Key alone line=$(echo $PARAMS | sed "s/,/\n/g" | grep "^$key$") if [ -n "$line" ]; then echo "set"; return; fi # Key + value line=$(echo $PARAMS | sed "s/,/\n/g" | grep "^$key=" | cut -d '=' -f 2-) if [ -n "$line" ]; then echo $line; return; fi # unset echo "unset" } function is_set() { param=$1 value=$(get_parameter $param) if [ "$value" != "unset" ]; then return 1; else return 0; fi } function run() { local action local item - local rc=0 + local global_rc=0 rc parse_args $@ for action in $(get_actions); do - debug "Running action '$action'" - action_switch $action $item - rc=$((rc+$?)) + rc=0 + main_switch $action $item + rc=$? + if [ $rc -ne 0 ]; then echo "rc: $rc"; fi + global_rc=$((rc+$rc)) + done - return $rc + if [ $global_rc -ne 0 ]; then echo "global_rc: $global_rc"; fi + return $global_rc } function get_default_items() { echo $DEFAULT_ITEMS } function get_default_params() { echo $DEFAULT_PARAMS } function get_default_actions() { echo $DEFAULT_ACTIONS } function check_action() { function_exists $1 return $? } -function action_switch() { +function main_switch() { local action=$1 local function_to_call="${CALLBACK_PREFIX}${action}" check_action $function_to_call if [ $? -eq 0 ]; then debug "Calling action '$action' => '$function_to_call' on item(s) '$(get_items)'" $function_to_call $(get_items) return $? else error "invalid action: '$action' => '${CALLBACK_PREFIX}${action}' (not implemented ?)" return 1 fi return 0 } # EOF diff --git a/lib/bash/debugging.sh b/lib/bash/debugging.sh index 10c83e5..992f96d 100644 --- a/lib/bash/debugging.sh +++ b/lib/bash/debugging.sh @@ -1,34 +1,35 @@ #!/bin/bash function error() { error_echo $@ } function warn() { warning_echo $@ } function debug() { - is_set debug - if [ $? -eq 1 ]; then debug_echo $@; fi + is_set quiet; if [ $? -eq 1 ]; then return 0; fi + is_set debug; if [ $? -eq 1 ]; then debug_echo $@; fi } function perma() { + is_set quiet; if [ $? -eq 1 ]; then return 0; fi color_echo "${Green}*${NoColor} "$@ } function verbose() { - is_set verbose - if [ $? -eq 1 ]; then echo " "$@; fi + is_set quiet; if [ $? -eq 1 ]; then return 0; fi + is_set verbose; if [ $? -eq 1 ]; then echo " "$@; fi } function check_file_exists() { if [ -r $1 ]; then return 0 else error "File not found: $1" return 1 fi } # EOF diff --git a/lib/bash/tools.sh b/lib/bash/tools.sh index 4043555..2562dac 100644 --- a/lib/bash/tools.sh +++ b/lib/bash/tools.sh @@ -1,43 +1,62 @@ #!/bin/bash +function get_file_encoding() { + local filename=$1 + local output=$(file --brief $filename) + case $output in + *ASCII*) + echo "unicode" + return 0;; + *UTF-8*) + echo "unicode" + return 0;; + *8859*) + echo "iso" + return 0;; + "*") + echo "unknown";; + esac + return 1 +} + function function_exists() { if [ $(type "$1" 2>&1 | grep -c "$1"' is a function') -eq 1 ]; then return 0 else return 1 fi } function check_OS() { OS=$(uname | tr "[A-Z]" "[a-z]") if [ "$OS" == "linux" ]; then return 0; fi OS="unknown" return 1 } function check_OS_subtype() { OS_SUBTYPE="unknown" if [ -r /etc/gentoo-release ]; then OS_SUBTYPE="gentoo"; return 0; fi return 1 } function check_AMC_version() { AMC_VERSION="unknown" which auto-multiple-choice > /dev/null 2>&1 if [ $? -gt 0 ]; then AMC_VERSION="none" return 1 fi case $OS in "linux") case $OS_SUBTYPE in "gentoo") AMC_VERSION=$(eix --xml auto-multiple-choice | grep 'installed="1"' | tr " " "\n" | grep '^id' | cut -d '"' -f 2) return 0;; esac esac return 1 } # EOF