April Project End Report

This time life was too busy and April project remained a dream. Better luck next time, I hope

Conclusion of the the April Project

From the April project setup:

The April project team is "templates" and "documentation". My first goal is to create a template for a command line tool. I often have a need to create a command line tool and I would be much faster and had more of them, if I had a pre-thought structure to follow. I have also decided to us Go lang for my command line tools in the future. While my brain thinks in Python, the "single deployable binary" is extremely convenient. I have a couple of ideas that probably two gets implemented in April.

I also will document and formalize a template for a Google Cloud Function projects (at least for Python, stretch goal for Go lang as well). timokoola/wordformemailreport is a good basis for more generic template.

And finally, I want to document the architecture of the word form collector in a single post I can use as a landing page in the future.

Sometimes life is more interesting than coding and it was this time. I like this project setup and I think it will be done some time later this year. For May I have other plans...

May Project

I have been slowly building this tool for collecting Finnish noun forms see e.x. February project post. Now it is finally time to start building the UI. This month's goal is to build basics of it and have it running in Google Cloud. I plan to build it using Django. More of that soon.

March Project End Report

This month I changed my initial plan and went on and continued my February project – Finnish Word Form Collector I added several new components to the system. As I reminder my goal is to generate big enough dataset to test a library that generates Finnish noun forms (e.g. if you asked for plural genitive of 'koira' it would return 'koirien'). The bulk of this data has so far come from the Finnish books of Project Gutenberg.

This system now has five services running in GCP

Report of new word forms found. Report generated at 2023-03-31 04:07:06.

Total: 383627

Total last 7 days: 298

Total last 24 hours: 60

Prompts for 2023-03-31T00:07:07.942637

  • nugaa Astevaihtelu: _ -> _ (plural nominatiivi nimentö mikä? kuka? monikossa -t)

  • tappo Astevaihtelu: p -> pp, pp -> p (singular elatiivi sisäeronto mistä? kenestä? -sta, -stä)

  • susijahti Astevaihtelu: t -> d, d -> t (plural elatiivi sisäeronto mistä? kenestä? -sta, -stä)

  • markka Astevaihtelu: k -> kk, kk -> k (singular genetiivi omanto minkä? kenen? -n, -en, -in, -den, -ten, -tten)

  • kookosvoi Astevaihtelu: _ -> _ (singular ablatiivi ulkoeronto miltä? keneltä) -lta, -ltä)

  • kajuutta Astevaihtelu: t -> tt, tt -> t (singular genetiivi omanto minkä? kenen? -n, -en, -in, -den, -ten, -tten)

  • askellin Astevaihtelu: lt -> ll, ll -> lt (plural adessiivi ulko-olento millä? kenellä? -lla, -llä)

  • taival Astevaihtelu: p -> v, v -> p (singular inessiivi sisäolento missä? kenessä? -ssa, -ssä)

  • säppi Astevaihtelu: p -> pp, pp -> p (singular partitiivi osanto, eronto mitä? ketä? -a, -ä, -ta, -tä)

  • syli Astevaihtelu: _ -> _ (plural instruktiivi keinonto miten (keinoa, välinettä) -n)

Sent by the New Word Forms Report Generator

The final function collects the existing data and send it in to my email inbox every morning.

Additionally, I created extremely low effort hack to generate an RSS feed timokoola/quickrssfrommd: Repository that contains scripts to generate RSS feed from source markdowns. I use this to add new word forms to the system until I have an editor UI in my use.

Conclusion of the March project

I am decently happy about the results and the functionality of the system. It now runs mostly on its own and generates me roughly 50-60 new word forms a day with zero effort (and when I add word forms manually to RSS I get way more). I also got pretty comfortable with Google Cloud Function and Cloud Run. The monthly cost of the system is roughly 30 euro cents and most of that is object storage cost. I have now all the pieces in place to start the editor project later on.

April Project

The April project team is "templates" and "documentation". My first goal is to create a template for a command line tool. I often have a need to create a command line tool and I would be much faster and had more of them, if I had a pre-thought structure to follow. I have also decided to us Go lang for my command line tools in the future. While my brain thinks in Python, the "single deployable binary" is extremely convenient. I have a couple of ideas that probably two gets implemented in April.

I also will document and formalize a template for a Google Cloud Function projects (at least for Python, stretch goal for Go lang as well). timokoola/wordformemailreport is a good basis for more generic template.

And finally, I want to document the architecture of the word form collector in a single post I can use as a landing page in the future.

Finnish Word Forms - Month End Report

So, the project of this month was:

In February I want a solid, running tool chain that generates me Finnish word forms as a dataset. It also can recognize most urgently needed missing word forms so when the editor is in place, the editor UI can prompt for user to add new word forms.

