Update question bank and session log; enhance quiz functionality and progress tracking

This commit is contained in:
2025-08-15 11:16:41 +02:00
parent e93c8cede6
commit 6d5e6aad77
4 changed files with 95 additions and 56 deletions

View File

@@ -1,38 +1,38 @@
General|Which command creates a compressed tar archive?|bzip2 dir|gzip dir|tar czf archive.tar.gz dir|3
General|How do you append output to a file in Bash?|>>|>|&>|1
General|Which command finds all files named "passwd" under /etc?|find /etc -name passwd|ls /etc/passwd|grep passwd /etc|1
General|How do you switch to the root user?|sudo root|sudo su -|su -|3
General|Which command shows the SELinux context of a file?|ls -l|ls -Z|ls --context|2
General|How do you create a new user?|useradd|usermod|adduser|1
General|Which command lists all running containers?|docker ps|podman ps|podman list|2
General|How do you mount an NFS share?|mount -t nfs server:/share /mnt|mount -o loop image.iso /mnt|mount -t ext4 /dev/sda1 /mnt|1
General|How do you schedule a one-time job for 5 minutes from now?|at now + 5 minutes|cron 5|crontab -e|1
General|Which command sets a file's permissions to rwxr-xr--?|chmod 777 file|chmod 754 file|chmod 644 file|2
General|How do you check the status of firewalld?|firewall-cmd --state|systemctl firewall|firewallctl status|1
General|How do you extend a logical volume by 1G?|lvresize -L 1G /dev/vg/lv|lvextend -L +1G /dev/vg/lv|lvcreate -L 1G /dev/vg/lv|2
General|How do you display the last 10 lines of a file?|tail file|head file|less file|1
General|How do you change a user's password aging policy?|usermod|passwd|chage|3
General|How do you list all available systemd targets?|systemctl list-active-targets|systemctl list-units --type=target --all|systemctl list-targets|3
General|How do you display the current runlevel?|runlevel|who -r|systemctl get-default|1
General|How do you set a service to start at boot?|systemctl boot|systemctl start|systemctl enable|3
General|How do you transfer a file securely to a remote host?|scp file user@host:/path|ftp file user@host:/path|rsync file user@host:/path|1
General|How do you display the UUID of a filesystem?|blkid|lsblk|uuidgen|1
General|How do you reload the systemd daemon?|systemctl reload|systemctl daemon-reload|systemctl restart|2
Networking|How do you set the hostname to mars.domain250.example.com?|hostnamectl set-hostname mars.domain250.example.com|nmcli con mod hostname mars.domain250.example.com|echo "mars.domain250.example.com" > /etc/hostname|1
Networking|Which command sets the IP address, gateway, and DNS for enp0s3?|ifconfig enp0s3 172.25.250.100 netmask 255.255.255.0|ip addr add 172.25.250.100/24 dev enp0s3|nmcli connection modify enp0s3 autoconnect yes ipv4.method manual ipv4.addresses 172.25.250.100 ipv4.gateway 172.25.250.254 ipv4.dns 172.25.250.254|3
General|How do you append output to a file in Bash?|&>|>|>>|3
General|Which command finds all files named "passwd" under /etc?|ls /etc/passwd|find /etc -name passwd|grep passwd /etc|2
General|How do you switch to the root user?|sudo root|su -|sudo su -|2
General|Which command shows the SELinux context of a file?|ls -Z|ls --context|ls -l|1
General|How do you create a new user?|usermod|adduser|useradd|3
General|Which command lists all running containers?|podman ps|podman list|docker ps|1
General|How do you mount an NFS share?|mount -o loop image.iso /mnt|mount -t nfs server:/share /mnt|mount -t ext4 /dev/sda1 /mnt|2
General|How do you schedule a one-time job for 5 minutes from now?|cron 5|crontab -e|at now + 5 minutes|3
General|Which command sets a file's permissions to rwxr-xr--?|chmod 754 file|chmod 644 file|chmod 777 file|1
General|How do you check the status of firewalld?|firewall-cmd --state|firewallctl status|systemctl firewall|1
General|How do you extend a logical volume by 1G?|lvresize -L 1G /dev/vg/lv|lvcreate -L 1G /dev/vg/lv|lvextend -L +1G /dev/vg/lv|3
General|How do you display the last 10 lines of a file?|head file|less file|tail file|3
General|How do you change a user's password aging policy?|passwd|usermod|chage|3
General|How do you list all available systemd targets?|systemctl list-units --type=target --all|systemctl list-active-targets|systemctl list-targets|3
General|How do you display the current runlevel?|who -r|systemctl get-default|runlevel|3
General|How do you set a service to start at boot?|systemctl boot|systemctl enable|systemctl start|2
General|How do you transfer a file securely to a remote host?|rsync file user@host:/path|scp file user@host:/path|ftp file user@host:/path|2
General|How do you display the UUID of a filesystem?|lsblk|uuidgen|blkid|3
General|How do you reload the systemd daemon?|systemctl daemon-reload|systemctl restart|systemctl reload|1
Networking|How do you set the hostname to mars.domain250.example.com?|nmcli con mod hostname mars.domain250.example.com|hostnamectl set-hostname mars.domain250.example.com|echo "mars.domain250.example.com" > /etc/hostname|2
Networking|Which command sets the IP address, gateway, and DNS for enp0s3?|nmcli connection modify enp0s3 autoconnect yes ipv4.method manual ipv4.addresses 172.25.250.100 ipv4.gateway 172.25.250.254 ipv4.dns 172.25.250.254|ifconfig enp0s3 172.25.250.100 netmask 255.255.255.0|ip addr add 172.25.250.100/24 dev enp0s3|1
SELinux|How do you allow httpd to serve content on port 82?|semanage port -a -t http_port_t -p tcp 82|firewall-cmd --add-port=82/tcp --permanent|setenforce 0|1
User Management|Which command creates a user 'natasha' and adds to group 'sysmgrs'?|useradd natasha -G sysmgrs|useradd -g sysmgrs natasha|adduser natasha sysmgrs|1
User Management|How do you create a user 'sarah' with no interactive shell?|useradd sarah -G nologin|adduser sarah --no-login|useradd sarah --shell /sbin/nologin|3
Scheduling|What is the correct crontab entry to log "EX200 in progress" every 2 min?|2 * * * * logger "EX200 in progress"|0 2 * * * logger "EX200 in progress"|*/2 * * * * logger "EX200 in progress"|3
Permissions|How do you give user 'natasha' rw access to /var/tmp/fstab using ACL?|chmod 600 /var/tmp/fstab|chown natasha /var/tmp/fstab|setfacl -m u:natasha:rw- /var/tmp/fstab|3
Scheduling|What is the correct crontab entry to log "EX200 in progress" every 2 min?|*/2 * * * * logger "EX200 in progress"|2 * * * * logger "EX200 in progress"|0 2 * * * logger "EX200 in progress"|1
Permissions|How do you give user 'natasha' rw access to /var/tmp/fstab using ACL?|chown natasha /var/tmp/fstab|chmod 600 /var/tmp/fstab|setfacl -m u:natasha:rw- /var/tmp/fstab|3
Permissions|How do you deny user 'harry' all access to /var/tmp/fstab using ACL?|chmod 000 /var/tmp/fstab|setfacl -m u:harry:- /var/tmp/fstab|chown nobody /var/tmp/fstab|2
Permissions|How do you set group ownership of /home/managers to sysmgrs and setgid?|chown root:sysmgrs /home/managers && chmod g+s /home/managers|setfacl -m g:sysmgrs:rwx /home/managers|chmod 770 /home/managers|1
NTP|How do you configure chrony to use materials.example.com as NTP server?|systemctl enable ntpd|Edit /etc/chrony.conf and add 'server materials.example.com iburst'|ntpdate materials.example.com|2
Autofs|How do you configure autofs to mount remoteuser1's home from materials.example.com?|autofs --mount /rhome/remoteuser1|Add '/rhome /etc/auto.rhome' to /etc/auto.master and 'remoteuser1 -rw materials.example.com:/rhome/remoteuser1' to /etc/auto.rhome|mount -t nfs materials.example.com:/rhome/remoteuser1 /rhome/remoteuser1|2
User Management|How do you create user 'manalo' with UID 3533?|adduser manalo --uid=3533|useradd -u 3533 manalo|useradd manalo -U 3533|2
Archiving|How do you create a gzip archive of /usr/local as /root/backup.tar.gz?|gzip /usr/local > /root/backup.tar.gz|tar -cvf /root/backup.tar.gz /usr/local|tar -czvf /root/backup.tar.gz /usr/local|3
Swap|How do you add a 512M swap partition and make it persistent?|Create partition, mkswap /dev/vdb3, add UUID to /etc/fstab|swapon /dev/vdb3|echo "/dev/vdb3 swap swap defaults 0 0" >> /etc/fstab|1
LVM|How do you create a logical volume 'qa' of 60 PE in group 'qagroup' and format ext3?|lvcreate -n qa -l 60 qagroup && mkfs.ext3 /dev/qagroup/qa|lvcreate -n qa -l 60 qagroup && mkfs.ext4 /dev/qagroup/qa|lvcreate -n qa -L 60M qagroup && mkfs.ext3 /dev/qagroup/qa|1
Permissions|How do you give natasha rw and harry no access to /var/tmp/fstab using ACL?|chmod 600 /var/tmp/fstab|setfacl -m u:natasha:rw- /var/tmp/fstab|setfacl -m u:natasha:rw-,u:harry:- /var/tmp/fstab|3
Permissions|How do you set group ownership of /home/managers to sysmgrs and setgid?|setfacl -m g:sysmgrs:rwx /home/managers|chown root:sysmgrs /home/managers && chmod g+s /home/managers|chmod 770 /home/managers|2
NTP|How do you configure chrony to use materials.example.com as NTP server?|Edit /etc/chrony.conf and add 'server materials.example.com iburst'|ntpdate materials.example.com|systemctl enable ntpd|1
Autofs|How do you configure autofs to mount remoteuser1's home from materials.example.com?|autofs --mount /rhome/remoteuser1|mount -t nfs materials.example.com:/rhome/remoteuser1 /rhome/remoteuser1|Add '/rhome /etc/auto.rhome' to /etc/auto.master and 'remoteuser1 -rw materials.example.com:/rhome/remoteuser1' to /etc/auto.rhome|3
User Management|How do you create user 'manalo' with UID 3533?|useradd manalo -U 3533|adduser manalo --uid=3533|useradd -u 3533 manalo|3
Archiving|How do you create a gzip archive of /usr/local as /root/backup.tar.gz?|tar -cvf /root/backup.tar.gz /usr/local|tar -czvf /root/backup.tar.gz /usr/local|gzip /usr/local > /root/backup.tar.gz|2
Swap|How do you add a 512M swap partition and make it persistent?|swapon /dev/vdb3|echo "/dev/vdb3 swap swap defaults 0 0" >> /etc/fstab|Create partition, mkswap /dev/vdb3, add UUID to /etc/fstab|3
LVM|How do you create a logical volume 'qa' of 60 PE in group 'qagroup' and format ext3?|lvcreate -n qa -l 60 qagroup && mkfs.ext4 /dev/qagroup/qa|lvcreate -n qa -l 60 qagroup && mkfs.ext3 /dev/qagroup/qa|lvcreate -n qa -L 60M qagroup && mkfs.ext3 /dev/qagroup/qa|2
Permissions|How do you give natasha rw and harry no access to /var/tmp/fstab using ACL?|setfacl -m u:natasha:rw-,u:harry:- /var/tmp/fstab|setfacl -m u:natasha:rw- /var/tmp/fstab|chmod 600 /var/tmp/fstab|1
Scripting|How do you find all files under /usr less than 10M with sgid and save to /root/myfile?|find /usr -size -10M -perm -2000 > /root/myfile|find /usr -size -10M -perm -4000 > /root/myfile|find /usr -size +10M -perm -2000 > /root/myfile|1
Scripting|How do you create a script to find SUID files between 30k and 50k in /usr?|find /usr -size +30k -size -50k -perm /g=s > /root/newfiles|find /usr -size +30k -size -50k -perm /o=s > /root/newfiles|find /usr -size +30k -size -50k -perm /u=s > /root/newfiles|3
Scripting|How do you create a script to find SUID files between 30k and 50k in /usr?|find /usr -size +30k -size -50k -perm /g=s > /root/newfiles|find /usr -size +30k -size -50k -perm /u=s > /root/newfiles|find /usr -size +30k -size -50k -perm /o=s > /root/newfiles|2

