Audacity is open with /home/user/Music/audiobook.aup loaded. The project contains a single wavetrack (5 seconds of narration) and no label tracks. Add a label track and place four chapter labels on it, in this order from earliest to latest: 'Intro', 'Chapter 1', 'Chapter 2', 'Outro'. Save the project so the label track and its four labels are persisted to /home/user/Music/audiobook.aup. Exact timestamps do not matter — only that there are exactly four labels with those exact titles on one label track.

audiobook.aup is still valid

Exactly 1 label track exists

Label track has exactly 4 labels

Label 'Intro' exists

check-label-exists /home/user/Music/audiobook.aup 'Chapter 1'

Label 'Chapter 1' exists

check-label-exists /home/user/Music/audiobook.aup 'Chapter 2'

Label 'Chapter 2' exists

Label 'Outro' exists

Original wavetrack count preserved (1)


Audacity is open with /home/user/Music/input.wav already loaded (a 2.5-second mono 44.1 kHz WAV file). Export this audio as a FLAC file to /home/user/Music/output.flac with 16-bit sample format.

Exported FLAC exists

Codec is flac

Sample rate is 44100 Hz

FLAC has 1 channel (mono)

Container format is flac


Audacity is open with /home/user/Music/source.wav already loaded (a 3-second stereo 44.1 kHz WAV file). Export this audio as an MP3 file to /home/user/Music/song.mp3 using default bit-rate settings.

Exported MP3 exists

Codec is mp3

MP3 has 2 channels (stereo)

MP3 duration is at least 2.5 seconds


Audacity is open with /home/user/Music/voice.wav already loaded (a 3-second mono 44.1 kHz WAV file). Export this audio as an OGG Vorbis file to /home/user/Music/voice.ogg with quality setting 0.5.

Exported OGG exists

Codec is vorbis

Duration is at least 2.5 seconds


Audacity is open with /home/user/Music/song.aup loaded. The project contains a single stereo wavetrack (~3 seconds). The project currently has no metadata tags. Set these tag values exactly: Title: Starlight, Artist: Nova Sound, Year: 2025. Save the project with Ctrl+S (so the tags are persisted inside /home/user/Music/song.aup). Export the audio as a WAV file to /home/user/Music/starlight.wav using 'WAV (Microsoft) signed 16-bit PCM' format. Both the updated /home/user/Music/song.aup AND the exported /home/user/Music/starlight.wav must exist.

song.aup is still valid

check-tag-value /home/user/Music/song.aup TITLE Starlight

TITLE tag is 'Starlight' in .aup

check-tag-value /home/user/Music/song.aup ARTIST 'Nova Sound'

ARTIST tag is 'Nova Sound' in .aup

check-tag-value /home/user/Music/song.aup YEAR 2025

YEAR tag is '2025' in .aup

Exported WAV exists at /home/user/Music/starlight.wav

Exported WAV codec is pcm_s16le

Exported WAV is stereo (2 channels)

Exported container format is WAV


Audacity is open with /home/user/Music/quiet.wav already loaded as a single mono 44.1 kHz audio track. The track is a quiet 3-second 440 Hz sine tone with peak amplitude near -20 dBFS. Select the entire audio and apply an Amplify effect with +6.0 dB amplification. Then export the result to /home/user/Music/amplified.wav as a mono 44100 Hz 16-bit PCM WAV file.

Amplified WAV exists

Codec is pcm_s16le

Sample rate 44100 Hz

Mono (1 channel)

Duration >= 2.9s

check-export-peak-db /home/user/Music/amplified.wav -15.5 -12.5

Peak amplitude boosted to near -14 dBFS (source was -20 dBFS, +6 dB applied)

check-export-dominant-freq /home/user/Music/amplified.wav 0.5 2.5 440 3

Dominant frequency still 440 Hz (amplify preserves frequency)


Audacity is open with /home/user/Music/long.wav already loaded as a single mono 44.1 kHz audio track - a 10-second sine tone at 440 Hz. Select exactly the region from 3.0 seconds to 7.0 seconds and remove it (cut), so the selected 4-second region is removed entirely, leaving a continuous 6-second track. Export the result to /home/user/Music/trimmed.wav using 'WAV (Microsoft) signed 16-bit PCM' at 44100 Hz mono.

Trimmed WAV exists

Codec pcm_s16le

Mono

44100 Hz

Duration >= 5.9s (after 4s cut)

Duration <= 6.15s (the cut really happened — not still 10s)

check-export-dominant-freq /home/user/Music/trimmed.wav 1.0 3.0 440 3

Retained audio still 440 Hz


Audacity is open with /home/user/Music/single.wav loaded (a 3-second 440 Hz sine tone at amplitude 0.3, mono 44.1 kHz - peak around -10 dBFS). Duplicate the track so there are two identical tracks at the same time offset. Save the project to /home/user/Music/single.aup. Export the full mix (both tracks playing simultaneously) to /home/user/Music/doubled.wav using 'WAV (Microsoft) signed 16-bit PCM' at 44100 Hz mono.

Project file saved

Project has exactly 2 wavetracks (duplicate created)

Doubled mix WAV exists

Codec pcm_s16le

Mono mix

Duration ~3s

check-export-peak-db /home/user/Music/doubled.wav -5.5 -2.5

Peak is ~6 dB above original (two identical tracks sum to ~2x amplitude)

check-export-dominant-freq /home/user/Music/doubled.wav 0.5 2.5 440 3

Dominant frequency still 440 Hz


Audacity is open with /home/user/Music/steady.wav loaded (a 5-second 440 Hz sine tone at constant amplitude 0.7). Apply a fade-in effect to the first 1 second (0 to 1s) and a fade-out effect to the last 1 second (4 to 5s). Export the result to /home/user/Music/faded.wav as a mono 44100 Hz 16-bit PCM WAV file.

Faded WAV exists

Codec pcm_s16le

Mono

Duration ~5s

check-export-region-silent /home/user/Music/faded.wav 0.0 0.05 -25

Start of track is faded in (near silent in first 50 ms)

check-export-region-silent /home/user/Music/faded.wav 4.95 5.0 -25

End of track is faded out (near silent in last 50 ms)

check-export-region-rms-db /home/user/Music/faded.wav 2.0 3.0 -10 -4

Middle region retains full-amplitude tone (~-9 dB RMS for 0.5 amplitude sine)


Audacity is open with an empty project. First, change the Project Rate to 48000 Hz. Generate a linear chirp with these exact settings: Waveform = Sine, Start frequency = 200 Hz, End frequency = 4000 Hz, Start amplitude = 0.8, End amplitude = 0.8, Interpolation = Linear, Duration = 4.0 seconds. Then append 2.0 seconds of silence after the chirp. The total track length should be 6.0 seconds. Export the full track to /home/user/Music/chirp_silence.wav using 'WAV (Microsoft) signed 16-bit PCM' at 48000 Hz mono.

Chirp+silence WAV exists

Codec pcm_s16le

48000 Hz

Mono

Duration ~6s

check-export-region-silent /home/user/Music/chirp_silence.wav 4.5 5.9 -30

Last ~2s region is silence

check-export-region-rms-db /home/user/Music/chirp_silence.wav 1.0 3.0 -10 -1

First 4s has signal (chirp RMS roughly -3 to -5 dB for amp 0.8)

check-export-dominant-freq /home/user/Music/chirp_silence.wav 0.0 0.2 400 40

Chirp starts near 200 Hz (sampled 0-0.2s)

check-export-dominant-freq /home/user/Music/chirp_silence.wav 3.8 4.0 3700 15

Chirp ends near 4000 Hz (sampled 3.8-4.0s)


Audacity is open with /home/user/Music/podcast.wav loaded (a 12-second mono 44.1 kHz tone). Add a new label track. Create exactly three labels in that label track: at time 0.0s with title 'intro', at time 4.0s with title 'main', at time 8.0s with title 'outro'. Save the Audacity project to /home/user/Music/podcast.aup. Export the label track to /home/user/Music/podcast_labels.txt. Do not export the audio itself - only the labels text file and the .aup project are required outputs.

Audacity project saved

Project file is a valid .aup

Exactly 1 label track

Exactly 3 labels total

Label 'intro' exists

Label 'main' exists

Label 'outro' exists

any(abs(float(l['t']) - 0.0) < 0.15 for l in result if l['title']=='intro') and any(abs(float(l['t']) - 4.0) < 0.15 for l in result if l['title']=='main') and any(abs(float(l['t']) - 8.0) < 0.15 for l in result if l['title']=='outro')

Label timestamps are at 0.0, 4.0, 8.0 (within 0.15s)

Exported labels text file exists

Labels text file is non-empty (3 entries > 30 bytes)


Audacity is open with an empty project. Generate white noise with these exact settings: Noise type = White, Amplitude = 0.8, Duration = 3.0 seconds. Select the entire noise audio and apply a low-pass filter with Cutoff frequency = 1000 Hz and Rolloff = 24 dB per octave. Export the filtered audio to /home/user/Music/filtered_noise.wav using 'WAV (Microsoft) signed 16-bit PCM' at 44100 Hz mono.

Filtered noise WAV exists

Codec pcm_s16le

44100 Hz

Mono

Duration ~3s

check-export-band-energy-ratio-max /home/user/Music/filtered_noise.wav 2000 0.35

Most energy below 2000 Hz (high-frequency content attenuated by low-pass)

check-export-region-rms-db /home/user/Music/filtered_noise.wav 0.5 2.5 -25 -3

There IS signal (not accidentally exported silence)


Audacity is open with /home/user/Music/uneven.wav already loaded as a single mono 44.1 kHz track (a 5-second 440 Hz sine tone with varying amplitude). Apply a Normalize effect to -1.0 dB. Export the result to /home/user/Music/normalized.wav as a mono 44100 Hz 16-bit PCM WAV file.

Normalized WAV exists

Codec pcm_s16le

44100 Hz

Mono

Duration ~4s

check-export-peak-db /home/user/Music/normalized.wav -1.7 -0.3

Peak normalized to -1 dB (within 0.7 dB)

check-export-dominant-freq /home/user/Music/normalized.wav 0.5 3.5 330 3

Dominant frequency preserved at 330 Hz


Audacity is open with /home/user/Music/source_a4.wav loaded (a 3-second 440 Hz sine tone, amplitude 0.5, mono 44.1 kHz). Modify the audio so that its pitch is increased from 440 Hz to 880 Hz without changing its duration. Save the result to: /home/user/Music/pitched.wav. The output must be a mono 44.1 kHz WAV file encoded as signed 16-bit PCM.

Pitched WAV exists

Codec pcm_s16le

Mono

Duration ~3s (pitch shift preserves duration)

Duration <= 3.2s (not tempo-shifted)

check-export-dominant-freq /home/user/Music/pitched.wav 0.5 2.5 880 5

Dominant frequency raised to ~880 Hz (one octave up)


Audacity is open with /home/user/Music/phrase.wav loaded — a 3-second linear chirp sweeping from 300 Hz to 3000 Hz. Apply the Reverse effect to reverse the audio in time. Export the result to /home/user/Music/reversed.wav as a mono 44100 Hz 16-bit PCM WAV file.

Reversed WAV exists

Codec pcm_s16le

Mono

Duration ~3s

check-export-dominant-freq /home/user/Music/reversed.wav 0.0 0.1 2900 20

First 0.1s now has high frequency (was end of original chirp ~3000 Hz)

check-export-dominant-freq /home/user/Music/reversed.wav 2.9 3.0 400 40

Last 0.1s now has low frequency (was start of original chirp ~300 Hz)


Audacity is open with /home/user/Music/voiceover.wav loaded (a 6-second 330 Hz tone at amplitude 0.6). Silence the audio from 2.0s to 4.0s. Export the result to /home/user/Music/silenced.wav as a mono 44100 Hz 16-bit PCM WAV file.

Silenced WAV exists

Codec pcm_s16le

Mono

Duration >= 5.9s (unchanged)

check-export-region-silent /home/user/Music/silenced.wav 2.1 3.9 -40

Region 2.1-3.9s is silent (<-40 dB RMS)

check-export-region-rms-db /home/user/Music/silenced.wav 0.5 1.5 -10 -3

Region before the silence retains original tone

check-export-region-rms-db /home/user/Music/silenced.wav 4.5 5.5 -10 -3

Region after the silence retains original tone


Audacity is open with /home/user/Music/beat.wav loaded (a 4-second 440 Hz sine tone, amplitude 0.5, mono 44.1 kHz). Select all audio and apply a tempo change with Percent Change = +100.000 percent so the tempo is doubled and the audio is compressed to roughly 2.0 seconds. The pitch should be preserved (still 440 Hz). Export the result to /home/user/Music/faster.wav using 'WAV (Microsoft) signed 16-bit PCM' at 44100 Hz mono.

Tempo-changed WAV exists

Codec pcm_s16le

Mono

Duration >= 1.85s (compressed from 4s)

Duration <= 2.2s (confirms tempo was doubled, not left unchanged)

check-export-dominant-freq /home/user/Music/faster.wav 0.3 1.5 440 5

Dominant frequency still 440 Hz (tempo change preserves pitch)


Audacity is open with /home/user/Music/base.wav already loaded as the first track (a 3-second stereo 44.1 kHz WAV). Import /home/user/Music/overlay.wav (a 3-second mono 44.1 kHz WAV) as a second track. Mix the two tracks together and export the result to /home/user/Music/mixed.wav as a stereo 44100 Hz 16-bit PCM WAV file.

Mixed WAV exists

Codec is pcm_s16le

Mixed file has 2 channels (stereo)

Duration is at least 2.5 seconds