This was detailed in more detail in Collector Design Post. I am planning to write a proper final design of the system with. Current active code that is running in GCP Cloud run is in the repository timokoola/wordformcollector.

Current status is that I have a collector running and storing feed results to GCP Bucket. I'd say minimum goal was met, I would like to also have two more parts of the system running (one that counts and reports current collection contents and one that generates prompts for feeding the system the word forms it needs), but this is enough to collect me some initial test data before an editor is ready. At the moment I have roughly 380000 word forms for Finnish words. I also have functional code for counting different word forms per noun declination class and word form (e.g. it is possible to say that for words that declinate like "yksi" I am missing plural inessive form).

March Project

Still pondering about March project. My initial thought was:

In March I will have a break from serious stuff and the course Three.js Journey — Learn WebGL with Three.js and perhaps think of something I can share as and end result.

But let's see, I might do something else...

Finnish Word Forms - Collector

So, the project of this month is to:

In February I want a solid, running tool chain that generates me Finnish word forms as a dataset. It also can recognize most urgently needed missing word forms so when the editor is in place, the editor UI can prompt for user to add new word forms.

Presented as a flowchart this looks in high-level like this:

Populate Database from Backup
Read a File
Sanitize Input
Run Voikko
Store to Database
Generate Metrics
Send Report
Backup Database

It looks a lot like a "data pipeline" but I am trying to keep it simple in the beginning. I'll write a command line tool that does all this. Everything will be run inside a Docker container (main reason being getting Voikko to run on Mac is hard, so for local testing I will need Docker, I have not fixed how this tool is run in the cloud yet). I will use MongoDB as a database for this phase for simple reason I've been using quite a bit lately. Additionally, even if the editor will have a relational database at this point I am not quite sure about the final schema.

Data flow in detail

Populate Database from Backup

As a first step the database is regenerated from the backup. The command line tool will have configuration option to select the location of the database backup. The initial database contains words extracted from the Gutenberg project Finnish books. I had created scripts for that earlier and I am now reusing and adapting those for this purpose.

Read a File

The second step is to ingest a file of Finnish text. Eventually I plan to support reading in RSS feeds. Before editor I plan to have a way to add words and thought it might be easiest to provide a RSS feed of those myself.

Sanitize Input

This step is easy, split text to words, remove punctuation, and make everything lower case.

Run Voikko

This step is also a pretty straightforward. Running Voikko produces output like this (example input "ruskeihin" - plural Illative case of "ruskea" - "brown"):

{
"BOOKWORD": "ruskeihin",
"BASEFORM": "ruskea",
"CLASS": "nimisana_laatusana",
"COMPARISON": "positive",
"FSTOUTPUT": "[Lnl][Xp]ruskea[X]ruske[Sill][Nm]ihin",
"NUMBER": "plural",
"SIJAMUOTO": "sisatulento",
"STRUCTURE": "=ppppppppp",
"WORDBASES": "+ruskea(ruskea)"
}

Here important for our use case are "SIJAMUOTO" and "NUMBER". We store all the additional information as well for possible future uses.

In this phase we also add information from kotus word list Kaino - Kotimaisten kielten keskuksen nykysuomen sanalista. This list contains a list of words along with their type of noun declination (there are 50 different types for nouns) and their constant gradation type (e.g. for Finnish word "taive" letter "v" turns into "p", plural genitive form of "taive" is "taipeiden"). At the end of this phase all words that we can find from Kotus world list we store following type of information:

{
"av": "_",
"tn": 15,
"word": "ruskea",
"BOOKWORD": "ruskeihin",
"BASEFORM": "ruskea",
"CLASS": "nimisana_laatusana",
"COMPARISON": "positive",
"FSTOUTPUT": "[Lnl][Xp]ruskea[X]ruske[Sill][Nm]ihin",
"NUMBER": "plural",
"SIJAMUOTO": "sisatulento",
"STRUCTURE": "=ppppppppp",
"WORDBASES": "+ruskea(ruskea)"
}

In addition to information we got from Voikko we add Consonant gradation type in field "av" and the declination type in the field "tn". While for the moment we are only interested in noun forms (tn values from 1 to 52), we just store everything we encounter just in case.

Store to Database

This step is pretty straightforward, we add all records that we generated in the previous step. We might store information for all the new words for metrics step but that might be available also from the database.

Generate Metrics

I have not figured out this step yet, but I would at least want to get number of new forms we have seen during this step.

Generate and Send Report

Report is generated based on the contents of database. At this step we want to know what are the most urgently needed missing forms to possibly input themselves from the editor or through RSS feed.

Backup database

To make it possible to build up a database from scratch, we backup the database contents at this step.

