5 December 2019

Learn Finnish on a Budget

Start here

For absolute beginners, there is Aura's Finnish Lessons on YouTube. It's a good setup for the subsequent resources. This course is especially good at learning pronunciation.

The entire playlist https://www.youtube.com/watch?v=gQPy8Yjt61s&list=PLmWGG0B5AnRAMCK567_E80zUlLIStl43y

An alternative to the above is FinnishWithAnna. I've included it below Aura's Finnish Lessons because I feel the pronunciation in that course is more thorough. Still, FinnishWithAnna is an amazing resourse which much more content. It's especially good at explaining some of the more advanced topics.


If you like to study from text, I think the grammar section of Finnish for Busy People (Uusi Kielemme) is the best complete grammar resource https://uusikielemme.fi/finnish-grammar/ In my opinion, it's written in a straight forward manner.


Supisuomea is a Finnish language and culture beginners course for all adult learners. The course itself is in Finnish, which makes it a little harder for complete beginners. However, it's in a format that makes it ok for people quite new to the language.

Supisuomea video course https://areena.yle.fi/1-4163476

Supisuomea video episode notes https://yle.fi/aihe/artikkeli/2015/12/15/supisuomea Click the blue button NÄYTÄ NAVIGAATIO and then for example - "Supisuomea, osa 1: Persoonapronominit, verbin persoonataivutus ja adjektiivit". osa 1 means episode 1.

I would review the notes before each episode.


English UK to Finnish Audio Language Course from 50Languages.com

https://www.50languages.com teach languages. This free Finnish audio course contains 100 carefully planned audio lessons. All dialogues and sentences are spoken by native speakers.

English and Finnish https://www.50lingue.com/book2/EN/ENFI/ENFI-all.zip

Finnish only https://www.50languages.com/_1language/FIFI.ZIP

Yle news in easy Finnish

This news program reports current news using uncomplicated language, hence the name. Turn on video text and you have a reading and listening practice.



Lang-8 is a community of native speakers that support your language learning. They have two products, although I recommend the phone app because it's more active.

Website https://lang-8.com/

Phone app https://hinative.com/en-US

27 September 2019

Getting the RP working with your WiFi network

Here's an easy way to get the Raspberry Pi to connect to your network.

Create the file wpa_supplicant.conf and put it in the boot folder of the SD card. Add the following to wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


These settings are entered in your network settings, and the file is deleted after boot.

16 May 2019

Migrate from one host to another with 301 redirects

I recently had to migrate from one host to another. Search engines can be finicky about such things, and you risk SEO penalties. One way to ensure migration goes smoothly is to add this to the top of your .htaccess file in the old host's web root. Note, do this at the same time your new host content goes live.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^([^.:]+\.)*oldsite\.example\.com\.?(:[0-9]*)?$ [NC]
RewriteRule ^(.*)$ http://newsite.example.net/$1 [R=301,L]

The above code tells search engines you have moved host.

If you want to have your new content set up before hand, remember to set the following in the robots.txt file prior, so search engines won't think you are stealing content from your old site.

User-agent: *
Disallow: /

21 October 2018


Note to self: Whenever creating Virtual Hosts in Apache, don't name your dev site .dev

Name it .lan instead. For some reason browsers are forcing .dev domains to access the web as you will see with the https:// prefix.

Installing Magento 2.2 on Ubuntu 18.04

I'm learning Magento and needed to install Magento 2.2 on Linux; however, it's is a bit trickier than normal, due to Magento 2.2 not supporting php7.2 yet (support for 7.2 will come in Magento 2.3).

You will need to install either 7.0.13–7.0.x or 7.1.x, but these versions are not in the default repositories. You can add a ppa from here.

It's also best to read the guide to set it up here.

Then you can run your php7.1 install

Note: make sure you install 7.1 modules only. The dom module is actually the xml module.
leon@leon:/var/www/html/magento$ sudo apt install php7.1-
php7.1-bcmath     php7.1-dev        php7.1-intl       php7.1-odbc       php7.1-snmp       php7.1-xsl
php7.1-bz2        php7.1-enchant    php7.1-json       php7.1-opcache    php7.1-soap       php7.1-zip
php7.1-cgi        php7.1-fpm        php7.1-ldap       php7.1-pgsql      php7.1-sqlite3    
php7.1-cli        php7.1-gd         php7.1-mapi       php7.1-phpdbg     php7.1-sybase     
php7.1-common     php7.1-gmp        php7.1-mbstring   php7.1-pspell     php7.1-tidy       
php7.1-curl       php7.1-imap       php7.1-mcrypt     php7.1-readline   php7.1-xml        
php7.1-dba        php7.1-interbase  php7.1-mysql      php7.1-recode     php7.1-xmlrpc  