Container format is wav


Audacity is open with /home/user/Music/empty.aup loaded. The project currently has zero audio tracks. Create three new mono audio tracks and give each a specific name, in this exact top-to-bottom order: 'Drums' (top-most track), 'Bass' (middle), 'Synth' (bottom). Save the project so the changes are persisted to /home/user/Music/empty.aup.

empty.aup is still valid

Project has exactly 3 wavetracks

A track named 'Drums' exists

A track named 'Bass' exists

A track named 'Synth' exists

[t.get('name') for t in result] == ['Drums', 'Bass', 'Synth']

Track order is Drums, Bass, Synth top-to-bottom

No label tracks were added


Audacity is open with /home/user/Music/mix.aup loaded. The project has three wavetracks in this top-to-bottom order: 'Bass' (index 0), 'Drums' (index 1), 'Keys' (index 2). All tracks are currently unmuted and unsoloed. Configure the track mute/solo state as follows: mute the 'Bass' track, solo the 'Drums' track, leave the 'Keys' track neither muted nor soloed. Save the project so the mute/solo flags are persisted inside /home/user/Music/mix.aup.

mix.aup is still valid

Project still has 3 wavetracks

check-track-mute /home/user/Music/mix.aup 0 true

Track 0 (Bass) is muted

check-track-solo /home/user/Music/mix.aup 1 true

Track 1 (Drums) is soloed

check-track-mute /home/user/Music/mix.aup 2 false

Track 2 (Keys) is NOT muted

check-track-solo /home/user/Music/mix.aup 2 false

Track 2 (Keys) is NOT soloed

check-track-mute /home/user/Music/mix.aup 1 false

Track 1 (Drums) is NOT muted

check-track-solo /home/user/Music/mix.aup 0 false

Track 0 (Bass) is NOT soloed


Audacity is already running. Change the Default Sample Format setting to '32-bit float'. Save the preference so it persists to the configuration file.

check-preference Quality DefaultSampleFormat 524293

Default sample format is 524293 (32-bit float)


Audacity is open with /home/user/Music/ambient.aup already loaded. The project contains a single wavetrack. Set the project metadata as follows: Artist: 'Ambient Artist', Title: 'Relaxing Sounds', Album: 'Chill Collection', Year: 2023, Track Number: 5, Genre: 'Ambient', Comments: 'Generated for testing'. Save the project.

Project file is still a valid .aup

check-tag-value /home/user/Music/ambient.aup TITLE 'Relaxing Sounds'

TITLE tag is 'Relaxing Sounds'

check-tag-value /home/user/Music/ambient.aup ARTIST 'Ambient Artist'

ARTIST tag is 'Ambient Artist'

check-tag-value /home/user/Music/ambient.aup ALBUM 'Chill Collection'

ALBUM tag is 'Chill Collection'

check-tag-value /home/user/Music/ambient.aup YEAR 2023

YEAR tag is '2023'

check-tag-value /home/user/Music/ambient.aup GENRE Ambient

GENRE tag is 'Ambient'

check-tag-contains /home/user/Music/ambient.aup COMMENTS 'Generated for testing'

COMMENTS tag contains 'Generated for testing'


Audacity is open with /home/user/Music/tone44.wav already loaded (a 2-second mono 44.1 kHz WAV). Change the project rate to 22050 Hz (which will resample the audio). Export the result to /home/user/Music/tone22.wav as a mono 22050 Hz 16-bit PCM WAV file.

Resampled WAV exists

Sample rate is 22050 Hz

Channel count is 1 (mono)

Codec is pcm_s16le


Audacity is open with /home/user/Music/stereo.wav already loaded (a 2-second stereo 44.1 kHz WAV). Convert the stereo track to mono and export the result to /home/user/Music/mono.wav as a mono 44100 Hz 16-bit PCM WAV file.

Mono WAV exists

Codec is pcm_s16le

Channel count is 1 (mono)

Sample rate is 44100 Hz


Open the file /home/user/Documents/quarters.xlsx in LibreOffice Calc. The workbook has sheets Q1, Q2, Q3, Q4 (each with Product in column A and Sales in column B for 8 products in rows 2-9) and a 'PriorYear' sheet with the same 8 products and their prior-year totals in column B.

1. Create a new sheet named 'Annual'.
2. On Annual, fill row 1 with bold headers: A1='Product', B1='Annual', C1='Prior Year', D1='YoY %'.
3. In A2:A9 copy the 8 product names from Q1.A2:A9 (Alpha, Beta, Gamma, Delta, Epsilon, Zeta, Eta, Theta).
4. In B2 enter =Q1.B2+Q2.B2+Q3.B2+Q4.B2 (or use =SUM(Q1.B2,Q2.B2,Q3.B2,Q4.B2)) and fill down through B9.
5. In C2 enter =VLOOKUP(A2,PriorYear.A2:B9,2,0) and fill down through C9.
6. In D2 enter =(B2-C2)/C2*100 and fill down through D9.
7. In A10 type 'Total' and make it bold. In B10 enter =SUM(B2:B9). In C10 enter =SUM(C2:C9).
8. Save the file.

Annual sheet exists

Annual A1 = Product

Annual B1 = Annual

Annual C1 = Prior Year

Annual D1 = YoY %

Annual A1 bold

Annual A2 = Alpha

Annual A9 = Theta

Annual B2 Alpha = 55000

Annual B3 Beta = 35300

Annual B4 Gamma = 66000

Annual B6 Epsilon = 87500

Annual B9 Theta = 48500

Annual C2 Alpha prior = 50000

Annual D2 Alpha YoY = 10.0

Annual D4 Gamma YoY approx 13.79

Annual A10 = Total

Annual A10 bold

Annual B10 total annual = 420300

Annual C10 total prior = 378000

result.get('formula') is not None and 'Q1' in result.get('formula','').upper() and 'Q4' in result.get('formula','').upper()

Annual B2 references Q1 and Q4

result.get('formula') is not None and ('VLOOKUP' in result.get('formula','').upper() or 'INDEX' in result.get('formula','').upper() or 'PRIORYEAR' in result.get('formula','').upper())

Annual C2 pulls prior year via lookup or direct reference


Open the file /home/user/Documents/attendance.xlsx in LibreOffice Calc. It contains a sheet called 'Attendance' with 20 students (rows 2-21) and 20 class dates (columns B-U). Row 1 has headers: Student Name (A), then date headers (B1 through U1). Each cell in the attendance grid contains 'P' (present), 'A' (absent), or 'L' (late).

1. In cell V1, type 'Days Present' and make it bold.
2. In cell W1, type 'Days Absent' and make it bold.
3. In cell X1, type 'Days Late' and make it bold.
4. In cell Y1, type 'Attendance %' and make it bold.
5. In V2, enter the formula =COUNTIF(B2:U2,"P") to count how many days Olivia Parker was present.
6. In W2, enter the formula =COUNTIF(B2:U2,"A") to count absent days.
7. In X2, enter the formula =COUNTIF(B2:U2,"L") to count late days.
8. In Y2, enter the formula =V2/20*100 to calculate attendance percentage.
9. Copy all four formulas (V2:Y2) down through rows 3-21 for all 20 students.
10. In cell A22, type 'Class Average' and make it bold.
11. In V22, enter the formula =AVERAGE(V2:V21) to compute the average days present across all students.
12. In Y22, enter the formula =AVERAGE(Y2:Y21) to compute the average attendance percentage.
13. Save the file.

check-cell-value V1 "Days Present" Attendance

V1 = 'Days Present'

V1 is bold

check-cell-value W1 "Days Absent" Attendance

W1 = 'Days Absent'

W1 is bold

check-cell-value X1 "Days Late" Attendance

X1 = 'Days Late'

X1 is bold

check-cell-value Y1 "Attendance %" Attendance

Y1 = 'Attendance %'

Y1 is bold

result.get('formula') is not None and 'COUNTIF' in result.get('formula','').upper()

V2 contains a COUNTIF formula

V2 = 18 (Olivia Parker present days)

W2 = 1 (Olivia Parker absent days)

X2 = 1 (Olivia Parker late days)

Y2 = 90 (Olivia Parker 90% attendance)

V3 = 12 (Liam Johnson present days)

W3 = 2 (Liam Johnson absent days)

Y3 = 60 (Liam Johnson 60% attendance)

V6 = 19 (Ava Jones present days)

Y6 = 95 (Ava Jones 95% attendance)

V21 = 17 (Benjamin Lewis present days)

check-cell-value A22 "Class Average" Attendance

A22 = 'Class Average'

check-cell-formatted A22 true Attendance

A22 is bold

V22 = 14.95 (average days present)

Y22 = 74.75 (average attendance %)


Open the file /home/user/Documents/budget.xlsx in LibreOffice Calc. It contains a sheet called 'January' with columns: Category (A), Planned (B), Actual (C). Row 1 has headers (bold), rows 2-9 have 8 expense categories: Rent, Utilities, Groceries, Transport, Insurance, Entertainment, Healthcare, Savings.

1. Create a new sheet called 'February'. In row 1, add the same headers: A1='Category', B1='Planned', C1='Actual'. Copy the 8 category names from January A2:A9 into February A2:A9. Leave the Planned and Actual columns in February empty (the agent just needs to set up the structure).
2. Create a new sheet called 'March' with the same structure as February (headers in row 1, category names in A2:A9).
3. Create a new sheet called 'Q1 Summary'.
4. In the Q1 Summary sheet:
   - A1: 'Category' (bold)
   - B1: 'Total Planned' (bold)
   - C1: 'Total Actual' (bold)
   - D1: 'Difference' (bold)
5. Copy the 8 category names from January A2:A9 into Q1 Summary A2:A9.
6. In Q1 Summary B2, enter the formula =January.B2+February.B2+March.B2 to sum planned amounts across all three months.
7. Copy this formula pattern down through B3:B9 for all categories.
8. In Q1 Summary C2:C9, enter similar formulas summing the Actual columns across all three months (e.g., C2 = =January.C2+February.C2+March.C2).
9. In Q1 Summary D2:D9, enter formulas computing the difference: D2 = =B2-C2 (Total Planned minus Total Actual).
10. Save the file.

Sheet 'February' exists

Sheet 'March' exists

Sheet 'Q1 Summary' exists

Workbook has 4 sheets total

February A1 = 'Category'

February A2 = 'Rent'

March A1 = 'Category'

check-cell-value A1 Category "Q1 Summary"

Q1 Summary A1 = 'Category'

check-cell-formatted A1 true "Q1 Summary"

Q1 Summary A1 is bold

check-cell-value B1 "Total Planned" "Q1 Summary"

Q1 Summary B1 = 'Total Planned'

check-cell-formatted B1 true "Q1 Summary"

Q1 Summary B1 is bold

check-cell-value C1 "Total Actual" "Q1 Summary"

Q1 Summary C1 = 'Total Actual'

check-cell-formatted C1 true "Q1 Summary"

Q1 Summary C1 is bold

check-cell-value D1 Difference "Q1 Summary"

Q1 Summary D1 = 'Difference'

check-cell-formatted D1 true "Q1 Summary"

Q1 Summary D1 is bold

Q1 Summary A2 = 'Rent'

result.get('formula') is not None and 'January' in result.get('formula','') or 'JANUARY' in result.get('formula','').upper()

Q1 Summary B2 contains a cross-sheet formula referencing January

Q1 Summary B2 = 1500 (January Rent planned, Feb+Mar are 0)

result.get('formula') is not None and ('B2' in result.get('formula','').upper() and 'C2' in result.get('formula','').upper())

Q1 Summary D2 contains formula referencing B2 and C2


Open the file /home/user/Documents/roster.xlsx in LibreOffice Calc. The sheet 'Roster' has bold headers in row 1 (A='Student ID', B='Name', C='Exam1', D='Exam2', E='Exam3') and 25 students in rows 2-26 with numeric scores 0-100.

Compute weighted final grades, assign letter grades, and summarize the distribution:

1. In F1 type 'Final' (bold). In G1 type 'Grade' (bold).
2. In F2:F26 enter =C2*0.3+D2*0.3+E2*0.4 (30% Exam1, 30% Exam2, 40% Exam3).
3. In G2:G26 enter a nested IF formula that assigns a letter grade from the Final: 'A' if >=90, else 'B' if >=80, else 'C' if >=70, else 'D' if >=60, else 'F'. Use: =IF(F2>=90,"A",IF(F2>=80,"B",IF(F2>=70,"C",IF(F2>=60,"D","F")))).
4. Create a new sheet named 'GradeSummary'.
5. On GradeSummary, in row 1 enter bold headers: A1='Grade', B1='Count'.
6. In A2:A6 enter 'A', 'B', 'C', 'D', 'F' (in that order).
7. In B2:B6 enter =COUNTIF(Roster.G2:G26,A2) (and fill down).
8. Save the file.

F1 = 'Final'

G1 = 'Grade'

F1 bold

G1 bold

result.get('formula') is not None and '0.3' in result.get('formula','') and '0.4' in result.get('formula','')

F2 uses weighted formula

F2 Alice final = 95.3

F9 Henry final = 49.5

F14 Mia final = 95.5

result.get('formula') is not None and 'IF' in result.get('formula','').upper()

G2 uses nested IF

G2 grade = A (Alice 95.3)

G9 grade = F (Henry 49.5)

G3 grade = B (Bob 87.9)

G6 grade = D (Eve 60.7)

G7 grade = C (Frank 72.0)

'GradeSummary' sheet exists

GradeSummary A1 = 'Grade'

GradeSummary B1 = 'Count'

check-cell-formatted A1 true GradeSummary

GradeSummary A1 bold