Next Step

Now that we have a design in place and we have some data, the next step is to explore data we have collected from the Gutenberg books. After that we will figure out the metrics and reporting steps and after that we are ready to write the final script. Final step is to put that script running in GCP environment in regular intervals.

Genuary Results & February Project

Two months ago I wrote this about hobby projects:

  • Ship or abandon something monthly
  • Write a simple specification at the start to list things that I want to achieve (use case/problem to solve, what technologies and why I chose)
  • Write one starter blog post and one concluding blog post for a month
  • Keep up a backlog of ideas and things to learn, and review it often. Be conscious about adding stuff to the backlog. Also, let go of ideas that never seem to get done, write a blog post about the idea and move on.

How I Think about Hobby Projects

This is the concluding post for month of January which I did some Genuary prompts (wrote two posts about them), but eventually got too busy with new work-work project that needed to abandon them and I am moving on with a new project that has been brewing with me for long. I even have some things already written for it and running in Google cloud.

February Project

I am interested in writing a library that can form declinated Finnish noun forms from a base form. For instance, one could ask for "plural genitive of 'koira'" and it would return you 'koirien'. But I am getting ahead of myself, first we need a lot of words to test the eventual library. You may have heard that Finnish noun declination is a bit complicated but also it is pretty well documented and there are existing tools and a pretty comprehensive list of Finnish words and what their declination is.

Supporting Material

  • Kotus - The Institute for Languages of Finland publishes a list of Finnish words associated with the rule of their declination that is available here Kaino - Kotimaisten kielten keskuksen nykysuomen sanalista. This is a primary source for building this things
  • Voikko is a Finnish language toolset that includes a function to detect which form a word is in Voikko – Free linguistic software for Finnish. This tool is will be a big part of the toolchain for generating the needed test set.
  • Project Gutenberg has been by my source for word forms for my initial tests but I will expand this to more modern open sources of text and add a tool to add test words personally. Eventually, I want to have an editor for adding individual missing words and to use as a visual aid for testing the library.

The February project goals

In February I want a solid, running tool chain that generates me Finnish word forms as a dataset. It also can recognize most urgently needed missing word forms so when the editor is in place, the editor UI can prompt for user to add new word forms.

The secondary goal is to prepare for GCP certification test I will have to renew before end of April. I will build using GCP tools such as Cloud Functions, Big Query (excellent for making queries to decent size data set) and perhaps others. I am planning to use Django for the editor, but that will be coming perhaps as the April project. At the end of this month I want to have:

  • Automated constantly running "word form collector" that reports the size of the dataset and request for some missing words daily. This will be either a Python or a Go script running as one or more Google Cloud Function

Upcoming months

I have not set up my plans to far ahead but I have planned for March and April. In March I will have a break from serious stuff and the course Three.js Journey — Learn WebGL with Three.js and perhaps think of something I can share as and end result. In April I want to come back to the word forms and come up with the editor. For May, I have no plans but I want it to be another fun month like Three.js March.

Genuary Day 3

Here is my entries for GENUARY 2023 – day three - Glitch.

I took day 1 expanding circles, made the circles standing up ovals, added filter on top of it to add some noise, and made the animation ease "rough" and go back forth (i.e. gsap yoyo: true) to achieve this kind of chaotic flaming eye that periodically collapses in.

See the Pen genuary day 3 glitch with day1? by Timo Koola (@tkoola) on CodePen.

Genuary Day 1 & 2

Here are my entries for GENUARY 2023 – days one and two.

Prompt for Day one is 'Perfect loop / Infinite loop / endless GIFs'. I took the assignment with the following:

  • Circles that expand from the center "simple fly through space effect"
  • Fly through the HSV colour space, every circle is 3.6 degrees clockwise in Hue from the previous one. In effect, fly through 100 circles to come back to where you started
  • Record a GIF (I did, it was way too big to be shared)
  • Technologies used: GSAP - GreenSock, SVG, simple and fast.

You can see the end result at:

See the Pen Genuary day 1 - perfect loop by Timo Koola (@tkoola) on CodePen.

Future ideas:

  • The loop is a bit off, but I ran out of my own timebox, might want to fix that
  • I'd like to redo this as a shader
  • I wanted to add a sparkle/marker at the point of the circle where the current circle colour is in at hue degrees. The sparkle would rotate slowly full 360 degrees, but also ran out of time with this one.

Day 2 – Made in 10 minutes

My setup:

  • Take off existing CSS-doodle Codepen I had laying around
  • Change the palette, and tune it for ten minutes, hands off the keyboard

Picked up a "desert" palette from Coolors - The super fast color palettes generator!:

