2025-02-09 02:01:58 -06:00
#!/bin/bash
source " $( dirname " $0 " ) /common.sh"
# Challenge categories and levels
declare -A CHALLENGE_CATEGORIES =(
[ "file" ]= "File System Operations"
[ "perm" ]= "Permissions & Security"
[ "text" ]= "Text Processing"
[ "proc" ]= "Process Management"
[ "net" ]= "Network Operations"
2025-02-09 03:25:43 -06:00
[ "pipe" ]= "Pipelines & Redirection"
[ "shell" ]= "Shell Scripting"
[ "git" ]= "Git Operations"
)
# Challenge difficulty descriptions
declare -A DIFFICULTY_DESCRIPTIONS =(
[ 1]= "Beginner - Basic command usage"
[ 2]= "Intermediate - Combined commands"
[ 3]= "Advanced - Complex operations"
[ 4]= "Expert - System administration"
[ 5]= "Master - Advanced scripting"
2025-02-09 02:01:58 -06:00
)
2025-02-09 02:33:45 -06:00
# Challenge definitions with metadata
2025-02-09 02:01:58 -06:00
# Format: type|name|difficulty|skills|task|hints|setup_requirements|verification_criteria
declare -A CHALLENGES =(
[ "1.1" ]= "file_search|Find Recent Files|1|file_ops,search|Find all .conf files modified in the last 24 hours and save the list to recent_configs.txt|Try using find with -mtime|none|output_file=recent_configs.txt;file_count=10"
[ "1.2" ]= "file_count|File Statistics|1|file_ops,search|Generate a report showing count of files by extension|Consider using find and awk|none|report_exists=true;extension_count=5"
[ "1.3" ]= "file_organize|Smart File Organizer|2|file_ops|Create directories for different file types and sort files accordingly|Look into file command|none|dir_structure=complete;files_sorted=true"
[ "1.4" ]= "file_cleanup|System Cleanup|2|file_ops,search|Find and list all empty files and zero-byte files|Combine find with size tests|none|empty_files_found=true;report_generated=true"
[ "1.5" ]= "file_dedup|Duplicate Hunter|3|file_ops,search|Find and handle duplicate files using md5sum|Consider using sort and uniq|none|duplicates_identified=true;report_accurate=true"
# Level 2: Permissions
[ "2.1" ]= "perm_basic|Permission Fundamentals|1|permissions|Set up basic file permissions following security best practices|Remember user-group-others order|users=app_user1|permissions_correct=true;ownership_correct=true"
[ "2.2" ]= "perm_acl|ACL Master|2|permissions|Implement complex ACL rules for multiple users|Look into setfacl usage|users=app_user1,app_user2|acl_rules_correct=true"
[ "2.3" ]= "perm_special|Special Permission Bits|2|permissions|Configure SUID/SGID permissions correctly|Understanding special bits|none|special_bits_correct=true"
[ "2.4" ]= "perm_recursive|Directory Tree Fix|3|permissions|Fix permissions recursively while maintaining security|Consider find with exec|none|tree_permissions_correct=true"
[ "2.5" ]= "perm_audit|Security Auditor|3|permissions|Perform security audit and generate detailed report|Use stat and lsattr|none|audit_complete=true;report_detailed=true"
# Level 3: Text Processing
[ "3.1" ]= "text_search|Log Detective|1|text_proc,search|Find and analyze specific patterns in log files|grep with context|none|patterns_found=true;count_correct=true"
[ "3.2" ]= "text_extract|Data Extraction Pro|2|text_proc|Extract and format specific fields from log files|awk is your friend|none|fields_extracted=true;format_correct=true"
[ "3.3" ]= "text_transform|Format Converter|2|text_proc|Transform data between different formats|sed for substitution|none|transformation_correct=true"
[ "3.4" ]= "text_report|Report Generator|3|text_proc|Create a detailed system report from various logs|Combine multiple tools|none|report_complete=true;format_valid=true"
[ "3.5" ]= "text_analyze|Pattern Analyzer|3|text_proc,search|Analyze complex error patterns and generate statistics|Use grep with perl regex|none|analysis_complete=true;stats_accurate=true"
)
# Challenge verification functions
verify_challenge() {
local challenge_id = $1
local start_time = $2
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $challenge_id ] } "
# Check prerequisites
if ! check_requirements " $requirements " ; then
log_message "ERROR" "Challenge prerequisites not met"
return 1
2025-02-09 02:36:28 -06:00
fi
2025-02-09 02:01:58 -06:00
# Record attempt
record_attempt " $challenge_id " " $start_time "
# Run specific verification
local category = ${ type %%_* }
case " $category " in
"file" ) verify_file_challenge " $challenge_id " " $criteria " ;;
"perm" ) verify_permission_challenge " $challenge_id " " $criteria " ;;
"text" ) verify_text_challenge " $challenge_id " " $criteria " ;;
*) log_message "ERROR" "Unknown challenge category: $category " ;;
esac
}
# Check challenge prerequisites
check_requirements() {
local requirements = $1
[[ " $requirements " == "none" ]] && return 0
IFS = ';' read -ra REQS <<< " $requirements "
for req in " ${ REQS [@] } " ; do
IFS = '=' read -r key value <<< " $req "
case " $key " in
"users" )
for user in ${ value //,/ } ; do
if ! id " $user " & >/dev/null; then
log_message "ERROR" "Required user $user not found"
return 1
fi
done
;;
# Add more requirement checks as needed
esac
done
return 0
}
# Verify file-related challenges
verify_file_challenge() {
local challenge_id = $1
local criteria = $2
local result = 0
IFS = ';' read -ra CHECKS <<< " $criteria "
for check in " ${ CHECKS [@] } " ; do
IFS = '=' read -r key value <<< " $check "
case " $key " in
"output_file" )
[[ -f " $value " ]] && (( result++))
;;
"file_count" )
[[ " $( find " $CHALLENGE_DIR /files" -type f | wc -l) " -eq " $value " ]] && (( result++))
;;
# Add more specific checks
esac
done
verify_result " $challenge_id " " $result " " ${# CHECKS [@] } " "File challenge verification"
}
# Verify permission-related challenges
verify_permission_challenge() {
local challenge_id = $1
local criteria = $2
local result = 0
IFS = ';' read -ra CHECKS <<< " $criteria "
for check in " ${ CHECKS [@] } " ; do
IFS = '=' read -r key value <<< " $check "
case " $key " in
"users" )
for user in ${ value //,/ } ; do
if ! id " $user " & >/dev/null; then
log_message "ERROR" "Required user $user not found"
return 1
fi
done
;;
# Add more permission checks as needed
esac
done
verify_result " $challenge_id " " $result " " ${# CHECKS [@] } " "Permission challenge verification"
}
# Verify text-related challenges
verify_text_challenge() {
local challenge_id = $1
local criteria = $2
local result = 0
IFS = ';' read -ra CHECKS <<< " $criteria "
for check in " ${ CHECKS [@] } " ; do
IFS = '=' read -r key value <<< " $check "
case " $key " in
"patterns_found" )
[[ " $( grep -c " $value " " $CHALLENGE_DIR /files/logs/" *.log) " -ge 1 ]] && (( result++))
;;
"count_correct" )
[[ " $( grep -c " $value " " $CHALLENGE_DIR /files/logs/" *.log) " -eq " $value " ]] && (( result++))
;;
# Add more text checks as needed
esac
done
verify_result " $challenge_id " " $result " " ${# CHECKS [@] } " "Text challenge verification"
}
# Record challenge attempt
record_attempt() {
local challenge_id = $1
local start_time = $2
local duration = $(($( date +%s) - start_time))
local command_count = $( grep -c "^ $start_time " " $COMMAND_LOG " )
echo " $challenge_id , $( get_attempt_number " $challenge_id " ) , $start_time , $command_count , $duration ,0" >> " $ATTEMPT_FILE "
}
# Get attempt number for challenge
get_attempt_number() {
local challenge_id = $1
local attempts = $( grep -c "^ $challenge_id ," " $ATTEMPT_FILE " )
echo $(( attempts + 1 ))
}
# Enhanced result verification with detailed feedback
verify_result() {
local challenge_id = $1
local actual = $2
local expected = $3
local message = $4
local end_time = $( date +%s)
if [[ " $actual " == " $expected " ]] ; then
2025-02-09 03:25:43 -06:00
log_message "SUCCESS" "Challenge $challenge_id completed successfully!"
echo -e "\n ${ GREEN } 🎉 Congratulations! Challenge completed! ${ NC } "
echo -e " ${ BLUE } Summary: ${ NC } "
echo -e "- Time taken: $( format_duration $(( end_time - start_time))) "
echo -e "- Commands used: $( get_command_count " $challenge_id " ) "
2025-02-09 02:01:58 -06:00
2025-02-09 03:25:43 -06:00
# Calculate and award points
2025-02-09 02:01:58 -06:00
local duration = $(( end_time - start_time))
local command_count = $( get_command_count " $challenge_id " )
local bonus_points = $( calculate_bonus_points " $duration " " $command_count " )
2025-02-09 03:25:43 -06:00
local total_points = $(( 100 + bonus_points))
echo -e "\n ${ YELLOW } Points earned: ${ NC } "
echo -e "- Base points: 100"
echo -e "- Time bonus: $time_bonus "
echo -e "- Efficiency bonus: $efficiency_bonus "
echo -e "- Total points: $total_points "
# Update progress
update_challenge_status " $challenge_id " "1" " $end_time "
award_points " $challenge_id " " $total_points "
# Show next challenge suggestion
suggest_next_challenge " $challenge_id "
2025-02-09 02:01:58 -06:00
return 0
else
2025-02-09 03:25:43 -06:00
log_message "ERROR" "Challenge incomplete: $actual / $expected requirements met"
echo -e "\n ${ RED } Challenge not completed yet. ${ NC } "
echo -e "Progress: $actual / $expected requirements met"
echo -e "\n ${ YELLOW } Tips: ${ NC } "
echo -e "- Use 'hint' command for guidance"
echo -e "- Check your work carefully"
echo -e "- Try breaking down the task into smaller steps"
2025-02-09 02:01:58 -06:00
return 1
fi
}
# Calculate bonus points based on time and efficiency
calculate_bonus_points() {
local duration = $1
local command_count = $2
local time_bonus = 0
local efficiency_bonus = 0
# Time bonus
if [[ " $duration " -lt 60 ]] ; then
time_bonus = 50
elif [[ " $duration " -lt 120 ]] ; then
time_bonus = 25
fi
# Efficiency bonus
if [[ " $command_count " -le 3 ]] ; then
efficiency_bonus = 50
elif [[ " $command_count " -le 5 ]] ; then
efficiency_bonus = 25
fi
echo $(( time_bonus + efficiency_bonus))
}
2025-02-09 02:33:45 -06:00
# Get challenge details
2025-02-09 02:01:58 -06:00
get_challenge_details() {
local challenge_id = $1
2025-02-09 02:33:45 -06:00
if [[ -n " ${ CHALLENGES [ $challenge_id ] :- } " ]] ; then
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $challenge_id ] } "
echo -e " ${ BLUE } Challenge $challenge_id : ${ NC } $name "
echo -e " ${ BLUE } Difficulty: ${ NC } $( printf '★%.0s' $( seq 1 " $difficulty " )) "
echo -e " ${ BLUE } Skills: ${ NC } $skills "
echo -e " ${ BLUE } Task: ${ NC } $task "
return 0
fi
return 1
2025-02-09 02:01:58 -06:00
}
# Update challenge status
update_challenge_status() {
local challenge_id = $1
local success = $2
local end_time = $3
# Update attempt status
sed -i " $ s/,0 $/, $success /" " $ATTEMPT_FILE "
# Record completion if successful
if [[ " $success " == "1" ]] ; then
echo " $challenge_id , $end_time ,completed, ${ CHALLENGES [ $challenge_id ] } " >> " $PROGRESS_FILE "
fi
}
# List available challenges
list_challenges() {
2025-02-09 02:33:45 -06:00
echo -e "\n ${ BLUE } Available Challenges: ${ NC } "
2025-02-09 02:01:58 -06:00
for challenge_id in " ${ !CHALLENGES[@] } " ; do
if ! is_challenge_completed " $challenge_id " ; then
2025-02-09 02:33:45 -06:00
IFS = '|' read -r type name difficulty skills task _ <<< " ${ CHALLENGES [ $challenge_id ] } "
2025-02-09 02:01:58 -06:00
echo -e "\n ${ YELLOW } Challenge $challenge_id ${ NC } ( $difficulty ★)"
echo "Type: $type "
echo "Skills: $skills "
echo "Task: $task "
fi
done
2025-02-09 03:25:43 -06:00
}
# Function to add new challenge
add_challenge() {
local id = $1
local type = $2
local name = $3
local difficulty = $4
local skills = $5
local task = $6
local hints = $7
local requirements = $8
local criteria = $9
# Validate challenge ID format
if [[ ! $id = ~ ^[ 1-9] \. [ 1-5] $ ]] ; then
log_message "ERROR" "Invalid challenge ID format. Must be level.number (e.g., 1.1)"
return 1
fi
# Validate challenge type
if [[ -z " ${ CHALLENGE_CATEGORIES [ $type ] } " ]] ; then
log_message "ERROR" "Invalid challenge type. Available types: ${ !CHALLENGE_CATEGORIES[*] } "
return 1
fi
# Validate difficulty
if (( difficulty < 1 || difficulty > 5)) ; then
log_message "ERROR" "Invalid difficulty. Must be between 1 and 5"
return 1
fi
# Add challenge to CHALLENGES array
CHALLENGES[ $id ]= " ${ type } | ${ name } | ${ difficulty } | ${ skills } | ${ task } | ${ hints } | ${ requirements } | ${ criteria } "
log_message "SUCCESS" "Added challenge $id : $name "
return 0
}
# Function to list available challenges by category
list_challenges_by_category() {
local category = ${ 1 :- all }
echo -e "\n ${ BOLD } Available Challenges: ${ NC } "
echo "===================="
if [[ " $category " == "all" ]] ; then
for cat in " ${ !CHALLENGE_CATEGORIES[@] } " ; do
echo -e "\n ${ BLUE }${ CHALLENGE_CATEGORIES [ $cat ] } : ${ NC } "
for id in " ${ !CHALLENGES[@] } " ; do
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $id ] } "
if [[ ${ type %%_* } == " $cat " ]] ; then
echo -e " ${ YELLOW } $id ${ NC } ( $( printf '★%.0s' $( seq 1 " $difficulty " )) ) - $name "
echo -e " ${ CYAN } Skills: ${ NC } $skills "
echo -e " ${ CYAN } Task: ${ NC } $task "
fi
done
done
else
if [[ -z " ${ CHALLENGE_CATEGORIES [ $category ] } " ]] ; then
log_message "ERROR" "Invalid category. Available categories: ${ !CHALLENGE_CATEGORIES[*] } "
return 1
fi
echo -e "\n ${ BLUE }${ CHALLENGE_CATEGORIES [ $category ] } : ${ NC } "
for id in " ${ !CHALLENGES[@] } " ; do
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $id ] } "
if [[ ${ type %%_* } == " $category " ]] ; then
echo -e " ${ YELLOW } $id ${ NC } ( $( printf '★%.0s' $( seq 1 " $difficulty " )) ) - $name "
echo -e " ${ CYAN } Skills: ${ NC } $skills "
echo -e " ${ CYAN } Task: ${ NC } $task "
fi
done
fi
}
# Function to suggest next challenge
suggest_next_challenge() {
local current_id = $1
local level = ${ current_id %.* }
local number = ${ current_id #*. }
echo -e "\n ${ BLUE } What's next? ${ NC } "
# Suggest next challenge in same level
local next_number = $(( number + 1 ))
local next_id = " ${ level } . ${ next_number } "
if [[ -n " ${ CHALLENGES [ $next_id ] :- } " ]] ; then
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $next_id ] } "
echo -e "→ Try challenge ${ YELLOW } $next_id ${ NC } : $name "
else
# Suggest first challenge of next level
local next_level = $(( level + 1 ))
local next_id = " ${ next_level } .1"
if [[ -n " ${ CHALLENGES [ $next_id ] :- } " ]] ; then
IFS = '|' read -r type name difficulty skills task hints requirements criteria <<< " ${ CHALLENGES [ $next_id ] } "
echo -e "→ Ready for next level? Try ${ YELLOW } $next_id ${ NC } : $name "
fi
fi
}
# Function to format duration
format_duration() {
local seconds = $1
local minutes = $(( seconds / 60 ))
local hours = $(( minutes / 60 ))
minutes = $(( minutes % 60 ))
seconds = $(( seconds % 60 ))
if (( hours > 0)) ; then
printf "%dh %dm %ds" $hours $minutes $seconds
elif (( minutes > 0)) ; then
printf "%dm %ds" $minutes $seconds
else
printf "%ds" $seconds
fi
2025-02-09 02:01:58 -06:00
}