GradeSummary A2 = 'A'

GradeSummary A6 = 'F'

GradeSummary B2 count A = 5

GradeSummary B3 count B = 7

GradeSummary B4 count C = 6

GradeSummary B5 count D = 4

GradeSummary B6 count F = 3

GradeSummary B2 uses COUNTIF


Open the file /home/user/Documents/competition.xlsx in LibreOffice Calc. Sheet 'Results' has Name (A), Country (B), Score (C) with 20 competitors in rows 2-21.

1. In D1 type 'Rank' and make it bold. In E1 type 'Percentile' and make it bold. In F1 type 'Medal' and make it bold.
2. In D2 enter =RANK(C2,C$2:C$21) and fill down through D21. Higher scores should get rank 1.
3. In E2 enter =PERCENTRANK(C$2:C$21,C2) and fill down through E21.
4. In F2 enter a nested-IF that returns 'Gold' when the rank is 1, 'Silver' when 2, 'Bronze' when 3, 'Finalist' when rank is 4 or 5, and empty string otherwise: =IF(D2=1,"Gold",IF(D2=2,"Silver",IF(D2=3,"Bronze",IF(D2<=5,"Finalist","")))). Fill down through F21.
5. In A23 fill in 'Top Country' and make it bold.
6. In B23 enter =INDEX(B2:B21,MATCH(1,D2:D21,0)) to return the country of the rank-1 competitor.
7. Save the file.

D1 = Rank

E1 = Percentile

F1 = Medal

D1 bold

D2 Ana rank = 7

D5 Dora rank = 2

D9 Haru rank = 1

D3 Bill rank = 3

D12 Kira rank = 5

result.get('formula') is not None and 'RANK' in result.get('formula','').upper()

D2 uses RANK

result.get('formula') is not None and 'PERCENTRANK' in result.get('formula','').upper()

E2 uses PERCENTRANK

F9 Haru = Gold

F5 Dora = Silver

F3 Bill = Bronze

F12 Kira (rank 5) = Finalist

F17 Pia (rank 4) = Finalist

check-cell-value A23 "Top Country" Results

A23 = Top Country

A23 bold

B23 = JPN (country of gold medalist)

result.get('formula') is not None and ('INDEX' in result.get('formula','').upper() or 'VLOOKUP' in result.get('formula','').upper())

B23 uses INDEX/MATCH or VLOOKUP


Open the file /home/user/Documents/regional_sales.xlsx in LibreOffice Calc. The sheet 'Sales' has bold headers in row 1 (A='Region', B='Q1', C='Q2', D='Q3', E='Q4', F='Total') and 12 regions in rows 2-13. The Total column in F2:F13 already has =SUM(B2:E2) formulas.

Apply two conditional-formatting rules:

1. Select range B2:E13 and apply a 'Color Scale' conditional format so that low values shade red and high values shade green. A 3-color or 2-color red-to-green scale is fine.

2. Select range F2:F13 and add a 'Condition' rule of type 'Cell value is > 100000'. Apply a cell style that uses a RED font color and BOLD weight for matching cells (you can create a new style called 'HighTotal' for this, or reuse 'Bad').

Save the file back to /home/user/Documents/regional_sales.xlsx in xlsx format.

'Sales' sheet exists

Sales!A1 = 'Region'

Sales!F1 = 'Total'

Conditional formatting exists on B2:E13

Conditional formatting exists on F2:F13

Saved file exists


Open the file /home/user/Documents/contacts.xlsx in LibreOffice Calc. The sheet 'Contacts' has bold headers in row 1 (A='Full Name', B='Email', C='Phone') and 25 contact rows in rows 2-26. Several emails have mixed case or trailing whitespace, and some are duplicates of each other.

Clean and annotate the list:

1. In D1 type 'First Name' (bold). In E1 type 'Last Name' (bold). In F1 type 'Clean Email' (bold). In G1 type 'Is Duplicate' (bold).
2. In D2:D26 extract the first name using =TRIM(LEFT(A2,FIND(" ",A2)-1)).
3. In E2:E26 extract the last name using =TRIM(MID(A2,FIND(" ",A2)+1,100)).
4. In F2:F26 produce a clean email with =LOWER(TRIM(B2)).
5. In G2:G26 mark duplicates of the cleaned email with =IF(COUNTIF($F$2:$F$26,F2)>1,"Yes","No").
6. Save the file.

check-cell-value D1 "First Name" Contacts

D1 = 'First Name'

check-cell-value E1 "Last Name" Contacts

E1 = 'Last Name'

check-cell-value F1 "Clean Email" Contacts

F1 = 'Clean Email'

check-cell-value G1 "Is Duplicate" Contacts

G1 = 'Is Duplicate'

D1 bold

G1 bold

result.get('formula') is not None and 'LEFT' in result.get('formula','').upper()

D2 uses LEFT()

result.get('formula') is not None and 'MID' in result.get('formula','').upper()

E2 uses MID()

result.get('formula') is not None and 'LOWER' in result.get('formula','').upper()

F2 uses LOWER()

G2 uses COUNTIF()

D2 first name = John

E2 last name = Smith

check-cell-value F2 john@example.com Contacts

F2 clean email = john@example.com

G2 = No (John not duplicate)

D3 = Jane

E3 = Doe

check-cell-value F3 jane@example.com Contacts

F3 = jane@example.com

G3 = Yes (Jane is duplicated)

check-cell-value F4 bob@example.com Contacts

F4 = bob@example.com

G4 = Yes (Bob Smith is duplicated)

G22 = Yes (second Jane Doe row)

G23 = Yes (second Bob Smith row)

G26 = Yes (third Jane Doe row)

G24 = No (Sam King not duplicate)

check-cell-value F16 owen@example.com Contacts

F16 = owen@example.com (lowercased)


Open the file /home/user/Documents/orders.xlsx in LibreOffice Calc. Sheet 'Orders' has Order ID (A), Order Date (B), Amount (C) with 20 orders in rows 2-21 spanning January-March 2025.

1. In D1 type 'Year' and make it bold. In E1 type 'Month' and make it bold. In F1 type 'Weekday' and make it bold. In G1 type 'Is Weekend' and make it bold.
2. In D2 enter =YEAR(B2) and fill down through D21.
3. In E2 enter =MONTH(B2) and fill down through E21.
4. In F2 enter =WEEKDAY(B2,2) and fill down through F21. (Mode 2: Monday=1, Sunday=7.)
5. In G2 enter =IF(F2>=6,"Yes","No") and fill down through G21.
6. Create a new sheet named 'MonthlyTotals'.
7. On MonthlyTotals: A1='Month' (bold), B1='Total' (bold). A2=1, A3=2, A4=3.
8. In B2 enter =SUMIF(Orders.E2:E21,A2,Orders.C2:C21). Fill down through B4.
9. Save the file.

D1 = Year

E1 = Month

F1 = Weekday

G1 = Is Weekend

D1 bold

D2 year = 2025

E2 month = 1 (January)

E10 month = 2 (February)

E21 month = 3 (March)

G3 (Jan 5 Sun) = Yes weekend

G2 (Jan 3 Fri) = No

result.get('formula') is not None and 'YEAR' in result.get('formula','').upper()

D2 uses YEAR()

result.get('formula') is not None and 'WEEKDAY' in result.get('formula','').upper()

F2 uses WEEKDAY()

MonthlyTotals sheet exists

MonthlyTotals A1 = Month

MonthlyTotals B1 = Total

check-cell-formatted A1 true MonthlyTotals

MonthlyTotals A1 bold

MonthlyTotals B2 January = 880

MonthlyTotals B3 February = 820

MonthlyTotals B4 March = 955

result.get('formula') is not None and 'SUMIF' in result.get('formula','').upper()

MonthlyTotals B2 uses SUMIF


Open the file /home/user/Documents/employees.xlsx in LibreOffice Calc. It contains a sheet called 'Staff' with columns: ID (A), First Name (B), Last Name (C), Department (D), Salary (E), Start Date (F). Row 1 has headers, rows 2-16 have 15 employees.

1. In cell G1, type 'Full Name' and make it bold.
2. In cells G2 through G16, enter a formula to concatenate First Name and Last Name with a space between them. For row 2: =B2&" "&C2 (or =CONCATENATE(B2," ",C2)).
3. Create a new sheet called 'Department Summary'.
4. In the Department Summary sheet:
   - A1: 'Department' (bold)
   - B1: 'Employee Count' (bold)
   - C1: 'Avg Salary' (bold)
5. Enter department names in column A:
   - A2: Engineering
   - A3: Marketing
   - A4: Sales
   - A5: HR
6. In B2, enter =COUNTIF(Staff.D$2:Staff.D$16,A2) to count Engineering employees.
7. In C2, enter =AVERAGEIF(Staff.D$2:Staff.D$16,A2,Staff.E$2:Staff.E$16) to calculate average salary for Engineering.
8. Copy the formulas in B2:C2 down to rows 3-5 for the other departments.
9. Save the file.

Staff G1 = 'Full Name'

Staff G1 is bold

check-cell-value G2 "Alice Johnson" Staff

Staff G2 = 'Alice Johnson' (concatenated name)

result.get('formula') is not None and ('CONCATENATE' in result.get('formula','').upper() or '&' in result.get('formula',''))

G2 contains a CONCATENATE or & formula

Sheet 'Department Summary' exists

check-cell-value A1 Department "Department Summary"

Dept Summary A1 = 'Department'

check-cell-formatted A1 true "Department Summary"

Dept Summary A1 is bold

check-cell-value B1 "Employee Count" "Department Summary"

Dept Summary B1 = 'Employee Count'

check-cell-formatted B1 true "Department Summary"

Dept Summary B1 is bold

check-cell-value C1 "Avg Salary" "Department Summary"

Dept Summary C1 = 'Avg Salary'

Dept Summary B2 contains COUNTIF formula

check-cell-value B2 5 "Department Summary"

Dept Summary B2 = 5 (Engineering has 5 employees)

result.get('formula') is not None and 'AVERAGEIF' in result.get('formula','').upper()

Dept Summary C2 contains AVERAGEIF formula

check-cell-value C2 101200 "Department Summary"

Dept Summary C2 = 101200 (avg Engineering salary)

check-cell-value B3 3 "Department Summary"

Dept Summary B3 = 3 (Marketing has 3 employees)

check-cell-value B4 4 "Department Summary"

Dept Summary B4 = 4 (Sales has 4 employees)


Open the file /home/user/Documents/expenses.xlsx in LibreOffice Calc. The sheet 'Expenses' has bold headers in row 1 (A='Date', B='Category', C='Description', D='Amount') and 30 expense rows in rows 2-31 covering categories Food, Transport, Utilities, Entertainment, and Health.

Do the following:

1. In cell E1 type 'Running Balance' and make it bold.
2. In E2:E31 enter a running-balance formula. Use =SUM($D$2:D2) in E2 and fill down so each row shows the cumulative sum of Amount from row 2 to that row.
3. Create a new sheet named 'Summary'.
4. On 'Summary', fill row 1 with bold headers: A1='Category' and B1='Total'.
5. In A2:A6 enter the category names in this exact order: 'Food', 'Transport', 'Utilities', 'Entertainment', 'Health'.
6. In B2:B6 use SUMIFS (or SUMIF) over Expenses.D:D filtered by category name in column A (e.g. B2=SUMIFS(Expenses.D:D,Expenses.B:B,A2)).
7. In A8 type 'Top Category' and make it bold. In B8 enter a formula using INDEX/MATCH over Summary B2:B6 and A2:A6 to return the category name with the largest total (e.g. =INDEX(A2:A6,MATCH(MAX(B2:B6),B2:B6,0))).
8. Save the file (it should stay at /home/user/Documents/expenses.xlsx).

check-cell-value E1 "Running Balance" Expenses

Expenses!E1 = 'Running Balance'

Expenses!E1 is bold

result.get('formula') is not None and 'SUM' in result.get('formula','').upper()

E2 uses a SUM formula

E2 running balance = 45

E31 running balance (grand total) = 1715

'Summary' sheet exists

Summary!A1 = 'Category'

Summary!B1 = 'Total'

Summary!A1 is bold

Summary!B1 is bold

Summary!A2 = 'Food'

Summary!A3 = 'Transport'

Summary!A4 = 'Utilities'

check-cell-value A5 Entertainment Summary

Summary!A5 = 'Entertainment'

Summary!A6 = 'Health'

Summary!B2 Food total = 260

Summary!B3 Transport total = 210

Summary!B4 Utilities total = 345

Summary!B5 Entertainment total = 270

Summary!B6 Health total = 630

Summary!B2 uses a SUMIFS/SUMIF formula

check-cell-value A8 "Top Category" Summary

Summary!A8 = 'Top Category'

Summary!A8 is bold

Summary!B8 = 'Health' (top category)

result.get('formula') is not None and 'INDEX' in result.get('formula','').upper() and 'MATCH' in result.get('formula','').upper()

Summary!B8 uses INDEX/MATCH


Open /home/user/Documents/attendance.xlsx in LibreOffice Calc. The workbook contains a sheet named 'Attendance' with 20 students and their daily attendance records. Export the data to three different formats in the /home/user/Documents/ directory:

1. attendance_export.csv - CSV format with comma separator
2. attendance_export.html - HTML format as a table
3. attendance_export.ods - ODF Spreadsheet format

Ensure all three files are created with the complete attendance data. Save any changes to the original workbook before closing.

CSV export file exists

CSV file is in correct format

check-csv-rows /home/user/Documents/attendance_export.csv 20 true

CSV has 20 data rows plus header

HTML export file exists

HTML file is in correct format

HTML contains attendance data

