Skip to content

Commit

Permalink
Merge pull request #38 from LyonSyonII/dev
Browse files Browse the repository at this point in the history
Overhaul chapter 5 and small fixes
  • Loading branch information
LyonSyonII authored Jul 7, 2024
2 parents b61dd4d + 655ffc5 commit 2c858bc
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 30 deletions.
Binary file added frontend/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions frontend/src/components/Checkpoint/checkpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ export function subscribe(id: string, run: (checkpoints: Set<string>) => Promise
runOnSubscribed && callSubscribed(level);
}

export async function getAll() {
return idb.entries(store);
}

export async function stringifyStore(): Promise<string> {
const entries = (await idb.entries(store))
.map(([k, v]: [IDBValidKey, Set<string>]) => [k, JSON.stringify([...v.values()])]);
return JSON.stringify(entries);
}

/** Parses a specified JSON, sets the store to the parsed values and returns it. */
export async function parseStore(json: string): Promise<[IDBValidKey, Set<string>][]> {
const parsed = JSON.parse(json) as [ IDBValidKey, string ][];
const entries: [IDBValidKey, Set<string>][] = parsed.map(([k, v]) => [k, new Set(JSON.parse(v))]);
await idb.setMany(entries);
return entries;
}

const subscribed: Map<string, ((checkpoints: Set<string>) => Promise<void>)[]> = new Map();

