Port some posts and slides to Astro

This commit is contained in:
Maciej Jur 2023-04-08 19:47:34 +02:00
parent cd515ec8d9
commit ced9aa4138
21 changed files with 1635 additions and 27 deletions

2
.gitignore vendored
View file

@ -22,3 +22,5 @@ pnpm-debug.log*
# binary blobs # binary blobs
public/**/*.jpg public/**/*.jpg
public/**/*.png
public/**/*.webp

View file

@ -1,13 +1,14 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import rehypeKatex from 'rehype-katex'; import rehypeKatex from 'rehype-katex';
import remarkMath from 'remark-math'; import remarkMath from 'remark-math';
import remarkEmoji from 'remark-emoji';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
markdown: { markdown: {
remarkPlugins: [ remarkPlugins: [
remarkMath [remarkEmoji as any, {accessible: true}],
remarkMath,
], ],
rehypePlugins: [ rehypePlugins: [
[rehypeKatex, {output: 'mathml'}] [rehypeKatex, {output: 'mathml'}]

View file

@ -15,6 +15,7 @@
"leaflet": "^1.9.3", "leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"rehype-katex": "^6.0.2", "rehype-katex": "^6.0.2",
"remark-emoji": "^3.1.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"reveal.js": "^4.4.0", "reveal.js": "^4.4.0",
"sass": "^1.61.0" "sass": "^1.61.0"

View file

@ -16,6 +16,9 @@ dependencies:
rehype-katex: rehype-katex:
specifier: ^6.0.2 specifier: ^6.0.2
version: 6.0.2 version: 6.0.2
remark-emoji:
specifier: ^3.1.1
version: 3.1.1
remark-math: remark-math:
specifier: ^5.1.1 specifier: ^5.1.1
version: 5.1.1 version: 5.1.1
@ -1192,6 +1195,10 @@ packages:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
dev: false dev: false
/emoticon@4.0.1:
resolution: {integrity: sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw==}
dev: false
/es-module-lexer@1.2.1: /es-module-lexer@1.2.1:
resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==} resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==}
dev: false dev: false
@ -1723,6 +1730,10 @@ packages:
p-locate: 5.0.0 p-locate: 5.0.0
dev: false dev: false
/lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: false
/log-symbols@5.1.0: /log-symbols@5.1.0:
resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -2213,6 +2224,12 @@ packages:
'@types/nlcst': 1.0.0 '@types/nlcst': 1.0.0
dev: false dev: false
/node-emoji@1.11.0:
resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==}
dependencies:
lodash: 4.17.21
dev: false
/node-releases@2.0.10: /node-releases@2.0.10:
resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==}
dev: false dev: false
@ -2475,6 +2492,15 @@ packages:
unified: 10.1.2 unified: 10.1.2
dev: false dev: false
/remark-emoji@3.1.1:
resolution: {integrity: sha512-kVCTaHzX+/ls67mE8JsGd3ZX511p2FlAPmKhdGpRCb5z6GSwp+3sAIB5oTySIetPh7CtqfGf7JBUt5fyMjgOHw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
emoticon: 4.0.1
mdast-util-find-and-replace: 2.2.2
node-emoji: 1.11.0
dev: false
/remark-gfm@3.0.1: /remark-gfm@3.0.1:
resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
dependencies: dependencies:

View file

@ -40,8 +40,8 @@ function fold(headings: Heading[]) {
<a href={`#${heading.slug}`}>{heading.text}</a> <a href={`#${heading.slug}`}>{heading.text}</a>
{heading.children && ( {heading.children && (
<ul> <ul>
{heading.children?.map((child: any) => ( {heading.children?.map(child => (
<li><a href={`#${heading.slug}`}>{heading.text}</a></li> <li><a href={`#${child.slug}`}>{child.text}</a></li>
))} ))}
</ul> </ul>
)} )}

View file

@ -7,11 +7,6 @@ interface MenuItem {
/** Config for the menu displayed in site navbar. */ /** Config for the menu displayed in site navbar. */
const menu: MenuItem[] = [ const menu: MenuItem[] = [
{
identifier: 'projects',
name: 'Projects',
url: '/projects/',
},
{ {
identifier: 'posts', identifier: 'posts',
name: 'Posts', name: 'Posts',

View file

@ -2,6 +2,13 @@ import { defineCollection, z } from 'astro:content';
export const collections = { export const collections = {
posts: defineCollection({
schema: z.object({
title: z.string(),
date: z.date(),
tags: z.array(z.string()).optional(),
})
}),
aoc: defineCollection({ aoc: defineCollection({
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),

View file

@ -0,0 +1,16 @@
---
title: "2022 in Review"
date: 2022-12-31T21:14:47+01:00
---
First of all, happy new year! :smile:
## In retrospect
This year was a pretty good year, I am especially happy that I managed to learn Rust. I also found enough time to do the entirety of the [Advent of Code 2022 in Rust](https://github.com/kamoshi/advent-of-code/tree/master/2022/rust/src/solutions), which is really cool. This year I bought some books written in the Japanese language, which felt really magical, as that's something I wished to get ahold of for years. Sadly I didn't have enough time to read them all this year. I have lots of books and other things left to read still.
## Plans for the next year
- Japanese - I would like to focus on Japanese, because it's something that's been dragging on forever by now. It would be cool to finally reach a point where I can comfortably read books, newspapers etc. in Japanese. This isn't really the most important part of my studies, so I have to squeeze it in whenever.
- Koko - I would like to write a programming language, which I named Koko. It doesn't actually exist yet, but I think that it will be a very fun experience if I do end up creating it.
- Haskell - I've been thinking about learning this programming language for a while now, and it seems like one of these languages that are just way too iconic and cool :sunglasses: to pass on. I feel like learning Haskell will be a one of a kind adventure.
- Drawing - I would like to learn to draw, but I already know this will be an extremely time consuming endeavour, so it has to go on the back burner. Unless, somehow, I do find enough time to do it.

View file

@ -0,0 +1,8 @@
---
title: "Another sad day for humanity"
date: 2022-02-24T18:17:26+01:00
---
Humans prove again and again that the greatest threat to humanity is humanity itself, and the greatest threat to a man is another man. With the attack on Ukraine by Russian Federation, once again needless human suffering is bound to happen. Sadly this is not what matters for politicians, for whom human death is just an another statistic.
I can only pray for peace.

218
src/content/posts/css.md Normal file
View file

@ -0,0 +1,218 @@
---
title: "CSS - How do you even write that?"
date: 2022-10-01T21:06:44+02:00
tags: ["webdev"]
---
## Writing CSS is hard
I've heard many people say that CSS is pretty difficult to write. There are hundreds of properties to remember, some of which aren't even compatible with some browsers yet. CSS spec is certainly full of landmines and edge cases which not a single human can fully remember... and yet, I do enjoy writing CSS. Or rather, I should say that I enjoy writing SCSS, but fundamentally it doesn't change all that much.
{% sidenote() %}
According to the [index of CSS properties](https://www.w3.org/Style/CSS/all-properties.en.html) at the time of writing there are 158 properties with recommendation or note statuses. There are hundreds more properties with different statuses.
{% end %}
Throughout the years CSS has gotten better. We can now use things such as flexboxes or grids, we can create beautiful animations without an ounce of JavaScript being involved. Of course, first we have to learn all the various properties, how to combine them together to create the desired effects. However, in my experience at least, this isn't even the hardest part about CSS. I know lots of properties and complex selectors, and how to use them, and I do admit it was pretty difficult to figure out all of this stuff myself. The only thing I know for certain now is that there is no single straightforward way to *structure* your CSS.
Using Sass does help, because we can use it to nest various rules together and split them into different files. We can `@use` these files in other files. Even then, I haven't found an easy way to write CSS that scales in a bigger project. In my experience it's extremely easy to turn your styles into a hot mess - extremely fragile to any changes and difficult to modify.
## The road to better CSS
When I first started writing CSS I had the idea that CSS is all about writing styles that can be reused. Ideally, we should be able to write a small stylesheet that can easily be used for all the various parts of our websites and it should just work, right?
Sadly the reality is *significantly more difficult*. HTML is a structured markup language with strict hierarchical nature. When we write CSS we write styles that are supposed to be applied to this structure, which means that, whether we like it or not, our styles will end up reflecting the way HTML is structured one way or another. When we change HTML we can break our styles, sometimes in very unpredictable ways.
One way we could write CSS is like this:
```scss
.blog-post {
...
&.center {
margin: 0 auto;
...
}
&.tech {
...
}
header {
...
.title {
...
}
}
}
```
This might seem fairly reasonable at first, but there are a couple of problems that this might end up causing us in the future.
First thing is that we are using "modifier" classes to modify the `.blog-post` class, to give it some different look, possibly because of being used in a different context. The result of nesting rules like that is creating rules with high specificity, which are sometimes very hard to override. For instance, the `.blog-post header .title` rule has a specificity of (2, 1). We won't be able to override that style with a rule `.blog-post .title` (2, 0).
{% sidenote() %}
Specificity is simply a number [calculated](https://specificity.keegan.st/) from the complexity of the selector. The higher the specificity, the more priority the CSS rule has. Many people argue that we should always aim for as low specificity as possible, which means we should use as simple rules as possible (but still specific!).
{% end %}
Another problem is that we are using a very generic element `<header>` as a selector, which means that every single `<header>` that is a child of `<element class="blog-post">` will receive these styles. That could be a bad thing if we would like to use `<header>` element in semantically different contexts, for example as an article header and as a section header.
Third problem is that at some point we might realize that in fact certain elements don't necessarily have to be an integral part of a hierarchy of HTML nodes. We could for example want to reuse the `<header>` element in a different part of the website with the same style. If the styles of this element depended on styles of the `.blog-post` element, we would be in pretty big trouble.
## Reusability
We all would like to write reusable styles, but I honestly feel like all this talk about reusability is kind of the wrong way to look at the problem. What if we tried to write a new CSS rule for every single piece of our website anew without reusing anything? Surely, we would just end up with a colossal CSS file spanning over 6000 CSS rules with a total size of about 500 kB. We wouldn't really reuse anything. What's the opposite of that? What if we tried to reuse every single CSS rule? Well, then we would have to write a single CSS rule per every property we use, and then use these classes to assign each property individually.
{% sidenote() %}
The last idea is actually a thing, there are CSS frameworks out there which use this idea of "atomic CSS". One such example is [Tailwind CSS](https://tailwindcss.com/).
{% end %}
If we only used a single class per each property in CSS and assigned many of such classes to each HTML tag, wouldn't we just end up doing exactly the same thing as in the first idea, except now by doing it within the `class` attribute? Consider this element:
```html
<div class="flex items-baseline mt-4 mb-6 pb-6 border-b border-slate-200">
```
How is it different from just creating a class for each element and assigning properties in CSS? This whole topic is pretty difficult... Maybe there is a golden mean to this problem? Classes that are small enough to be reusable in HTML, but at the same time not devolved into singular properties?
I personally think that it is *possible* to find classes which are small enough to be reusable, but also not insignificant. However, it is possibly the most difficult thing to design, or to find, or to architect, or whatever you would want to call it, in CSS.
## To BEM, or not to BEM?
{% sidenote() %}
In short, [BEM](https://getbem.com/) is a naming convention which is all about writing class names in a very specific way. We write names as combinations of three parts: block, element and modifier, with the latter two being optional.
{% end %}
One of the things which have helped me improve the state of my CSS stylesheets is trying to incorporate BEM into the way I write my rules. I won't explain what it is exactly, because that's not the point, but I'll try to summarize my findings.
If we tried to rewrite the previous example into BEM, we could theoretically rewrite it as such:
```scss
.blog-post {
...
&--centered {
margin: 0 auto;
...
}
&__header {
...
}
&__header-title {
...
}
}
```
BEM definitely helps manage specificity, as each rule will affect exactly a single class with the selectors consisting of that single class, ie. `.blog-post__header-title {}`. By assigning an unique class to each rule we also alleviate the problem with our styles leaking and having unwanted effects; we end up writing extremely precise rules. However, BEM doesn't help us architect what part exactly we should consider a single atomic "block". We still can easily commit mistakes when it comes to the *granularity* of styles.
BEM could devolve into writing separate "blocks" for each HTML element. We could also treat the entire website as a single BEM block. So, as it turns out, we still don't know how to write styles that are *reusable* for the various parts of the website. It is entirely up to us to decide which elements constitute a part worth treating as a singular block in BEM.
One problem that I have personally encountered with BEM is not being able to figure out how to approach the fact that a single "block" can have multiple variants. For instance, we could have three cards, each containing slightly different content:
```html
<aside>
<section id="A" class="???">
Card with some content
...
</section>
<section id="B" class="???">
Card with slightly different content content
...
</section>
<section id="C" class="???">
<img alt="some image we would like to show" />
</section>
</aside>
```
Should we treat the variations of the block as modifiers indicated in BEM by the `--modifier`? But then we wouldn't be able to style the elements of these blocks, as in BEM you can't write `--modifier__element`. Should we treat these blocks as completely different elements and create a multi-class rule for the common styles? That's certainly an option. Maybe we could also create a generic class with common styles called `.card`, and then create rules for the more specific styles using different classes, ie. `.card-info`, `.card-image`? In this case we wouldn't have problems with the convention, but we would run into a different problem. Namely the class `.card-info` can't be used individually - we always have to remember to use both `.card` and `.card-info` at the same time.
Maybe the option with the multi-class selector is the most rational then?
```scss
.card {
padding: 1em;
border: 1px solid black;
border-radius: 1em;
...
}
.card-info {
@extend .card;
&__info {
margin-top: 1em;
...
}
}
```
After compilation we would have:
```scss
.card, .card-info {
padding: 1em;
border: 1px solid black;
border-radius: 1em;
...
}
.card-info__info {
margin-top: 1em;
...
}
```
## Styles in Hugo
I have found that Hugo, other than being a really useful tool for creating static websites, also helps in architecting them in scalable ways and helps demarcate boundaries between the various parts of pages. Hugo provides us with two similar mechanisms for creating reusable components - partials and shortcodes.
Partials are pieces of HTML code defined in separate files, which we can reuse in the structure of the website, by calling them like this:
```html
<aside>
{{- partial "panel" . -}}
</aside>
```
On the other hand, shortcodes are pieces of HTML code defined in separate files, which we can use only in the markdown content that we have written for the site generator.
```md
## Calendar
Here is *my* calendar:
{{</* calendar */>}}
Please take care...
```
The fact that in Hugo we can componentize parts of our websites and explicitly reuse them in various places means that we end up defining what constitutes a building block of the website. I think that this helps in creating a manageable architecture which ends up extendable and modifiable in the future.
Given that we have defined the distinct blocks, we can use BEM to style these blocks individually. For example we could write a BEM block for the panel, or the calendar:
```scss
.p-panel {
...
&__info {
...
}
&--active {
...
}
}
.sc-calendar {
...
&--collapsed {
...
}
}
```
I've added here my own convention of marking partial styles with the prefix `p-` and shortcodes with the prefix `sc-`.
So far, I've had good results with using BEM in conjunction with the Hugo partials and shortcodes. These mechanisms make sure that I always know what constitutes a block and what might be reused in different parts of the website.
One of the problems with this approach which I've run into is that it's sometimes difficult to connect the various pieces together into a coherent whole. We could have partials for sidebar, header and article, but how do we connect them? We have to write some CSS glue for the layout itself.
Another problem arises when we have some nested partials. The inner partial's HTML code could potentially depend on the outer context for layout. If we had a helper partial `H`, partials `A` and `B` which depended on `H`, and the partial `H` depended on the outer context for styles, then we wouldn't be able to write the styles of `H` completely independently. We would somehow have to connect `A` and `B` with `H` in CSS.
## Closing thoughts
CSS styles remain an open-ended question, as there's not a single ideal solution to writing styles. We can only try to always write the most manageable and scalable stylesheets possible. It's also entirely up to us to figure out how to do it, because different approaches might yield different results in different projects.

View file

@ -0,0 +1,24 @@
---
title: "Each Person Has a Goal"
date: 2022-02-07T15:47:23+01:00
---
When we begin our lives we don't really have any goals, plans or anything really. It's like we just exist for the sake of being, and we go on like this through the first stages of our lives. We gradually find things we like doing or which bring us some form of enjoyment, and that's what ultimately steers our lives in some direction.
But still, it is all mostly imaginary, because at the bottom of everything there is just the human thought that *it* is worth doing. Is there a point to photography? Or sculpting? Or biking? Or playing video games? Some people will say no to some of these things, because they simply aren't interested in it. I know that I'm not interested in sculpting, so I don't want to do it, however for some other people sculpting will give a meaning to their lives.
Ultimately everything we do in our lives is just a something that *we* think is worth doing, it is something that comes from inside our minds and nowhere else. You can't tell someone else what they should do in their lives, because that simply won't work.
## Directionless life
If you don't have any direction in life, then that means you just haven't imagined a single good enough reason for you to spend your time one way or another. The only way to find a goal is to try doing a lot of things and hope something "clicks". If you don't have any passions or goals, it means you just haven't found *the thing*. Only you yourself can ever know what it is, once you find it - yourself.
## Following others
Following others and sticking to others is fine, as long as this doesn't mean you're giving up your own goals in the process. Just think about it, if you don't do what you should be doing to accomplish what you think is worthwhile, will you be proud of yourself in a couple of years? Or a decade? Of course, this doesn't mean you should only ever think about just yourself. Spending time with others is good too :slight_smile:
Time is precious, in fact it is a single most presious thing in our possession. Each single possible moment and day in your life is unique. It's like a set of unique moments which you can use up to accomplish things you think are worthwhile - or not. Sometimes you should stop and think whether the way you are spending your time is worthwhile.
## Finishing thoughts
Ultimately how you spend your time will not be perfect, it's fine to waste time, as long as it all makes you happy in the end. Just live your life first and foremost!

View file

@ -0,0 +1,53 @@
---
title: "Estimating package delivery time"
date: 2022-06-21T18:44:53+02:00
---
In the last few months I have ordered a dozen of items from Japan. In total there were six distinct orders that were delivered to me in separate boxes. Here's the data for the time between being sent out (dispatch from outward office of exchange) from Japan and arriving (arrival at inward office of exchange) in Poland.
| Location | Outbound | Inbound | Diff days |
|---------------|-----------------|-----------------|-------------|
| TOKYO INT BAG | 3/29/2022 4:20 | 4/3/2022 6:22 | 5.084722222 |
| OSAKA INT BAG | 4/9/2022 14:30 | 4/15/2022 6:38 | 5.672222222 |
| OSAKA INT BAG | 4/11/2022 14:30 | 4/22/2022 5:29 | 10.62430556 |
| TOKYO INT BAG | 4/19/2022 13:20 | 4/22/2022 6:05 | 2.697916667 |
| OSAKA INT BAG | 4/21/2022 14:30 | 4/28/2022 18:33 | 7.16875 |
| TOKYO INT BAG | 5/10/2022 13:20 | 5/18/2022 2:37 | 7.553472222 |
We have $n = 6$ samples and using this data we can calculate the mean $\bar X$ as well as the standard deviation $s$ of the sample.
$$
\bar X \approx 6.466898148
$$
$$
s \approx 2.672243145
$$
We do not know the properties of the population, and we only have 6 samples, so we have to use the Student's t-distribution here. There are $k = n - 1 = 5$ degrees of freedom.
Let's assume confidence level of 95%.
$$
\alpha = 1 - 0.95 = 0.05
$$
We can use the table for t-distribution to find that the value of $t_{\alpha, n-1} = 2.571$. Now we can calculate the confidence interval for the mean $\mu$ delivery time between Japan and Poland.
$$
(\bar X - t_{\alpha, n-1} \frac{s}{\sqrt{n}}; \bar X + t_{\alpha, n-1} \frac{s}{\sqrt{n}})
$$
$$
t_{\alpha, n-1} \frac{s}{\sqrt{n}} \approx 2.804347194
$$
$$
(\bar X - 2.804347194; \bar X + 2.804347194) = (3.662550954; 9.271245342)
$$
With these results we can say with 95% confidence that the mean time of delivery from Japan to Poland lies somewhere between 3.66 days and 9.27 days. We can also calculate different results for different confidence levels to get some more interesting overview:
| Confidence level | \\(t_{\alpha, n-1} \frac{s}{\sqrt{n}}\\) | Confidence interval |
|------------------|------------------------------------------|----------------------------|
| 99% | 4.398820806 | (2.068077342; 10.86571895) |
| 95% | 2.804347194 | (3.662550954; 9.271245342) |
| 90% | 2.198294244 | (4.268603904; 8.665192392) |
| 80% | 1.610099019 | (4.856799129; 8.076997167) |
| 50% | 0.792770797 | (5.674127351; 7.259668946) |

View file

@ -0,0 +1,152 @@
---
title: "Introduction to Hanafuda Koikoi"
date: 2021-09-09T22:30:02+02:00
tags: ["Japan", "hanafuda"]
---
## TL;DR
So what exactly is Hanafuda? In short, its a type of card game originating in Japan. To be exact the game is called Hanafuda Koikoi, while the cards are called “Hanafuda” flower cards. The reason why theyre called that is that they feature many different drawings of various plants and seasons. There are exactly 48 playing cards in each set, featuring 12 plants and seasons, which is exactly 4 cards for each plant and season. On top of the plant/season grouping there also exist groups of cards which allow you to collect points within the game, collectively known as Yaku. The goal of the game is to collect more points than your opponent by collecting these combinations.
## Cards
### January
Pine - Matsu 松
{{ icon(src="hanafuda/matsu1.svg", h="64") }} {{ icon(src="hanafuda/matsu2.svg", h="64") }} {{ icon(src="hanafuda/matsu3.svg", h="64") }} {{ icon(src="hanafuda/matsu4.svg", h="64") }}
### February
Plum - Ume 梅
{{ icon(src="hanafuda/ume1.svg", h="64") }} {{ icon(src="hanafuda/ume2.svg", h="64") }} {{ icon(src="hanafuda/ume3.svg", h="64") }} {{ icon(src="hanafuda/ume4.svg", h="64") }}
### March
Cherry blossom - Sakura 桜
{{ icon(src="hanafuda/sakura1.svg", h="64") }} {{ icon(src="hanafuda/sakura2.svg", h="64") }} {{ icon(src="hanafuda/sakura3.svg", h="64") }} {{ icon(src="hanafuda/sakura4.svg", h="64") }}
### April
Wisteria - Fuji 藤
{{ icon(src="hanafuda/fuji1.svg", h="64") }} {{ icon(src="hanafuda/fuji2.svg", h="64") }} {{ icon(src="hanafuda/fuji3.svg", h="64") }} {{ icon(src="hanafuda/fuji4.svg", h="64") }}
### May
Iris - Shobu 菖蒲
{{ icon(src="hanafuda/ayame1.svg", h="64") }} {{ icon(src="hanafuda/ayame2.svg", h="64") }} {{ icon(src="hanafuda/ayame3.svg", h="64") }} {{ icon(src="hanafuda/ayame4.svg", h="64") }}
### June
Peony - Botan 牡丹
{{ icon(src="hanafuda/botan1.svg", h="64") }} {{ icon(src="hanafuda/botan2.svg", h="64") }} {{ icon(src="hanafuda/botan3.svg", h="64") }} {{ icon(src="hanafuda/botan4.svg", h="64") }}
### July
Clover - Hagi 萩
{{ icon(src="hanafuda/hagi1.svg", h="64") }} {{ icon(src="hanafuda/hagi2.svg", h="64") }} {{ icon(src="hanafuda/hagi3.svg", h="64") }} {{ icon(src="hanafuda/hagi4.svg", h="64") }}
### August
Susuki - Susuki 芒
{{ icon(src="hanafuda/susuki1.svg", h="64") }} {{ icon(src="hanafuda/susuki2.svg", h="64") }} {{ icon(src="hanafuda/susuki3.svg", h="64") }} {{ icon(src="hanafuda/susuki4.svg", h="64") }}
### September
Chrysanthemum - Kiku 菊
{{ icon(src="hanafuda/kiku1.svg", h="64") }} {{ icon(src="hanafuda/kiku2.svg", h="64") }} {{ icon(src="hanafuda/kiku3.svg", h="64") }} {{ icon(src="hanafuda/kiku4.svg", h="64") }}
### October
Maple - Momiji 紅葉
{{ icon(src="hanafuda/momiji1.svg", h="64") }} {{ icon(src="hanafuda/momiji2.svg", h="64") }} {{ icon(src="hanafuda/momiji3.svg", h="64") }} {{ icon(src="hanafuda/momiji4.svg", h="64") }}
### November
Willow - Yanagi 柳
{{ icon(src="hanafuda/yanagi1.svg", h="64") }} {{ icon(src="hanafuda/yanagi2.svg", h="64") }} {{ icon(src="hanafuda/yanagi3.svg", h="64") }} {{ icon(src="hanafuda/yanagi4.svg", h="64") }}
### December
Paulownia - Kiri 桐
{{ icon(src="hanafuda/kiri1.svg", h="64") }} {{ icon(src="hanafuda/kiri2.svg", h="64") }} {{ icon(src="hanafuda/kiri3.svg", h="64") }} {{ icon(src="hanafuda/kiri4.svg", h="64") }}
## Gameplay
The game is played by two players. The game begins by choosing the Oya - the player who will have the first turn in the game. First, each person takes a single card and the person who chooses the card from the earlier month out of the two is chosen as the Oya.
After the Oya has been chosen the cards are reshuffled, 8 cards are placed on the table and each player is given a deck of 8 cards. The players play in turns, starting with the Oya, with each turn consisting of two phases. In the first phase of a turn the player tries to match a card from their deck with any card present on the table. If a match is made the player takes both cards and keeps them separate from the deck of cards. If a match is not possible the player has to choose any card from the deck and place it on the table. The cards are matched by the month (plant present on the card). After the first phase is complete the player has to take a single card from the pile of the unused cards and try to match it with any of the cards left on the table. If a match is made, the player takes both cards. If theres no match possible the player has to leave the card on the table. Once both phases of the turn are complete the turn comes to an end and the next player can play their turn.
At any point of the game the collected cards can form a special group of cards called Yaku, which is equal to a certain amount of points in the game. Once a player forms any single Yaku they can choose to end the game and get the points for the Yaku, or they can choose to continue playing the game by calling "Koikoi" in hope of collecting more Yaku and points. The catch is that once a player calls Koikoi the opponent can try to collect any Yaku as well and if they do they can end the game (or call Yaku too). If your opponent manages to end the game by collecting a Yaku after youve called a Koikoi your Yaku points are nullified - only your opponent gets their points for the Yaku!
If a player manages to collect multiple Yaku the points are summed, with the exception being the “lights” Yaku (Shikou, Gokou, Ameshikoi, etc.) - its only possible to “upgrade” your Yaku to a higher valued one. Some Yaku are incremental, for example the base number of points for the Kasu Yaku is 1 point for 10 cards, but if you manage to collect additional cards, each is valued at 1 point (12 Kasu cards would be 3 points).
## Yaku
### Gokou 五光
Points: 10点
{{ icon(src="hanafuda/matsu4.svg", h="64") }} {{ icon(src="hanafuda/sakura4.svg", h="64") }} {{ icon(src="hanafuda/susuki4.svg", h="64") }} {{ icon(src="hanafuda/yanagi4.svg", h="64") }} {{ icon(src="hanafuda/kiri4.svg", h="64") }}
Five light cards, can't be combined with any other light combinations.
### Shikou 四光
Points: 8点
{{ icon(src="hanafuda/matsu4.svg", h="64") }} {{ icon(src="hanafuda/sakura4.svg", h="64") }} {{ icon(src="hanafuda/susuki4.svg", h="64") }} {{ icon(src="hanafuda/kiri4.svg", h="64") }}
Four light cards excluding "Ono no Michikaze", can't be combined with any other light combinations.
### Ameshikou 雨四光
Points: 7点
{{ icon(src="hanafuda/yanagi4.svg", h="64") }} + any 3 of {{ icon(src="hanafuda/matsu4.svg", h="64") }} {{ icon(src="hanafuda/sakura4.svg", h="64") }} {{ icon(src="hanafuda/susuki4.svg", h="64") }} {{ icon(src="hanafuda/kiri4.svg", h="64") }}
Four light cards including "Ono no Michikaze", can't be combined with any other light combinations.
### Sankou 三光
Points: 5点
Any 3 of {{ icon(src="hanafuda/matsu4.svg", h="64") }} {{ icon(src="hanafuda/sakura4.svg", h="64") }} {{ icon(src="hanafuda/susuki4.svg", h="64") }} {{ icon(src="hanafuda/kiri4.svg", h="64") }}
Three light cards excluding "Ono no Michikaze", can't be combined with any other light combinations.
### Inoshikachou 猪鹿蝶
Points: 5点α
{{ icon(src="hanafuda/hagi4.svg", h="64") }} {{ icon(src="hanafuda/momiji4.svg", h="64") }} {{ icon(src="hanafuda/botan4.svg", h="64") }}
Boar, deer and butterfly.
### Tsukimizake 月見酒
Points: 5点
{{ icon(src="hanafuda/susuki4.svg", h="64") }} {{ icon(src="hanafuda/kiku4.svg", h="64") }}
Moon and sake cup.
### Hanamizake 花見酒
Points: 5点
{{ icon(src="hanafuda/sakura4.svg", h="64") }} {{ icon(src="hanafuda/kiku4.svg", h="64") }}
Cherry blossom curtain and sake cup.
### Tane 種・タネ
Points: 1点α
Any 5 of {{ icon(src="hanafuda/ume4.svg", h="64") }} {{ icon(src="hanafuda/susuki3.svg", h="64") }} {{ icon(src="hanafuda/fuji4.svg", h="64") }} {{ icon(src="hanafuda/kiku4.svg", h="64") }} {{ icon(src="hanafuda/ayame4.svg", h="64") }} {{ icon(src="hanafuda/momiji4.svg", h="64") }} {{ icon(src="hanafuda/botan4.svg", h="64") }} {{ icon(src="hanafuda/yanagi3.svg", h="64") }} {{ icon(src="hanafuda/hagi4.svg", h="64") }}
Five Tane cards, 1 additional point for each additional Tane card.
### Akatan-Aotan 赤短・青短
Points: 10点α
{{ icon(src="hanafuda/matsu3.svg", h="64") }} {{ icon(src="hanafuda/ume3.svg", h="64") }} {{ icon(src="hanafuda/sakura3.svg", h="64") }} {{ icon(src="hanafuda/botan3.svg", h="64") }} {{ icon(src="hanafuda/kiku3.svg", h="64") }} {{ icon(src="hanafuda/momiji3.svg", h="64") }}
Three red poetry ribbons and three blue ribbons.
### Akatan 赤短
Points: 5点α
{{ icon(src="hanafuda/matsu3.svg", h="64") }} {{ icon(src="hanafuda/ume3.svg", h="64") }} {{ icon(src="hanafuda/sakura3.svg", h="64") }}
Three red poetry ribbons.
### Aotan 青短
Points: 5点α
{{ icon(src="hanafuda/botan3.svg", h="64") }} {{ icon(src="hanafuda/kiku3.svg", h="64") }} {{ icon(src="hanafuda/momiji3.svg", h="64") }}
Three blue ribbons.
### Tan 短
Points: 1点α
Any 5 of {{ icon(src="hanafuda/matsu3.svg", h="64") }} {{ icon(src="hanafuda/ume3.svg", h="64") }} {{ icon(src="hanafuda/sakura3.svg", h="64") }} {{ icon(src="hanafuda/fuji3.svg", h="64") }} {{ icon(src="hanafuda/ayame3.svg", h="64") }} {{ icon(src="hanafuda/botan3.svg", h="64") }} {{ icon(src="hanafuda/hagi3.svg", h="64") }} {{ icon(src="hanafuda/kiku3.svg", h="64") }} {{ icon(src="hanafuda/momiji3.svg", h="64") }} {{ icon(src="hanafuda/yanagi2.svg", h="64") }}
Five ribbon cards, 1 additional point for each additional ribbon card.
### Kasu カス
Points: 1点α
{{ icon(src="hanafuda/matsu1.svg", h="64") }} {{ icon(src="hanafuda/matsu2.svg", h="64") }}
{{ icon(src="hanafuda/ume1.svg", h="64") }} {{ icon(src="hanafuda/ume2.svg", h="64") }}
{{ icon(src="hanafuda/sakura1.svg", h="64") }} {{ icon(src="hanafuda/sakura2.svg", h="64") }}
{{ icon(src="hanafuda/fuji1.svg", h="64") }} {{ icon(src="hanafuda/fuji2.svg", h="64") }}
{{ icon(src="hanafuda/ayame1.svg", h="64") }} {{ icon(src="hanafuda/ayame2.svg", h="64") }}
{{ icon(src="hanafuda/botan1.svg", h="64") }} {{ icon(src="hanafuda/botan2.svg", h="64") }}
{{ icon(src="hanafuda/hagi1.svg", h="64") }} {{ icon(src="hanafuda/hagi2.svg", h="64") }}
{{ icon(src="hanafuda/susuki1.svg", h="64") }} {{ icon(src="hanafuda/susuki2.svg", h="64") }}
{{ icon(src="hanafuda/kiku1.svg", h="64") }} {{ icon(src="hanafuda/kiku2.svg", h="64") }}
{{ icon(src="hanafuda/momiji1.svg", h="64") }} {{ icon(src="hanafuda/momiji2.svg", h="64") }}
{{ icon(src="hanafuda/yanagi1.svg", h="64") }}
{{ icon(src="hanafuda/kiri1.svg", h="64") }} {{ icon(src="hanafuda/kiri2.svg", h="64") }} {{ icon(src="hanafuda/kiri3.svg", h="64") }}
Ten plain cards, 1 additional point for each additional plain card.
## Action
Here's an example of two Japanese players playing a game of Hanafuda Koikoi!
{{ youtube(id="2Vs2WxWsxSU", class="md_youtube") }}

View file

@ -0,0 +1,24 @@
---
title: "なぜ日本語か?今まで勉強してた言語"
date: 2023-02-11T22:29:25+01:00
---
私は日本語を7年間ぐらい勉強してたが。
えーー、7年間!?時間が早く経つな〜
## はじめ
初めには、何話かアニメを見たけど、あれからあまりアニメをみない。アニメを見る人じゃないから。漫画もあまり読まない。でも、あのアニメの一つは「僕だけがいない街」と呼ばれるアニメで、すごく素晴らしく面白い。あのアニメを見る後で、もっとアニメを見るようにして、日本語の勉強をしはじめた。
「わー、その言語は素晴らしい」と思った。
平仮名と片仮名の勉強が二週間ぐらいかかりました。後で漢字を学びはじめたが、今まで終わりがない。漢字は難しく、漢字の数も恐ろしいな。
## いままで
6年間に渡って、1000漢字ぐらいを学んだ。文法はたくさんの事も学んだ。だって、日本語で本を読みたいから。日本語はとても美しい言語。漢字が難しいけど、漢字のない日本語が同じじゃないだろう。漢字は日本語の美しさの一面と思う。それに、漢字と送り仮名はとっても面白く、漢字が中国からの字けど、まるで、ずっと前から日本語の字であるように見える。
日本語は美しき音がすると思う。たくさんの歌を聴いて、歌詞が分かる時、とても嬉しい。いつか、日本語の歌が分かりやすいようになりたい。
まだまだ、頑張るぞ!

View file

@ -0,0 +1,346 @@
---
title: "Password Managers"
date: 2023-01-18T18:29:58+01:00
---
# Password managers
Maciej Jur
2023.01.20
-----
## Password managers
- Introduction
- Types of password managers
- Choosing a password manager
- Using a password manager
- LastPass leak
- Summary
-----
## Not every password is safe
![Password](/static/slides/password-managers/safe-password.png)
---
Password I used for most of my accounts in the past:
![My password](/static/slides/password-managers/my-password.png)
www.security.org/how-secure-is-my-password/
-----
### Why reuse passwords?
![a](/static/slides/password-managers/threatlist-2.png)
https://www.darkreading.com/endpoint/password-reuse-problems-persist-despite-known-risks
---
![a](/static/slides/password-managers/threatlist-1.png)
https://www.darkreading.com/endpoint/password-reuse-problems-persist-despite-known-risks
-----
### Some more statistics
![a](/static/slides/password-managers/2021-09-23-image.jpg)
https://www.techspot.com/news/91388-most-people-reuse-passwords-across-multiple-sites.html
---
![a](/static/slides/password-managers/2021-09-23-image-2.webp)
https://www.techspot.com/news/91388-most-people-reuse-passwords-across-multiple-sites.html
---
![a](/static/slides/password-managers/2021-09-23-image-3.webp)
https://www.techspot.com/news/91388-most-people-reuse-passwords-across-multiple-sites.html
-----
### Password managers can help
![a](/static/slides/password-managers/vault.png)
-----
## Types of password managers
- Offline
- Online
- Stateless
- Hardware
-----
### Offline password managers
---
#### Example: KeePass(XC)
![KeePassXC](/static/slides/password-managers/keepassxc.webp)
---
#### These password managers can still be online
Dropbox, Google Drive, SyncThing, etc.
![replication](/static/slides/password-managers/replication.png)
https://keepass.info/help/kb/trigger_examples.html
---
#### Pros
- Simple and safe to use
- Your password vault never leaves your device (unless you want it to)
- You can transfer vaults between devices using thumb drives or cloud sync
---
#### Cons
- You have to move/sync the vault beetwen devices on your own
- That could be a hassle
-----
### Online password managers
---
#### Example: LastPass
![lastpass](/static/slides/password-managers/lastpass.png)
---
#### Pros
- Most of the pros of offline password managers
- Automatic sync, can access your vault as long as you have access to the Internet
- It's slightly more convenient
---
#### Cons
- The vault lives on some random server
- You have to trust the ___service provider___
- You have to trust the ___security___ of the service provider
-----
### Stateless password managers
Instead of saving your passwords and encrypting them with a key derived from a master password, these password managers generate passwords on the fly by hashing a master password with the website name.
---
#### Example: LessPass
![a](/static/slides/password-managers/lesspass-graph.png)
---
#### Pros
- You don't have to synchronize your vault between any of your devices.
---
#### Cons
- If your master password is compromised, all of your passwords are.
- If a website has a password policy, you might not be able to generate a password that respects it.
- If password needs to be updated for whatever reason, you need to keep that state somewhere.
Example: Password for "StackOverflow2"
- If you already have some passwords that you can't change (for various reasons), a static password generator won't help you.
-----
### Hardware password managers
---
#### Example: OnlyKey
It emulates a HID keyboard and can be programmed to navigate the steps to log in to pretty much any website, even if the login requires tabbing around multiple screens.
---
<iframe width="1024" height="576" src="https://www.youtube.com/embed/CBDKx2_br3g" title="How-To: Secure your Workstation and Online Accounts with OnlyKey" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
---
#### Pros
- Pin protected
- Durable, waterproof, and tamper resistant design
- The device isn't connected to the Internet
---
#### Cons
- Cost (260,00 PLN) and learning curve
- There's a limit to how much you can store
- OnlyKey can store up to 24 online accounts
-----
## Choosing a password manager
- Type of password manager - this is the easier choice
- Which password manager - this is the harder choice
---
Spoiler alert:
`There are a lot of them`
---
Some of them:
![Various password managers](/static/slides/password-managers/various-password-managers.png)
https://allthatsaas.com/roundup/best-password-managers/
---
Do I use any one of these?
---
Answer: Yes
![I use bitwarden](/static/slides/password-managers/i-use-bitwarden.png)
-----
### A short comparison
![comparison](/static/slides/password-managers/comparison1.jpg)
https://blog.devolutions.net/2019/01/updated-2019-most-popular-password-managers-compared/
---
#### Why do I use Bitwarden?
Honestly, I'm not sure.
But it has sync and I like the fact that its components are open-source:
https://github.com/bitwarden
-----
## Using a password manager
I will show Bitwarden, because I already know it.
![Bitwarden-example](/static/slides/password-managers/bitwarden-sample.webp)
-----
### Vault
![bitwarden vault](/static/slides/password-managers/bitwarden-vault.png)
---
#### Mobile vault
![bitwarden vault mobile](/static/slides/password-managers/bitwarden-vault-mobile.png)
-----
### Autofill
![bitwarden autofill](/static/slides/password-managers/bitwarden-autofill.png)
---
#### Mobile autofill
![bitwarden autofill mobile](/static/slides/password-managers/bitwarden-autofill-mobile.jpg)
-----
### Generating passwords
![bitwarden generating](/static/slides/password-managers/bitwarden-generating.png)
-----
### Out of curiosity
How do you configure OnlyKey?
---
#### Slots
![onlykey-slots](/static/slides/password-managers/onlykey-slots.png)
https://docs.onlykey.io/usersguide.html
---
#### Autofill
![onlykey-autofill](/static/slides/password-managers/onlykey-autofill.png)
https://docs.onlykey.io/usersguide.html
---
#### Even more complex
You need to perform the following:
1. Enter the Username
2. Press TAB
3. Press RETURN
4. Wait for website to load next page
5. Enter the password
6. Press TAB
7. Press RETURN
---
You can enter `\t` or `\r` inline with slot data to type the extra TAB or RETURN and `\d3` to DELAY 3 seconds.
Username:
`onlykey \t \r \d3 `
Password:
`password \t \r `
---
![onlykey-advanced-autofill](/static/slides/password-managers/onlykey-advanced-autofill.png)
https://docs.onlykey.io/usersguide.html
-----
## LastPass Leak
December 22, 2022
https://blog.lastpass.com/2022/12/notice-of-recent-security-incident/
---
> "Based on our investigation to date, we have learned that an unknown threat actor accessed a cloud-based storage environment ___leveraging information obtained from the incident we previously disclosed in August of 2022___."
---
### August 2022
> "An employees work account was compromised to gain unauthorized access to the companys development environment, which stores some of LastPass source code."
https://techcrunch.com/2022/12/14/parsing-lastpass-august-data-breach-notice/
---
> "The threat actor was also able to copy a backup of customer vault data from the encrypted storage container which is stored in a proprietary binary format that contains both unencrypted data, such as website URLs, as well as fully-encrypted sensitive fields such as website usernames and passwords, secure notes, and form-filled data."
---
> "These encrypted fields remain secured with 256-bit AES encryption and can only be decrypted with a unique encryption key derived from each users master password using our Zero Knowledge architecture. As a reminder, the master password is never known to LastPass and is not stored or maintained by LastPass."
---
### What do we get from that?
- Password managers increase our security...
- ...but not ultimately
---
### It's not the end of the world
Thanks to zero knowledge architecture the attacker still has to crack the master password, which could take years ...
---
... as long as we used a secure password for the master password.
-----
## Summary
- Password manager helps manage passwords
- Allows us to use unique, complex passwords for different accounts without having to remember them all
- By using a password manager, you can improve your security without sacrificing convenience.
- To choose the best password manager for your needs, consider factors such as security, compatibility and convenience.
---
In general, password managers are an essential tool for anyone who wants to improve their online security and protect their personal information.
-----
## Any questions?

View file

@ -0,0 +1,701 @@
---
title: "Rust introduction"
date: 2023-02-10T13:51:58+01:00
---
# Introduction to...
![Rust](/static/slides/rust-introduction/rust.png)
-----
## Introduction
-----
### Types
---
#### Primitives
- signed ints: `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
- unsigned ints: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`
- floating point: `f32`, `f64`
- char: Unicode scalar
- bool: `true`, `false`
- unit: `()`
---
| Length | Signed | Unsigned |
| ------- | ------ | -------- |
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
---
#### Compound
| Name | Type | Example value |
| ----- | ----------- | ------------- |
| Array | `[3; i32]` | `[1, 2, 3]` |
| Tuple | `(i32, bool)` | `(1, true)` |
---
#### Enum
```rs
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
```
---
```rs
enum Coin {
Penny,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
```
---
#### Option & Result
```rs
enum Option<T> {
None,
Some(T),
}
enum Result<T, E> {
Ok(T),
Err(E),
}
```
---
#### Struct
```rs [1-4|6-10|12-19]
struct Container {
a: i32,
b: i32,
}
impl Container {
fn sum_ab(&self) -> i32 {
self.a + self.b
}
}
fn main() {
let container = Container {
a: 10,
b: 15,
};
let sum = container.sum_ab();
}
```
---
#### Vector
A contiguous growable array type, written as `Vec<T>`, short for vector.
---
```rs [1-3|5-6|8-9|11-12]
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
assert_eq!(vec.len(), 2);
assert_eq!(vec[0], 1);
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.len(), 1);
vec[0] = 7;
assert_eq!(vec[0], 7);
```
---
The `vec!` macro is provided for convenient initialization:
```rs
let mut vec1 = vec![1, 2, 3];
vec1.push(4);
let vec2 = Vec::from([1, 2, 3, 4]);
assert_eq!(vec1, vec2);
```
-----
### Control flow
---
#### if
```rs
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
```
---
```rs
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}
```
---
#### loop
```rs
fn main() {
loop {
println!("again!");
}
}
```
---
```rs
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}
```
---
### while
```rs
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("LIFTOFF!!!");
}
```
---
### for
```rs
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
```
-----
### Iterators
JS:
```js
myList
.filter((t) => t !== "Filter me out")
.forEach(console.log);
```
Rust:
```rs
myList.into_iter()
.filter(|v| v != "Filter me out")
.for_each(|v| println!("{}", v));
```
---
| Funtion | What it does |
| ---------- | ------------ |
| .take(n) | reduces an iterator to its first n elements |
| .skip(n) | skips the first n elements |
| .cloned() | clones each element in the iterator |
| .enumerate | turns an iterator over elements t to an iterator over elements `(t: T, idx: usize)` |
| .cycle | loops the iterator infinitely |
| .rev | reverses an iterator |
-----
### Attributes
---
```rs [1-4|7-11|13-15|17-21]
// A function marked as a unit test
#[test]
fn test_foo() {
/* ... */
}
// A conditionally-compiled module
#[cfg(target_os = "linux")]
mod bar {
/* ... */
}
// A lint attribute used to suppress a warning/error
#[allow(non_camel_case_types)]
type int8_t = i8;
// Inline function, when compiling to machine code
#[inline(always)]
fn siema() {
/* ... */
}
```
-----
### Ownership
---
```rs [1-4|6-8|10-12|14-16|19-20|22-23|25-26|28-31]
struct Container {
a: i32,
b: i32,
}
fn consume(container: Container) -> i32 {
container.a + container.b
}
fn borrow(container: &Container) -> i32 {
container.a + container.b
}
fn borrow_mut(container: &mut Container) -> i32 {
container.a + container.b
}
fn main() {
let c1 = Container { a: 10, b: 15 };
let c2 = Container { ..c1 };
let sum1 = consume(c1);
// let sum1 = consume(c1); // illegal
let sum2 = borrow(&c2);
let sum2 = borrow(&c2); // ok
let mut c3 = Container { ..c2 };
let sum3 = borrow_mut(&mut c3);
let sum3 = borrow_mut(&mut c3); // ok
}
```
---
#### Borrow checker
![compiler error](/static/slides/rust-introduction/Screenshot_20230210_174448.png)
---
#### Mutable borrow
```rs [4|6-8|10-14|16-19]
fn main() {
// --snip--
let mut c3 = Container { ..c2 };
// ok
let ref1 = &c3;
let ref2 = &c3;
// ok
let ref1 = &mut c3;
ref1.a;
// compiler knows the first borrow can be dropped here
let ref2 = &mut c3;
// illegal
let ref1 = &mut c3;
let ref2 = &mut c3;
ref1.a;
}
```
---
#### Borrow checker
![compiler error](/static/slides/rust-introduction/Screenshot_20230210_175828.png)
-----
### Lifetimes
---
```rs [1-3|5-9|11-14]
fn test(arr: &[i32]) -> impl Iterator<Item=&i32> {
return arr.iter().cycle()
}
fn main() { // works
let x = vec![1, 2, 3];
let x = test(&x);
x.take(9).for_each(|i| print!("{i}") );
}
fn main() { // doesn't work
let x = test(&vec![1, 2, 3]);
x.take(9).for_each(|i| print!("{i}") );
}
```
---
![borrow cheecker](/static/slides/rust-introduction/Screenshot_20230222_180500.png)
---
```rs
fn borrow(c: &Container) {
// -- snip --
}
```
---
```rs
fn borrow<'a>(c: &'a Container) {
// -- snip --
}
```
---
```rs [1-17|4-8|11-15]
fn main() {
let i = 3; // Lifetime for `i` starts. ────────────────┐
// │
{ // │
let borrow1 = &i; // `borrow1` lifetime starts. ──┐│
// ││
println!("borrow1: {}", borrow1); // ││
} // `borrow1` ends. ─────────────────────────────────┘│
// │
// │
{ // │
let borrow2 = &i; // `borrow2` lifetime starts. ──┐│
// ││
println!("borrow2: {}", borrow2); // ││
} // `borrow2` ends. ─────────────────────────────────┘│
// │
} // Lifetime ends. ─────────────────────────────────────┘
```
---
```rs
struct Container<'a> {
x: &'a i32,
y: &'a i32,
}
```
---
```rs
fn main() {
let x = 1;
let v;
{
let y = 2;
let f = Container { x: &x, y: &y };
v = f.x;
}
println!("{}", *v);
}
```
---
![borrow checker](/static/slides/rust-introduction/Screenshot_20230221_184708.png)
---
```rs
struct Container<'a, 'b> {
x: &'a i32,
y: &'b i32,
}
```
---
Day 21:
```rs
fn chain_eval<'data, 'a>(
start: &'data str,
dependees: &'a HashMap<&'data str, Vec<&'data str>>,
awaiting: &'a mut HashMap<&'data str, Shout>,
finished: &'a mut HashMap<&'data str, i64>,
) {
// -- snip --
}
```
---
```rs
pub fn run() -> () {
// 'data lifetime start
let data = utils::read_lines(utils::Source::Day(21));
let data = parse_data(&data);
println!("Day 21");
println!("Part 1: {}", solve1(&data));
println!("Part 2: {}", solve2(&data));
}
```
---
```rs [5-8|10-13]
fn test(arr: &[i32]) -> impl Iterator<Item=&i32> {
return arr.iter().cycle()
}
fn main() { // doesn't work
let x = test(&vec![1, 2, 3]);
x.take(9).for_each(|i| print!("{i}") );
}
fn main() { // works
let x = test(&[1, 2, 3]);
x.take(9).for_each(|i| print!("{i}") );
}
```
---
```rs [5-10]
fn test(arr: &[i32]) -> impl Iterator<Item=&i32> {
return arr.iter().cycle()
}
fn main() {
let x = {
let x: &'static [i32] = &[1, 2, 3];
test(&x)
};
x.take(9).for_each(|i| print!("{i}") );
}
```
-----
### Unsafe
---
```rs
unsafe fn test(n: i32) -> i32 {
// do something unsafe
n * 5
}
fn test2() -> i32 {
unsafe { test(4) }
}
fn main() {
let x = unsafe { test(4) };
let x = test2();
}
```
-----
### Traits
Haskell:
```hs
class Cool a where
giveMeNumber :: a -> Integer
```
Rust:
```rs
trait Cool {
fn give_me_number(&self) -> i32;
}
```
---
Haskell:
```hs
newtype Hello = Hello Integer
instance Cool Hello where
giveMeNumber (Hello n) = n * 10
```
Rust:
```rs
struct Hello(i32);
impl Cool for Hello {
fn give_me_number(&self) -> i32 { self.0 * 10 }
}
```
---
Haskell:
```hs
main = do
let test = Hello 2
putStrLn $ show $ giveMeNumber test
```
Rust:
```rs
fn main() {
let test = Hello(2);
println!("{}", test.give_me_number())
}
```
---
#### Some built in traits:
- ToString
- Display and Debug
- Default
- From and Into
- Clone and Copy
- Deref
- Iterator and IntoIterator
---
#### Default
```rs
#[derive(Default, Debug)]
struct Hello { a: i32, b: i32, c: Vec<i32> }
fn main() {
let x = Hello { a: 22, ..Default::default() };
println!("{x:?}")
}
```
```txt
Hello { a: 22, b: 0, c: [] }
```
---
#### Sized
```rs
// core::marker::Sized
pub trait Sized { }
```
```rs
fn test() -> dyn Iterator<Item=i32> {
[1, 2, 3].into_iter()
}
```
![compiler](/static/slides/rust-introduction/Screenshot_20230223_191210.png)
---
```rs
fn test() -> Box<dyn Iterator<Item=i32>> + Sized {
Box::from([1, 2, 3].into_iter())
}
```
---
#### Send & Sync
- A type is Send if it is safe to send it to another thread.
- A type is Sync if it is safe to share between threads (T is Sync if and only if &T is Send).
-----
### ?
```rs
fn test() -> Option<i32> {
let mut test: Vec<i32> = vec![1, 2, 3];
let x = test.pop()?;
let y = test.pop()?.checked_add(22)?;
Some(x * y)
}
fn main() {
println!("{}", test().unwrap())
}
```

View file

@ -1,14 +0,0 @@
---
title: "HELLO"
date: 2019-12-12
---
## HEllo!
fjdshfhdskf
---
dsad
$$a + b = 10$$

View file

@ -2,7 +2,7 @@
import Article from '../../layouts/Article.astro'; import Article from '../../layouts/Article.astro';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
export async function getStaticPaths () { export async function getStaticPaths() {
return (await getCollection('aoc')) return (await getCollection('aoc'))
.map(entry => ({params: {slug: entry.slug}, props: {entry}})); .map(entry => ({params: {slug: entry.slug}, props: {entry}}));
} }

View file

@ -0,0 +1,17 @@
---
import Article from '../../layouts/Article.astro';
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
return (await getCollection('posts'))
.map(entry => ({params: {slug: entry.slug}, props: {entry}}));
}
const { entry } = Astro.props;
const { Content, headings } = await entry.render();
---
<Article frontmatter={entry.data} headings={headings}>
<Content />
</Article>

View file

@ -0,0 +1,17 @@
---
import dayjs from "dayjs";
import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content';
const posts = (await getCollection('posts'))
.sort((a, b) => a.data.date < b.data.date ? 1 : -1)
.map(entry => ({
title: entry.data.title,
slug: `/posts/${entry.slug}`,
date: dayjs(entry.data.date),
}))
---
<List title="Posts" pages={posts} />

View file

@ -1,6 +1,7 @@
--- ---
import 'reveal.js/dist/reveal.css'; import 'reveal.js/dist/reveal.css';
import 'reveal.js/dist/theme/white.css'; import 'reveal.js/dist/theme/black.css';
import 'reveal.js/plugin/highlight/monokai.css';
import Base from '../../layouts/Base.astro'; import Base from '../../layouts/Base.astro';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
@ -16,7 +17,7 @@ const { entry } = Astro.props;
<Base> <Base>
<div class="reveal"> <div class="reveal">
<div class="slides"> <div class="slides">
<section data-markdown> <section data-markdown data-separator="^\n-----\n$" data-separator-vertical="^\n---\n$">
<textarea data-template>{entry.body}</textarea> <textarea data-template>{entry.body}</textarea>
</section> </section>
</div> </div>
@ -24,9 +25,22 @@ const { entry } = Astro.props;
<script> <script>
import Reveal from 'reveal.js'; import Reveal from 'reveal.js';
import Markdown from 'reveal.js/plugin/markdown/markdown'; import Markdown from 'reveal.js/plugin/markdown/markdown';
import Highlight from 'reveal.js/plugin/highlight/highlight';
Reveal.initialize({ Reveal.initialize({
plugins: [ Markdown ] hash: true,
plugins: [Markdown, Highlight]
}); });
</script> </script>
<style is:global>
.slides img {
margin-left: auto;
margin-right: auto;
max-height: 60vh;
}
</style>
<span slot="header"></span>
<span slot="footer"></span>
</Base> </Base>