,,,,Exported from Coolors.cohttps://coolors.co/ffa86b-ffba78-ffcc84-ffd991-ffe69e

Here is my original Codepen css doodle patterns, rotating with gsap:

See the Pen css doodle patterns, rotating with gsap by Timo Koola (@tkoola) on CodePen.

And now a cup of warm tea and start coding...

...and done. Took me 9 minutes, but like every ten minute project it came with a lot of preparation:

See the Pen css doodle patterns, rotating with gsap by Timo Koola (@tkoola) on CodePen.

With more time I would have added a stagger there for some more interesting motion

While doodling around these two items I also came up with solution for day 3 prompt glitch, but more about that tomorrow.

How I Think about Hobby Projects

I've done some thinking about hobby projects and how to organize them. I doodle around quite a lot, but I would be happier if there were some structure around the things I do outside my nine-to-five job.

Premises:

  • I run a one-person consulting company, only one that cares about my skill development is me
  • I consider all coding to be work, even the fun stuff.
  • Skills I can sell differ from skills I like to exercise. Hobby projects allow me to do fun stuff and build skills I can sell down the line.
  • Sometimes, I want to explore product concepts, even MVPs, for future companies, but my primary motivation is that I enjoy coding. No, scratch that, I love to program. It is the intersection of humanities, math, serving people, creativity, and having fun. Don't let anyone tell you otherwise.
  • I want to ship stuff (even if shipping meant just that I wrote some code and a blog post) and not this stuff to stress me out too much
  • I don't want too much process, but I like deadlines, measurable outcomes, and rules for abandoning projects.
  • As a software professional, I take pride that I can be thrown to any project and will provide value. I choose projects based on what I have yet to experience. While this is fun and works for my brain, I could use a solid go-to tech stack. I envy people who can bang the keyboard and build a reliable web app in a working day. One of my goals is to make sure that, over time, I have this go-to toolkit.

With these premises, I've come up with these rules:

  • Ship or abandon something monthly
  • Write a simple specification at the start to list things that I want to achieve (use case/problem to solve, what technologies and why I chose)
  • Write one starter blog post and one concluding blog post for a month
  • Keep up a backlog of ideas and things to learn, and review it often. Be conscious about adding stuff to the backlog. Also, let go of ideas that never seem to get done, write a blog post about the idea and move on.

I will evolve these rules over time. I practised this a bit in November with #NaNoGeMo (see NanoGenMo 2022 - Start). I use December to prepare for my first actual month of this process and to ensure my Obsidian operation and plugins are up to date.

The goal is to come up with a plan for January's project, understand the technologies I need, write a blog post about my Obsidian use, and be ready to publish a long blog post on January 1 on my January project.

NanoGenMo 2022 - Day 17 - Another Discussion with GPT-3

This is another discussion with GPT-3 where I try techiques to keep a text flowing. Everything in bold is my prompts, and the rest is generated by GPT-3.

Rowan sat under a tree exhausted. The fight with the dragon only made him more weary. He could barely open his eyes.

Suddenly he heard a rustling in the bushes. He leapt to his feet and drew his sword, preparing for another battle. But it was just a small rabbit.

He let out a sigh of relief and sheathed his sword. He wanted nothing more than to lay down and rest, but he knew he had to keep moving. He had to find the others and warn them about the dragon. Even if it was mortally wounded it could still pose a threat.

He forced himself to stand up and started walking, but he could barely put one foot in front of the other. He felt like he was going to collapse at any moment.

Suddenly, he heard the sound of wings flapping. He turned around and saw the dragon, flying towards him, its mouth open wide, ready to devour him. Dragon hissed in pain and anger.

Rowan tried to run, but he was so weary that he could barely move. The dragon was upon him in an instant. It snatched him up in its teeth and started to fly away.

Rowan knew that he was going to die. There was no escape from the dragon's clutches. He just hoped that his death would be quick and painless. But all of a sudden, he felt himself falling.

The dragon had been shot by an arrow and it was dropping him from its mouth. He hit the ground hard, but he was still alive. He looked up and saw the dragon flying away, an arrow lodged in its side.

Someone had saved him. He didn't know who it was, but he was grateful. He was too tired to move, so he just lay there, hoping that someone would come and find him. And then he passed out.

He slowly came to and found himself in a strange place. He was in a huge cavernous room with a high ceiling. Dozens of people were milling around and there was a fire burning in a pit in the center of the room.

He tried to get up, but he was still weak from his ordeal. Someone came over to him and helped him sit up.

"Are you alright?" the man asked.

"I think so," Rowan said. "What is this place?"

"This is the dragons' lair," the man replied. "You were lucky that we found you when we did. The dragon would have eaten you if we hadn't killed it."

