added project 2
This commit is contained in:
@@ -33,27 +33,19 @@ linux-sysadmin-journey/
|
||||
- [x] User management
|
||||
- [x] SSH configuration
|
||||
- [x] Firewall setup
|
||||
|
||||
### Next Focus Areas
|
||||
- [ ] Advanced Networking
|
||||
- [ ] DNS configuration
|
||||
- [ ] Network services
|
||||
- [ ] Advanced firewall rules
|
||||
- [ ] Service Deployment ✅
|
||||
- [x] Service Deployment
|
||||
- [x] Web server setup
|
||||
- [x] Database configuration
|
||||
- [x] Automation and Scripting
|
||||
- [x] Shell scripting
|
||||
- [x] Scheduled tasks
|
||||
|
||||
### Next Focus Areas
|
||||
- [ ] Project 2: [Your Next Project Name]
|
||||
- [ ] [First objective]
|
||||
- [ ] [Second objective]
|
||||
|
||||
### Upcoming
|
||||
- [ ] Service Deployment
|
||||
- [ ] Web server setup
|
||||
- [ ] Database configuration
|
||||
- [ ] Automation and Scripting
|
||||
- [ ] Shell scripting
|
||||
- [ ] Scheduled tasks
|
||||
### Future Projects
|
||||
- [ ] Advanced Networking
|
||||
- [ ] DNS configuration
|
||||
- [ ] Network services
|
||||
|
||||
@@ -56,7 +56,7 @@ This project documents the setup of a basic home lab environment using VirtualBo
|
||||
- Default gateway: 10.0.2.2
|
||||
- Host IP: 169.254.167.242
|
||||
|
||||
### Current Status
|
||||
### Current Status (Project Paused)
|
||||
- ✅ Basic VM Setup: Complete
|
||||
- ✅ Network Configuration: Complete
|
||||
- ✅ Security Measures: Complete
|
||||
@@ -64,10 +64,8 @@ This project documents the setup of a basic home lab environment using VirtualBo
|
||||
- ✅ Service Deployment: Complete
|
||||
- Apache web server
|
||||
- MySQL database
|
||||
- ⏳ Advanced Networking: In Progress
|
||||
- DNS configuration
|
||||
- Network services
|
||||
- Advanced firewall rules
|
||||
- ⏸️ Advanced Networking: Paused
|
||||
- Future enhancement opportunity
|
||||
|
||||
### Next Steps
|
||||
1. Advanced Networking
|
||||
@@ -150,4 +148,16 @@ sudo ufw status numbered
|
||||
|
||||
## Additional Documentation
|
||||
- [Security Setup Details](security-setup.md)
|
||||
- [Lessons Learned & Challenges](lessons-learned.md)
|
||||
- [Lessons Learned & Challenges](lessons-learned.md)
|
||||
|
||||
## Project Completion Summary
|
||||
1. Successfully set up Ubuntu Server VM
|
||||
2. Implemented basic security measures
|
||||
3. Configured monitoring and maintenance
|
||||
4. Deployed web and database services
|
||||
5. Documented all configurations and procedures
|
||||
|
||||
## Future Enhancements
|
||||
- Advanced networking features
|
||||
- Additional service deployments
|
||||
- Performance optimizations
|
||||
@@ -0,0 +1,155 @@
|
||||
# Command Line Mastery: The Linux Admin's Journey
|
||||
|
||||
## 🎮 Game Overview
|
||||
Master the command line through progressive challenges, earn achievements, and level up your Linux administration skills.
|
||||
|
||||
## 🎯 Game Structure
|
||||
Each level represents a core skill area, with increasingly complex challenges.
|
||||
|
||||
## 🏆 Achievement System
|
||||
- **Novice**: Complete basic challenges
|
||||
- **Adept**: Solve intermediate problems
|
||||
- **Expert**: Master advanced scenarios
|
||||
- **Guru**: Complete all challenges with optimal solutions
|
||||
|
||||
## 🎲 Levels
|
||||
|
||||
### Level 1: File System Navigator 📁
|
||||
**Theme**: Master file system operations and navigation
|
||||
|
||||
#### Stage 1-1: The File Hunter
|
||||
```bash
|
||||
Mission: Locate critical system files
|
||||
Skills: find, locate, which
|
||||
Bonus: Complete under 5 minutes
|
||||
```
|
||||
|
||||
#### Stage 1-2: Permission Puzzler
|
||||
```bash
|
||||
Mission: Fix incorrect permissions in /var/www
|
||||
Skills: chmod, chown, ACLs
|
||||
Bonus: Use single-line commands
|
||||
```
|
||||
|
||||
### Level 2: Process Whisperer 💻
|
||||
**Theme**: Process management and control
|
||||
|
||||
#### Stage 2-1: Resource Detective
|
||||
```bash
|
||||
Mission: Identify and handle resource-heavy processes
|
||||
Skills: top, ps, nice
|
||||
Challenge: No system slowdown
|
||||
```
|
||||
|
||||
#### Stage 2-2: Service Sorcerer
|
||||
```bash
|
||||
Mission: Debug and fix failing services
|
||||
Skills: systemctl, journalctl
|
||||
Bonus: Automate the fix
|
||||
```
|
||||
|
||||
### Level 3: Text Transformer 📝
|
||||
**Theme**: Advanced text processing and analysis
|
||||
|
||||
#### Stage 3-1: Log Archaeologist
|
||||
```bash
|
||||
Mission: Extract critical information from logs
|
||||
Skills: grep, awk, sed
|
||||
Challenge: Parse complex log formats
|
||||
```
|
||||
|
||||
#### Stage 3-2: Data Manipulator
|
||||
```bash
|
||||
Mission: Transform and analyze system data
|
||||
Skills: cut, sort, uniq
|
||||
Bonus: Create summary reports
|
||||
```
|
||||
|
||||
### Level 4: Network Ninja 🌐
|
||||
**Theme**: Network diagnostics and analysis
|
||||
|
||||
#### Stage 4-1: Connection Debugger
|
||||
```bash
|
||||
Mission: Solve network connectivity issues
|
||||
Skills: ping, traceroute, netstat
|
||||
Challenge: Fix DNS issues
|
||||
```
|
||||
|
||||
#### Stage 4-2: Traffic Analyzer
|
||||
```bash
|
||||
Mission: Monitor and analyze network traffic
|
||||
Skills: tcpdump, ss, iptables
|
||||
Bonus: Detect suspicious activity
|
||||
```
|
||||
|
||||
### Level 5: System Sentinel 🛡️
|
||||
**Theme**: System monitoring and optimization
|
||||
|
||||
#### Stage 5-1: Resource Watcher
|
||||
```bash
|
||||
Mission: Monitor and optimize system resources
|
||||
Skills: vmstat, iostat, free
|
||||
Challenge: Improve system performance
|
||||
```
|
||||
|
||||
#### Stage 5-2: Performance Tuner
|
||||
```bash
|
||||
Mission: Analyze and enhance system performance
|
||||
Skills: sar, tune2fs, sysctl
|
||||
Bonus: Document optimization strategy
|
||||
```
|
||||
|
||||
## 🌟 Scoring System
|
||||
- **Basic Completion**: 100 points
|
||||
- **Time Bonus**: +50 points
|
||||
- **Efficiency Bonus**: +50 points
|
||||
- **Creative Solution**: +100 points
|
||||
- **Documentation**: +50 points
|
||||
|
||||
## 🏅 Achievements
|
||||
- **Speed Demon**: Complete challenges under par time
|
||||
- **Efficiency Expert**: Use minimal commands
|
||||
- **Documentation Master**: Create detailed solution guides
|
||||
- **Script Savant**: Automate challenge solutions
|
||||
- **Perfect Solver**: Complete all bonus objectives
|
||||
|
||||
## 📊 Progress Tracking
|
||||
```
|
||||
Level 1: File System Navigator
|
||||
[▯▯▯▯▯] 0/5 Stages Complete
|
||||
[▯▯▯▯▯] 0/5 Achievements Unlocked
|
||||
|
||||
Level 2: Process Whisperer
|
||||
[▯▯▯▯▯] 0/5 Stages Complete
|
||||
[▯▯▯▯▯] 0/5 Achievements Unlocked
|
||||
```
|
||||
|
||||
## 🎓 Certification Path
|
||||
1. **Level Mastery**: Complete all stages in a level
|
||||
2. **Skill Mastery**: Earn all achievements in a category
|
||||
3. **Command Line Master**: Complete all levels and achievements
|
||||
|
||||
## 📚 Resources
|
||||
- Command reference sheets
|
||||
- Best practices guides
|
||||
- Solution templates
|
||||
- Challenge documentation
|
||||
|
||||
## 🔄 Daily Challenges
|
||||
Random challenges from completed levels to maintain skills:
|
||||
- **Monday Mystery**: Random file system challenge
|
||||
- **Tuesday Trouble**: Process management puzzle
|
||||
- **Wednesday Workout**: Text processing exercise
|
||||
- **Thursday Threat**: Network analysis scenario
|
||||
- **Friday Fix**: System optimization challenge
|
||||
|
||||
## 🎮 How to Play
|
||||
1. Start at Level 1
|
||||
2. Complete each stage's mission
|
||||
3. Document your solutions
|
||||
4. Earn achievements
|
||||
5. Progress to next level
|
||||
6. Complete daily challenges to maintain skills
|
||||
|
||||
Ready to begin your journey to Command Line Mastery?
|
||||
Choose your first mission from Level 1! 🚀
|
||||
@@ -0,0 +1,127 @@
|
||||
# Level 1: File System Navigator 📁
|
||||
|
||||
## Overview
|
||||
Master the fundamentals of file system operations and navigation.
|
||||
|
||||
## Environment Setup
|
||||
```bash
|
||||
# Run the setup script
|
||||
chmod +x ~/linux-sysadmin-journey/projects/02-command-line-mastery/setup/level1-setup.sh
|
||||
./level1-setup.sh
|
||||
```
|
||||
|
||||
## Stages
|
||||
|
||||
### Stage 1-1: The File Hunter
|
||||
**Mission**: Master file search and manipulation techniques
|
||||
|
||||
**Challenges**:
|
||||
|
||||
1. **Basic Search** (100 points)
|
||||
```bash
|
||||
# Find all .conf files modified in the last 3 hours
|
||||
# Expected output: At least config_*.conf files
|
||||
```
|
||||
|
||||
2. **Content Search** (150 points)
|
||||
```bash
|
||||
# Find all log files containing "ERROR" and count errors per file
|
||||
# Create a summary report
|
||||
```
|
||||
|
||||
3. **Size-based Search** (200 points)
|
||||
```bash
|
||||
# Locate files larger than 50MB
|
||||
# Create a report with file sizes in human-readable format
|
||||
```
|
||||
|
||||
4. **Complex Search** (250 points)
|
||||
```bash
|
||||
# Find empty files AND directories
|
||||
# Move them to ~/challenge/files/cleanup/
|
||||
```
|
||||
|
||||
5. **Advanced Filter** (300 points)
|
||||
```bash
|
||||
# Find files with specific permissions (600)
|
||||
# Generate a security report
|
||||
```
|
||||
|
||||
**Bonus Challenge** (+500 points):
|
||||
Create a script that:
|
||||
- Monitors directory for new files
|
||||
- Categorizes them by type
|
||||
- Moves them to appropriate subdirectories
|
||||
- Generates hourly reports
|
||||
|
||||
**Success Criteria**:
|
||||
- [ ] All files correctly identified
|
||||
- [ ] Commands properly documented
|
||||
- [ ] Generated reports are accurate
|
||||
- [ ] Used efficient search methods
|
||||
- [ ] Implemented error handling
|
||||
|
||||
### Stage 1-2: Permission Puzzler
|
||||
**Mission**: Master file permissions and access control
|
||||
|
||||
**Setup Script Features**:
|
||||
- Creates complex directory structure
|
||||
- Sets various permissions
|
||||
- Simulates multi-user environment
|
||||
- Creates access control scenarios
|
||||
|
||||
**Challenges**:
|
||||
|
||||
1. **Basic Permissions** (100 points)
|
||||
```bash
|
||||
# Fix basic file permissions
|
||||
# Verify with ls -l
|
||||
```
|
||||
|
||||
2. **Recursive Changes** (150 points)
|
||||
```bash
|
||||
# Implement directory structure permissions
|
||||
# Maintain security best practices
|
||||
```
|
||||
|
||||
3. **ACL Implementation** (200 points)
|
||||
```bash
|
||||
# Set up ACLs for user groups
|
||||
# Test access scenarios
|
||||
```
|
||||
|
||||
4. **Special Permissions** (250 points)
|
||||
```bash
|
||||
# Configure SUID/SGID
|
||||
# Implement sticky bits
|
||||
```
|
||||
|
||||
5. **Complex Scenario** (300 points)
|
||||
```bash
|
||||
# Implement full web server permissions
|
||||
# Set up user access control
|
||||
# Configure automated permission updates
|
||||
```
|
||||
|
||||
**Bonus Challenge** (+500 points):
|
||||
Create a permission monitoring system that:
|
||||
- Detects unauthorized changes
|
||||
- Logs modification attempts
|
||||
- Reverts unauthorized changes
|
||||
- Sends notifications
|
||||
|
||||
## Scoring System
|
||||
- Base points for completion
|
||||
- Time bonus (varies by challenge)
|
||||
- Efficiency bonus (fewer commands = more points)
|
||||
- Style points for elegant solutions
|
||||
- Documentation quality bonus
|
||||
|
||||
## Verification Scripts
|
||||
```bash
|
||||
# Run verification
|
||||
./verify-level1.sh
|
||||
|
||||
# Check score
|
||||
./check-score.sh
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
# Level 2: Process Whisperer 💻
|
||||
|
||||
## Overview
|
||||
Master process management and system resource control.
|
||||
|
||||
### Stage 2-1: Resource Detective
|
||||
**Mission**: Identify and manage resource-intensive processes
|
||||
|
||||
**Setup**:
|
||||
```bash
|
||||
# Create resource-intensive processes
|
||||
yes > /dev/null &
|
||||
dd if=/dev/zero of=/dev/null &
|
||||
```
|
||||
|
||||
**Challenges**:
|
||||
1. Identify top CPU-consuming processes
|
||||
2. Find memory-intensive applications
|
||||
3. Adjust process priorities
|
||||
4. Kill runaway processes
|
||||
5. Monitor system load
|
||||
|
||||
**Success Criteria**:
|
||||
- [ ] Processes correctly identified
|
||||
- [ ] Resources optimized
|
||||
- [ ] System stability maintained
|
||||
- [ ] Efficient command usage
|
||||
|
||||
**Skills Used**:
|
||||
- `top`/`htop`
|
||||
- `ps`
|
||||
- `nice`/`renice`
|
||||
- `kill`/`pkill`
|
||||
- `uptime`
|
||||
|
||||
### Stage 2-2: Service Sorcerer
|
||||
**Mission**: Troubleshoot and fix system services
|
||||
|
||||
**Setup**:
|
||||
```bash
|
||||
# Install and configure test services
|
||||
sudo apt install nginx
|
||||
sudo systemctl stop nginx
|
||||
```
|
||||
|
||||
**Challenges**:
|
||||
1. Check service status
|
||||
2. Analyze service logs
|
||||
3. Fix dependencies
|
||||
4. Configure service parameters
|
||||
5. Create basic systemd service
|
||||
|
||||
**Success Criteria**:
|
||||
- [ ] Services running correctly
|
||||
- [ ] Logs properly analyzed
|
||||
- [ ] Dependencies resolved
|
||||
- [ ] Automation implemented
|
||||
|
||||
**Skills Used**:
|
||||
- `systemctl`
|
||||
- `journalctl`
|
||||
- `service`
|
||||
- `status`
|
||||
- Log analysis
|
||||
@@ -0,0 +1,267 @@
|
||||
#!/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"
|
||||
)
|
||||
|
||||
# Challenge definitions with detailed metadata
|
||||
# Format: type|name|difficulty|skills|task|hints|setup_requirements|verification_criteria
|
||||
declare -A CHALLENGES=(
|
||||
# Level 1: File Operations
|
||||
["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
|
||||
}
|
||||
|
||||
# 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
|
||||
log_message "SUCCESS" "Challenge $challenge_id: $message"
|
||||
update_challenge_status "$challenge_id" "1" "$end_time"
|
||||
|
||||
# Calculate bonus points
|
||||
local duration=$((end_time - start_time))
|
||||
local command_count=$(get_command_count "$challenge_id")
|
||||
local bonus_points=$(calculate_bonus_points "$duration" "$command_count")
|
||||
|
||||
award_points "$challenge_id" "$((100 + bonus_points))"
|
||||
return 0
|
||||
else
|
||||
log_message "ERROR" "Challenge $challenge_id: Completed $actual/$expected checks"
|
||||
update_challenge_status "$challenge_id" "0" "$end_time"
|
||||
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))
|
||||
}
|
||||
|
||||
# Get challenge details with color formatting
|
||||
get_challenge_details() {
|
||||
local challenge_id=$1
|
||||
IFS='|' read -r type name difficulty skills task hints requirements _ <<< "${CHALLENGES[$challenge_id]}"
|
||||
|
||||
cat << EOF
|
||||
${BOLD}Challenge ${challenge_id}${NC}: ${YELLOW}$name${NC}
|
||||
${BLUE}Difficulty${NC}: $(printf '★%.0s' $(seq 1 "$difficulty"))
|
||||
${BLUE}Skills${NC}: $skills
|
||||
${BLUE}Task${NC}: $task
|
||||
${BLUE}Hint${NC}: $hints
|
||||
EOF
|
||||
}
|
||||
|
||||
# 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() {
|
||||
echo -e "\n${BOLD}Available Challenges:${NC}"
|
||||
for challenge_id in "${!CHALLENGES[@]}"; do
|
||||
IFS='|' read -r type name difficulty skills task hints requirements _ <<< "${CHALLENGES[$challenge_id]}"
|
||||
if ! is_challenge_completed "$challenge_id"; then
|
||||
echo -e "\n${YELLOW}Challenge $challenge_id${NC} ($difficulty★)"
|
||||
echo "Type: $type"
|
||||
echo "Skills: $skills"
|
||||
echo "Task: $task"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Directory structure
|
||||
CHALLENGE_DIR=~/challenge
|
||||
TRACKING_DIR="$CHALLENGE_DIR/.tracking"
|
||||
DATA_DIR="$TRACKING_DIR/data"
|
||||
REPORT_DIR="$TRACKING_DIR/reports"
|
||||
|
||||
# Data files
|
||||
PROGRESS_FILE="$DATA_DIR/progress.csv"
|
||||
SCORE_FILE="$DATA_DIR/score.csv"
|
||||
LOG_FILE="$DATA_DIR/challenge.log"
|
||||
COMMAND_LOG="$DATA_DIR/commands.log"
|
||||
TIME_LOG="$DATA_DIR/time.log"
|
||||
HINT_FILE="$DATA_DIR/hints_used.csv"
|
||||
ACHIEVEMENT_FILE="$DATA_DIR/achievements.csv"
|
||||
ATTEMPT_FILE="$DATA_DIR/attempts.csv"
|
||||
SKILL_FILE="$DATA_DIR/skills.csv"
|
||||
|
||||
# Formatting
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Achievement definitions with categories
|
||||
declare -A ACHIEVEMENTS=(
|
||||
# Speed achievements
|
||||
["speed_demon"]="Complete any challenge in under 1 minute|speed"
|
||||
["speed_runner"]="Complete 3 challenges in under 5 minutes|speed"
|
||||
|
||||
# Efficiency achievements
|
||||
["efficiency_expert"]="Complete a challenge using minimal commands|efficiency"
|
||||
["command_master"]="Use advanced command options|efficiency"
|
||||
|
||||
# Learning achievements
|
||||
["self_learner"]="Complete without hints|learning"
|
||||
["persistent"]="Try until success|learning"
|
||||
["explorer"]="Try multiple solution approaches|learning"
|
||||
|
||||
# Skill achievements
|
||||
["file_master"]="Master file operations|skill"
|
||||
["permission_guru"]="Master permission management|skill"
|
||||
["search_expert"]="Master file searching|skill"
|
||||
)
|
||||
|
||||
# Skill tracking definitions
|
||||
declare -A SKILLS=(
|
||||
["file_ops"]="File Operations"
|
||||
["permissions"]="Permission Management"
|
||||
["search"]="File Search and Analysis"
|
||||
["text_proc"]="Text Processing"
|
||||
["monitoring"]="System Monitoring"
|
||||
)
|
||||
|
||||
# Logging function with severity levels
|
||||
log_message() {
|
||||
local severity=$1
|
||||
local message=$2
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
local color
|
||||
|
||||
case $severity in
|
||||
"INFO") color=$BLUE ;;
|
||||
"SUCCESS") color=$GREEN ;;
|
||||
"WARNING") color=$YELLOW ;;
|
||||
"ERROR") color=$RED ;;
|
||||
*) color=$NC ;;
|
||||
esac
|
||||
|
||||
echo -e "${color}[$severity]${NC} $message"
|
||||
echo "[$timestamp] [$severity] $message" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Initialize environment with comprehensive setup
|
||||
init_environment() {
|
||||
log_message "INFO" "Initializing enhanced challenge environment..."
|
||||
|
||||
# Create directory structure
|
||||
for dir in "$DATA_DIR" "$REPORT_DIR" "$CHALLENGE_DIR"/{files,backup,temp}; do
|
||||
if ! mkdir -p "$dir"; then
|
||||
log_message "ERROR" "Failed to create directory: $dir"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Initialize data files with headers
|
||||
cat > "$PROGRESS_FILE" << EOF
|
||||
challenge_id,timestamp,status,difficulty,skills_used
|
||||
EOF
|
||||
|
||||
cat > "$SCORE_FILE" << EOF
|
||||
challenge_id,points,timestamp,efficiency_bonus,speed_bonus
|
||||
EOF
|
||||
|
||||
cat > "$ATTEMPT_FILE" << EOF
|
||||
challenge_id,attempt_number,timestamp,commands_used,duration,success
|
||||
EOF
|
||||
|
||||
cat > "$SKILL_FILE" << EOF
|
||||
skill_id,level,experience,last_used
|
||||
EOF
|
||||
|
||||
# Initialize skills
|
||||
for skill in "${!SKILLS[@]}"; do
|
||||
echo "$skill,1,0,0" >> "$SKILL_FILE"
|
||||
done
|
||||
|
||||
setup_command_tracking
|
||||
log_message "SUCCESS" "Environment initialized successfully"
|
||||
}
|
||||
|
||||
# Enhanced command tracking
|
||||
setup_command_tracking() {
|
||||
local track_cmd='
|
||||
command_status=$?
|
||||
cmd=$(history 1 | cut -c 8-)
|
||||
timestamp=$(date +%s)
|
||||
echo "$timestamp|$command_status|$cmd" >> '"$COMMAND_LOG"'
|
||||
analyze_command "$cmd"
|
||||
'
|
||||
|
||||
if ! grep -q "PROMPT_COMMAND" ~/.bashrc; then
|
||||
echo "PROMPT_COMMAND='$track_cmd'" >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
fi
|
||||
}
|
||||
|
||||
# Command analysis for skill progression
|
||||
analyze_command() {
|
||||
local cmd=$1
|
||||
case "$cmd" in
|
||||
*find*) update_skill "search" 2 ;;
|
||||
*chmod*|*chown*) update_skill "permissions" 2 ;;
|
||||
*grep*|*sed*|*awk*) update_skill "text_proc" 2 ;;
|
||||
*ps*|*top*|*netstat*) update_skill "monitoring" 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Update skill progression
|
||||
update_skill() {
|
||||
local skill=$1
|
||||
local exp_gain=$2
|
||||
local current_level current_exp
|
||||
|
||||
IFS=, read -r _ current_level current_exp _ < <(grep "^$skill," "$SKILL_FILE")
|
||||
|
||||
current_exp=$((current_exp + exp_gain))
|
||||
if [ $current_exp -ge $((current_level * 100)) ]; then
|
||||
current_level=$((current_level + 1))
|
||||
current_exp=0
|
||||
log_message "SUCCESS" "🎓 Skill Level Up: ${SKILLS[$skill]} is now level $current_level!"
|
||||
fi
|
||||
|
||||
sed -i "/^$skill,/c\\$skill,$current_level,$current_exp,$(date +%s)" "$SKILL_FILE"
|
||||
}
|
||||
|
||||
# Enhanced progress tracking with recommendations
|
||||
show_progress() {
|
||||
clear
|
||||
echo -e "\n${BOLD}🎮 Challenge Progress Report${NC}"
|
||||
echo "=============================="
|
||||
|
||||
# Show statistics
|
||||
show_statistics
|
||||
|
||||
# Show achievements by category
|
||||
show_achievements
|
||||
|
||||
# Show skill progression
|
||||
show_skills
|
||||
|
||||
# Show recommendations
|
||||
show_recommendations
|
||||
}
|
||||
|
||||
# Detailed statistics display
|
||||
show_statistics() {
|
||||
local total_score=0
|
||||
local challenges_completed=0
|
||||
|
||||
while IFS=, read -r challenge points _ efficiency_bonus speed_bonus; do
|
||||
[ -z "$challenge" ] && continue
|
||||
total_score=$((total_score + points + ${efficiency_bonus:-0} + ${speed_bonus:-0}))
|
||||
((challenges_completed++))
|
||||
done < "$SCORE_FILE"
|
||||
|
||||
echo -e "\n${BOLD}📊 Statistics${NC}"
|
||||
echo "----------------"
|
||||
printf "Challenges Completed: %d/10\n" "$challenges_completed"
|
||||
printf "Total Score: %d/1500\n" "$total_score"
|
||||
printf "Average Score: %d\n" "$((total_score / (challenges_completed || 1)))"
|
||||
}
|
||||
|
||||
# Achievement display by category
|
||||
show_achievements() {
|
||||
echo -e "\n${BOLD}🏆 Achievements${NC}"
|
||||
echo "----------------"
|
||||
|
||||
local categories=("speed" "efficiency" "learning" "skill")
|
||||
|
||||
for category in "${categories[@]}"; do
|
||||
echo -e "\n${YELLOW}${category^} Achievements:${NC}"
|
||||
while IFS=, read -r achievement timestamp description; do
|
||||
[ -z "$achievement" ] && continue
|
||||
IFS='|' read -r achievement_desc achievement_cat <<< "${ACHIEVEMENTS[$achievement]}"
|
||||
[[ "$achievement_cat" == "$category" ]] && echo " ✓ $achievement_desc"
|
||||
done < "$ACHIEVEMENT_FILE"
|
||||
done
|
||||
}
|
||||
|
||||
# Skill progression display
|
||||
show_skills() {
|
||||
echo -e "\n${BOLD}🎓 Skills${NC}"
|
||||
echo "----------------"
|
||||
|
||||
while IFS=, read -r skill level exp last_used; do
|
||||
[ -z "$skill" ] && continue
|
||||
local skill_name="${SKILLS[$skill]}"
|
||||
local progress=$((exp * 100 / (level * 100)))
|
||||
printf "%s (Level %d): [%-20s] %d%%\n" \
|
||||
"$skill_name" "$level" \
|
||||
"$(printf '#%.0s' $(seq 1 $((progress / 5))))" \
|
||||
"$progress"
|
||||
done < "$SKILL_FILE"
|
||||
}
|
||||
|
||||
# Learning recommendations
|
||||
show_recommendations() {
|
||||
echo -e "\n${BOLD}📚 Recommendations${NC}"
|
||||
echo "----------------"
|
||||
|
||||
# Analyze weak skills
|
||||
local weakest_skill=""
|
||||
local lowest_level=999
|
||||
|
||||
while IFS=, read -r skill level _; do
|
||||
[ -z "$skill" ] && continue
|
||||
if [ "$level" -lt "$lowest_level" ]; then
|
||||
lowest_level=$level
|
||||
weakest_skill=$skill
|
||||
fi
|
||||
done < "$SKILL_FILE"
|
||||
|
||||
[ -n "$weakest_skill" ] && echo "Focus on improving: ${SKILLS[$weakest_skill]}"
|
||||
|
||||
# Suggest next challenges based on skill levels
|
||||
echo "Recommended next challenges:"
|
||||
suggest_challenges
|
||||
}
|
||||
|
||||
# Check if challenge is completed
|
||||
is_challenge_completed() {
|
||||
local challenge=$1
|
||||
grep -q "^$challenge," "$SCORE_FILE" && return 0
|
||||
return 1
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Import common functions and variables
|
||||
source "$(dirname "$0")/common.sh"
|
||||
|
||||
# Challenge-specific setup
|
||||
setup_file_challenges() {
|
||||
log_message "Setting up file system challenges..."
|
||||
|
||||
# Create complex directory structure
|
||||
for dir in {1..5}; do
|
||||
mkdir -p "$CHALLENGE_DIR/files/project$dir/{src,config,logs,data}"
|
||||
|
||||
# Create various file types
|
||||
touch "$CHALLENGE_DIR/files/project$dir/src/main.py"
|
||||
touch "$CHALLENGE_DIR/files/project$dir/src/test.py"
|
||||
echo "debug=true" > "$CHALLENGE_DIR/files/project$dir/config/settings.conf"
|
||||
|
||||
# Create log files with realistic content
|
||||
for severity in INFO WARN ERROR DEBUG; do
|
||||
for i in {1..10}; do
|
||||
echo "[$(date -d "@$(($(date +%s) - RANDOM % 86400))" '+%Y-%m-%d %H:%M:%S')] [$severity] Message $i" >> "$CHALLENGE_DIR/files/project$dir/logs/app.log"
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
setup_permission_challenges() {
|
||||
log_message "Setting up permission challenges..."
|
||||
|
||||
# Create test users and groups
|
||||
for i in {1..3}; do
|
||||
sudo groupadd -f "app_group$i" 2>/dev/null
|
||||
sudo useradd -M -N -g "app_group$i" "app_user$i" 2>/dev/null
|
||||
done
|
||||
|
||||
# Create files with specific permissions
|
||||
mkdir -p "$CHALLENGE_DIR/files/permissions_test"
|
||||
for i in {1..5}; do
|
||||
echo "content$i" > "$CHALLENGE_DIR/files/permissions_test/file$i.txt"
|
||||
chmod $((600 + i)) "$CHALLENGE_DIR/files/permissions_test/file$i.txt"
|
||||
done
|
||||
}
|
||||
|
||||
create_verification_functions() {
|
||||
cat << 'EOF' > "$CHALLENGE_DIR/.tracking/verify-challenges.sh"
|
||||
#!/bin/bash
|
||||
|
||||
source "$(dirname "$0")/common.sh"
|
||||
|
||||
# Verification functions for each challenge
|
||||
verify_file_search() {
|
||||
local challenge_num=$1
|
||||
local description=$2
|
||||
local command=$3
|
||||
local expected=$4
|
||||
|
||||
log_message "Verifying challenge $challenge_num: $description"
|
||||
|
||||
local result
|
||||
result=$(eval "$command")
|
||||
|
||||
if [[ "$result" == "$expected" ]]; then
|
||||
award_points $challenge_num 100
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
verify_permission_setup() {
|
||||
local file=$1
|
||||
local expected_perms=$2
|
||||
local expected_owner=$3
|
||||
|
||||
local actual_perms=$(stat -c "%a" "$file")
|
||||
local actual_owner=$(stat -c "%U:%G" "$file")
|
||||
|
||||
[[ "$actual_perms" == "$expected_perms" && "$actual_owner" == "$expected_owner" ]]
|
||||
}
|
||||
|
||||
# Challenge verification functions
|
||||
verify_challenge_1() {
|
||||
# Find recent conf files
|
||||
verify_file_search 1 "Find recent configuration files" \
|
||||
"find \$CHALLENGE_DIR/files -name '*.conf' -mtime -1 | wc -l" \
|
||||
"10"
|
||||
}
|
||||
|
||||
verify_challenge_2() {
|
||||
# Count ERROR entries in logs
|
||||
verify_file_search 2 "Count ERROR messages" \
|
||||
"grep -r 'ERROR' \$CHALLENGE_DIR/files/*/logs | wc -l" \
|
||||
"15"
|
||||
}
|
||||
|
||||
# Add more verification functions...
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
create_challenge_tracker() {
|
||||
cat << 'EOF' > "$CHALLENGE_DIR/.tracking/challenge-tracker.sh"
|
||||
#!/bin/bash
|
||||
|
||||
source "$(dirname "$0")/common.sh"
|
||||
|
||||
# Track command usage
|
||||
track_command() {
|
||||
local command=$1
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $command" >> "$CHALLENGE_DIR/.tracking/commands.log"
|
||||
}
|
||||
|
||||
# Track time spent
|
||||
track_time() {
|
||||
local challenge=$1
|
||||
local start_time=$2
|
||||
local end_time=$3
|
||||
local duration=$((end_time - start_time))
|
||||
echo "$challenge,$duration" >> "$CHALLENGE_DIR/.tracking/time.log"
|
||||
}
|
||||
|
||||
# Show challenge hints
|
||||
show_hint() {
|
||||
local challenge=$1
|
||||
case $challenge in
|
||||
1) echo "Try using 'find' with -mtime flag" ;;
|
||||
2) echo "Consider 'grep' with -r flag" ;;
|
||||
*) echo "No hint available" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Show challenge status
|
||||
show_status() {
|
||||
local total_score=0
|
||||
local completed=0
|
||||
|
||||
echo "Challenge Status:"
|
||||
echo "----------------"
|
||||
|
||||
while IFS=, read -r challenge score; do
|
||||
total_score=$((total_score + score))
|
||||
[[ $score -gt 0 ]] && ((completed++))
|
||||
printf "Challenge %s: %s points\n" "$challenge" "$score"
|
||||
done < "$SCORE_FILE"
|
||||
|
||||
echo "----------------"
|
||||
printf "Total Score: %s/1500\n" "$total_score"
|
||||
printf "Completed: %s/10 challenges\n" "$completed"
|
||||
}
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Main setup function
|
||||
main() {
|
||||
init_environment
|
||||
setup_file_challenges
|
||||
setup_permission_challenges
|
||||
create_verification_functions
|
||||
create_challenge_tracker
|
||||
|
||||
log_message "Challenge environment ready!"
|
||||
cat << EOF
|
||||
${GREEN}Level 1 Setup Complete!${NC}
|
||||
|
||||
Available commands:
|
||||
- ${YELLOW}check-progress${NC}: Show current progress
|
||||
- ${YELLOW}verify-challenge <num>${NC}: Verify specific challenge
|
||||
- ${YELLOW}show-hint <num>${NC}: Get hint for challenge
|
||||
- ${YELLOW}show-status${NC}: Display challenge status
|
||||
|
||||
Start with challenge 1: Find all recent configuration files
|
||||
Good luck!
|
||||
EOF
|
||||
}
|
||||
|
||||
# Run setup
|
||||
main
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
CHALLENGE_DIR=~/challenge
|
||||
PROGRESS_FILE="$CHALLENGE_DIR/.progress"
|
||||
SCORE_FILE="$CHALLENGE_DIR/.score"
|
||||
LOG_FILE="$CHALLENGE_DIR/.challenge.log"
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
show_progress() {
|
||||
local current_score=$(cat "$SCORE_FILE" 2>/dev/null || echo "0")
|
||||
local total_possible=1500 # Base challenges + bonus
|
||||
local progress=$((current_score * 100 / total_possible))
|
||||
|
||||
echo -e "${GREEN}Challenge Progress${NC}"
|
||||
echo "----------------------------------------"
|
||||
echo -e "Current Score: ${YELLOW}$current_score${NC} / $total_possible points"
|
||||
echo -e "Progress: ${YELLOW}$progress%${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Show recent activity
|
||||
echo -e "\n${GREEN}Recent Activity:${NC}"
|
||||
tail -n 5 "$LOG_FILE"
|
||||
|
||||
# Show incomplete challenges
|
||||
echo -e "\n${GREEN}Remaining Challenges:${NC}"
|
||||
"$CHALLENGE_DIR/.tracking/verify-level1.sh" --list-incomplete
|
||||
}
|
||||
|
||||
show_progress
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
source "$(dirname "$0")/setup/common.sh"
|
||||
source "$(dirname "$0")/setup/challenges.sh"
|
||||
|
||||
# Function to start a challenge
|
||||
start_challenge() {
|
||||
local challenge_id=$1
|
||||
|
||||
# Clear screen and show welcome message
|
||||
clear
|
||||
echo -e "${BOLD}🎮 Command Line Mastery Challenge${NC}"
|
||||
echo "=============================="
|
||||
|
||||
# Show challenge details
|
||||
get_challenge_details "$challenge_id"
|
||||
|
||||
# Initialize challenge environment
|
||||
echo -e "\n${BLUE}Setting up challenge environment...${NC}"
|
||||
"$CHALLENGE_DIR/.tracking/level1-setup.sh"
|
||||
|
||||
# Record start time
|
||||
local start_time=$(date +%s)
|
||||
echo "$challenge_id,$start_time" > "$CHALLENGE_DIR/.tracking/current_challenge"
|
||||
|
||||
echo -e "\n${GREEN}Challenge environment ready!${NC}"
|
||||
echo -e "Type ${YELLOW}verify-challenge${NC} when you're ready to check your solution"
|
||||
echo -e "Type ${YELLOW}show-hint${NC} if you need help"
|
||||
echo -e "Type ${YELLOW}show-progress${NC} to see your progress\n"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "Usage: $0 <challenge-id>"
|
||||
echo "Available challenges:"
|
||||
list_challenges
|
||||
exit 1
|
||||
fi
|
||||
|
||||
start_challenge "$1"
|
||||
Reference in New Issue
Block a user