ODS export file exists

ODS file is in correct format

Original xlsx file still exists


Open /home/user/Documents/budget.xlsx in LibreOffice Calc. The workbook contains multiple sheets with budget data across different categories or time periods. Export the entire workbook to ODF Spreadsheet format at /home/user/Documents/budget_backup.ods. The ODS file should preserve all sheets and data. Save any changes before closing.

ODS export file exists

File is in ODS format

Original xlsx file still exists


Open /home/user/Documents/contacts.xlsx in LibreOffice Calc. The workbook contains a sheet with contact information including names and email addresses. Export the contact data to two different formats in the /home/user/Documents/ directory:

1. contacts_export.csv - CSV format with comma separator
2. contacts_export.html - HTML format as a table

Ensure both files are created with the complete contact data. Save any changes to the original workbook before closing.

CSV export file exists

CSV file is in correct format

check-csv-rows /home/user/Documents/contacts_export.csv 15 true

CSV has 15 data rows plus header

HTML export file exists

HTML file is in correct format

HTML contains contact data

Original xlsx file still exists


Open /home/user/Documents/inventory.xlsx in LibreOffice Calc. The workbook contains inventory management data with product information, quantities, and reorder flags. Export the active sheet to HTML format at /home/user/Documents/inventory_report.html. The HTML should render the data as a properly formatted table. Save any changes before closing.

HTML export file exists

File is in HTML format

check-html-contains /home/user/Documents/inventory_report.html Ball Bearing 6205

HTML contains inventory item

Original xlsx file still exists


Open /home/user/Documents/quarters.xlsx in LibreOffice Calc. The workbook contains multiple sheets including Q1, Q2, Q3, Q4, PriorYear, and an Annual summary sheet. Export the Annual sheet to CSV format at /home/user/Documents/quarterly_report.csv. The CSV should include all data from the Annual sheet with headers. Save any changes before closing.

CSV export file exists

File is in CSV format

check-csv-rows /home/user/Documents/quarterly_report.csv 8 true

CSV has 8 data rows plus header (total 9 lines)

Original xlsx file still exists


Open the file /home/user/Documents/grades.xlsx in LibreOffice Calc. It contains a sheet called 'Grades' with columns: Student (A), Midterm (B), Final (C), Project (D). Row 1 has headers, rows 2-11 have 10 students.

1. In cell E1, type 'Weighted Average' and make it bold.
2. In cells E2 through E11, enter a formula that calculates each student's weighted average: Midterm * 0.3 + Final * 0.4 + Project * 0.3. For row 2, this would be =B2*0.3+C2*0.4+D2*0.3.
3. In cell F1, enter 'Letter Grade' and make it bold.
4. In cells F2 through F11, enter a nested IF formula to assign letter grades based on the weighted average in column E:
   - 90 or above: 'A'
   - 80-89: 'B'
   - 70-79: 'C'
   - 60-69: 'D'
   - Below 60: 'F'
   For row 2: =IF(E2>=90,"A",IF(E2>=80,"B",IF(E2>=70,"C",IF(E2>=60,"D","F"))))
5. Save the file.

check-cell-value E1 "Weighted Average" Grades

E1 = 'Weighted Average'

E1 is bold

check-cell-value F1 "Letter Grade" Grades

F1 = 'Letter Grade'

F1 is bold

result.get('formula') is not None and '0.3' in result.get('formula','') or '0.4' in result.get('formula','')

E2 contains weighted average formula

E2 = 88.7 (Alice: 88*0.3+92*0.4+85*0.3)

F2 contains an IF formula

F2 = 'B' (88.7 -> B grade)

E4 = 92.0 (Charlie: 95*0.3+89*0.4+93*0.3)

F4 = 'A' (92.0 -> A grade)


Open the file /home/user/Documents/quotes.xlsx in LibreOffice Calc. It has two sheets. 'Catalog' has columns SKU (A), Product (B), Unit Price (C) for 10 products (rows 2-11). 'Quotes' has columns SKU (A) and Qty (B) for 10 quote lines (rows 2-11).

1. Go to the Quotes sheet. In C1 type 'Product Name' and make it bold. In D1 type 'Unit Price' and make it bold. In E1 type 'Line Total' and make it bold.
2. In C2 enter a formula that uses INDEX and MATCH to pull the product name from Catalog based on the SKU in A2. Example: =INDEX(Catalog.B$2:B$11,MATCH(A2,Catalog.A$2:A$11,0)). Fill down through C11.
3. In D2 enter a formula that uses INDEX and MATCH to pull the unit price. Example: =INDEX(Catalog.C$2:C$11,MATCH(A2,Catalog.A$2:A$11,0)). Fill down through D11.
4. In E2 enter =B2*D2 and fill down through E11.
5. In A12 type 'Grand Total' and make it bold.
6. In E12 enter =SUM(E2:E11).
7. Save the file.

check-cell-value C1 "Product Name" Quotes

Quotes C1 = Product Name

C1 bold

D1 = Unit Price

E1 = Line Total

C2 uses INDEX/MATCH

C2 = Gadget X (SKU P003)

C3 = Widget A (SKU P001)

C4 = Contraption (SKU P008)

result.get('formula') is not None and 'INDEX' in result.get('formula','').upper()

D2 uses INDEX

D2 unit price = 22.75

E2 line total = 113.75

E3 line total = 125.00 (Widget A x10)

check-cell-value A12 "Grand Total" Quotes

A12 = Grand Total

A12 bold

E12 grand total = 1427.37


Open the file /home/user/Documents/stock.xlsx in LibreOffice Calc. Sheet 'Stock' has columns SKU (A), Item (B), On Hand (C), Daily Usage (D), Reorder Point (E), Max Stock (F) with 15 items in rows 2-16.

1. In G1 type 'Days of Supply' and make it bold. In H1 type 'Status' and make it bold. In I1 type 'Reorder Qty' and make it bold.
2. In G2 enter =C2/D2 and fill down through G16.
3. In H2 enter a nested-IF formula: =IF(C2<E2/2,"Critical",IF(C2<E2,"Low","OK")). Fill down through H16.
4. In I2 enter =IF(OR(H2="Critical",H2="Low"),F2-C2,0). Fill down through I16.
5. Create a new sheet named 'StatusSummary'.
6. On StatusSummary, enter: A1='Status' (bold), B1='Count' (bold), A2='Critical', A3='Low', A4='OK'.
7. In StatusSummary B2 enter =COUNTIF(Stock.H2:H16,A2). In B3 enter =COUNTIF(Stock.H2:H16,A3). In B4 enter =COUNTIF(Stock.H2:H16,A4).
8. Save the file.

check-cell-value G1 "Days of Supply" Stock

G1 = Days of Supply

H1 = Status

I1 = Reorder Qty

G1 bold

G2 Bolts days = 6

G3 Nuts days = 2.5

H2 Bolts = Low

H3 Nuts = Critical

H4 Washers = OK

H5 Screws = Critical

H13 Springs = Critical

H16 Valves = Critical

I2 Bolts reorder = 170

I4 Washers reorder = 0 (OK)

I5 Screws reorder = 145

result.get('formula') is not None and result.get('formula','').upper().count('IF') >= 2

H2 is nested IF

StatusSummary sheet exists

check-cell-value A1 Status StatusSummary

StatusSummary A1 = Status

StatusSummary B1 = Count

check-cell-formatted A1 true StatusSummary

StatusSummary A1 bold

check-cell-value A2 Critical StatusSummary

StatusSummary A2 = Critical

StatusSummary B2 (Critical count) = 6

StatusSummary B3 (Low count) = 4

StatusSummary B4 (OK count) = 5

result.get('formula') is not None and 'COUNTIF' in result.get('formula','').upper()

StatusSummary B2 uses COUNTIF


Open the file /home/user/Documents/loan.xlsx in LibreOffice Calc. The sheet 'Loan' has loan inputs in B1:B3 (Principal=24000, Annual Rate=0.06, Term Months=12) and schedule headers already in row 6 (Month, Payment, Interest, Principal, Balance).

1. In cell C1 enter the formula =PMT(B2/12,B3,-B1) so the single monthly payment is shown. Make C1 bold.
2. Fill rows 7 through 18 with month numbers 1..12 in column A.
3. In rows 7 through 18, fill column B (Payment) with =-PMT(B$2/12,B$3,-B$1) so every row shows the same monthly payment (positive number, about 2065.52).
4. In rows 7 through 18, fill column C (Interest) with =-IPMT(B$2/12,A7,B$3,-B$1) style formulas (row reference must use the month number in column A).
5. In rows 7 through 18, fill column D (Principal) with =-PPMT(B$2/12,A7,B$3,-B$1) style formulas.
6. In rows 7 through 18, fill column E (Balance) as the running remaining balance. E7 should be =B1-D7 and each subsequent row should be =E[prev]-D[current], so E18 ends at 0.
7. In A19 type 'Totals' and make it bold.
8. In B19 enter =SUM(B7:B18). In C19 enter =SUM(C7:C18). In D19 enter =SUM(D7:D18).
9. Save the file .

result.get('formula') is not None and 'PMT' in result.get('formula','').upper()

C1 contains a PMT formula

C1 computes approximately 2065.52 monthly payment

A7 = 1 (month 1)

A18 = 12 (month 12)

B7 payment approx 2065.52

B18 payment approx 2065.52

result.get('formula') is not None and 'IPMT' in result.get('formula','').upper()

C7 has an IPMT formula

abs((result.get('value') or 0) - 120) < 1.0

C7 first-month interest approx 120

result.get('formula') is not None and 'PPMT' in result.get('formula','').upper()

D7 has a PPMT formula

D7 first-month principal approx 1945.52

E18 ending balance approximately 0

A19 = 'Totals'

A19 is bold

B19 total payments approx 24786.28

D19 total principal approx 24000


Open the file /home/user/Documents/report_data.xlsx in LibreOffice Calc. It contains a sheet called 'Data' with columns: Month (A), Revenue (B), Expenses (C). Row 1 has headers, rows 2-7 have data for January through June.

1. Select cells A1:C1 and merge them (Format > Merge Cells > Merge Cells). Type 'Financial Report H1 2025' in the merged cell. Make it bold.
2. The data should now be in rows 2-8 (headers shifted to row 2, data in rows 3-8). Note: if the merge replaced the headers, re-enter 'Month' in A2, 'Revenue' in B2, 'Expenses' in C2.
3. In cell A9 (or the row after the last data row), type 'TOTAL' and make it bold.
4. In B9, enter the formula =SUM(B3:B8) for total revenue.
5. In C9, enter the formula =SUM(C3:C8) for total expenses.
6. In cell D2, type 'Profit'.
7. In cells D3 through D8, enter formulas =B3-C3 (Revenue minus Expenses) for each month.
8. In D9, enter the formula =SUM(D3:D8) for total profit.
9. Save the file .

Note: The exact row numbers depend on how the merge affects the layout. The key is: merged title in row 1, headers in row 2, data in rows 3-8, totals in row 9.

A1:C1 is merged

'Financial Report H1 2025' in str(result.get('display','')) or 'Financial Report H1 2025' in str(result.get('value',''))

A1 contains 'Financial Report H1 2025'

A1 is bold

str(result.get('value','')).strip() == 'Profit' or str(result.get('display','')).strip() == 'Profit'

D2 = 'Profit'

any('TOTAL' in str(row) for row in result.get('data',[]) if row)

Sheet contains a 'TOTAL' row

any(337000 == val or 337000.0 == val for row in result.get('data',[]) if row for val in row if isinstance(val,(int,float)))

Total revenue = 337000 appears in the sheet

any(271000 == val or 271000.0 == val for row in result.get('data',[]) if row for val in row if isinstance(val,(int,float)))

Total expenses = 271000 appears in the sheet

any(66000 == val or 66000.0 == val for row in result.get('data',[]) if row for val in row if isinstance(val,(int,float)))

Total profit = 66000 appears in the sheet


Open the file /home/user/Documents/revenue.xlsx in LibreOffice Calc. Sheet 'Revenue' has Month (A) and Revenue (B) in row 1, and 12 months Jan-Dec with revenue values in rows 2-13.

1. In C1 type 'Running Total' and make it bold.
2. In D1 type 'MoM Growth %' and make it bold.
3. In E1 type 'Status' and make it bold.
4. In C2 enter =B2. In C3 enter =C2+B3. Fill this running-sum pattern down through C13.
5. In D2 type the text 'N/A'.
6. In D3 enter =(B3-B2)/B2*100. Fill this pattern down through D13 so each row computes the month-over-month growth from the previous month.
7. In E2 type the text 'N/A'.
8. In E3 enter =IF(D3<0,"Down","Up"). Fill down through E13.
9. Save the file .

check-cell-value C1 "Running Total" Revenue

C1 = Running Total

C1 bold

check-cell-value D1 "MoM Growth %" Revenue

D1 = MoM Growth %

D1 bold

E1 = Status

E1 bold

C2 running total = 100000

C3 running total = 210000

C13 final running total = 1558000

D2 = N/A

D3 growth = 10.0

D4 growth approx -4.5454

E2 = N/A

E3 = Up

E4 = Down

E13 = Down

result.get('formula') is not None and result.get('formula','').upper().startswith('=IF')

E8 uses IF formula


Open the file /home/user/Documents/orders.xlsx in LibreOffice Calc. The workbook has three sheets:
- 'Orders' with bold headers in row 1 (A='Order ID', B='Customer', C='Item', D='Qty', E='Price', F='Total w/ Tax'). Rows 2-21 already contain values for Order ID (ORD-001..ORD-020), Item, Qty (1-5) and Price - the Customer column (B) and Total column (F) are blank.
- 'Customers' with bold headers A1='Customer Name' and 9 customer names in A2:A10.
- 'Settings' with A1='Tax Rate' (bold) and B1=0.08.