Rowan was shocked. He had been in the dragon's lair all along. He was surrounded by the people who had killed the dragon. He should have been scared, but he wasn't. He felt safe with these people.

"Thank you for saving me," he said.

"Don't thank us," the man said. "Thank her."

He pointed to a woman across the room. She was standing in front of the fire, her back to them. Rowan couldn't see her face, but he knew who she was. He had seen her before, in his dreams.

"The Dragon Slayer," he whispered.

"Yes," the man said. "Her name is Sarah."

Rowan felt a sense of awe as he looked at her. She was the one who had saved him. She was the one who had killed the dragon.

He wanted to talk to her, to thank her, but he was too afraid. He didn't know what to say. So he just watched her from across the room, wondering who this mysterious woman was.

Next morning, Rowan was taken to meet Sarah. She was just as he had seen her in his dreams. She was beautiful, but there was something else about her that he couldn't quite put his finger on.

"Thank you for saving me," he said.

"You're welcome," she replied. "But I didn't do it for you. I did it for the dragon."

"The dragon?" Rowan was confused. "Why would you want to save it?"

"Dragons are misunderstood creatures," she explained. "They're not all evil. Some of them are actually quite gentle."

"But this dragon was different," Rowan said. "It was going to kill me."

"I know," Sarah said. "But I couldn't just stand by and watch it happen. I had to do something."

Rowan looked at her in wonder. He had never met anyone like her before. She was brave and selfless and he knew that he would never forget her.

Rowan spent a week in the camp and then he set off on his own again. But this time he wasn't alone. He had made a new friend, one who would always be there for him, even when he was dreaming.

Chapter 2 - Capital

Rowan was standing of the deck of a ship, looking out at the vast ocean. It was a beautiful day and the sun was shining. He was on his way home, back to his home country after being away for many years.

He was excited to see his family again and to finally be home. But he was also nervous. He had changed so much in the years that he was away. He wasn't sure if his family would even recognize him.

As the ship approached the shore, he could see the capital city in the distance. It was just as he remembered it. The city was bustling with people and there was a feeling of excitement in the air.

He disembarked the ship and made his way through the streets. He was surprised at how much the city had changed. There were new buildings and new faces. But he soon found his way to his old home.

He knocked on the door and waited. He heard footsteps inside and then the door opened. His mother was standing there, looking at him with surprise.

"Rowan?" she said, disbelief in her voice.

"Yes, it's me," he replied.

She pulled him into a hug and he could feel her shaking.

"I thought you were dead," she said.

"I'm sorry," he replied. "I should have written to you."

"It's okay," she said,pulling away from him. "I'm just glad you're home."

Rowan looked around the house and saw that it was exactly the same as he remembered it. Nothing had changed. It was like he had never left.

"Where's Father?" he asked.

"He's out," she replied. "He'll be back soon."

"I'll go and find him," Rowan said.

He left the house and made his way through the streets. He was surprised at how many people he recognized. He had been away for so long, but it seemed like nothing had changed.

He soon found his father's workshop. It was a small building, but it was always full of people. His father was a blacksmith and he was very good at his job.

Rowan walked in and saw his father working at the forge. He walked up to him and tapped him on the shoulder. His father turned around and looked at him in disbelief.

"Rowan?" he said.

"Yes, it's me," Rowan replied.

His father pulled him into a hug and patted him on the back.

"I thought you were dead," he said.

"I'm sorry," Rowan replied. "I should have written to you."

"It's okay," his father said,pulling away from him. "I'm just glad you're home."

"I've missed you," Rowan said.

"I've missed you too, son," his father replied.

"I'm sorry I didn't write," Rowan said. "I was just so busy."

"It's okay," his father said. "I understand. I'm just glad you're home."

Rowan stayed with his family for a few weeks and then he decided it was time to move on. He had seen all he needed to see in the capital and he was ready for a new adventure.

He said goodbye to his family and set off into the unknown. He had no idea where he was going, but he was excited to find out. He was finally living the life he always wanted to live. And he was going to make the most of it.

summarize story so far

Rowan is a young man who was away from his home country for many years. He returns home and is surprised to see how much the city has changed. He soon finds his father and they have a heartwarming reunion. Rowan decides to set off on a new adventure.

What happened to Sarah?

Sarah is the woman who saved Rowan from the dragon. She is brave and selfless and he knows that he will never forget her.

Will Rowan and Sarah meet again?

It is possible that Rowan and Sarah will meet again.

Rowan saw a tree that was very special, what was that tree?

The tree was special because it was the tree that Sarah was standing in front of when he first saw her.

After meeting his father Rowan decided to set of an a new adventure. On a crisp morning after the harvest festival he packed his packs, kissed his horse good bye and set off into the wide open world.