async function callSubscribed(level: string) {
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/components/CodeBlock/persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,14 @@ export async function get(key: string): Promise<string | undefined> {
export async function set(key: string, value: string) {
return idb.set(key, value, store);
}

export async function stringifyStore(): Promise<string> {
return JSON.stringify(await idb.entries(store));
}

/** Parses a specified JSON, sets the store to the parsed values and returns it. */
export async function parseStore(json: string): Promise<[IDBValidKey, string][]> {
const entries = JSON.parse(json) as [ IDBValidKey, string ][];
await idb.setMany(entries);
return entries;
}
5 changes: 3 additions & 2 deletions frontend/src/components/WIP.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
:::danger[WIP]
This page is still Work In Progress, check back soon!
:::danger[Page in testing phase]
This page should be finished, but there might be some bugs or things that are hard to understand.
Proceed with caution!
:::
6 changes: 3 additions & 3 deletions frontend/src/content/docs/en/first-steps/1-introduction.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Introduction
title: A small introduction
description: An introduction to the Rust Quest interactive book.
---

Expand Down Expand Up @@ -27,11 +27,11 @@ It is possible that sometimes you won't understand what's going on, and that's o
Most exercises follow the "learn by doing" approach, and will expect you to find the solution on your own, even if you do not fully understand.
If you find yourself stuck, you can always click on the "Hint" button (the light bulb icon) to get a little help.

Try running the following snippet (click the "Run" button on the right or press ` + ↵` on your keyboard while editing):
Try running the following snippet (click the "Run" button on the right or press `Ctrl + ↵` on your keyboard while editing):

export const errorMsg =
`Woops, something went wrong and the code does not compile!
If you've mistakenly messed up the code, click the "Reset" button to return it back to its original state.`
If you've mistakenly messed up the code, click the "Reset" button to return it back to its original state.`;

<Hint visible="true">
I'm a hint 💡
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function Grocer(props) {
/>
)
}
/** Grocer text. Text with the grocer's background but without padding or portrait. */
/** Grocer Text. Text with the grocer's background but without padding or portrait. */
export function GT(props) {
return (
<PText
Expand Down
66 changes: 44 additions & 22 deletions frontend/src/content/docs/en/first-steps/5-killing-some-slimes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ import RobotGame from "@components/RobotGame/RobotGame.astro";
import Hint from "@components/Hint.astro";
import { Content as WIP } from "@components/WIP.mdx";

:::danger[Page in testing phase]
This page should be finished, but there might be some bugs or things that are hard to understand.
Proceed with caution!
:::
<WIP />

After long days of paperwork and chores, you've finally recieved your first real quest!
You can't contain the excitement and quickly open the letter:
Expand Down Expand Up @@ -66,6 +63,9 @@ If you have any issue, don't hesitate to reach out to our customer support for f
We wish you a happy monster extermination!
</QuestionCard>


Woops, while you were reading one of these gelatinous things approached you.

<Hint>
Remember the instructions:
- `up();`
Expand All @@ -84,21 +84,21 @@ Don't forget the semicolon at the end of each function!

<Checkpoint id="5-2-robot">

Once the simulation is complete, the robot swiftly starts moving and punches the slime to death.
Once the simulation is complete, the robot swiftly moves and punches the slime to death, well done!.

One down, many more to go!
But the machine's fighting isn't specially stealthy, causing it to alert a nearby monster.

<RobotGame
id="5-3-robot"
question="Kill another one!"
question="Finish another one!"
/>
</Checkpoint>

<Checkpoint id="5-3-robot">
Another slime bites the dust!

Now there's two simulations?
No problem, you can handle this!
The robot tries to follow your instructions, but the slime is surprisingly quick, and dodges every blow.

Seems like only one simulation isn't enough, let's try with two!

<Hint>
Each "simulation" is represented by a different board.
Expand All @@ -114,7 +114,9 @@ Try solving the first simulation and see what happens.

<Checkpoint id="5-4-robot">

Seems like you're getting the hang of it!
This time the monster tries to dodge like before, but the machine predicts the movement and explodes it with a very cool rocket fist.

> robotpunchingslime.png
<QuestionCard background="var(--color-paper)" border={false} rounded>
#### New functions unlocked
Expand All @@ -129,10 +131,18 @@ Two new functions have been unlocked:
If a function name is too long, you can abreviate it to only the initials.
For example, `is_slime_left()` can be called as `isl()`.

This is only for this book, don't try doing it in real code!
*This is only for this book, don't try doing it in real code!*
:::
</QuestionCard>

Great, new instructions!
But why would these unlock now?

<b style="color: red; text-decoration: underline;">WARNING WARNING, THE ROBOT IS OVERHEATED, PLEASE REDUCE THE SIMULATION STEPS TO A MINIMUM</b>

...Well, here we have the answer.
Maybe we can use them to avoid unnecessary steps?

<Hint>
See the "Minimum Steps" message below every simulation?
This means that you have to solve it in that amount of steps.
Expand All @@ -155,14 +165,15 @@ if ? {
</Checkpoint>

<Checkpoint id="5-5-robot">
Good!
Work smarter, not harder 😉.
Good! Work smarter, not harder 😉.

Unaware of your power, more slimes come to you.

<Hint>
If you're receiving the "You don't need more than two instructions" message, it means that the problem can be solved with a more general approach.

Read you code and see if you can simplify it.
For example, the following code:
Read your code and see if you can simplify it.
For example, the following snippet:
```rust
if is_slime_left() {
down(); // repeated
Expand Down Expand Up @@ -204,18 +215,21 @@ if ? {

<Checkpoint id="5-6-robot">
:::note[Why only 2 instructions in each condition?]
In this exercise, I forced you to write only two instructions in each `if`, why?
In this exercise, you've been forced to write only two instructions in each `if`, why?

Well, code repetition should be avoided, "be as lazy as possible", they say.
Imagine that instead of only `up()`, the extra code was 20 lines long, seems harder to manage, right?

Try always simplifying your code, it will pay off.
Try to always write simpler code, it will pay off.
:::

Well done, all slimes will tremble in fear when they hear your name!
Well done, all slimes will tremble in fear when they hear your name!

...Or at least most of them, because the ones in front of you seem completely unfazed with your killing.
Let's teach them a lesson!

<Hint>
If you're in doubt, try solving it without accounting for the minimum steps and then think on what you can do to reduce them.
If you're in doubt, try solving it without accounting for the minimum steps and then think of what you can do to reduce them.

A good way to know when to use conditionals is to solve the problem aloud:
*if the slime is on the left of the robot, go there, if not...*
Expand All @@ -227,7 +241,10 @@ question="Different minimum steps?"
</Checkpoint>

<Checkpoint id="5-7-robot">
You even handled a different amount of steps for simulation, excellent job!
You even handled a different amount of steps for simulation, excellent job!

But then you hear a characteristic _squish_, you look behind and there they are, it's an ambush!
<b style="color: red; text-decoration: underline">WARNING WARNING, IMPOSSIBLE SITUATION FOUND, USE OF `else` IS REQUIRED</b>

Okay, I know `if`, but... What's this `else`?
<Hint>
Expand Down Expand Up @@ -256,7 +273,12 @@ In this case the normal line of thought would be to use a `is_slime_up()` functi
For this reason, we can use `else` to signify a case where none of our previous conditions is met.
:::

And finally, the last one!
No slimes in sight, at last, your job is done.

Or so you thought, because to your horror three slimes fall from the sky, prepared for the final fight.

> threeslimesfight.png
Hang on, you're almost there!

<Hint>
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/utils/userSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as checkpoints from "../components/Checkpoint/checkpoint";
import * as usercodes from "../components/CodeBlock/persistence";

export function login() {

}

export async function saveData() {
const data = {
checkpoints: await checkpoints.stringifyStore(),
usercodes: await usercodes.stringifyStore(),
};
fetch("...", {
method: "POST",
body: JSON.stringify(data)
})
}

export async function loadData() {
const response = await fetch("...", {
method: "GET"
});
const parsed = JSON.parse(await response.json());
await checkpoints.parseStore(parsed.checkpoints);
await usercodes.parseStore(parsed.usercodes);
}
4 changes: 2 additions & 2 deletions frontend/src/validation/5-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ We hope you're ready for some fun, because this will be your first hunt quest!
As you're still a rookie, your mission will be to kill some slimes and collect their blobs, which are quite valued in alchemy.
Because you're a Programmer, you won't be killing them yourself.
Instead, with this letter comes the spell "summon robot", which will summon a companion that you'll have to command.
Instead, with this letter comes the spell "summon_robot()", which will summon a companion that you'll have to command.
Read the instructions before using it!
Please, read the instructions before using it.
Good luck!
`;

Expand Down

0 comments on commit 2c858bc

Please sign in to comment.