Do the following:

1. Create a named range called exactly 'CustomerList' that points to Customers.A2:A10.
2. Create a named range called exactly 'TaxRate' that points to Settings.B1.
3. On the 'Orders' sheet, select cells B2:B21 and open Validity. Set 'Allow' to 'Cell range', and for the source enter =CustomerList (so the dropdown pulls from the named range).
4. On the 'Orders' sheet, in F2:F21 enter the formula =E2*D2*(1+TaxRate) and fill down so each row uses the TaxRate named range.
5. Save the file  keeping it at /home/user/Documents/orders.xlsx.

'Orders' sheet exists

'Customers' sheet exists

'Settings' sheet exists

Named range 'CustomerList' references Customers sheet

Named range 'TaxRate' references Settings sheet

Orders!B2 has data-validation rule

Orders!B21 has data-validation rule

result.get('formula') is not None and 'TAXRATE' in result.get('formula','').upper().replace(' ','')

Orders!F2 formula references TaxRate named range

Orders!F21 formula references TaxRate named range


Open the file /home/user/Documents/payroll.xlsx in LibreOffice Calc. Sheet 'Payroll' has Employee (A), Hourly Rate (B), Hours Worked (C) with 12 employees in rows 2-13.

1. Fill row 1 cells D1 'Regular Pay', E1 'Overtime Pay', F1 'Gross', G1 'Tax', H1 'Net' and make all of them bold.
2. In D2 enter =MIN(C2,40)*B2 to compute regular pay (hours up to 40 at the base rate). Fill down through D13.
3. In E2 enter =MAX(0,C2-40)*B2*1.5 to compute overtime pay (hours over 40 at 1.5x). Fill down through E13.
4. In F2 enter =D2+E2 for gross. Fill down through F13.
5. In G2 enter a nested-IF progressive tax formula: =IF(F2<500,0,IF(F2<=1500,(F2-500)*0.1,100+(F2-1500)*0.2)). Fill down through G13.
6. In H2 enter =F2-G2 for net pay. Fill down through H13.
7. In A14 type 'Totals' and make it bold. In D14 enter =SUM(D2:D13). In E14 enter =SUM(E2:E13). In F14 enter =SUM(F2:F13). In G14 enter =SUM(G2:G13). In H14 enter =SUM(H2:H13).
8. Save the file .

check-cell-value D1 "Regular Pay" Payroll

D1 = Regular Pay

D1 bold

check-cell-value E1 "Overtime Pay" Payroll

E1 = Overtime Pay

F1 = Gross

G1 = Tax

H1 = Net

D2 Alice regular = 800

E2 Alice overtime = 150

F2 Alice gross = 950

G2 Alice tax = 45

H2 Alice net = 905

G2 is a nested IF (has >=2 IF tokens)

F3 Bob gross = 600

G3 Bob tax = 10

F4 Carol gross = 1375

G4 Carol tax = 87.5

F7 Frank gross = 1875

G7 Frank tax = 175

G8 Grace tax = 0 (gross 420 below bracket)

A14 = Totals

A14 bold

F14 total gross = 11887

G14 total tax approx 634.2

H14 total net approx 11252.8


Open LibreOffice Calc and change two user preferences so that they persist in the user profile:

1. Set 'Number of worksheets in new document' to 5.
2. Set 'Always save as' for 'Spreadsheet' documents to 'Excel 2007-365 (*.xlsx)'.

Save the settings, and make sure the preferences flush to ~/.config/libreoffice/4/user/registrymodifications.xcu.

Default sheet count for new workbooks = 5

check-calc-pref default_save_filter_calc "MS Excel 2007"

Default save format for Calc is MS Excel 2007 (.xlsx)


Open LibreOffice Calc and change two user preferences so that they persist in the user profile:

1. Set 'Number of worksheets in new document' to 3.
2. Set 'Always save as' for 'Spreadsheet' documents to 'ODF Spreadsheet (*.ods)'.

Save the settings, and make sure the preferences flush to ~/.config/libreoffice/4/user/registrymodifications.xcu.

Default sheet count for new workbooks = 3

check-calc-pref default_save_filter_calc "ODF Spreadsheet"

Default save format for Calc is ODF Spreadsheet (.ods)


Open LibreOffice Calc and change two user preferences so that they persist in the user profile:

1. Set 'Number of worksheets in new document' to 4.
2. Set 'Always save as' for 'Spreadsheet' documents to 'MS Excel 2007-365 (*.xlsx)'.

Save the settings, and make sure the preferences flush to ~/.config/libreoffice/4/user/registrymodifications.xcu.

Default sheet count for new workbooks = 4


Open LibreOffice Calc and change two user preferences so that they persist in the user profile:

1. Set 'Number of worksheets in new document' to 6.
2. Set 'Always save as' for 'Spreadsheet' documents to 'ODF Spreadsheet (*.ods)'.

Save the settings, and make sure the preferences flush to ~/.config/libreoffice/4/user/registrymodifications.xcu.

Default sheet count for new workbooks = 6


Open LibreOffice Calc and change two user preferences so that they persist in the user profile:

1. Set 'Number of worksheets in new document' to 7.
2. Set 'Always save as' for 'Spreadsheet' documents to 'Excel 97-2003 (*.xls)'.

Save the settings, and make sure the preferences flush to ~/.config/libreoffice/4/user/registrymodifications.xcu.

Default sheet count for new workbooks = 7

check-calc-pref default_save_filter_calc "Excel 97-2003"

Default save format for Calc is Excel 97-2003 (.xls)


Open the file /home/user/Documents/catalog.xlsx in LibreOffice Calc.

The workbook has two sheets:
- 'Catalog': bold headers in row 1 (A='SKU', B='Product', C='Units Sold', D='List Price') and 25 products in rows 2-26.
- 'Tiers': bold headers in row 1 (A='Min Units', B='Tier', C='Discount'), with rows 2-5 defining the tiers sorted ascending: (0, 'Bronze', 0), (100, 'Silver', 0.05), (500, 'Gold', 0.10), (1000, 'Platinum', 0.15).

Build a discounted-price breakdown and a tier-level summary:

1. On Catalog, in row 1 add bold headers E1='Tier', F1='Discounted Price', G1='Revenue'.
2. In E2:E26 use =VLOOKUP(C2,Tiers.A:C,2,1) to fetch the Tier name for each row (approximate-match VLOOKUP against the ascending Min Units column).
3. In F2:F26 use =D2*(1-VLOOKUP(C2,Tiers.A:C,3,1)) to compute the per-unit discounted price.
4. In G2:G26 enter =C2*F2 (revenue = units sold * discounted price).
5. Create a new sheet named 'TierSummary'.
6. On TierSummary, in row 1 add bold headers A1='Tier', B1='Revenue'. In A2:A5 enter 'Bronze', 'Silver', 'Gold', 'Platinum' (in that order).
7. In B2:B5 enter =SUMIFS(Catalog.G:G,Catalog.E:E,A2) (revenue totalled per tier).
8. In D1 add bold header 'Best Tier'. In D2 enter =INDEX(A2:A5,MATCH(MAX(B2:B5),B2:B5,0)) so D2 returns the tier name with the highest revenue.
9. Save the file .

Catalog E1 = 'Tier'

check-cell-value F1 "Discounted Price" Catalog

Catalog F1 = 'Discounted Price'

Catalog G1 = 'Revenue'

Catalog E1 bold

result.get('formula') is not None and 'VLOOKUP' in result.get('formula','').upper()

Catalog E2 uses VLOOKUP

Catalog F2 uses VLOOKUP

Catalog E2 tier = 'Bronze'

Catalog E7 tier = 'Gold'

Catalog E10 tier = 'Platinum'

Catalog F2 discounted price = 20

Catalog F7 discounted price = 90

Catalog F10 discounted price = 8.5

Catalog G2 revenue = 1000

Catalog G7 revenue = 49500

Catalog G10 revenue = 10200

'TierSummary' sheet exists

TierSummary A1 = 'Tier'

TierSummary B1 = 'Revenue'

check-cell-formatted A1 true TierSummary

TierSummary A1 bold

TierSummary A2 = 'Bronze'

check-cell-value A5 Platinum TierSummary

TierSummary A5 = 'Platinum'

TierSummary B2 Bronze total = 7900

TierSummary B3 Silver total = 54102.5

TierSummary B4 Gold total = 339750

TierSummary B5 Platinum total = 49300

result.get('formula') is not None and 'SUMIF' in result.get('formula','').upper()

TierSummary B2 uses SUMIFS/SUMIF

check-cell-value D1 "Best Tier" TierSummary

TierSummary D1 = 'Best Tier'

TierSummary D2 = 'Gold'

result.get('formula') is not None and 'INDEX' in result.get('formula','').upper() and 'MATCH' in result.get('formula','').upper()

TierSummary D2 uses INDEX/MATCH


Open the file /home/user/Documents/products.xlsx in LibreOffice Calc. It contains a sheet called 'Products' with columns: Product Name (A), Base Price (B), Cost (C). Row 1 has headers (bold), rows 2-16 have 15 products.

1. In cell D1, enter 'Profit Margin %' and make it bold.
2. In cells D2:D16, enter the formula =(B2-C2)/B2*100 to calculate the profit margin as a percentage. For row 2: =(B2-C2)/B2*100.
3. In cell E1, enter 'Discounted Price (10%)' and make it bold.
4. In cells E2:E16, enter the formula =B2*0.9 to apply a 10% discount to the base price.
5. In cell F1, enter 'Tax (8.5%)' and make it bold.
6. In cells F2:F16, enter the formula =E2*0.085 to calculate the tax amount on the discounted price.
7. In cell G1, enter 'Final Price' and make it bold.
8. In cells G2:G16, enter the formula =E2+F2 to calculate the final price (discounted price plus tax).
9. In cell A17, enter 'MIN' and make it bold. In cell A18, enter 'MAX' and make it bold. In cell A19, enter 'AVERAGE' and make it bold.
10. In B17, enter =MIN(B2:B16). In B18, enter =MAX(B2:B16). In B19, enter =AVERAGE(B2:B16).
11. Copy the MIN/MAX/AVERAGE formulas across columns C through G (so C17:G17 have MIN formulas, C18:G18 have MAX formulas, C19:G19 have AVERAGE formulas).
12. Save the file .

check-cell-value D1 "Profit Margin %" Products

D1 = 'Profit Margin %'

D1 is bold

result.get('formula') is not None and 'B2' in result.get('formula','').upper() and 'C2' in result.get('formula','').upper()

D2 contains a margin formula referencing B2 and C2

abs(float(result.get('value', 0)) - 58.32) < 0.5

D2 value is approximately 58.32% (Wireless Mouse margin)

check-cell-value E1 "Discounted Price (10%)" Products

E1 = 'Discounted Price (10%)'

E1 is bold

result.get('formula') is not None and '0.9' in result.get('formula','') or '*0.9' in result.get('formula','')

E2 contains a 10% discount formula

check-cell-value F1 "Tax (8.5%)" Products

F1 = 'Tax (8.5%)'

F1 is bold

check-cell-value G1 "Final Price" Products

G1 = 'Final Price'

G1 is bold

result.get('formula') is not None and 'E2' in result.get('formula','').upper() and 'F2' in result.get('formula','').upper()

G2 contains formula =E2+F2

A17 = 'MIN'

A17 is bold

A18 = 'MAX'

A18 is bold

A19 = 'AVERAGE'

A19 is bold

result.get('formula') is not None and 'MIN' in result.get('formula','').upper()

B17 contains a MIN formula

B17 = 9.99 (min base price)

result.get('formula') is not None and 'MAX' in result.get('formula','').upper()

B18 contains a MAX formula

B18 = 89.99 (max base price)

result.get('formula') is not None and 'AVERAGE' in result.get('formula','').upper()

B19 contains an AVERAGE formula


Open the file /home/user/Documents/commissions.xlsx in LibreOffice Calc. It contains a sheet called 'Sales' with columns: Salesperson (A), Region (B), Monthly Sales (C). Row 1 has bold headers, rows 2-21 have 20 sales records.

1. In cell D1, enter 'Commission Rate' and make it bold.
2. In cell E1, enter 'Commission Amount' and make it bold.
3. In D2, enter a nested IF formula to determine the commission rate based on sales tiers:
   - If Monthly Sales (C2) > 20000, the rate is 10% (0.10)
   - If Monthly Sales (C2) >= 10000, the rate is 8% (0.08)
   - Otherwise, the rate is 5% (0.05)
   The formula should be: =IF(C2>20000,0.1,IF(C2>=10000,0.08,0.05))
4. In E2, enter the formula =C2*D2 to calculate the commission amount.
5. Copy both formulas (D2:E2) down through rows 3-21 for all 20 records.
6. Create a new sheet called 'Commission Summary'.
7. In the Commission Summary sheet:
   - A1: 'Metric' (bold)
   - B1: 'Value' (bold)
   - A2: 'Total Sales'
   - B2: =SUM(Sales.C2:C21)
   - A3: 'Total Commission'
   - B3: =SUM(Sales.E2:E21)
   - A4: 'Average Commission Rate'
   - B4: =B3/B2 (this should yield the weighted average rate)
8. Save the file .

check-cell-value D1 "Commission Rate" Sales

D1 = 'Commission Rate'

D1 is bold

check-cell-value E1 "Commission Amount" Sales

E1 = 'Commission Amount'

E1 is bold