NanoGenMo 2022 - Day 16 - Discussion with GPT-3

I am trying an idea that I would offer GPT-3 a pretty comprehensive prompt per chapter describing the premise of the chapter, terrain, characters, and some kind of a skeleton run through of the chapter. I also want everything related to the world be contextual knowledge. While figuring that out I had a following discussion with GPT-3 about a chapter contents of fantasy novel where the protagonist fights dragon. It feels like I am still missing something about the prompts. Here everything quoted is GPT-3 and everything is else was written by me.

Discussion with GPT-3

generate a structured description of a fantasy book chapter progression for a mid-level staff writer

  1. The chapter opens with the staff writer's protagonist in the middle of a battle with a dragon.
  2. The protagonist is victorious, and the dragon is slain.
  3. The protagonist is celebrated by the people of the kingdom for their heroic deed.
  4. The staff writer's protagonist is then approached by the king, who offers them a position on his court.
  5. The protagonist accepts, and begins their new life as a member of the king's court.
  6. The chapter ends with the staff writer's protagonist reflecting on their new life, and the challenges that lie ahead.

Tell me about the protagonist's battle with the dragon.

The protagonist is in the middle of a battle with a dragon. The dragon is a fearsome creature, and the protagonist is having a tough time. However, they eventually triumph, and the dragon is slain. This victory is celebrated by the people of the kingdom, and the protagonist is hailed as a hero.

What is the name of the protagonist?

The name of the protagonist is not mentioned in the chapter progression.

Come up with name suggestions for a fantasy book protagonist

  1. Aric
  2. Eleri
  3. Finn
  4. Rowan
  5. Aelin

Describe the character, looks and personality of Rowan, the fantasy book protagonist

Rowan is a strong and courageous character who has a heart of gold. They are always fighting for what is right, and they have a deep sense of justice. Rowan is also very loyal, and they would do anything for their friends and allies. They are a fierce warrior, and they are not afraid of anything. Rowan is also very intelligent, and they are always thinking ahead. They are always prepared for anything that comes their way.

Invent names for a dragon

  1. Drago
  2. Ember
  3. Inferno
  4. Smoke
  5. Sulfur

Describe the character, looks and personality of Sulfur, the dragon that fought Rowan

Sulfur is a large and powerful dragon with a fearsome appearance. They are ruthless and cruel, and they enjoy nothing more than causing destruction. They are also very intelligent, and they are always one step ahead of their enemies. Sulfur is a fierce and powerful opponent, and they are not to be §underestimated.§

What colour is Sulfur? What does it smell like?

Sulfur is a bright red colour, and they smell of smoke and brimstone.

Generate a chapter of a Fantasy novel that contains the following elements:

  1. Rowan is in the middle of a battle with a dragon Sulfur. Describe the scene and surroundings
  2. In six paragraphs tell how Rowan is victorious, and the dragon is slain.
  3. Rowan is celebrated by the people of the kingdom for their heroic deed.
  4. Rowan is then approached by the king, who offers them a position on his court
  5. Rowan accepts and begins their new life as a member of the king's court.
  6. The chapter ends with Rowan reflecting on their new life and the challenges ahead. two paragraphs

The scene is chaotic as Rowan and the dragon Sulfur battle. The dragon is huge and powerful, and Rowan is having a tough time. However, they eventually triumph, and the dragon is slain. This victory is celebrated by the people of the kingdom, and the protagonist is hailed as a hero.

Rowan is then approached by the king, who offers them a position on his court. Rowan accepts and begins their new life as a member of the king's court. The chapter ends with Rowan reflecting on their new life and the challenges ahead.

Tell me more about the fight between Rowan and Sulfur

Sulfer is a large and powerful dragon, and they are very difficult to defeat. Rowan is a skilled warrior, and they are very intelligent. They are able to think ahead, and they are always prepared for anything. This allows them to eventually triumph over the dragon, and they are able to slay it.

Write a dialogue between Rowan and Sulfur in the heat of the battle

Sulfur: You will never defeat me, weakling!

Rowan: We'll see about that. I'm not afraid of you.

Sulfur: You should be. I'm the most powerful dragon in the world.

Rowan: I don't believe that. I know I can defeat you.

Sulfur: We'll see about that.

A bard meets Rowan in a public house and offers him ale to tell the story.

Bard: Hey there, Rowan! I heard about your battle with the dragon Sulfur. That was quite a feat!

Rowan: It was nothing, really.

Bard: Nonsense! I'm sure it was quite a harrowing experience. Would you mind if I bought you an ale and heard the story?

Rowan: That would be great, thank you.

Bard: So, tell me what happened.

