Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions app/instructor/exercises/[id]/ExerciseManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ export default function ExerciseManager({ exercise: initial, sessions, assignedU
}

async function toggleAssignment(userId: string, currentlyAssigned: boolean) {
const newIds = currentlyAssigned
? assignedUsers.filter((u) => u.id !== userId).map((u) => u.id)
: [...assignedUsers.map((u) => u.id), userId];
const newIds = userId === '__all__'
? allParticipants.map((u) => u.id)
: currentlyAssigned
? assignedUsers.filter((u) => u.id !== userId).map((u) => u.id)
: [...assignedUsers.map((u) => u.id), userId];
setSaving(true);
try {
const res = await fetch(`/api/instructor/exercises/${exercise.id}`, {
Expand Down Expand Up @@ -139,7 +141,18 @@ export default function ExerciseManager({ exercise: initial, sessions, assignedU
<div className="card">
<div className="card-header">
<span className="card-title">Participants</span>
<span className="badge badge-purple">{assignedUsers.length} assigned</span>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<span className="badge badge-purple">{assignedUsers.length} assigned</span>
{assignedUsers.length < allParticipants.length && (
<button
onClick={() => toggleAssignment('__all__', false)}
disabled={saving}
className="btn btn-sm btn-primary"
>
Assign All
</button>
)}
</div>
</div>
{allParticipants.length === 0 ? (
<p style={{ color: 'var(--text3)', fontSize: 13 }}>No participant accounts exist yet.</p>
Expand Down
263 changes: 169 additions & 94 deletions docs/go-reloaded/coding-go-reloaded.md

Large diffs are not rendered by default.

47 changes: 43 additions & 4 deletions docs/go-reloaded/question0.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
### Question 1
## Drill 1 — Read Input Text from Stdin

Your program receives two arguments: an input filename and an output filename. You read the input file, process it, and write to the output.
Write a function that reads the entire input from stdin and returns it as a string:

A classmate reads the entire file into memory as one string and processes it all at once. You consider reading it line by line instead.
```go
func readInput() string
```

**Which approach did you choose — and why? What are the trade-offs between whole-file-in-memory vs line-by-line for a text transformation tool like this? What breaks in each approach when the input file is very large?**
**Requirements:**
- Read all lines from stdin
- Join them back with newlines
- Return the full text as a single string

**Starter:**
```go
package main

import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
// TODO: implement
return ""
}

func main() {
text := readInput()
fmt.Print(text)
}
```

**Stdin (paste into the stdin box):**
```
hello world
this is a test
```

**Expected output:**
```
hello world
this is a test
```
57 changes: 54 additions & 3 deletions docs/go-reloaded/question1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
### Question 2
## Drill 2 — Convert `(hex)` Tags

You need to handle `(up)`, `(low)`, and `(cap)` — each with an optional number modifier like `(up, 3)`.
Write a function that finds every `(hex)` tag and replaces the word immediately before it with its decimal value:

**Walk through your implementation decision: did you handle the simple case `(up)` and the numbered case `(up, 3)` in the same code path or separately? What made that the right call? What would break if you tried to force both into a single handler?**
```go
func convertHex(text string) string
```

**Requirements:**
- The word before `(hex)` is always a valid hexadecimal number
- Replace that word with its decimal equivalent
- Remove the `(hex)` tag from the output

**Starter:**
```go
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

func convertHex(text string) string {
// TODO: implement
return text
}

func main() {
text := readInput()
fmt.Println(convertHex(text))
}
```

**Stdin:**
```
1E (hex) files were added
```

**Expected output:**
```
30 files were added
```

**Hint:** Use `strconv.ParseInt(s, 16, 64)` to parse hex, and `strconv.FormatInt(n, 10)` to convert back to decimal.
43 changes: 38 additions & 5 deletions docs/go-reloaded/question10.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
### Question 11
## Drill 11 — Test Punctuation Cleanup

You have 8 transformation rules to implement. Two approaches are on the table:
Use your full pipeline. Verify punctuation spacing works correctly including grouped punctuation.

- **Approach A:** One large function that scans the text and handles every rule in a single pass.
- **Approach B:** A pipeline — separate functions for each rule, applied in sequence.
**Starter:**
```go
package main

**Which did you choose — and what are the real trade-offs? Think specifically about: what happens when two rules interact (e.g., `(up)` fires on a word that also needs punctuation cleanup), how easy it is to add a 9th rule later, and how you'd write unit tests for each approach.**
import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

// TODO: paste your full transform pipeline here

func main() {
text := readInput()
fmt.Print(transform(text))
}
```

**Stdin:**
```
I was sitting over there ,and then BAMM !!
```

**Expected output:**
```
I was sitting over there, and then BAMM!!
```
42 changes: 39 additions & 3 deletions docs/go-reloaded/question11.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
### Question 12
## Drill 12 — Test Single-Quote Formatting

The spec says to use only standard Go packages. You need to do string manipulation, file I/O, number base conversion, and pattern matching.
Use your full pipeline. Verify single-quote pairs are formatted correctly for both single-word and multi-word cases.

**Map out which standard Go packages you used for which rules — and for at least one rule, explain why you chose that package's approach over writing the logic manually. What does the standard library give you that a hand-rolled solution might get wrong?**
**Starter:**
```go
package main

import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

// TODO: paste your full transform pipeline here

func main() {
text := readInput()
fmt.Print(transform(text))
}
```

**Stdin:**
```
I am exactly how they describe me: ' awesome '
```

**Expected output:**
```
I am exactly how they describe me: 'awesome'
```
42 changes: 38 additions & 4 deletions docs/go-reloaded/question12.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
### Question 13
## Drill 13 — Test the Article Rule

Your auditor is another student. The spec says: *"We advise you to create your own tests for yourself and for when you will correct your auditees."*
Use your full pipeline. Verify `a` → `an` works for vowels and `h`.

You need to write tests that are genuinely useful — not just the four sample inputs from the spec.
**Starter:**
```go
package main

**Design a test suite for go-reloaded. What categories of input would you test beyond the given samples? List at least 6 specific test cases — including at least two that target interactions between rules (e.g., a word that needs both `(cap)` and punctuation cleanup) — and explain what each one is designed to catch.**
import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

// TODO: paste your full transform pipeline here

func main() {
text := readInput()
fmt.Print(transform(text))
}
```

**Stdin:**
```
There it was. A amazing rock!
```

**Expected output:**
```
There it was. An amazing rock!
```
42 changes: 39 additions & 3 deletions docs/go-reloaded/question13.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
### Question 14
## Drill 14 — Combined Rules

The spec guarantees that when `(hex)` or `(bin)` is used, the word before it will always be a valid number in that base. But in a real production tool, you can't make that guarantee.
Use your full pipeline. This input exercises multiple rules at once — case modifiers, punctuation, and the article rule all interact.

**Without changing the spec's required behavior for valid inputs, how would you design your error handling for invalid inputs? What should the program output, exit with, or log — and how does Go's idiomatic error handling pattern (`if err != nil`) shape the way you structure this decision across your codebase?**
**Starter:**
```go
package main

import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

// TODO: paste your full transform pipeline here

func main() {
text := readInput()
fmt.Print(transform(text))
}
```

**Stdin:**
```
it (cap) was the best of times, it was the worst of times (up) , it was the age of wisdom, it was the age of foolishness (cap, 6) , it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of darkness, it was the spring of hope, IT WAS THE (low, 3) winter of despair.
```

**Expected output:**
```
It was the best of times, it was the worst of TIMES, it was the age of wisdom, It Was The Age Of Foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of darkness, it was the spring of hope, it was the winter of despair.
```
53 changes: 50 additions & 3 deletions docs/go-reloaded/question14.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
## Reflection Prompt (Bonus)
## Drill 15 — Edge Cases

After completing go-reloaded, you look back at your code. You notice that the section handling `(low, n)`, `(up, n)`, and `(cap, n)` is almost identical three times — just with a different string transformation applied.
Use your full pipeline. This input combines all rules and tests boundary conditions — make sure nothing breaks.

**What refactoring would eliminate the duplication? Write the signature of a Go function that could replace all three, and explain what you'd pass as an argument to make it work for all cases. What does this refactoring reveal about the design principle your original implementation missed?**
**Starter:**
```go
package main

import (
"bufio"
"fmt"
"os"
"strings"
)

func readInput() string {
var lines []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n")
}

// TODO: paste your full transform pipeline here

func main() {
text := readInput()
fmt.Print(transform(text))
}
```

**Stdin:**
```
Simply add 42 (hex) and 10 (bin) and you will see the result is 68.
```

**Expected output:**
```
Simply add 66 and 2 and you will see the result is 68.
```

**Also test with:**
```
Ready, set, go (up) !
```
**Expected:**
```
Ready, set, GO!
```

Try both inputs — your pipeline should handle them without any changes to the code.
Loading
Loading