result.get('formula') is not None and 'IF' in result.get('formula','').upper()

D2 contains an IF formula

D2 = 0.08 (Bob East 19573 falls in 8% tier)

E2 = 1565.84 (19573 * 0.08)

result.get('formula') is not None and ('C2' in result.get('formula','').upper() and 'D2' in result.get('formula','').upper())

E2 formula references C2 and D2

D4 = 0.05 (Bob South 8770 falls in 5% tier)

E4 = 438.5 (8770 * 0.05)

D8 = 0.10 (Henry South 23353 falls in 10% tier)

E8 = 2335.3 (23353 * 0.10)

D21 = 0.05 (David East 7875 falls in 5% tier)

Sheet 'Commission Summary' exists

check-cell-value A1 Metric "Commission Summary"

Commission Summary A1 = 'Metric'

check-cell-formatted A1 true "Commission Summary"

Commission Summary A1 is bold

check-cell-value B1 Value "Commission Summary"

Commission Summary B1 = 'Value'

check-cell-formatted B1 true "Commission Summary"

Commission Summary B1 is bold

check-cell-value A2 "Total Sales" "Commission Summary"

Commission Summary A2 = 'Total Sales'

check-cell-value B2 268628 "Commission Summary"

Commission Summary B2 = 268628 (total sales)

result.get('formula') is not None and 'SUM' in result.get('formula','').upper()

Commission Summary B2 contains a SUM formula

check-cell-value A3 "Total Commission" "Commission Summary"

Commission Summary A3 = 'Total Commission'

check-cell-value B3 21511.47 "Commission Summary"

Commission Summary B3 = 21511.47 (total commission)

check-cell-value A4 "Average Commission Rate" "Commission Summary"

Commission Summary A4 = 'Average Commission Rate'

result.get('formula') is not None and 'B3' in result.get('formula','').upper() and 'B2' in result.get('formula','').upper()

Commission Summary B4 formula references B3 and B2


Open the file /home/user/Documents/sales_data.xlsx in LibreOffice Calc. It contains a sheet called 'Sales' with columns: Product (A), Region (B), Q1 (C), Q2 (D), Q3 (E), Q4 (F). Row 1 has headers, rows 2-13 have 12 products.

1. Create a new sheet called 'Summary'.
2. In cell A1 of the Summary sheet, enter 'Total Revenue'.
3. In cell B1 of the Summary sheet, enter the formula =SUM(Sales.C2:F13) to sum all quarterly revenue.
4. In cell A2 of the Summary sheet, enter 'Average Per Quarter'.
5. In cell B2 of the Summary sheet, enter the formula =B1/4.
6. Make cells A1 and A2 in the Summary sheet bold.
7. Save the file .

Sheet 'Summary' exists

check-cell-value A1 "Total Revenue" Summary

Summary A1 = 'Total Revenue'

result.get('formula','').upper().replace(' ','').find('SUM') >= 0

Summary B1 contains a SUM formula

Summary B1 = 66050 (total of all quarterly revenue)

check-cell-value A2 "Average Per Quarter" Summary

Summary A2 = 'Average Per Quarter'

result.get('formula') is not None and 'B1' in result.get('formula','').upper()

Summary B2 contains a formula referencing B1

Summary B2 = 16512.5 (66050/4)

Summary A1 is bold

Summary A2 is bold


Open the file /home/user/Documents/students.xlsx in LibreOffice Calc. It contains two sheets:
- 'Roster' with columns: Student ID (A), Name (B), Major (C). Row 1 has headers, rows 2-13 have 12 students with IDs 1001-1012.
- 'Scores' with columns: Student ID (A), Test 1 (B), Test 2 (C), Test 3 (D). Row 1 has headers, rows 2-13 have the same 12 students' test scores.

1. Go to the 'Scores' sheet.
2. In cell E1, enter 'Student Name' and make it bold.
3. In cell E2, enter the formula =VLOOKUP(A2,Roster.$A$1:$B$13,2,0) to look up the student's name from the Roster sheet based on the Student ID in column A. Copy this formula down through E3:E13 for all students.
4. In cell F1, enter 'Average' and make it bold.
5. In cell F2, enter the formula =AVERAGE(B2:D2) to compute the average of the three test scores. Copy this formula down through F3:F13.
6. Sort the entire data range A1:F13 by column F (Average) in descending order, so the highest-scoring student appears at the top. Make sure headers stay in row 1.
7. Save the file .

check-cell-value E1 "Student Name" Scores

Scores E1 = 'Student Name'

Scores E1 is bold

Scores F1 = 'Average'

Scores F1 is bold

Scores E2 contains a VLOOKUP formula

check-cell-value E2 "Irene Taylor" Scores

Scores E2 = 'Irene Taylor' (highest avg student after sort)

Scores F2 contains an AVERAGE formula