along with an extensive list of php7.1 modules magento uses

bc-math (Magento Commerce only for 2.2.0 - 2.2.3. Magento Commerce and Magento Open Source as of 2.2.4.)
gd, ImageMagick 6.3.7 (or later) or both

Copy your magento download folder

sudo cp -r magento /var/www/html/

Set the correct ownership

sudo chown -R leon:www-data /var/www/html/

Read this guide carefully. It's wasn't too clear to me which of the two options were for a local dev environment, but I added myself to the www-data group

Note: To add yourself as a primary or secondary group member of www-data, be aware of the difference between the -g and -G flags. For more info about how being a primary group member works, check out this nice article. If you want a really quick explanation, -g gets you primary membership which means everything you create will be assigned the www-data group instead of your default user group. Secondary membership will give you access, but anything you create will still be your default user group. I think primary is best used if you create another user specifically for magento or web dev. This certainly applies if you are working on a dev server, but I prefer to keep things as is, then modify anything I create for magento with chown.

sudo usermod -a -G www-data leon

and confirm it

groups leon

You should see www-data in your groups.

leon : leon adm cdrom sudo dip www-data plugdev lpadmin sambashare

Set ownership and permissions for www-data

cd /var/www/html/magento && sudo find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} + && sudo find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} + && sudo chown -R :www-data . && sudo chmod u+x bin/magento

Note: After installing php extensions, restart apache for changes to take effect.

service apache2 restart

Finally, visit http://localhost/magento/setup

If you get an HTTP ERROR 500 check your apache error.log for problems.

Update: If you have issues with the layout post install, try the following...

Enable mod rewrite

sudo a2enmod rewrite

and in 000-default.conf (apache2 > sites-available), add this before the closing </VirtualHost> tag.

<Directory "/var/www/html">
    AllowOverride  all

AllowOverride all allows access to .htaccess files, which are important to access for Magento. If you found this solution after googling a similar problem, you'll have to replace 000-default.conf with whatever your VH file is running from.

13 October 2018

Minimal introduction to WebPack

WebPack is a module bundler.

First setup your project to work with node. In your project root, run

npm init

Install webpack locally foreach project. Note: this is the recommended practice. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version.

npm install --save-dev webpack
npm install --save-dev webpack-cli 

Next create a webpack config file (optional) in the root directory.

touch webpack.config.js

Configure that file (optional). Note: by default this is internally set to production.

