From 3ae2b3192895d6353adcc956f86a2a4ce68228ea Mon Sep 17 00:00:00 2001 From: Kevin Matsubara Date: Thu, 1 Jan 2026 12:09:57 +0100 Subject: [PATCH] Add code notes and examples. --- portfolio/education.json | 132 +++++++++ portfolio/en/code/blazor.html | 5 + portfolio/en/code/elm.html | 5 + portfolio/en/code/haskell.html | 10 + portfolio/en/software.html | 28 +- portfolio/jp/code/blazor.html | 5 + portfolio/jp/code/elm.html | 5 + portfolio/jp/code/haskell.html | 5 + portfolio/jp/software.html | 33 ++- portfolio/nl/code/blazor.html | 5 + portfolio/nl/code/elm.html | 5 + portfolio/nl/code/haskell.html | 5 + portfolio/nl/software.html | 34 ++- .../pages/en/software/code/blazor/commands.md | 41 +++ .../pages/en/software/code/csharp/strings.md | 49 ++++ .../pages/en/software/code/csharp/types.md | 10 + .../pages/en/software/code/elm/composition.md | 8 + portfolio/pages/en/software/code/elm/dry.md | 59 ++++ .../pages/en/software/code/elm/formatting.md | 33 +++ .../en/software/code/elm/maybeandthen.md | 93 +++++++ .../pages/en/software/code/elm/maybemap.md | 50 ++++ .../en/software/code/haskell/caesar-cipher.md | 36 +++ ...ional-expressions-and-guarded-equations.md | 44 +++ .../code/haskell/curried-functions.md | 71 +++++ .../code/haskell/graham-hutton-answers.md | 257 ++++++++++++++++++ .../code/haskell/lambda-expressions.md | 52 ++++ .../pages/en/software/code/haskell/lists.md | 124 +++++++++ .../software/code/haskell/pattern-matching.md | 14 + .../code/haskell/recursive-functions.md | 27 ++ .../pages/en/software/code/haskell/strings.md | 38 +++ .../en/software/projects/attachment-module.md | 1 + .../projects/board-of-education-bot.md | 1 + .../projects/configuration-automation.md | 1 + .../projects/digital-experience-platform.md | 1 + .../projects/embedded-internet-radio.md | 1 + .../software/projects/festival-simulator.md | 1 + .../en/software/projects/ios-airports.md | 1 + .../en/software/projects/kanji-application.md | 1 + .../en/software/projects/metroid-shooter.md | 1 + .../software/projects/raspberry-pi-jukebox.md | 3 + .../pages/en/software/projects/swiv-for-pi.md | 1 + .../pages/en/software/projects/teslamaze.md | 1 + .../software/projects/wifi-extension-board.md | 1 + .../software/projects/windows-10-cookbook.md | 1 + portfolio/site.hs | 71 +++++ portfolio/templates/code.html | 27 ++ portfolio/templates/software.html | 4 - 47 files changed, 1388 insertions(+), 13 deletions(-) create mode 100644 portfolio/education.json create mode 100644 portfolio/en/code/blazor.html create mode 100644 portfolio/en/code/elm.html create mode 100644 portfolio/en/code/haskell.html create mode 100644 portfolio/jp/code/blazor.html create mode 100644 portfolio/jp/code/elm.html create mode 100644 portfolio/jp/code/haskell.html create mode 100644 portfolio/nl/code/blazor.html create mode 100644 portfolio/nl/code/elm.html create mode 100644 portfolio/nl/code/haskell.html create mode 100644 portfolio/pages/en/software/code/blazor/commands.md create mode 100644 portfolio/pages/en/software/code/csharp/strings.md create mode 100644 portfolio/pages/en/software/code/csharp/types.md create mode 100644 portfolio/pages/en/software/code/elm/composition.md create mode 100644 portfolio/pages/en/software/code/elm/dry.md create mode 100644 portfolio/pages/en/software/code/elm/formatting.md create mode 100644 portfolio/pages/en/software/code/elm/maybeandthen.md create mode 100644 portfolio/pages/en/software/code/elm/maybemap.md create mode 100644 portfolio/pages/en/software/code/haskell/caesar-cipher.md create mode 100644 portfolio/pages/en/software/code/haskell/conditional-expressions-and-guarded-equations.md create mode 100644 portfolio/pages/en/software/code/haskell/curried-functions.md create mode 100644 portfolio/pages/en/software/code/haskell/graham-hutton-answers.md create mode 100644 portfolio/pages/en/software/code/haskell/lambda-expressions.md create mode 100644 portfolio/pages/en/software/code/haskell/lists.md create mode 100644 portfolio/pages/en/software/code/haskell/pattern-matching.md create mode 100644 portfolio/pages/en/software/code/haskell/recursive-functions.md create mode 100644 portfolio/pages/en/software/code/haskell/strings.md create mode 100644 portfolio/templates/code.html delete mode 100644 portfolio/templates/software.html diff --git a/portfolio/education.json b/portfolio/education.json new file mode 100644 index 0000000..31dc911 --- /dev/null +++ b/portfolio/education.json @@ -0,0 +1,132 @@ +{ + "courses": [ + { + "name": "Blazor Deep Dive", + "sub": "From beginner to advanced in .NET 8", + "instructor": "Frank Liu", + "achieveDate": "2025-04-18", + "duration": 14.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/responsive-web-design-tutorial-course-html5-css3-bootstrap/", + "certificate": "https://www.udemy.com/certificate/UC-8b73ec23-4187-4ec2-9b0c-6b1c9e109220/", + "skills": ".NET, Blazor" + }, + { + "name": "Entity Framework Core", + "sub": "A full tour", + "instructor": "Trevoir Williams", + "achieveDate": "2025-04-14", + "duration": 10.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/responsive-web-design-tutorial-course-html5-css3-bootstrap/", + "certificate": "https://www.udemy.com/certificate/UC-0c891709-9105-498c-b9db-f7b2eef2b83a/", + "skills": ".NET, Entity Framework" + }, + { + "name": "Responsive Web Design Essentials", + "sub": "HTML5 CSS3 Bootstrap", + "instructor": "Daniel Walter Scott", + "achieveDate": "2024-06-22", + "duration": 16.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/responsive-web-design-tutorial-course-html5-css3-bootstrap/", + "certificate": "https://www.udemy.com/certificate/UC-154acaf8-cdf8-4194-9f93-2e978ed96611/", + "skills": "CSS, Bootstrap" + }, + { + "name": "Elm", + "sub": "The Complete Guide", + "instructor": "Carlos Saltos", + "achieveDate": "2024-01-27", + "duration": 21.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/elm-the-complete-guide/", + "certificate": "https://www.udemy.com/certificate/UC-17b9db07-37a1-43e1-be5e-1e179e3c1c09/", + "skills": "Elm, functional programming" + }, + { + "name": "F#", + "sub": "From the Ground Up", + "instructor": "Kit Eason", + "achieveDate": "2023-06-02", + "duration": 5.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/fsharp-from-the-ground-up/", + "certificate": "https://www.udemy.com/certificate/UC-821edd16-10a7-499f-b66e-2bd97f3ce3dd/", + "skills": "F#, functional programming" + }, + { + "name": "Drupal 9", + "sub": "Site Builder", + "instructor": "", + "achieveDate": "2022-07-28", + "duration": 24, + "institution": "Acquia", + "link": "https://certification.acquia.com/user/18196", + "certificate": "", + "skills": "CMS, Drupal" + }, + { + "name": "LPIC-1", + "sub": "", + "instructor": "", + "achieveDate": "2022-01-25", + "duration": 48, + "institution": "Linux professional institute certification", + "link": "https://www.lpi.org/our-certifications/", + "certificate": "", + "skills": "Linux" + }, + { + "name": "Docker Mastery", + "sub": "Kubernetes + Swarm from a Docker Captain", + "instructor": "Bret Fisher", + "achieveDate": "2021-04-28", + "duration": 21, + "institution": "Udemy", + "link": "https://www.udemy.com/course/docker-mastery/", + "certificate": "https://www.matsubara.nl/udemy-certs/UC-19ac22fe-70fa-47bd-804c-83f3aa4ac218.jpg", + "skills": "Docker, DevOps" + }, + { + "name": "Beginning C++ Programming", + "sub": "From Beginner to Beyond", + "instructor": "Dr. Frank Mitropoulos", + "achieveDate": "2020-05-07", + "duration": 46, + "institution": "Udemy", + "link": "https://www.udemy.com/course/beginning-c-plus-plus-programming/", + "certificate": "https://www.matsubara.nl/udemy-certs/UC-9f15ebd2-2a9a-489f-b8ca-7e8b175bc12f.pdf", + "skills": "C++" + }, + { + "name": "Learn Linux in 5 Days", + "sub": "and Level Up Your Career", + "instructor": "Jason Cannon", + "achieveDate": "2019-02-03", + "duration": 6.5, + "institution": "Udemy", + "link": "https://www.udemy.com/course/learn-linux-in-5-days/", + "certificate": "https://www.matsubara.nl/udemy-certs/UC-0BB6GYJ1.pdf", + "skills": "Basic Linux" + } + ], + "education": [ + { + "name": "Computer engineering of applied computer science", + "diploma": "Bachelor of computer science", + "school": "Avans Hogeschool", + "location": "Breda, Netherlands", + "start": 2012, + "end": 2016 + }, + { + "name": "Interactive media design", + "diploma": "MBO diploma", + "school": "Eindhovenseschool / Sint Lucas", + "location": "Eindhoven, Netherlands", + "start": 2009, + "end": 2012 + } + ] +} \ No newline at end of file diff --git a/portfolio/en/code/blazor.html b/portfolio/en/code/blazor.html new file mode 100644 index 0000000..86d7bd3 --- /dev/null +++ b/portfolio/en/code/blazor.html @@ -0,0 +1,5 @@ +--- +title: "Blazor" +logosub: ".NET Blazor developer" +language: "en" +--- \ No newline at end of file diff --git a/portfolio/en/code/elm.html b/portfolio/en/code/elm.html new file mode 100644 index 0000000..26fb1a5 --- /dev/null +++ b/portfolio/en/code/elm.html @@ -0,0 +1,5 @@ +--- +title: "Elm" +logosub: "Functional programmer" +language: "en" +--- \ No newline at end of file diff --git a/portfolio/en/code/haskell.html b/portfolio/en/code/haskell.html new file mode 100644 index 0000000..55d1600 --- /dev/null +++ b/portfolio/en/code/haskell.html @@ -0,0 +1,10 @@ +--- +title: "Haskell" +logosub: "Functional programmer" +language: "en" +--- + + +type class + +type class constraint diff --git a/portfolio/en/software.html b/portfolio/en/software.html index 4696de9..1ec7dfb 100644 --- a/portfolio/en/software.html +++ b/portfolio/en/software.html @@ -1,7 +1,29 @@ --- -title: Software -logosub: Software +title: "Software" +logosub: "Software developer" language: "en" --- -$partial("templates/software.html")$ +

Projects

+$for(projects)$ +

$year$ - $title$

+$endfor$ + +
+ +

Code

+ +Haskell + +
+ +

Education

+

Computer engineering of applied computer science

+Bachelor of computer science
+

Avans Hogeschool - Breda, Netherlands

+

2012 - 2016

+ +

Interactive media design

+MBO diploma +

Eindhovenseschool / Sint Lucas - Eindhoven, Netherlands

+

2009 - 2012

diff --git a/portfolio/jp/code/blazor.html b/portfolio/jp/code/blazor.html new file mode 100644 index 0000000..910b104 --- /dev/null +++ b/portfolio/jp/code/blazor.html @@ -0,0 +1,5 @@ +--- +title: "Blazor" +logosub: "ブレイザー" +language: "jp" +--- \ No newline at end of file diff --git a/portfolio/jp/code/elm.html b/portfolio/jp/code/elm.html new file mode 100644 index 0000000..2d2bd0b --- /dev/null +++ b/portfolio/jp/code/elm.html @@ -0,0 +1,5 @@ +--- +title: "Elm" +logosub: "関数型プログラミング" +language: "jp" +--- \ No newline at end of file diff --git a/portfolio/jp/code/haskell.html b/portfolio/jp/code/haskell.html new file mode 100644 index 0000000..690f4e2 --- /dev/null +++ b/portfolio/jp/code/haskell.html @@ -0,0 +1,5 @@ +--- +title: "Haskell" +logosub: "関数型プログラミング" +language: "jp" +--- \ No newline at end of file diff --git a/portfolio/jp/software.html b/portfolio/jp/software.html index 5a79930..9d10e3c 100644 --- a/portfolio/jp/software.html +++ b/portfolio/jp/software.html @@ -1,7 +1,34 @@ --- -title: Software -logosub: Software +title: "ソフトウェア" +logosub: "開発者" language: "jp" --- -$partial("templates/software.html")$ +

プロジェクト

+$for(projects)$ +

$year$ - $title$

+$endfor$ + +
+ +

Code

+ +

コードのメモと例。

+ + + +
+ +

教育

+

計算機科学

+学士
+

Avans Hogeschool - ブレダ、オランダ

+

2012 - 2016

+ +

コミュニケーションデザイン

+

Eindhovenseschool / Sint Lucas - アイントホーフェン、オランダ

+

2009 - 2012

\ No newline at end of file diff --git a/portfolio/nl/code/blazor.html b/portfolio/nl/code/blazor.html new file mode 100644 index 0000000..7b830d4 --- /dev/null +++ b/portfolio/nl/code/blazor.html @@ -0,0 +1,5 @@ +--- +title: "Blazor" +logosub: ".NET Blazor ontwikkelaar" +language: "nl" +--- \ No newline at end of file diff --git a/portfolio/nl/code/elm.html b/portfolio/nl/code/elm.html new file mode 100644 index 0000000..97e9bbd --- /dev/null +++ b/portfolio/nl/code/elm.html @@ -0,0 +1,5 @@ +--- +title: "Elm" +logosub: "Functioneel programmeur" +language: "nl" +--- \ No newline at end of file diff --git a/portfolio/nl/code/haskell.html b/portfolio/nl/code/haskell.html new file mode 100644 index 0000000..8b69819 --- /dev/null +++ b/portfolio/nl/code/haskell.html @@ -0,0 +1,5 @@ +--- +title: "Haskell" +logosub: "Functioneel programmeur" +language: "nl" +--- \ No newline at end of file diff --git a/portfolio/nl/software.html b/portfolio/nl/software.html index f315104..0bd6b2d 100644 --- a/portfolio/nl/software.html +++ b/portfolio/nl/software.html @@ -1,7 +1,35 @@ --- -title: Software -logosub: Software +title: "Software" +logosub: "Software ontwikkelaar" language: "nl" --- -$partial("templates/software.html")$ +

Projecten

+$for(projects)$ +

$year$ - $title$

+$endfor$ + +
+ +

Code

+ +

Notities en voorbeelden van code.

+ + + +
+ +

Opleiding

+

Technische informatica

+Bachelor of computer science
+

Avans Hogeschool - Breda

+

2012 - 2016

+ +

Interactieve media vormgeving

+MBO diploma +

Eindhovenseschool / Sint Lucas - Eindhoven

+

2009 - 2012

\ No newline at end of file diff --git a/portfolio/pages/en/software/code/blazor/commands.md b/portfolio/pages/en/software/code/blazor/commands.md new file mode 100644 index 0000000..20a7f84 --- /dev/null +++ b/portfolio/pages/en/software/code/blazor/commands.md @@ -0,0 +1,41 @@ +--- +logosub: "Software" +language: "en" +title: "Blazor commands" +code: "Blazor" +--- + +A collection of commands useful to work with blazor web applications. + + +* Create a new application. + +`dotnet new blazor -o BlazorWebAppMovies` + +* Compile and run the application, and hot-reload upon changes. + +`dotnet watch` + +* VS Code build: + +Command Palette (Ctrl+Shift+P), use the `.NET: Build` command to build the app. + +* Create gitignore file: + +`dotnet new gitignore` + +* [Scaffolding example](https://learn.microsoft.com/en-us/aspnet/core/blazor/tutorials/movie-database-app/part-2?view=aspnetcore-8.0&pivots=vsc#scaffold-the-model): + +`dotnet aspnet-codegenerator blazor CRUD -dbProvider sqlite -dc BlazorWebAppMovies.Data.BlazorWebAppMoviesContext -m Movie -outDir Components/Pages` + + +### Entity framework + +* Create a migration, this is also used when creating a new migration when the model has changed. + +`dotnet ef migrations add InitialCreate` + +* Update the database: + +`dotnet ef database update` + diff --git a/portfolio/pages/en/software/code/csharp/strings.md b/portfolio/pages/en/software/code/csharp/strings.md new file mode 100644 index 0000000..3828dd1 --- /dev/null +++ b/portfolio/pages/en/software/code/csharp/strings.md @@ -0,0 +1,49 @@ +## Strings + +#### Verbatim string with @: + +Preserves whitespace and characters like '\' do not need to be escaped. + +```c# +Console.WriteLine(@" c:\source\repos + (this is where your code goes)"); +``` + +Output: +``` +> c:\source\repos +> (this is where your code goes) +``` + +#### Escaped Unicode + +Use the **\u** plus a four-character code to represent Unicode characters (UTF-16) in a string. + +[Japanese UTF-16 table](http://www.rikai.com/library/kanjitables/kanji_codes.unicode.shtml) + +```c# +Console.WriteLine("\u3053\u3093\u306B\u3061\u306F World!"); +``` + +Output (UTF-16): +``` +> こんにちは World! +``` + +```c# +// To generate Japanese invoices: +Console.Write("\n\n\u65e5\u672c\u8a9e\u306e\u8acb\u6c42\u66f8\u3092\u751f\u6210\u3059\u308b\u306b\u306f\uff1a"); +``` + +Output (UTF-16): +``` +> 日本語の請求書を生成するには: +``` + +#### String interpolation + +Can be combined with verbatim strings. + +```c# +Console.WriteLine($@"C:\Output\{projectName}\Data"); +``` \ No newline at end of file diff --git a/portfolio/pages/en/software/code/csharp/types.md b/portfolio/pages/en/software/code/csharp/types.md new file mode 100644 index 0000000..dbba32e --- /dev/null +++ b/portfolio/pages/en/software/code/csharp/types.md @@ -0,0 +1,10 @@ +## Types + +Float Type Precision + +float ~6-9 digits 0.25F +double ~15-17 digits 0.25 +decimal 28-29 digits 0.25M + +Both lowercase 'f' or 'F' can be used, same for 'm' and 'M'. + diff --git a/portfolio/pages/en/software/code/elm/composition.md b/portfolio/pages/en/software/code/elm/composition.md new file mode 100644 index 0000000..1084258 --- /dev/null +++ b/portfolio/pages/en/software/code/elm/composition.md @@ -0,0 +1,8 @@ +--- +logosub: "Software" +language: "en" +title: "Composition" +code: "Elm" +--- + +[Elm composition operators << and >>](https://package.elm-lang.org/packages/elm/core/latest/Basics#(%3C%3C)) diff --git a/portfolio/pages/en/software/code/elm/dry.md b/portfolio/pages/en/software/code/elm/dry.md new file mode 100644 index 0000000..df5bae8 --- /dev/null +++ b/portfolio/pages/en/software/code/elm/dry.md @@ -0,0 +1,59 @@ +--- +logosub: "Software" +language: "en" +title: "DRY" +code: "Elm" +--- + +DRY means: "[Don't Repeat Yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)". + +This page contains some common mistakes I make when writing Elm code and how I processed feedback afterwards to improve it. + + +```elm +let + render item = + case warning item of + Just (Error tooltip) -> + [ Html.text <| text item + , Html.i + [ HtmlAttributes.class "icon-error" + , HtmlAttributes.title tooltip + ] + ] + -- Another case, very similar to the one above. + Just (Warning tooltip) -> + [ Html.text <| text item + , Html.i + [ HtmlAttributes.class "icon-warning" + , HtmlAttributes.title <| getWarningTooltip tooltip + ] + ] + + Nothing -> + [ Html.text <| text item ] + +``` + +```elm +let + render item = + let + createHtml class tooltip = + [ Html.text <| text item + , Html.i + [ HtmlAttributes.class class + , HtmlAttributes.title tooltip + ] + ] + in + case warning item of + Just (Error tooltip) -> + createHtml "icon-error" tooltip + + Just (Warning tooltip) -> + createHtml "icon-warning" (getWarningTooltip tooltip) + + Nothing -> + [ Html.text <| text item ] +``` diff --git a/portfolio/pages/en/software/code/elm/formatting.md b/portfolio/pages/en/software/code/elm/formatting.md new file mode 100644 index 0000000..737c151 --- /dev/null +++ b/portfolio/pages/en/software/code/elm/formatting.md @@ -0,0 +1,33 @@ +--- +logosub: "Software" +language: "en" +title: "Formatting" +code: "Elm" +--- + +You can add a docstring to an elm function like this: + +```elm + + +{- Render the Elm icon. -} + + +elmIcon : E.Element msg +elmIcon = + +``` + +But upon formatting, 2 new lines are automatically added. + +By adding a "|" pipe character, the docstring will get appended to the top op the function header. + +```elm + + +{-| Render the Elm icon. +-} +elmIcon : E.Element msg +elmIcon = + +``` diff --git a/portfolio/pages/en/software/code/elm/maybeandthen.md b/portfolio/pages/en/software/code/elm/maybeandthen.md new file mode 100644 index 0000000..c07b1a5 --- /dev/null +++ b/portfolio/pages/en/software/code/elm/maybeandthen.md @@ -0,0 +1,93 @@ +--- +logosub: "Software" +language: "en" +title: "Maybe AndThen" +code: "Elm" +--- + +Given are these functions, **hasPrecedingReleasedVersions** and **getSelectedItemIndex**, need to be optimized. + + +```elm + +hasPrecedingReleasedVersions = + case getSelectedItemIndex data.versionData of + Just index -> + Array.slice 0 index data.versionData.allItems + |> Array.toList + |> List.any + (\item -> + case item of + ReleasedVersion _ -> + True + _ -> + False + ) + Nothing -> + False +``` + +Currently, **getSelectedItemIndex** is defined as such: + +```elm + +getSelectedItemIndex : Model id -> Maybe Int +getSelectedItemIndex model = + case getSelectedItem model of + Just selected -> + Array.toIndexedList model.allItems + |> List.filter (\( _, item ) -> item == selected) + |> List.head + |> Maybe.map Tuple.first + + Nothing -> + Nothing + + +``` + +But using [Maybe.andThen](https://package.elm-lang.org/packages/elm/core/latest/Maybe#andThen) will allow to get rid of the **Nothing -> Nothing** here. +Also the **List.filter** and **List.head** combination can be shortened with a **List.find**. + +```elm + +getSelectedItemIndex : Model id -> Maybe Int +getSelectedItemIndex model = + getSelectedItem model + |> Maybe.andThen + (\selected -> + Array.toIndexedList model.allItems + |> List.find (\( _, item ) -> item == selected) + |> Maybe.map Tuple.first + ) + + +``` + +Finally, define a custom funcion to determine the boolean: + +```elm + +itemIsReleased : VersionData id -> Bool +itemIsReleased versionData = + case versionData of + WorkingVersion _ -> + False + ReleasedVersion + True + +``` + +The original function can now be changed to: + +```elm + +hasPrecedingReleasedVersions = + case getSelectedItemIndex data.versionData of + Just index -> + Array.slice 0 index data.versionData.allItems + |> Array.toList + |> List.any itemIsReleased + Nothing -> + False +``` \ No newline at end of file diff --git a/portfolio/pages/en/software/code/elm/maybemap.md b/portfolio/pages/en/software/code/elm/maybemap.md new file mode 100644 index 0000000..27ac631 --- /dev/null +++ b/portfolio/pages/en/software/code/elm/maybemap.md @@ -0,0 +1,50 @@ +--- +logosub: "Software" +language: "en" +title: "Maybe Map" +code: "Elm" +--- + +Here, a tooltip title attribute needs to be added if it is **Just**. + +```elm +let + divAttributes = + [ HA.classList + [ ( "my-div", True ) ] + ] + + combinedAttributes = + case settings.tooltip of + Just tooltip -> + divAttributes ++ [ HA.title tooltip ] + + Nothing -> + divAttributes +in +H.div + combinedAttributes + [ content ] + +``` + +This can be easier written with the [Maybe.map](https://package.elm-lang.org/packages/elm/core/latest/Maybe#map) and [Maybe.withDefault](https://package.elm-lang.org/packages/elm/core/latest/Maybe#withDefault) functions. + +```elm + +let + divAttributes = + [ HA.classList + [ ( "my-div", True ) ] + ] + + tooltipAttribute = + Maybe.map (\tooltip -> [ HA.title tooltip ]) settings.tooltip |> Maybe.withDefault [] + -- or you can do: + settings.tooltip |> Maybe.map (\tooltip -> [ HA.title tooltip ]) |> Maybe.withDefault [] + +in +H.div + (divAttributes ++ tooltipAttribute) + [ content ] +``` \ No newline at end of file diff --git a/portfolio/pages/en/software/code/haskell/caesar-cipher.md b/portfolio/pages/en/software/code/haskell/caesar-cipher.md new file mode 100644 index 0000000..0993271 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/caesar-cipher.md @@ -0,0 +1,36 @@ +--- +logosub: "Software" +language: "en" +title: "Caesar Cipher" +code: "Haskell" +--- + +The implementation of the [Caesar's Cipher](https://en.wikipedia.org/wiki/Caesar_cipher) in Haskell. + +*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html) + +```haskell +import Data.Char +import Prelude + +let2int :: Char -> Int +let2int c | isLower c = ord c - ord 'a' + | otherwise = ord c - ord 'A' + +int2let :: Int -> Bool -> Char +int2let n isLowercase = chr (ord (if isLowercase then 'a' else 'A') + n) + +shift :: Int -> Char -> Char +shift n c | isLower c = int2let ((let2int c + n) `mod` 26) (isLower c) + | isUpper c = int2let ((let2int c + n) `mod` 26) (isLower c) + | otherwise = c + +encode :: Int -> String -> String +encode n xs = [shift n x | x <- xs] + + +ghci> encode 5 "This is a Caesar Cipher" +-- "Ymnx nx f Hfjxfw Hnumjw" +ghci> encode (-5) "Ymnx nx f Hfjxfw Hnumjw" +-- "This is a Caesar Cipher" +``` \ No newline at end of file diff --git a/portfolio/pages/en/software/code/haskell/conditional-expressions-and-guarded-equations.md b/portfolio/pages/en/software/code/haskell/conditional-expressions-and-guarded-equations.md new file mode 100644 index 0000000..9ccdf39 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/conditional-expressions-and-guarded-equations.md @@ -0,0 +1,44 @@ +--- +logosub: "Software" +language: "en" +title: "Conditional expressions and Guarded equations" +code: "Haskell" +--- + +### Conditional expressions + +```haskell +signum :: Int -> Int +signum n = if n < 0 then -1 else + if n == 0 then 0 else 1 +``` + +And a **safetail** function, where an empty list is returned instead of an error when given an empty list. + +```haskell +safetail :: [a] -> [a] +safetail xs = if length xs > 0 then tail xs else [] +``` + +--- + +### Guarded equations + +An alternative to conditional expressions, functions can be defined with guarded equations. + +An example of the **signum** function: + +```haskell +signum :: Int -> Int +signum n | n < 0 = -1 + | n == 0 = 0 + | otherwise = 1 +``` + +Here is **safetail** with guarded equations: + +```haskell +safetail :: [a] -> [a] +safetail xs | length xs > 0 = tail xs + | otherwise = [] +``` \ No newline at end of file diff --git a/portfolio/pages/en/software/code/haskell/curried-functions.md b/portfolio/pages/en/software/code/haskell/curried-functions.md new file mode 100644 index 0000000..36c0237 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/curried-functions.md @@ -0,0 +1,71 @@ +--- +logosub: "Software" +language: "en" +title: "Curried functions" +code: "Haskell" +--- + +A function can return another function. + +```haskell +add' :: Int -> (Int -> Int) +add' x y = x+y +``` + +Here, **add'** is a function that takes an **Int** for an argument and results in a function of type: **Int -> Int**. +The function definition takes an integer **x**, followed by an integer **y**, it can be [curried](https://en.wikipedia.org/wiki/Currying). + +```haskell +addThree = add' 3 -- This is now a function with type: Int -> Int +result = addThree 5 -- Evaluates to 8 +``` + +Another example, + +```haskell +mult :: Int -> (Int -> (Int -> Int)) +mult x y z = x*y*z +``` + +And is applied as following: + +```haskell +mult x y z +-- Means same as: +((mult x) y) z +``` + +When used, it is like: + +```haskell +multTwo = mult 2 -- This is now a function with type: Int -> (Int -> Int) +multTwoThree = multTwo 3 -- This is: Int -> Int +result = multTwoThree 4 -- Evaluates to 2 * 3 * 4 = 24 + +-- or just: + +result = mult 2 3 4 -- Also evaluates to 24 +``` + +**Partial application** is about using curried functions, applying only some arguments and getting back a new function. + +```haskell +double = mult 2 -- This is now a function with type: Int -> (Int -> Int) + +result = double 3 4 -- Evaluates to 2 * 3 * 4 = 24 + +quadruple = double 2 -- Now quadruple :: Int -> Int +result = quadruple 3 -- Evaluates to 2 * 2 * 3 = 12 +``` + +The arrow function **->** in Haskell types is assumed to associate from the right. + +```haskell +Int -> Int -> Int -> Int + +-- is: + +Int -> (Int -> (Int -> Int)) +``` + +So, unless tuples are required, all functions in Haskell with multiple arguments are actually defined as curried functions, with a way to reduce excessive parenthesis. diff --git a/portfolio/pages/en/software/code/haskell/graham-hutton-answers.md b/portfolio/pages/en/software/code/haskell/graham-hutton-answers.md new file mode 100644 index 0000000..373d337 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/graham-hutton-answers.md @@ -0,0 +1,257 @@ +--- +logosub: "Software" +language: "en" +title: "Programming in Haskell by Graham Hutton" +code: "Haskell" +--- + +This book is what I used to learn the programming language Haskell. This page contains all my exercise answers. + +*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html) + +* [Chapter 4 - Defining functions](#Chapter-4) +* [Chapter 5 - List comprehensions](#Chapter-5) +* [Chapter 6 - Recursive functions](#Chapter-6) + +--- + +#### Chapter-4 +##### Defining functions + +###### exercise 1 + +```haskell +halve :: [Int] -> ([Int], [Int]) +halve xs = + (take n xs, drop n xs) + where n = length xs `div` 2 + +halve :: [Int] -> ([Int], [Int]) +halve xs = + splitAt (length xs `div` 2) xs +``` + +###### exercise 2 + +```haskell +-- a (head & tail) +third :: [a] -> a +third xs = head (tail (tail xs)) + +-- b (list indexing) +third :: [a] -> a +third xs = xs !! 2 + +-- c (pattern matching) +third :: [a] -> a +third (_:_:a:_) = a +``` + +###### exercise 3 + +```haskell +-- a (conditional expression) +safetail :: [a] -> [a] +safetail xs = if length xs > 0 then tail xs else [] + +-- b (guarded equation) +safetail :: [a] -> [a] +safetail xs | length xs > 0 = tail xs + | otherwise = [] + +-- c (pattern matching) +safetail :: [a] -> [a] +safetail [] = [] +safetail xs = tail xs + -- or: + -- safetail (_:xs) = xs +``` + +###### exercise 4 + +```haskell +(||) :: Bool -> Bool -> Bool +True || _ = True +_ || True = True +_ = False +``` + +###### exercise 5 + +```haskell +-- Use conditional expressions to define &&. +(<#>) :: Bool -> Bool -> Bool +a <#> b = + if a then + if b then True else False + else + False +``` + +###### exercise 6 + +```haskell +(<#>) :: Bool -> Bool -> Bool +a <#> b = + if a then b else False +``` + +###### exercise 7 + +```haskell +mult :: Int -> Int -> Int -> Int +mult x y z = x*y*z + +-- rewritten to use lambda functions. +mult :: Int -> (Int -> (Int -> Int)) +mult = \x -> (\y -> (\z -> x * y * z)) +``` + +###### exercise 8 + +[Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) + +```haskell +luhnDouble :: Int -> Int +luhnDouble x = x * 2 `mod` 9 + +luhn :: Int -> Int -> Int -> Int -> Bool +luhn a b c d = + sum ((map luhnDouble [a,c]) ++ [b,d]) `mod` 10 == 0 + +--ghci> luhn 1 7 8 4 +--True +--ghci> luhn 4 7 8 3 +--False +``` + +--- + +#### Chapter-5 +##### List comprehensions + +* exercise 1 + +```haskell +sum [x^2 | x <- [0..100]] +-- 338350 +``` + +###### exercise 2 + +```haskell +grid :: Int -> Int -> [(Int, Int)] +grid n m = + [(x,y) | x <- [0..n], y <- [0..m]] + +ghci> grid 1 2 +-- [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)] +``` + +###### exercise 3 + +```haskell +square :: Int -> [(Int,Int)] +square n = + [(x,y) | (x,y) <- grid n n, x /= y] + +ghci> square 2 +-- [(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)] +``` + +###### exercise 4 + +```haskell +replicate :: Int -> a -> [a] +replicate n item = + [item | _ <- [1..n]] + +ghci> replicate 4 "test" +-- ["test","test","test","test"] +``` + +###### exercise 5 + +[Pythagorean theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem) + +```haskell +isPythagorean :: Int -> Int -> Int -> Bool +isPythagorean x y z = + x^2 + y^2 == z^2 + +pyths :: Int -> [(Int,Int,Int)] +pyths n = + [(x,y,z) | x <- [1..n], y <- [1..n], z <- [1..n], isPythagorean x y z] + +ghci> pyths 10 +-- [(3,4,5),(4,3,5),(6,8,10),(8,6,10)] +``` + +###### exercise 6 + +[Perfect number](https://en.wikipedia.org/wiki/Perfect_number) + +```haskell +factors :: Int -> [Int] +factors n = [x | x <- [1..n], n `mod` x == 0] + +perfects :: Int -> [Int] +perfects limit = + [x | x <- [1..limit], sum (factors x) - x == x] + +ghci> perfects 10000 +-- [6,28,496,8128] +``` + +###### exercise 7 +*(I did not understand this one)* + +###### exercise 8 + +Use the **find** library function in [Data.List 9.8.2](https://downloads.haskell.org/ghc/9.8.2/docs/libraries/base-4.19.1.0-179c/Data-List.html#v:find) + +```haskell +find :: (a -> Bool) -> [a] -> Maybe a +-- The find function takes a predicate and a list and returns the first element in the list matching the predicate, or Nothing if there is no such element. +``` + +```haskell +positions :: Eq a => a -> [a] -> [Int] +positions x xs = + [i | (x',i) <- zip xs [0..], x == x'] + +-- using find function, though I doubt its correct... + +positions :: Eq a => a -> [a] -> [Int] +positions x xs = + [i | (x',i) <- zip xs [0..], isJust (find (==x) [x'])] + +positions 2 [1,1,0,2,46,6,8,9,2,3,4,2,4,9,2] +-- [3,8,11,14] + +-- You can also use: +positions :: Eq a => a -> [a] -> [Int] +positions x = elemIndices x +``` + +###### exercise 9 + +[Scalar product](https://en.wikipedia.org/wiki/Dot_product) + +```haskell +scalarproduct :: [Int] -> [Int] -> Int +scalarproduct xs ys = + sum [x*y | (x,y) <- zip xs ys] + +ghci> scalarproduct [1,2,3] [4,5,6] +-- 32 +``` + +###### execise 10 + +[Caesar's Cipher](./caesar-cipher) + +--- + +#### Chapter-6 +##### Recursive functions \ No newline at end of file diff --git a/portfolio/pages/en/software/code/haskell/lambda-expressions.md b/portfolio/pages/en/software/code/haskell/lambda-expressions.md new file mode 100644 index 0000000..e040b5b --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/lambda-expressions.md @@ -0,0 +1,52 @@ +--- +logosub: "Software" +language: "en" +title: "Lambda expressions" +code: "Haskell" +--- + +You can define a function like: + +```haskell +double :: Int -> Int +double x = x + x +``` + +Which can also be written as an anonymous function: + +```haskell +\x -> x + x +``` + +Here, the **\\** symbol represents the Greek letter lambda: **λ**. This is derived from [lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus). + +Lambda expressions can be used to more explicitly state that a function is returned. + +Consider: + +```haskell +const :: a -> b -> a +const x _ = x +``` + +This can be written using a lambda expression and added parenthesis in the type definition. This is more explicit in that a function is being returned. + +```haskell +const :: a -> (b -> a) +const x = \_ -> x +``` + +And as an anonymous function. Consider the difference between these similar functions that return a list of odd numbers: + +```haskell +odds :: Int -> [Int] +odds n = map f [0..n-1] + where f x = x*2 + 1 + +odds :: Int -> [Int] +odds n = map (\x -> x*2 + 1) [0..n-1] + +-- > odds 15 +-- > [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29] +``` + diff --git a/portfolio/pages/en/software/code/haskell/lists.md b/portfolio/pages/en/software/code/haskell/lists.md new file mode 100644 index 0000000..f095176 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/lists.md @@ -0,0 +1,124 @@ +--- +logosub: "Software" +language: "en" +title: "Lists" +code: "Haskell" +--- + +Lists are constructed one element at a time starting from an empty **[]** list using the *cons* operator **:**. For example, **[1,2,3]** can be decomposed as: + +```haskell +[1,2,3] +-- +1 : [2,3] +-- +1 : (2 : [3]) +-- +1 : (2 : (3 : [])) +``` + +To verify if a list with 3 numbers starts with the integer **1**, you can use pattern matching. + +```haskell +startsWithOne :: [Int] -> Bool +startsWithOne [1, _, _] = True +startsWithOne _ = False +``` + +### Access elements + +To access an element in a list, the indexing operator **!!** can be used. + +```haskell +-- Get the third element of a list. +third :: [a] -> a +third xs = xs !! 2 +``` + +### list comprehension + +* Wikipedia: [List comprehension](https://en.wikipedia.org/wiki/List_comprehension). + + +```haskell +ghci> [x^2 | x <- [1..6]] +-- [1,4,9,16,25,36] +``` + +* The **|** symbol is read as: "*such that*". +* The **<-** symbol is read as: "*drawn from*". +* And **x <- [1..6]** is called a: "*generator*". + +A list comprehension can have more than one generator. + +```haskell +ghci> [(x,y) | x <- [1,2,3], y <- [4,5]] +-- [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)] +``` + +Examples of list comprehensions: + +```haskell +halve :: [Int] -> ([Int], [Int]) +halve xs = + ([x | x <- xs, x < 4], [x | x <- xs, x >= 4]) + +-- halve [1,2,3,4,5,6] +-- ([1,2,3],[4,5,6]) +``` + +How to actually halve the list properly: + +```haskell +halve :: [Int] -> ([Int], [Int]) +halve xs = + (take n xs, drop n xs) + where n = length xs `div` 2 +-- or + splitAt (length xs `div` 2) xs +``` + +Here the **length** function replaces all elements with a 1 and sums the total: + +```haskell +length :: [a] -> Int +length xs = sum [1 | _ <- xs] +length [1,4,8,90] +-- 4 +``` + +You can use logical expressions as a **guard**, to filter values created by list comprehensions. + +```haskell +factors :: Int -> [Int] +factors n = [x | x <- [1..n], n `mod` x == 0] + +factors 20 +-- [1,2,4,5,10,20] +factors 13 +-- [1,13] +``` + +And you can use this **factors** function to determine **prime** numbers. + +* Wikipedia: [Prime number](https://en.wikipedia.org/wiki/Prime_number) + +```haskell +prime :: Int -> Bool +prime n = factors n == [1,n] + +prime 15 +--False +prime 13 +-- True +``` +And with this **prime** function, we can use list comprehension to determine a range of prime numbers! + +```haskell +primes :: Int -> [Int] +primes n = [x | x <- [2..n], prime x] + +primes 50 +-- [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47] +``` + diff --git a/portfolio/pages/en/software/code/haskell/pattern-matching.md b/portfolio/pages/en/software/code/haskell/pattern-matching.md new file mode 100644 index 0000000..b5b6b5f --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/pattern-matching.md @@ -0,0 +1,14 @@ +--- +logosub: "Software" +language: "en" +title: "Pattern matching" +code: "Haskell" +--- + +An example to determine the third element of a list, (with at least 3 elements): + +```haskell +third :: [a] -> a +third (_:_:x:_) = x +``` + diff --git a/portfolio/pages/en/software/code/haskell/recursive-functions.md b/portfolio/pages/en/software/code/haskell/recursive-functions.md new file mode 100644 index 0000000..398e438 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/recursive-functions.md @@ -0,0 +1,27 @@ +--- +logosub: "Software" +language: "en" +title: "Recursive functions" +code: "Haskell" +--- + +Recursion is the basic mechanism for looping in Haskell. + +Determine the [factorial](https://en.wikipedia.org/wiki/Factorial). + +```haskell +factorial :: Int -> Int +factorial 0 = 1 +factorial n = n * factorial (n-1) +``` + +The factorial of 3, actually is calculated as such: + +```haskell +factorial 3 +3 * factorial 2 +3 * (2 * factorial 1) +3 * (2 * (1 * factorial 0)) +3 * (2 * (1 * 1)) +``` + diff --git a/portfolio/pages/en/software/code/haskell/strings.md b/portfolio/pages/en/software/code/haskell/strings.md new file mode 100644 index 0000000..64a3cf9 --- /dev/null +++ b/portfolio/pages/en/software/code/haskell/strings.md @@ -0,0 +1,38 @@ +--- +logosub: "Software" +language: "en" +title: "Strings" +code: "Haskell" +--- + +Strings are not primitive types, but a list of characters. + +For example, + +```haskell +"abc" :: String +-- is actually: +['a','b','c'] :: [Char] +``` +Because of this, polymorphic functions on lists, can be used with strings. + +```haskell +"abcde" !! 2 +-- 'c' +take 3 "abcde" +-- "abc" +length "abcde" +-- 5 +zip "abc" [1,2,3,4] +-- [('a',1),('b',2),('c',3)] +``` + +And you can use list comprehensions with Strings. + +```haskell +count :: Char -> String -> Int +count x xs = length [x' | x' <- xs, x == x'] + +count 'a' "paragraph" +-- 3 +``` diff --git a/portfolio/pages/en/software/projects/attachment-module.md b/portfolio/pages/en/software/projects/attachment-module.md index b85c6d3..9a8986a 100644 --- a/portfolio/pages/en/software/projects/attachment-module.md +++ b/portfolio/pages/en/software/projects/attachment-module.md @@ -2,6 +2,7 @@ logosub: "Technical Specialist, Automation" language: "en" title: "Attachment module" +year: "2017" --- Sometimes a project owner wants a feature implemented in their project that the developers somehow are unable to realize. The project was a website containing a form that customers would enter text data on. The project owner asked for a feature which allowed customers to attach files to this form. diff --git a/portfolio/pages/en/software/projects/board-of-education-bot.md b/portfolio/pages/en/software/projects/board-of-education-bot.md index 177c051..78e7a10 100644 --- a/portfolio/pages/en/software/projects/board-of-education-bot.md +++ b/portfolio/pages/en/software/projects/board-of-education-bot.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 1" language: "en" title: "Board of Education Bot" +year: "2012" --- The Board of Education (Ro)Bot is a development platform made by Parallax. diff --git a/portfolio/pages/en/software/projects/configuration-automation.md b/portfolio/pages/en/software/projects/configuration-automation.md index 93a95c3..60add42 100644 --- a/portfolio/pages/en/software/projects/configuration-automation.md +++ b/portfolio/pages/en/software/projects/configuration-automation.md @@ -2,6 +2,7 @@ logosub: "Technical Specialist, Automation" language: "en" title: "Configuration Automation" +year: "2016" --- At Hitachi Vantara I worked on automating a configuration process using Python and several external API. diff --git a/portfolio/pages/en/software/projects/digital-experience-platform.md b/portfolio/pages/en/software/projects/digital-experience-platform.md index 36a54e0..482031e 100644 --- a/portfolio/pages/en/software/projects/digital-experience-platform.md +++ b/portfolio/pages/en/software/projects/digital-experience-platform.md @@ -2,6 +2,7 @@ logosub: "Backend developer" language: "en" title: "Digital Experience Platform" +year: "2023" --- A "Digital Experience Platform" is basically interactive software where data can be maintained, not much different from a regular application. But it's a marketing term, because software also needs to be sold. One such DXP I loved working on was for OPPLE. They are a brand of lighting products and have over 14000 different items. diff --git a/portfolio/pages/en/software/projects/embedded-internet-radio.md b/portfolio/pages/en/software/projects/embedded-internet-radio.md index 0ce321b..3cf6724 100644 --- a/portfolio/pages/en/software/projects/embedded-internet-radio.md +++ b/portfolio/pages/en/software/projects/embedded-internet-radio.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 3" language: "en" title: "Embedded Internet Radio" +year: "2014" --- This project gave me the opportunity to work with the SIR120 internet radio made by the company StreamIT. The radio involved connecting to exiting internet streams and interfacing with the LCD and buttons on the device. The code was written in C. diff --git a/portfolio/pages/en/software/projects/festival-simulator.md b/portfolio/pages/en/software/projects/festival-simulator.md index 69786fa..63ada1c 100644 --- a/portfolio/pages/en/software/projects/festival-simulator.md +++ b/portfolio/pages/en/software/projects/festival-simulator.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 2" language: "en" title: "Festival Simulator" +year: "2013" --- A team project in which a festival can be simulated to view how crowds of people behave. It was named: "SimFest-Tycoon". The user can build festivals, roads, snackbars and assign time periods when a band plays at a stage. The project was programmed in Java. A school project made by four people. The software allows users to build their own festival grounds. Snackbarstands, toilets, roads and stages can be placed to view how people form crowds and bottlenecks in certain areas. The user can also assign a band that plays for a certain time at a stage using a scheduler. diff --git a/portfolio/pages/en/software/projects/ios-airports.md b/portfolio/pages/en/software/projects/ios-airports.md index cf8c592..ae9392a 100644 --- a/portfolio/pages/en/software/projects/ios-airports.md +++ b/portfolio/pages/en/software/projects/ios-airports.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 4" language: "en" title: "iOS Airports" +year: "2015" --- A mobile iPhone application using a SQLite database to display airports around the world. With this project I got to experience working with Xcode and Swift to develop iOS mobile applications. diff --git a/portfolio/pages/en/software/projects/kanji-application.md b/portfolio/pages/en/software/projects/kanji-application.md index 6458d13..8a857a9 100644 --- a/portfolio/pages/en/software/projects/kanji-application.md +++ b/portfolio/pages/en/software/projects/kanji-application.md @@ -2,6 +2,7 @@ logosub: "Software developer" language: "en" title: "Kanji flashcard Android application" +year: "2018" --- In my free time I like to learn Japanese. I am married with someone from Japan, so being able talk with her parents in their own language is nice! You also pick up much of the culture through learning the language. diff --git a/portfolio/pages/en/software/projects/metroid-shooter.md b/portfolio/pages/en/software/projects/metroid-shooter.md index c5b9fc4..18a8d21 100644 --- a/portfolio/pages/en/software/projects/metroid-shooter.md +++ b/portfolio/pages/en/software/projects/metroid-shooter.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 2" language: "en" title: "Metroid Horizontal Shooter" +year: "2013" --- A simple Java 2D game using Nintendo's Metroid franchise sprites. This was a school project. This little game I made to practice programming with 2D graphics. It slowly gained more and more features like extra weapons and different levels, because I really enjoyed working on this project. diff --git a/portfolio/pages/en/software/projects/raspberry-pi-jukebox.md b/portfolio/pages/en/software/projects/raspberry-pi-jukebox.md index 413cd58..0222d6a 100644 --- a/portfolio/pages/en/software/projects/raspberry-pi-jukebox.md +++ b/portfolio/pages/en/software/projects/raspberry-pi-jukebox.md @@ -2,12 +2,15 @@ logosub: "Hardware tweaker" language: "en" title: "Raspberry Pi Jukebox" +year: "2016" --- I used a Raspberry Pi to stream internet radio. Python and Flask were used to create a simple website interface that resided on the Raspberry Pi using the Apache web engine. This simple site had buttons to control the LEDs, the station to stream and to adjust the volume. The LEDs were controlled using an Arduino and a Maxim MAX7219 IC. +I posted a tutorial about this long ago on Instructables: instructables.com/Raspberry-Pi-Internet-Radio-With-Flask +
Raspberry Pi. The game is played with regular keyboard and a custom joystick setup. The game was programmed in Python using the PyGame library. This project was mainly to create small game and interface it with a custom hardware setup. The setup uses an analog joystick to control the player's helicopter. An ADC (Analog Digital Converter) samples the analog data into digital data so that the Raspberry Pi (version 1, type B) could parse the data. diff --git a/portfolio/pages/en/software/projects/teslamaze.md b/portfolio/pages/en/software/projects/teslamaze.md index 34a5505..e1febe8 100644 --- a/portfolio/pages/en/software/projects/teslamaze.md +++ b/portfolio/pages/en/software/projects/teslamaze.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 1" language: "en" title: "TeslaMaze" +year: "2012" --- ## Gaming, Woodcraft and Teamwork! diff --git a/portfolio/pages/en/software/projects/wifi-extension-board.md b/portfolio/pages/en/software/projects/wifi-extension-board.md index 6dc517f..37621b7 100644 --- a/portfolio/pages/en/software/projects/wifi-extension-board.md +++ b/portfolio/pages/en/software/projects/wifi-extension-board.md @@ -2,6 +2,7 @@ logosub: "Avans TI internship" language: "en" title: "Wi-Fi extension board" +year: "2014" --- This project was part of my internship at Dazzletek in Breda. They no longer exist and the name "Dazzletek" now seems to belong to an American company. They created intelligent lighting control solutions and were part of Vitelec. My assignment was to create a prototype that would allow a device to communicate over Wi-Fi. I worked with a PIC microcontroller. diff --git a/portfolio/pages/en/software/projects/windows-10-cookbook.md b/portfolio/pages/en/software/projects/windows-10-cookbook.md index 1a96383..7fd8e14 100644 --- a/portfolio/pages/en/software/projects/windows-10-cookbook.md +++ b/portfolio/pages/en/software/projects/windows-10-cookbook.md @@ -2,6 +2,7 @@ logosub: "Avans TI student, year 4" language: "en" title: "Windows 10 Cookbook" +year: "2015" --- This UWP application was built with C# and XAML. diff --git a/portfolio/site.hs b/portfolio/site.hs index e04d54c..58d0ee0 100644 --- a/portfolio/site.hs +++ b/portfolio/site.hs @@ -198,6 +198,77 @@ main = hakyll $ do >>= loadAndApplyTemplate "templates/default.html" softwareCtx >>= relativizeUrls + match (fromList + [ "nl/code/blazor.html" + , "jp/code/blazor.html" + , "en/code/blazor.html" + ]) $ do + route idRoute + compile $ do + identifier <- getUnderlying + metadata <- getMetadata identifier + let language = lookupString "language" metadata + let lang = fromMaybe "en" language + + blazorPages <- loadAll "pages/en/software/code/blazor/*" + + let softwareCtx = + listField "blazorPages" (postCtx language) (return blazorPages) <> + langDict lang <> + defaultContext + + pandocCompiler + >>= loadAndApplyTemplate "templates/code.html" softwareCtx + >>= loadAndApplyTemplate "templates/default.html" softwareCtx + >>= relativizeUrls + + match (fromList + [ "nl/code/elm.html" + , "jp/code/elm.html" + , "en/code/elm.html" + ]) $ do + route idRoute + compile $ do + identifier <- getUnderlying + metadata <- getMetadata identifier + let language = lookupString "language" metadata + let lang = fromMaybe "en" language + + elmPages <- loadAll "pages/en/software/code/elm/*" + + let softwareCtx = + listField "elmPages" (postCtx language) (return elmPages) <> + langDict lang <> + defaultContext + + pandocCompiler + >>= loadAndApplyTemplate "templates/code.html" softwareCtx + >>= loadAndApplyTemplate "templates/default.html" softwareCtx + >>= relativizeUrls + + match (fromList + [ "nl/code/haskell.html" + , "jp/code/haskell.html" + , "en/code/haskell.html" + ]) $ do + route idRoute + compile $ do + identifier <- getUnderlying + metadata <- getMetadata identifier + let language = lookupString "language" metadata + let lang = fromMaybe "en" language + + haskellPages <- loadAll "pages/en/software/code/haskell/*" + + let softwareCtx = + listField "haskellPages" (postCtx language) (return haskellPages) <> + langDict lang <> + defaultContext + + pandocCompiler + >>= loadAndApplyTemplate "templates/code.html" softwareCtx + >>= loadAndApplyTemplate "templates/default.html" softwareCtx + >>= relativizeUrls match (fromList [ "index.html" diff --git a/portfolio/templates/code.html b/portfolio/templates/code.html new file mode 100644 index 0000000..cf66e65 --- /dev/null +++ b/portfolio/templates/code.html @@ -0,0 +1,27 @@ +
+
+

Code page

+
+
    + $if(blazorPages)$ + $for(blazorPages)$ +
  • $title$
  • + $endfor$ + $endif$ + + $if(elmPages)$ + $for(elmPages)$ +
  • $title$
  • + $endfor$ + $endif$ + + $if(haskellPages)$ + $for(haskellPages)$ +
  • $title$
  • + $endfor$ + $endif$ +
+
+ $body$ +
+
diff --git a/portfolio/templates/software.html b/portfolio/templates/software.html deleted file mode 100644 index 08369d8..0000000 --- a/portfolio/templates/software.html +++ /dev/null @@ -1,4 +0,0 @@ -

Projects

-$for(projects)$ -

$title$

-$endfor$ \ No newline at end of file