Scores F2 value is approximately 94.67 (Irene Taylor's average after sort)

Column F is sorted descending from row 2


Open the file /home/user/Documents/transactions.xlsx in LibreOffice Calc. Sheet 'Transactions' has columns Date (A), Store (B), Category (C), Amount (D) in row 1 (bold headers) and 40 data rows (2-41). Stores are North, South, West. Categories are Food, Clothing, Electronics, Home.

1. Create a new sheet named 'Summary'.
2. On Summary, fill row 1 with bold headers: A1='Store', B1='Food', C1='Clothing', D1='Electronics', E1='Home', F1='Total'.
3. In A2 type 'North'. In A3 type 'South'. In A4 type 'West'.
4. In B2 enter a formula using SUMIFS that sums Transactions column D where Store equals A2 and Category equals B$1. Example: =SUMIFS(Transactions.D:D,Transactions.B:B,$A2,Transactions.C:C,B$1). Copy this formula to cover B2:E4 so every store x category cell has the correct SUMIFS.
5. In F2 enter =SUM(B2:E2). Copy to F3 and F4.
6. In A5 type 'Total' and make it bold.
7. In B5 enter =SUM(B2:B4). Copy B5 across to C5, D5, E5, F5.
8. Save the file .

Summary sheet exists

Summary A1 = Store

Summary B1 = Food

Summary F1 = Total

Summary A1 bold

Summary A2 = North

Summary A3 = South

Summary A4 = West

result.get('formula') is not None and 'SUMIFS' in result.get('formula','').upper()

B2 uses SUMIFS

Summary B2 (North Food) = 500

Summary C2 (North Clothing) = 445

Summary D2 (North Electronics) = 280

Summary E2 (North Home) = 315

Summary B3 (South Food) = 780

Summary D4 (West Electronics) = 870

Summary F2 (North total) = 1540

Summary F3 (South total) = 1895

Summary F4 (West total) = 2625

Summary A5 = Total

Summary A5 bold

Summary B5 (Food total) = 2135

Summary F5 (grand total) = 6060


Open the file /home/user/Documents/contacts.xlsx in LibreOffice Calc. Sheet 'Contacts' has a single column A1 'Full Entry' with 15 contact strings in rows 2-16 in the format 'LastName, FirstName <email@domain>' (e.g. 'Smith, Jane <jane.smith@acme.io>').

1. In B1 enter 'Last Name', C1 enter 'First Name', D1 enter 'Email', E1 enter 'Domain'. Make all four headers bold.
2. In B2 enter a formula that extracts the last name (the text before the comma). Fill down through B16.
3. In C2 enter a formula that extracts the first name. Fill down through C16.
4. In D2 enter a formula that extracts the email address between '<' and '>'. Fill down through D16.
5. In E2 enter a formula that extracts the domain. Fill down through E16.
6. Save the file .

check-cell-value B1 "Last Name" Contacts

B1 = Last Name

check-cell-value C1 "First Name" Contacts

C1 = First Name

D1 = Email

E1 = Domain

B1 bold

B2 last name = Smith

C2 first name = Jane

check-cell-value D2 jane.smith@acme.io Contacts

D2 email = jane.smith@acme.io

E2 domain = acme.io

B3 last name = Brown

C3 first name = Alex

check-cell-value E3 example.com Contacts

E3 domain = example.com

B8 last name = Wilson

C8 first name = Rachel

B16 last name = Young

check-cell-value D16 chris.y@lexcorp.net Contacts

D16 email = chris.y@lexcorp.net

result.get('formula') is not None and ('LEFT' in result.get('formula','').upper() or 'MID' in result.get('formula','').upper())

B2 uses LEFT/MID

result.get('formula') is not None and 'MID' in result.get('formula','').upper() and 'FIND' in result.get('formula','').upper()

D2 uses MID and FIND


Open the file /home/user/Documents/timesheet.xlsx in LibreOffice Calc. The sheet 'Timesheet' has bold headers in row 1 (A='Employee', B='Mon', C='Tue', D='Wed', E='Thu', F='Fri', G='Hourly Rate') and 10 employees in rows 2-11 with their daily hours and hourly rate.

Extend the timesheet with computed columns and a totals row:

1. In H1 enter 'Total Hours' (bold). In I1 enter 'Regular Hours' (bold). In J1 enter 'Overtime Hours' (bold). In K1 enter 'Gross Pay' (bold).
2. In H2:H11 enter =SUM(B2:F2)-style formulas (fill down).
3. In I2:I11 enter =MIN(H2,40).
4. In J2:J11 enter =MAX(0,H2-40).
5. In K2:K11 enter =I2*G2+J2*G2*1.5 (regular pay plus overtime at 1.5x).
6. In A12 type 'Totals' and make it bold. In H12, I12, J12, K12 put SUM formulas that sum rows 2-11 of that column (e.g. H12=SUM(H2:H11)).
7. Save the file .

check-cell-value H1 "Total Hours" Timesheet

H1 = 'Total Hours'

check-cell-value I1 "Regular Hours" Timesheet

I1 = 'Regular Hours'

check-cell-value J1 "Overtime Hours" Timesheet

J1 = 'Overtime Hours'

check-cell-value K1 "Gross Pay" Timesheet

K1 = 'Gross Pay'

H1 bold

K1 bold

H2 uses SUM

H2 total hours (Alice) = 40

H3 total hours (Bob) = 50

H4 total hours (Carol) = 38

H7 total hours (Frank) = 52

I2 uses MIN

I2 regular hours (Alice) = 40

I4 regular hours (Carol, <40) = 38

J2 uses MAX

J2 overtime (Alice=40h) = 0

J3 overtime (Bob=50h) = 10

J7 overtime (Frank=52h) = 12

K2 gross pay (Alice) = 800

K3 gross pay (Bob) = 1375

K7 gross pay (Frank) = 1392

A12 = 'Totals'

A12 bold

H12 total of all total-hours = 430

I12 total regular hours = 389

J12 total overtime hours = 41

K12 total gross pay = 11097

H12 uses SUM


Google Chrome is open. Open two tabs, each showing a Wikipedia article about a functional programming language. Tab 0 must navigate to https://en.wikipedia.org/wiki/Lisp and tab 1 must navigate to https://en.wikipedia.org/wiki/Haskell. Wait for each page to fully load. Then bookmark both articles. When done, both tabs must be open, both articles must be in your browsing history, and both bookmarks must exist. Each Wikipedia article page has an h1 element containing the article title and an infobox table element — the verifier will check these DOM structures are present.

Lisp Wikipedia tab is open

Haskell Wikipedia tab is open

Lisp Wikipedia page was visited

Haskell Wikipedia page was visited

Tab 0 has an h1 element

Tab 1 has an h1 element

Tab 0 has a Wikipedia infobox table

Tab 1 has a Wikipedia infobox table

Lisp Wikipedia page is bookmarked

Haskell Wikipedia page is bookmarked


Search for the paper 'Attention Is All You Need' (the famous Transformer architecture paper) in Google Chrome and download it as a PDF. Save the PDF to /home/user/Downloads/attention_paper.pdf.

PDF file saved as attention_paper.pdf

check-file-contains /home/user/Downloads/attention_paper.pdf "Attention Is All You Need"

PDF contains 'Attention Is All You Need' in the title


Open Google Chrome. Navigate to https://httpbin.org/image/png in the first tab. This URL serves a PNG image directly. Save the image to the default Downloads folder as 'httpbin_image.png'. After saving, open a new tab and navigate to https://httpbin.org/robots.txt. Verify the robots.txt page loads and displays text content. Both tabs should remain open when done.

httpbin.org/image/png was visited

PNG image download completed

Tab with httpbin.org/robots.txt is open

httpbin.org/robots.txt was visited


Download and save two images from httpbin.org to the Downloads folder:
1. JPEG image from https://httpbin.org/image/jpeg → save as 'httpbin_image.jpeg'
2. PNG image from https://httpbin.org/image → save as 'httpbin_image.png'

Both files must exist in /home/user/Downloads/ with the exact filenames specified.

JPEG image saved as httpbin_image.jpeg in Downloads

PNG image saved as httpbin_image.png in Downloads


Google Chrome is open. Visit four image/binary endpoints on httpbin.org in four separate tabs: (1) https://httpbin.org/image/png, (2) https://httpbin.org/image/jpeg, (3) https://httpbin.org/image/webp, and (4) https://httpbin.org/image/svg. Each endpoint serves a different image format. Then bookmark the PNG, JPEG, and SVG image URLs (but NOT the webp URL). When done, all four URLs must appear in your browsing history, the four image tabs must be open, and exactly three of the four endpoints must be bookmarked (png, jpeg, svg).

httpbin.org/image/png was visited

httpbin.org/image/jpeg was visited

httpbin.org/image/webp was visited

httpbin.org/image/svg was visited

PNG tab is open

JPEG tab is open

WebP tab is open

SVG tab is open

PNG URL is bookmarked

JPEG URL is bookmarked

SVG URL is bookmarked

WebP URL is NOT bookmarked


Search for the paper 'ResNet: Enabling Deep Convolutional Neural Networks through Residual Learning' in Google Chrome and download it as a PDF. Save the PDF to /home/user/Downloads/resnet_paper.pdf.

PDF file saved as resnet_paper.pdf

check-file-contains /home/user/Downloads/resnet_paper.pdf "ResNet: Enabling Deep Convolutional Neural Networks through Residual Learning"

PDF contains 'ResNet: Enabling Deep Convolutional Neural Networks through Residual Learning' in the title


Open the following 2 Wikipedia pages and save them to the Downloads folder: (1) https://en.wikipedia.org/wiki/Linux - save as /home/user/Downloads/linux.html, (2) https://en.wikipedia.org/wiki/Open-source_software - save as /home/user/Downloads/open-source.html. The saved pages should be complete HTML files that can be opened in a browser.

Linux Wikipedia page saved as linux.html

linux.html contains 'Linux' keyword

Open-source Wikipedia page saved as open-source.html

open-source.html contains 'open-source' keyword


Google Chrome is open. Open five tabs and navigate them to the following URLs: (1) https://example.com, (2) https://example.org, (3) https://httpbin.org/get, (4) https://httpbin.org/ip, (5) https://en.wikipedia.org/wiki/Internet. Bookmark all five pages. Then close the tabs showing example.com and example.org, so that only three tabs remain open: httpbin.org/get, httpbin.org/ip, and the Internet Wikipedia page. The bookmarks for all five pages should still exist.

Tab with httpbin.org/get is open

Tab with httpbin.org/ip is open

Tab with Internet Wikipedia page is open

Tab with example.com has been closed

Tab with example.org has been closed

Bookmark for example.com still exists

Bookmark for example.org still exists

Bookmark for httpbin.org/get exists

Bookmark for httpbin.org/ip exists

Bookmark for Internet Wikipedia page exists


Google Chrome is open. Navigate to https://httpbin.org/forms/post. Then, submit a pizza order form at https://httpbin.org/forms/post with the following values:
- Customer name: John Smith
- Telephone: 555-1234
- E-mail: john@example.com
- Pizza Size: medium
- Comments: Extra cheese please

After submission, verify that the response page displays all submitted form data correctly.

httpbin.org/forms/post was visited

Form was submitted (httpbin.org/post visited)

Submitted page contains customer name 'John Smith'

Submitted page contains phone number '555-1234'


Submit a form to https://httpbin.org/forms/post with the following values: Customer name: 'Alan Wang', Telephone: '123-4567', E-mail: 'john@example.com', Pizza Size: 'Large', Pizza Toppings: 'Bacon' and 'Mushroom'. Save the server response to /home/user/form_response.json. The response should contain all the submitted form data.

check-file-contains /home/user/form_response.json "Alan Wang"

Form response contains customer name 'Alan Wang'

Form response contains phone number '123-4567'

Form response contains email 'john@example.com'

Form response contains pizza size 'Large'

Form response contains pizza topping 'Bacon'

Form response contains pizza topping 'Mushroom'


Submit a form to https://httpbin.org/forms/post with the following values: Customer name: 'Elena Rodriguez', Telephone: '123-4567', E-mail: 'john@example.com', Pizza Size: 'small', Pizza Toppings: 'onion', Delivery instructions: 'Please ring bell twice — nut allergy in household'. Save the server response to /home/user/form_response.json. The response should contain all the submitted form data.

check-file-contains /home/user/form_response.json "Elena Rodriguez"

Form response contains customer name 'Elena Rodriguez'

Form response contains pizza size 'small'

Form response contains pizza topping 'onion'

check-file-contains /home/user/form_response.json "ring bell twice"

check-file-contains /home/user/form_response.json "extra cheese"

Form response contains delivery instructions 'extra cheese'


Google Chrome is open. Visit the following five Wikipedia URLs in sequence, one after another in the same tab: (1) https://en.wikipedia.org/wiki/Alan_Turing, (2) https://en.wikipedia.org/wiki/Ada_Lovelace, (3) https://en.wikipedia.org/wiki/Grace_Hopper, (4) https://en.wikipedia.org/wiki/Tim_Berners-Lee, (5) https://en.wikipedia.org/wiki/Linus_Torvalds. After visiting all five pages, the final page (Linus_Torvalds) should still be displayed in the tab. Bookmark only the Linus_Torvalds page. When done, you should have one tab open showing Linus_Torvalds, with all five URLs in browsing history.

Alan_Turing Wikipedia page was visited

Ada_Lovelace Wikipedia page was visited

Grace_Hopper Wikipedia page was visited

Tim_Berners-Lee Wikipedia page was visited

Linus_Torvalds Wikipedia page was visited

Current tab shows Linus_Torvalds page

Bookmark for Linus_Torvalds exists


Google Chrome is open. Open three separate tabs and navigate each to a different httpbin.org GET endpoint with query parameters: (1) https://httpbin.org/get?project=atlas&env=prod, (2) https://httpbin.org/get?user=claude&role=admin, (3) https://httpbin.org/get?city=tokyo&year=2026. The page body for each is a JSON document that echoes the query parameters you sent, so the parameter values will be visible on the page. Bookmark each of the three response pages. When done you should have three tabs open, all three URLs should be in your browsing history, and all three should be bookmarked.

Second GET URL with user=claude query was visited

Third GET URL with city=tokyo query was visited

Tab with project=atlas query is open

Tab with user=claude query is open

Tab with city=tokyo query is open

Bookmark for the project=atlas response page exists

Bookmark for the user=claude response page exists

Bookmark for the city=tokyo response page exists


Google Chrome is open. Open the following 4 pages, each in its own tab: (1) https://en.wikipedia.org/wiki/Linux, (2) https://en.wikipedia.org/wiki/Open-source_software, (3) https://en.wikipedia.org/wiki/Ubuntu, (4) https://en.wikipedia.org/wiki/Linus_Torvalds. After all tabs are open, bookmark the Linux page (https://en.wikipedia.org/wiki/Linux) and the Linus Torvalds page (https://en.wikipedia.org/wiki/Linus_Torvalds). All 4 tabs must remain open when done.

Tab with Linux Wikipedia page is open

Tab with Open-source_software Wikipedia page is open

Tab with Ubuntu Wikipedia page is open

Tab with Linus Torvalds Wikipedia page is open

Bookmark for Linux Wikipedia page exists

Bookmark for Linus Torvalds Wikipedia page exists


Google Chrome is open. Navigate to https://httpbin.org/html in the first tab. This page contains a passage from Herman Melville's Moby Dick. Then open a second tab and navigate to https://httpbin.org/base64/Q2xhdWRlIENvZGUgaXMgYXdlc29tZQ== which displays the base64-decoded text 'Claude Code is awesome'. Bookmark both pages. When done, you should have two tabs open: one showing the Moby Dick text from httpbin.org/html and one showing the decoded base64 text.

Tab with httpbin.org/html is open

Tab with httpbin.org/base64 endpoint is open

Bookmark for httpbin.org/html exists

Bookmark for httpbin.org/base64 page exists


Visit Wikipedia pages in the following sequence and create bookmarks:
1. Start at https://en.wikipedia.org/wiki/World_Wide_Web
2. After the page loads, find and click the link to 'Tim Berners-Lee' on the page to navigate to https://en.wikipedia.org/wiki/Tim_Berners-Lee (the link is in the article text). Bookmark the Tim Berners-Lee page.
3. Open https://en.wikipedia.org/wiki/CERN
4. Navigate to https://en.wikipedia.org/wiki/HTML

Create bookmarks for:
- Tim Berners-Lee page
- CERN page

When done:
- All four Wikipedia pages must appear in browsing history
- At least two tabs must be open
- The two specified bookmarks must exist

World_Wide_Web Wikipedia page was visited

CERN Wikipedia page was visited

HTML Wikipedia page was visited

Bookmark for Tim Berners-Lee page exists

Bookmark for CERN page exists


Google Chrome is open. Navigate to https://en.wikipedia.org/wiki/Python_(programming_language) and bookmark this page. Then open a new tab and navigate to https://en.wikipedia.org/wiki/JavaScript and bookmark this page. Then open a third tab and navigate to https://en.wikipedia.org/wiki/Rust_(programming_language) and bookmark this page. Finally, close the tab that is showing the JavaScript Wikipedia page. When done, you should have exactly two tabs remaining: one showing the Python page and one showing the Rust page. All three bookmarks (Python, JavaScript, Rust) should still exist.

Tab with Python_(programming_language) Wikipedia page is open

Tab with Rust_(programming_language) Wikipedia page is open

JavaScript tab has been closed

Bookmark for Python_(programming_language) exists

Bookmark for JavaScript exists even though tab was closed

Bookmark for Rust_(programming_language) exists


Colorize the point cloud /home/user/Documents/plain.ply (350 ASCII points, no color) by assigning an RGB color value to every point. Export the colored cloud as a binary little-endian PLY at /home/user/Documents/plain_colored.ply with RGB color columns included. The output must still contain all 350 points and carry RGB color.

Colored PLY exists

Output is binary little-endian PLY

Output has 350 points

Output carries RGB color


Open /home/user/Documents/city.ply in CloudCompare. It is an ASCII PLY with 800 points spread roughly over the range 0..20 on every axis. Crop the cloud so that only points whose X, Y and Z coordinates all lie inside the axis-aligned box from (0, 0, 0) to (10, 10, 10) remain. Export the cropped cloud as an ASCII PLY at /home/user/Documents/city_cropped.ply. At least 50 points must remain after cropping.

Cropped PLY output exists

check-bbox-within /home/user/Documents/city_cropped.ply 0 0 0 10 10 10

All remaining points lie inside [0,0,0]-[10,10,10]

At least 50 points remain


Open /home/user/Documents/dense_field.ply in CloudCompare. It is an ASCII PLY with 2000 points uniformly distributed in the cube (0,0,0)..(20,20,20). Use the Cross Section tool or Edit > Crop to keep only points that lie inside the axis-aligned box (5, 5, 5)..(15, 15, 15). Export the cropped cloud as an ASCII PLY at /home/user/Documents/dense_field_roi.ply. At least 100 points must remain after cropping and every remaining point must lie inside that box.

Cropped PLY exists

Output is ASCII PLY

check-bbox-within /home/user/Documents/dense_field_roi.ply 5 5 5 15 15 15

All remaining points inside [5,5,5]..[15,15,15]

At least 100 points remain


Convert /home/user/Documents/source.ply to big-endian binary PLY format at /home/user/Documents/source_be.ply. The input is an ASCII PLY with exactly 450 points. The output must preserve all 450 points without modification and use binary big-endian encoding.

Big-endian PLY exists

Output is binary big-endian PLY

Output has 450 points


Export the point cloud from /home/user/Documents/colored.ply to /home/user/Documents/colored.asc as an ASCII cloud. The input is an ASCII PLY with 300 points that carry RGB color. The output must contain all 300 points with X, Y, Z, R, G, B columns (6 columns total) to preserve the color information.

ASC output exists

Output has 300 points

Output preserves RGB color


Compute cloud-to-cloud distances between /home/user/Documents/compared.ply and /home/user/Documents/reference.ply. Both are ASCII PLYs with 1000 points each; reference.ply is the same planar patch as compared.ply shifted by +2 units along Z. Attach the per-point distances to compared.ply as a scalar field and export the result as an ASCII PLY at /home/user/Documents/compared_c2c.ply with all 1000 points and the distance scalar field.

Output exists

Point count preserved

Scalar field property present beyond x,y,z

ASCII PLY


Open `/home/user/Documents/cloud.ply` and `/home/user/Documents/plane.obj` in CloudCompare. Compute the distance from each point in `cloud.ply` to the surface of `plane.obj`, and store the resulting per-point distance values as a scalar field associated with the point cloud. Export the enriched point cloud as an ASCII PLY file at `/home/user/Documents/cloud_c2m.ply`. The output must preserve all 800 points and include an additional per-vertex scalar property containing the computed distances.

Output exists

Point count preserved

ASCII PLY


Open /home/user/Documents/surface.ply in CloudCompare. It is an ASCII PLY with 1500 points on a curved paraboloid surface with no per-point normals. Compute per-point normals (default options are fine). Then export the cloud — including the computed normals — as an ASCII PLY at /home/user/Documents/surface_normals.ply. The output must have 1500 points and must include nx, ny, nz properties.

Output exists

1500 points

Normals present in output

ASCII PLY


Open /home/user/Documents/tower.ply in CloudCompare. It is an ASCII PLY with 2000 points distributed in a vertical column (X, Y in -1..1, Z in 0..10). Extract a thin horizontal slice: keep only points with Z in the interval [4.5, 5.5]. Export the resulting slice cloud as an ASCII PLY at /home/user/Documents/tower_slice.ply. The output must have at least 50 points and all points' Z coordinates must lie within [4.5, 5.5].

Slice exists

check-bbox-within /home/user/Documents/tower_slice.ply -2 -2 4.5 2 2 5.5

All points within Z in [4.5, 5.5]

At least 50 points remain

Strictly fewer points than original


Apply CSF (Cloth Simulation Filter) ground segmentation to /home/user/Documents/scene.ply (2500 points, ASCII). Classify points into ground and non-ground using default CSF parameters. Export only the ground points as an ASCII PLY at /home/user/Documents/ground.ply. The output should contain only points classified as ground.

Ground cloud exists

At least 1000 ground points

At most 2000 ground points (off-ground excluded)

check-bbox-within /home/user/Documents/ground.ply -100 -100 -1 100 100 2.5

All ground points are low-Z


Open /home/user/Documents/terrain.ply in CloudCompare. It is an ASCII PLY with 1000 points forming a terrain heightmap (X,Y in 0..10, Z a smooth function). Mesh this cloud using Delaunay 2.5D (best-fitting plane or XY plane, default options). The resulting mesh has a vertex per input point and a triangulated surface. Export the mesh as a PLY at /home/user/Documents/terrain_mesh.ply. Do not export the original cloud. The output must be a mesh with exactly 1000 vertices and at least 1500 triangular faces.

Output exists

Output is a mesh

1000 vertices match input cloud

At least 1500 triangular faces


Open `/home/user/Documents/reference.ply` and `/home/user/Documents/misaligned.ply` in CloudCompare. Register the point cloud in `misaligned.ply` to the coordinate frame of `reference.ply`, and save the resulting aligned cloud as `/home/user/Documents/aligned.ply` in ASCII PLY format. Export only the aligned cloud. The result should still contain 1200 points and should closely match the spatial extent of the reference cloud (approximately x in [-2.2, 5.2], y in [-2.2, 2.2], z in [-2.2, 2.2]).

Aligned PLY exists

Aligned cloud has the same 1200 points

check-bbox-within /home/user/Documents/aligned.ply -2.5 -2.5 -2.5 5.5 2.5 2.5

Aligned cloud bbox falls within reference cloud bbox

Exported as ASCII PLY


Open /home/user/Documents/two_clusters.ply in CloudCompare. It is an ASCII PLY with 1500 points split into two clearly-separated clusters: a large cluster (~1000 points) near the origin and a small cluster (~500 points) near (20, 20, 20). Segment the cloud into clusters. Identify the larger of the two clusters and export only that cluster as an ASCII PLY at /home/user/Documents/largest_cluster.ply. Do not export the smaller cluster. The output must have between 800 and 1200 points and its bounding box must lie within [-5, -5, -5]-[5, 5, 5].

Largest cluster exists

At least 800 points

At most 1200 points (small cluster excluded)

check-bbox-within /home/user/Documents/largest_cluster.ply -5 -5 -5 5 5 5

Cluster bbox is near origin (not the distant cluster)


Merge three ASCII XYZ point clouds: /home/user/Documents/north.xyz (250 points), /home/user/Documents/south.xyz (300 points), and /home/user/Documents/east.xyz (350 points) into a single point cloud. Export the merged cloud as a binary little-endian PLY at /home/user/Documents/combined.ply containing all 900 points (250+300+350). The output must be a point cloud (no mesh faces).

Combined PLY exists

Output is binary little-endian PLY

Merged cloud has 900 points (250+300+350)

Output is a cloud, not a mesh


Merge two ASCII XYZ point clouds: /home/user/Documents/left.xyz (200 points) and /home/user/Documents/right.xyz (300 points) into a single point cloud. Export the merged cloud as a binary little-endian PLY at /home/user/Documents/merged.ply containing all 500 points (200+300).

Merged PLY exists

Merged cloud has 500 points (200+300)

Output is PLY


Open /home/user/Documents/gear.obj in CloudCompare. It is an OBJ mesh with exactly 48 vertices and 80 triangular faces. Produce two output files: 1) A PLY mesh at /home/user/Documents/gear.ply preserving all 48 vertices and all 80 triangular faces (export the mesh, not the vertices-only cloud). 2) An ASCII XYZ point cloud at /home/user/Documents/gear.xyz containing only the 48 mesh vertices, with no color or extra columns (just X Y Z).