View File

@@ -1,3 +1,6 @@
Session start: 2025-08-15 10:19:42
Session start: 2025-08-15 11:16:11
XP and level updated: 0 XP, Level 1
XP and level updated: 0 XP, Level 1
XP and level updated: 0 XP, Level 1
XP and level updated: 10 XP, Level 1
Session end: 2025-08-15 10:19:52
Session end: 2025-08-15 11:16:34

80
main.py
View File

@@ -279,7 +279,7 @@ def update_xp(correct):
if correct:
xp, level, leveled_up = stats.add_xp(10)
else:
xp, level, _ = stats.get_xp_level()
xp, level = stats.get_xp_level()
xp = max(0, xp - 5)
stats.save_stats(xp, level, stats.get_total_time())
leveled_up = False
@@ -290,6 +290,10 @@ def update_xp(correct):
return xp, level
def show_timer(minutes, questions_file, session_log, total_time, xp, level, root):
# Initialize timer variables BEFORE any inner function definitions
seconds_left = minutes * 60
elapsed_time = 0
def update_timer():
nonlocal seconds_left, elapsed_time
if seconds_left > 0:
@@ -354,27 +358,45 @@ def show_timer(minutes, questions_file, session_log, total_time, xp, level, root
total_questions = 0
max_score = 300
# Show all questions in random order
# Shuffle and use each question only once per session
random.shuffle(lines)
questions_to_ask = lines
question_idx = 0
questions_to_ask = lines.copy()
# Create a frame for question/answer widgets ONCE
question_frame = tk.Frame(root)
question_frame.pack(pady=10)
# Add a label to show per-category progress
progress_label = tk.Label(root, text="", font=("Helvetica", 10), fg="blue")
progress_label.pack(pady=2)
def update_progress_label():
# Always show progress for each category, even if empty
progress_items = []
all_cats = set(score_by_category.keys())
for q in lines:
cat = q.split('|')[0] if q.split('|')[0] else "General"
all_cats.add(cat)
for cat in sorted(all_cats):
correct, total = score_by_category.get(cat, [0, 0])
progress_items.append(f"{cat[:3].upper()}:{correct}/{total}")
# Break into multiple lines if too many categories
max_per_line = 7
lines_out = [" | ".join(progress_items[i:i+max_per_line]) for i in range(0, len(progress_items), max_per_line)]
progress_label.config(text="\n".join(lines_out))
def ask_next_question():
nonlocal question_idx, total_questions, total_correct
if question_idx >= len(questions_to_ask):
nonlocal total_questions, total_correct
if not questions_to_ask:
# Show score page at end
total_score = int((total_correct / total_questions) * max_score) if total_questions else 0
root.destroy()
show_score_page(score_by_category, total_score)
return
qline = questions_to_ask[question_idx]
qline = questions_to_ask.pop(0)
parts = qline.split('|')
if len(parts) < 5:
question_idx += 1
ask_next_question()
return
@@ -410,7 +432,7 @@ def show_timer(minutes, questions_file, session_log, total_time, xp, level, root
radio_buttons.append(rb)
def check_answer():
nonlocal question_idx, total_questions, total_correct
nonlocal total_questions, total_correct
sel = answer_var.get()
correct = any(o['text'] == sel and o['correct'] for o in opts)
# Find the correct answer
@@ -429,20 +451,29 @@ def show_timer(minutes, questions_file, session_log, total_time, xp, level, root
new_xp, new_level = update_xp(True)
score_by_category.setdefault(category, [0, 0])[0] += 1
total_correct += 1
score_by_category.setdefault(category, [0, 0])[1] += 1
total_questions += 1
for b in radio_buttons: b.config(state=tk.DISABLED)
xp_label.config(text=f"XP: {new_xp}")
level_label.config(text=f"Level: {new_level}")
update_progress_label()
root.after(500, ask_next_question)
else:
messagebox.showinfo("Incorrect", f"Sorry, that's not correct.\n{detail}")
new_xp, new_level = update_xp(False)
score_by_category.setdefault(category, [0, 0])[1] += 1
total_questions += 1
for b in radio_buttons: b.config(state=tk.DISABLED)
xp_label.config(text=f"XP: {new_xp}")
level_label.config(text=f"Level: {new_level}")
root.after(500, lambda: [ask_next_question()])
score_by_category.setdefault(category, [0, 0])[1] += 1
total_questions += 1
xp_label.config(text=f"XP: {new_xp}")
level_label.config(text=f"Level: {new_level}")
update_progress_label()
# Show explanation, then immediately go to next question after dialog closes
def after_incorrect():
ask_next_question()
messagebox.showinfo("Incorrect", f"Sorry, that's not correct.\n{detail}")
root.after(10, after_incorrect)
submit_btn = tk.Button(question_frame, text="Submit", command=check_answer)
submit_btn.pack(pady=5)
stats = UserStatsSqlite(DB_PATH, SUBSCRIPTION_END_DATE)
timer_label = tk.Label(root, text=f"Time left: {minutes:02}:00:00", font=("Helvetica", 16))
timer_label.pack(pady=20)
@@ -460,17 +491,22 @@ def show_timer(minutes, questions_file, session_log, total_time, xp, level, root
total_time_label = tk.Label(root, text=f"Total session time: {format_time(stats.get_total_time())}", font=("Helvetica", 14))
total_time_label.pack(pady=5)
# Start the first question
def update_total_time_label():
nonlocal elapsed_time
# Show total time as (previous total + elapsed this session)
current_total = stats.get_total_time() + elapsed_time
total_time_label.config(text=f"Total session time: {format_time(current_total)}")
root.after(1000, update_total_time_label)
# Start the first question and live-updating total time
update_progress_label()
update_total_time_label()
ask_next_question()
def periodic_kill_steam():
kill_steam()
root.after(10000, periodic_kill_steam)
seconds_left = minutes * 60
elapsed_time = 0
root.after(1000, update_timer)
root.after(1000, update_rol_timer)
root.after(10000, periodic_kill_steam)

Binary file not shown.