Rowan: Well, it was chaotic. The dragon was huge and powerful, and I was having a tough time. However, I eventually triumphed, and the dragon was slain.

Bard: That's amazing! I'm sure the people of the kingdom were very grateful.

Rowan: They were. The king even offered me a position on his court.

Bard: That's quite an honor.

Rowan: It is. I'm looking forward to the challenges ahead.

NanoGenMo 2022 - Day 7 - Thinking of Generators

Yesterday and today I've read about the history of story generators. One particularly good summary of the history of these algorithms is Story Generator Algorithms | the living handbook of narratology. Here I lifted some ideas to try. My basic model will be this:

  • Generate characters for the story, both the main charaters. Figure out attributes and how it affects the dynamic between characters
  • Generate terrain and weather. While I hope I would have time to generate full on world with varying terrains, I think will just pick some existing world and draw a some kind of route on it and pick chapter scenery from that. Same goes for weather, I will pick weather that fits the timeline of the story. Relatively easy way would be to start from Spring and end somewhere in late Autumn
  • Generate high level chapter elements e.g. conflict, location, weather, encounters for the book
  • For each chapter generate more detailed arc e.g setup, conflict, after math, dialogue, update the world and character state (I am thinking this as a RPG campaign of sorts)
  • Come up with some scoring system for a story (generate a bunch of them and pick the most 'exciting' story based on the score)

When this kind of chapter generator is done, finalize the text with GPT-3.

NanoGenMo 2022 - Day 2 - Story outline

To make generation as easy as possible I have chosen following structure for the story:

  • Fantasy travel story, with a group of people, going there (whatever it is)
  • Generate some place names, environments, terrain, heroes, and come up with a system to generate events along the way
  • Trip is one way, after the journey, the group is a different place, probably lost some members and solved something

Putting this to a prompt for GPT-3 I came up with "Synopsis of a fantasy novel of a group of heroes travelling through a fantasy land where they meet many challenges, unexpected friends and dangerous foes."

With that prompt GPT-3 generated us:

The Questing Heroes are a band of adventurers who travel through the fantastical land of Evoria, encountering many challenges along the way. They make unlikely friends with some of the strange creatures they encounter, and battle dangerous foes in order to protect the innocent. Along the way, they discover ancient secrets and learn to work together in order to overcome the odds.

Day 3 plan is to create a tracery script to generate some more details about Evoria.

NanoGenMo 2022 - Start

Day 1 today for NanoGenMo. Today's goal are:

  • Set up repository
  • Write first blog post about it (you're looking at it)
  • Decide what to do tomorrow

Goals of the Project

  • Generate a book of 50000 words on Nov 30th, 20 or so chapters
  • Create tools over the course of month to generate characters, description of terrain, plot and chapter level subplots

Non-Goals of the Project

  • No code on Saturdays
  • Book doesn't need to make sense

Goals for Day 2

TIL: Visual Studio Code

Visual Studio Code TIL

My go-to code editor has been Visual Studio Code for the last couple of years. I’ve set it up from scratch the previous week for a new project.

As the project is more closed than most of my customer projects, I use the Foam system as my note-keeping system.

Foam is a personal knowledge management and sharing system inspired by Roam Research, built on Visual Studio Code and GitHub.

You can use Foam for organising your research, keeping re-discoverable notes, writing long-form content and, optionally, publishing it to the web.

Foam | A personal knowledge management and sharing system for VSCode

Today I encountered two different issues with Visual Studio Code that I needed to fix.

Bouncing Ghost Visual Studio Code

The first issue I encountered was caused by a spellright plugin Two icons in the Dock (macOS) · Issue #138838 · microsoft/vscode · GitHub

Setting ’Code’ to Path Resets After Restart

This one was my own doing. I’ve just forgotten to move the application to the Applications folder.

More Complicated Custom Components with Stencil.js

Lately, I've been thinking what custom items I want to add to this blog (+ the My language learning blog) and been kicking tyres of Stencil which according to its own documentation is:

Stencil is a toolchain for building reusable, scalable Design Systems. Generate small, blazing fast, and 100% standards based Web Components that run in every browser.

I pick it for two reasons:

  1. I can build custom web components using Typescript and other modern tools...
  2. ..., but I still can deliver it as a single blob of text, even just embed it in a static web page.

Stencil gets to do this because of the build step and the "just javascript" build target.

I am planning to write about the process here in following weeks. With at least following topics:

  1. Creating a very basic component
  2. Creating tests for that very basic component
  3. Building the said component using Github Actions
  4. Styling the component

Minor Blog Updates

Quick technical update to the blog today. I added two things: RSS feeds and sitemap. Adding an RSS feed to an Eleventy site is pretty straightforward. First, one installs the RSS — Eleventy plugin. Second step is to add following to .eleventyjs:

const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss);