PLY mesh exists

PLY output is a mesh

PLY has 48 vertices

PLY has 80 triangular faces

XYZ cloud exists

XYZ is detected as ASCII cloud

XYZ has 48 points

XYZ has no color columns


Open /home/user/Documents/shape.obj in CloudCompare. It is a triangular OBJ mesh with exactly 120 vertices and 240 faces. Extract only its vertices and save them as a plain 3-column ASCII XYZ point cloud at /home/user/Documents/shape.xyz. The output file must be a point cloud (not a mesh), contain all 120 vertices, have no RGB color columns, and be saved in the ASCII cloud format with only X, Y, Z columns.

XYZ output exists

Output is an ASCII cloud

Output has 120 points

Output has no RGB color


Open the point cloud /home/user/Documents/scan_binary.ply in CloudCompare. Create an ASCII-encoded PLY version of this point cloud and save it as: /home/user/Documents/scan_ascii.ply. The output must represent the same point cloud, preserving all 500 points and associated attributes.

ASCII PLY output exists

Output PLY is ASCII encoded

Output has exactly 500 points


Open /home/user/Documents/tetra.ply in CloudCompare. It is an ASCII PLY tetrahedron mesh with 4 vertices and 4 triangular faces. Save the mesh as an OBJ file at /home/user/Documents/tetra.obj. The exported OBJ must keep all 4 faces — export the mesh, not a vertices-only cloud.

OBJ output exists

Output OBJ contains faces

Output has 4 vertices

Output has 4 triangular faces


Open /home/user/Documents/lidar_intensity.xyz in CloudCompare. It is a 4-column ASCII point cloud (X Y Z Intensity) with 600 points — the 4th column is a scalar field that CloudCompare should import as 'Scalar field #1' or 'intensity'. Re-export the cloud twice, preserving the intensity scalar in both outputs:
1. File > Save As: save as an ASCII cloud at /home/user/Documents/lidar_intensity.asc with the X, Y, Z and the intensity scalar column enabled (4 columns).
2. File > Save As: save as a PLY file (ASCII or binary) at /home/user/Documents/lidar_intensity_out.ply with the intensity scalar exported (so the PLY carries a scalar / intensity property).
Both outputs must contain all 600 points.

ASC output exists

ASC has 600 points

ASC preserves intensity scalar (4 columns)

PLY output exists

PLY has 600 points


Apply a uniform 2x scale transformation to /home/user/Documents/small.ply. The input is an ASCII PLY with 250 points whose bounding box is (0, 0, 0) to (22, 22, 22). Export the scaled cloud as an ASCII PLY at /home/user/Documents/small_scaled.ply. The output must preserve all 250 points and have an X extent of at least 40 units.

Scaled PLY exists

Output is ASCII PLY

All 250 points preserved

check-bbox-min-extent /home/user/Documents/small_scaled.ply x 40

X extent is at least 40 after 2x scale


Open /home/user/Documents/thick.ply in CloudCompare. It is a densely-packed ASCII PLY with 1500 points inside a 10x10x10 cube. Use Edit > Subsample (Cloud Subsampling) and choose the 'Space' method (minimum distance) with a minimum distance large enough to thin the cloud to at least 80 but strictly fewer than 1500 points — for example a min distance around 1.0 unit. Export the subsampled cloud as an ASCII PLY at /home/user/Documents/thick_thin.ply. Do not export the original 1500-point cloud.

Subsampled PLY exists

Output is ASCII PLY

At least 80 points remain

Point count strictly less than original 1500


Open the ASCII point cloud /home/user/Documents/survey.xyz in CloudCompare. Create a binary little-endian PLY representation of this point cloud and save it to: /home/user/Documents/survey.ply. The resulting file must contain the same 600 points as the source data, with no points removed or altered.

Binary PLY output exists

Output PLY is binary little-endian

Output has 600 vertices


Extend the AWS architecture diagram at /home/user/Documents/aws_arch.drawio. The file contains 3 existing shapes (VPC, EC2, RDS). Add 7 new shapes with these labels: CloudFront, LoadBalancer, Web1, Web2, App1, App2, S3Bucket. Apply fill colors: Web1 and Web2 must be #dae8fc (blue); App1 and App2 must be #d5e8d4 (green). Connect LoadBalancer to Web1. The final diagram must have exactly 10 vertices on page 0. Save the file.

Diagram file exists

check-vertex-count /home/user/Documents/aws_arch.drawio 10 0

Page 0 has exactly 10 vertices

Original VPC label remains

Original EC2 label remains

Original RDS label remains

CloudFront added

LoadBalancer added

Web1 added

Web2 added

App1 added

App2 added

S3Bucket added

Prompt: Inspect the vertices list. Do the two shapes labeled 'Web1' and 'Web2' both have fillColor #dae8fc in their style string, AND do 'App1' and 'App2' both have fillColor #d5e8d4? Answer yes only if all four conditions are met.

Web1/Web2 are blue (#dae8fc) and App1/App2 are green (#d5e8d4)

Prompt: Inspect the connections list. Does it include an edge whose source vertex is labeled 'LoadBalancer' and whose target vertex is labeled 'Web1'? (Cross-reference source/target IDs with the vertices.)

Connection from LoadBalancer to Web1 exists


Create a BPMN payment processing flow at /home/user/Documents/payment_bpmn.drawio. Create 7 shapes on page 0: Start (ellipse), Receive Payment (rectangle), Validate (rectangle), Risk Check (diamond), Approve (rectangle), Reject (rectangle), End (ellipse). Connect them: Start->Receive Payment->Validate->Risk Check->Approve->End, and Risk Check->Reject. The diagram must have exactly 7 vertices and 7 edges. Save the file.

Diagram file exists

check-vertex-count /home/user/Documents/payment_bpmn.drawio 7 0

Exactly 7 vertices

check-edge-count /home/user/Documents/payment_bpmn.drawio 7 0

Exactly 7 edges

Start label exists

check-label-exists /home/user/Documents/payment_bpmn.drawio "Receive Payment"

Receive Payment label exists

Validate label exists

check-label-exists /home/user/Documents/payment_bpmn.drawio "Risk Check"

Risk Check label exists

Approve label exists

Reject label exists

End label exists

Prompt: Using the connections list (source/target IDs) and the vertices list (IDs to labels), verify that all four of these edges exist: (1) Validate -> Risk Check, (2) Risk Check -> Approve, (3) Risk Check -> Reject, (4) Approve -> End. Answer yes only if all four exist.

Decision-branch connections exist


Extend the network diagram at /home/user/Documents/network.drawio. The file contains two connected shapes (Router, Server). Add two rectangles: Firewall and Load Balancer. Connect Firewall to Load Balancer. Add a second page named Notes. Preserve all existing shapes and connections. Save the file.

Diagram file still exists

Original 'Router' shape preserved

Original 'Server' shape preserved

New 'Firewall' shape added

check-label-exists /home/user/Documents/network.drawio "Load Balancer"

New 'Load Balancer' shape added

Diagram has 2 pages (original + Notes)


Create a database schema diagram at /home/user/Documents/er_diagram.drawio. Create 4 rectangles labeled: Customer, Order, Product, Category. Connect them: Customer->Order, Order->Product, Product->Category. The diagram must have exactly 4 vertices and 3 edges. Save the file.

Diagram file exists at expected path

Shape 'Customer' exists

Shape 'Order' exists

Shape 'Product' exists

Shape 'Category' exists

Exactly 4 shapes

Exactly 3 edges


Modify the workflow at /home/user/Documents/wf_fix.drawio. The file contains 5 connected shapes: Input (id 2), Clean (id 3), Transform (id 4), Check (id 5, diamond), Save (id 6). Change fills: Input to #dae8fc (blue), Clean to #d5e8d4 (green), Transform to #d5e8d4 (green), Check to #fff2cc (yellow), Save to #f8cecc (red). Add shape labeled Reject. Connect Check to Reject. Final diagram must have 6 vertices. Save the file.

Diagram file exists

check-vertex-count /home/user/Documents/wf_fix.drawio 6 0

Exactly 6 vertices (5 original + Reject)

Input label remains

Clean label remains

Transform label remains

Check label remains

Save label remains

Reject added

check-style-property /home/user/Documents/wf_fix.drawio 2 fillColor "#dae8fc"

Input (id 2) fill is blue #dae8fc

check-style-property /home/user/Documents/wf_fix.drawio 3 fillColor "#d5e8d4"

Clean (id 3) fill is green #d5e8d4

check-style-property /home/user/Documents/wf_fix.drawio 4 fillColor "#d5e8d4"

Transform (id 4) fill is green #d5e8d4

check-style-property /home/user/Documents/wf_fix.drawio 5 fillColor "#fff2cc"

Check (id 5) fill is yellow #fff2cc

check-style-property /home/user/Documents/wf_fix.drawio 6 fillColor "#f8cecc"

Save (id 6) fill is red #f8cecc

Prompt: Using the connections list (source/target IDs) and the vertices list (IDs to labels), verify that there is an edge whose source label is 'Check' and target label is 'Reject'. Answer yes only if this edge exists.

Connection Check -> Reject exists


Create an office floor plan at /home/user/Documents/floorplan.drawio. Create 6 rectangles labeled: Lobby, MeetingRoom, Office1, Office2, Kitchen, Restroom. Apply fills: Lobby #f5f5f5, MeetingRoom #dae8fc, Kitchen #fff2cc. Connect adjacent rooms with at least 5 edges representing doorways: Lobby<->MeetingRoom, Lobby<->Office1, Lobby<->Office2, Lobby<->Kitchen, Kitchen<->Restroom. Save the file.

Diagram file exists

check-vertex-count /home/user/Documents/floorplan.drawio 6 0

Exactly 6 vertices

Lobby label exists

MeetingRoom label exists

Office1 label exists

Office2 label exists

Kitchen label exists

Restroom label exists

At least 5 doorway edges on page 0

Prompt: Inspect the vertices list. Does the vertex labeled 'Lobby' have fillColor=#f5f5f5 in its style, the vertex labeled 'MeetingRoom' have fillColor=#dae8fc, and the vertex labeled 'Kitchen' have fillColor=#fff2cc? All three must match.

Lobby/MeetingRoom/Kitchen have correct fill colors