module.exports = {
    mode: 'development'

Webpack expects ./src/index.js and ./dist/main.js as entry and output points by default. If you need to change this, edit the webpack.config.js and set them up there. See https://webpack.js.org/concepts/ for details.

Change mode: 'production' in webpack.config.js when you want to minimise your project.

Edit your package.json to include webpack in the scripts > build property

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "webpack"

Make sure your index.html (specified in package.json under main:) or whatever main app file, points to the dist output file.

<script src="dist/main.js"></script>

Export your JavaScript files using the latest ES6 syntax to your default /src/index.js file.

To test your project build, run

npm run build

Note the file created in /dist/main.js.

28 September 2018

How to update npm on Windows 8.1

Open PowerShell as Administrator

Find PowerShell: Windows key > Apps (by name) > Windows System (List organiser) > PowerShell

Then right click the PowerShell icon and select Run as Administrator

Execute the 3 commands

Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
npm install -g npm-windows-upgrade

27 February 2018

Learning about set theory

I recently had a problem thinking up a solution for a tricky database query. I'll use the common movie database paradigm to demonstrate it.

A registered user is able to store their preferred genres, so when they search for a movie by preferred genre, they can filter out the movies that don't appear in their preferred genres. As you know, you can have more than one preferred genre, and movies can be multiple genres, for example, romantic comedy. The requirement here, for a user that likes action, comedy, horror, and sci-fi, is not to see romantic comedies in their results because although they like comedies, they haven't specified romantic films on their list. If they wanted to see romantic comedies on their list they would have to also add the genre romantic to the list.

Ok, so the requirements are done with. How do we implement it. Well I got quite stuck to be honest. I started searching, but found it difficult to find a pre-written query for just what I needed. After Googleing "how to think in SQL", I then went on to explore set theory, which I remember doing something with in school, but didn't pair with databases, as people never really even had computers in their home during this time. So I didn't even know what a database was.

Doing some searching, I found this great YouTube tutorial on set theory. During it, I realised I could perhaps get what I needed by subtracting one set from another. Let's look at the tables first though.


In our normalised table structure, we are comparing the foreign key genres_id found in pivot tables movies_genres and users_genres.

Looking at figure 1, if we imagine one movie and one user, you can see we cannot subtract the set movies_genres.genres_id from users_genres.genres_id because the genres_id 3 is left over in movies_genres.genres_id. So movies_genres.genres_id is not a subset of users_genres.genres_id.

Example: Figure 1.

movies_genres.genres_id {1,2,3} 
users_genres.genres_id  {1,2}

In figure 2, we can subtract the set movies_genres.genres_id from users_genres.genres_id because all numbers appear in movies_genres.genres_id that appear in users_genres.genres_id. The 3 you can see in users_genres.genres_id is fine as we don't need to exactly match the query. Here movies_genres.genres_id is a subset of users_genres.genres_id because all numbers appear in the second set.

Example: Figure 2.

movies_genres.genres_id {1,2} 
users_genres.genres_id  {1,2,3}

So how do you test if one set is a subset of another set in MySQL? I've used the in() operator. I'll quote W3Schools for the explanation.

"The IN operator allows you to specify multiple values in a WHERE clause. The IN operator is a shorthand for multiple OR conditions."

To use the in() operator for subtraction, I negate it with not in(). This tests whether there are values left over when comparing genres_id between movies_genres and users_genres (see Figure 1.). This is essentially the subset check. When we can test to see which queries have failed the subset check, we can negate the results to select the movies we want.

So with that, this is how I do it in MySQL.

select * from movies 
where movies.id not in (
    select movies_id from movies_genres mg
    where mg.genres_id not in (
        select genres_id from users_genres ug 
            where ug.users_id = 2


I hope this is correct. I am quite inexperienced with SQL and never really learned it in an academic environment. I hope to solve more difficult MySQL problems with set theory in the future.

29 October 2017

Get a Dart-lang web dev environment installed for Visual Studio Code

This is for Windows, but it's pretty easy to figure out for Linux too.

Open Visual Studio Code and use the addon installer to install the Dart Code plugin from Danny Tuppeny

From the Dart site, download and install the dart-sdk.

Put the location of the sdk on your $PATH variable

C:\Program Files\Dart\dart-sdk\bin

Use Dart's pub tool (Dart's package manager) to install stagehand (the Dart project generator). In the terminal run

pub global activate stagehand

Then add the following to you $PATH (replacing your_username)


You will be using Dartium you view your web apps. Dartium is bundled with the Windows install of the SDK. You can find it in

C:\Program Files\Dart\chromium\chrome.exe 

Create a shortcut for convinience. Note: Dartium will no longer be needed from Dart 2.0.

To run a test app, create a test folder and open it in VS Code. Open the VS Code terminal and run

stagehand web-simple

Your test folder should be populated with the broilerplate dev files.

Provision the required packages by running

pub get

To launch your test app run

pub serve

Note the response (mine was http://localhost:8080/) and open that in the Dartium browser. You should see Your Dart app is running. You can still test apps in any other browser by opening the same address in that browser, but it may take a several seconds to build (check the terminal for feedback).

30 August 2017

Basic commands to quickly set file/folder permissions and ownership

Assuming you have navigated to the directry you want these changes to take effect ie. /var/www/your_vh_domain

Note: Remember to set individual restricted permissions to sensitive files and folders after this bulk action has taken place. For example, with WordPress you will want to set wp-config.php file to 600

Change folder permissions recursively

find public_html -type d -exec chmod 755 {} \;

Change file permissions recursively

find public_html -type f -exec chmod 644 {} \;

Change file ownership recursively - Set your own user and group as desired

chown -R leke:www-data public_html