Final bit is to add a file somewhere inside the source tree that renders the feed xml to url /feed.xml. That file contains a skeleton structure of an Atom or RSS feed and nunjucks statements to generate individual feed items. One model can be found in the eleventy documentation RSS — Eleventy.

Adding a sitemap is even more straightforward, one just adds a nunjucks file (again, somewhere) in the project structure that renders the xml for all pages. One thing to remember is to check that none of the urls you don't want to be listed are excluded by using the eleventyExcludeFromCollections option.

One thing still missing from the features I want is the social media share images, but that change requires some design work from me and the technical implementation of the bits required to utilize the @11tyrocks/eleventy-plugin-social-images - npm.

Minimal SCSS Templates

This is something I spotted yesterday and I wanted to have a permanent link back to them.

Simple Setup for Static Site with SCSS

This is pretty neat, one step up from index.html to a more structured web page but still very lightweight. I like to write my CSS in SCSS if given the choice, so this is very useful for me.

Minimum Static Site Setup with Sass | Stephanie Eckles

Minimal Setup for Eleventy

I've been planning to write my own Eleventy starter template and I think I will use this as a starting point https://github.com/5t3ph/11ty-sass-skeleton

Sunday Coding - More alpine.js

Like in the previous post about the Alpine.js this one is a quicky about a tool I created for my language learning blog kolmesanaa.

Clozemaster Study Goals

I use Clozemaster to do my daily Russian language vocabulary practice. I am running through the "Fluency Fast Track" word list that has 19,991 items to study. The goal I've set myself is to have at least started all words on that list by the end of this year. I've used Alfred - Productivity App for macOS to calculate a daily target but it has not been perfectly good. This assumes that every day is the same, and this is markedly not true. Specifically for me, I have more time to study on Saturdays and I would like to have a double the normal quota for that day.

Clozemaster Study Goals Calculated

Let's calculate some examples: Total target is 19,991. I've already started 5,366 words on that list. There are 327 days left of 2022 (as of Sunday the 13th of February) and there are 46 Saturdays still this year. This gets us to 327 + 46 gross days. We get the daily quota with calculation (19,991 - 5366) / (327 + 46) which gives us daily new word quota of 39, 78 Saturdays. I felt like this kind of relatively simple logic would work nicely as an Alpine.js web tool.

Persistence with Alpine.js

Before diving into code I will highlight two things. First, how to persist Alpine models to localStorage. To do this we need to install Persist plugin of the Alpine.js and after that using it will be almost trivial. If we convert the example from the last time to persist the number of button clicks, it will only change very little:

<div x-data="{count: $persist(0)}">
<button x-on:click="count = count + 1">Add</button>
<div x-text="count"></div>
</div>

Now if you keep on clicking we will remember how many times we did it for the next time you visit the page:

Eleventy Partials

Another adjustment I made was to create an Eleventy partial to be included in the templates to make sure Alpine.js plugins and the core are included and in the right order. That code is available in blogtimokooladev/alpinetags.html at master · timokoola/blogtimokooladev.

See it in Action

You can view the initial code I did for this tool at

See the Pen Clozemaster Counter by Timo Koola (@tkoola) on CodePen.

and the final version of the tool is live at kolmesanaa.link Clozemaster tool

Testing out Alpine.js

The template I used to create the site basics included Alpine.js that according to their own words is:

Alpine is a rugged, minimal tool for composing behavior directly in your markup. Think of it like jQuery for the modern web. Plop in a script tag and get going.

Let's try it with a simple button counter example

and that as code is surprisingly simple:

<div x-data="{count: 0}">
<button x-on:click="count = count + 1">Add</button>
<div x-text="count"></div>
</div>

Yes, it feels positively jQuery like. From reading a tutorial to this in 15 minutes.

Oh, and one more thing to my to-do list: fix syntax highlighting.

Minor Blog Updates

I've been slowly tweaking the site and I am almost ready to start writing in proper. Today, I fixed following things:

  • Missing meta tag
  • Dark mode text colour
  • Color of the link in footer

After today, all main styling is done and Lighthouse tests all pass with 100/100/100/100.

Things still to-do:

  • To write the about page (I need to update about pages of all my blogs now see Three Words and Timo Koola)
  • Company info page
  • Systematic checking of the styles on the page

And after that: writing...

Hello World

Hello, this is the first post on my new blog. It won't be much as this is very much "Work in Progress" in the sense of web 0.9. I am this to be a public face of my developer thinking Zettelkasten (my go-to tool at the moment is Obsidian) along with my language learning blog. My micro-blog is hosted by the nice folks at the Micro.blog