Category Archives: Programming

PicoBf: A brainf**k lang REPL environment for Pico Pi

こんぺこ〜こんぺこ〜こんぺこ!

I heard that Pico Pi @Raspberry_Pi only has MicroPython REPL at the moment, so I had some fun writing a brainf**k REPL in C++17 for Pico Pi XDDDDD (btw, the output image is also written in bf lang!)

The brainf**k interpreter is adapted from a previous project, you can find it in this post, Brainfuck Interpreter in C++17——A Modern Approach to Kill Your Brain.

Source code on GitHub, https://github.com/BlueCocoa/pico-bf

Hardware UART communication between Raspberry Pi 4 and Arduino Micro

作りましょう 作りましょう

あなたと私の世界をさぁ作りましょう

始めましょう 始めましょう

なにから始めましょう(ん~!?)

OK, let's start from communicating between Raspberry Pi 4 and Arduino Micro with hardware UART. For Raspberry Pi, GPIO pin 14 and 15 are the TX and RX pin of UART correspondingly.

1. Physical Connection

The first thing to note is that all GPIO pins on Raspberry Pi are 3.3v tolerance and Arduino Micro runs at 5v. If we connect Raspberry Pi with Arduino Micro directly, chances are that your Raspberry Pi can be damaged. Thus we need a bi-directional logic level converter.

But unfortunately, the one I brought came with separate headers that I needed to solder them onto the converter board by myself.

Well, the solder work may look just so so, but it works. That's what matters most. XD

The image below is my Arduino Micro and we can see that from right to left on the top bank, the third and fourth pin are the TX and RX pin.

Next, we need to connect them as the image demonstrates below.

Now we have done the physical part, time to move on to the software part.

Continue reading Hardware UART communication between Raspberry Pi 4 and Arduino Micro

OK Google, set Telegram as my YouTube music player!

To play music on YouTube in background on a mobile device requires YouTube Premium. Let's just set Telegram as our YouTube music player!

The idea is simple and straightforward. Firstly, apply a telegram bot and secure its token. Secondly, write a bot program that accepts one YouTube URL at a time from telegram user. Next, invoke youtube-dl to get the download URL of the best quality audio. Finally, send the downloaded audio file to corresponding telegram user.

The project is on my GitHub: https://github.com/BlueCocoa/youtube-music-bot

Continue reading OK Google, set Telegram as my YouTube music player!

Record YouTube Live Stream

最近不知不覺踩進了 hololive 這個兔子洞,其實真的蠻羨慕她們的,可以做自己喜歡的事,雖然其中也有不少人抱怨過休息的時間太少⋯⋯也許自己更羨慕的一點是可以有幾乎隨時一起嬉笑的朋友吧w

那麼雖然大多數 live stream 都會自動存檔,但是其中一部分 streamer 會選擇對某些直播不存檔,於是錯過直播的話,就只能等 clip 之類的了_(:3」∠)_ 因此就有了這個類似於電視錄影機一樣的想法~

项目放在了 GitHub 上 https://github.com/YouVCR/YouVCR~ 设置好 config.yaml 就可以使用了w

Continue reading Record YouTube Live Stream

可能隨時咕咕咕掉的 NLP 項目(1)—— 抓取 YouTube Live Chat

最近一邊想著畢業論文要寫什麼,一邊想著先做點有趣的東西~因為最近偶爾會看一下 YouTube 上烤肉 man 們剪輯的 hololive 的精華,所以暫且想要做個 NLP 相關的項目!不過倒不是自動翻譯這樣的功能,但具體是什麼自己還沒有完全想好(心裡有幾個點子,但是先寫出來又做不出來的話就太丟人了www),AAAAAAA~

那就總之先做一個抓取 YouTube Live Chat 的程式好了~其實小糾結了一下用什麼語言最方便,畢竟是抓取內容,而不是用 YouTube 官方的 API,所以也許 Python 是一個還不錯的選擇。

在寫這個工具的時候(2020 年 12 月 19 日,後文中的「目前」均指此日期),YouTube 上 Live Chat 回放的 API 是 https://www.youtube.com/live_chat_replay. 不過正如上面提到的,這個工具是直接爬取 Live Chat 的內容的,所以當你看到這篇博文的時候,很有可能 YouTube 已經更改了 API 或者內部的資料結構。

Continue reading 可能隨時咕咕咕掉的 NLP 項目(1)—— 抓取 YouTube Live Chat

NextDest

NextDest allows your device that has a public IPv6 address to be automatically registered and updated its DNS record.

With more and more ISPs offering public IPv6 addresses to their users, we can directly access our devices that have a public IPv6 address. But the public IPv6 address of your device can change from time to time and it's extremely hard to memorise an IPv6 address. 

Therefore we have DNS, a solution from a long time ago. Yet it's also boring and painful if we have to set the DNS record by hand.

That's why I wrote NextDest. The client-side detects the public IPv6 address on your device (by sending a request to the server-side, so everything is in your hand). Once it finds any available public IPv6 address, it will send a registration request to the server-side along with predefined device name (so that the server-side can decide which domain name should be updated). If everything works, the client-side will display the latest DNS record and the public IPv6 address of your device.

However, this is NOT the end of the story. If NextDest exposes your public IPv6 address to the Internet, your device could be attacked. 

So NextDest supports 4 modes:

1. direct mode

Internet <-> Endpoint

The real IPv6 on that device will be used for DNS resolving. 

All ports can be accessed from the Internet.

2. proxy mode

Internet <-> nextdest <-> Endpoint

An available IP will be used from your IP pool (defined in CIDR format, in the server-side config file).

Cloudflare (or other) only acts like a DNS, i.e, the real IP will show up in DNS record.

Network traffic is forwarded by NextDest.

Only ports defined in ports (in the server-side config file) can be accessed from the Internet.

3. cdn mode

Internet <-> Cloudflare <-> Endpoint

The real IPv6 on that device will be only used for DNS zone settings

All network traffic will be proxied by Cloudflare (or any equivalent), i.e, only CDN's IP will show up in DNS record.

Only 80 or 443 or other CDN provider allowed ports can be accessed from the Internet.

4. hybrid mode

It is the combination of proxy mode and cdn mode.

Project code

NextDest server-side source code: https://goth lab.com/ryza-cocoa/nextdest-server

NextDest client-side server code: https://gitlab.com/ryza-cocoa/nextdest

macOS version of Twitter Image Saver

A few days ago, I wrote a Twitter image saver with Rust, but it's a cli application, which makes it not so easy for daily use (I have to type some command to start or stop it, also need to edit the JSON config file manually). Therefore I rewrote it in GUI (to be accurate, a status bar application) on macOS.

It would be pretty easy to set up, click the Settings menu, fill in the consumer key and secret, and then select the directory where you'd like to save the images. Finally, add some accounts (without @) you interested into the list! The total number and the total size of images saved for the current session will be displayed in the drop-down menu.

Furthermore, this application's icon is the combination plus some modifications of two original ones; they were made by Anton Kalashnyk and Fauzan Adiima.

The source code of this project is on my GitLab.

Rust Learning from Zero (26) —— Save Twitter Images

I followed a few Twitter accounts that post yuri photos, and I saved some of these images when I saw them. 女の子になりたい!

However, it would be better if there is a bot that could do all this for me. And of course, applying for a Twitter developer account is a must. When your developer account is ready, you will need to generate a consumer key & secret pair.

This program will be really simple and straightforward. It reads from a config file that contains the consumer key & secret pair, as well as a list of usernames you interested in, and the path to the directory where you'd like to save images. A sample of the config file is shown below.

{
  "key": "KEYKEYKEYKEYKEYKEYKEYKEY",
  "secret": "SECRETSECRETSECRETSECRET",
  "img_dir": "imgs",
  "users": [
    "username1",
    "username2",
    "username3"
  ]
}

Substitute your own consumer key & secret, and then list some users you interested in in the users array.

Also, I don't want the program to be too complex, so I decide to not use any database. If you want to add more users to the list while the program is running, then just add them into the JSON file and save it. The program will try to reload the user list before the next round of polling data.

And this program is on OwO now! https://owo.ryza.moe/. You can download and install it on Linux with only one line command. (For more details about OwO, you can refer to this post, Rust Learning from Zero (23) —— The OwO software distribution system!)

bash <(curl -sSLf https://owo.ryza.moe/twitter-img-saver/install.sh)
Continue reading Rust Learning from Zero (26) —— Save Twitter Images

Rust Learning from Zero (25) —— Handle Continuous Features in Decision Tree with Rust

This post has two main purposes, 1) serves as personal notes for handling continuous features in decision tree; 2) try to use trait to add more computation operations to vectors, because the original Vec shipped with Rust is nowhere near the numpy in Python when it comes to scientific computation. (Though I know that Vec may not be designed to do handle such task.)

There are many ways to handle continuous descriptive features, such as discretions. This post will exploit weighted variance as a measurement for splitting continuous feature at a node.

The weighted variance is computed by the following equation, where $n$ is the number of rows in the data, $\mathcal{L}$ is the set of all unique labels, $D$ is the column with continuous features ($n$ rows), $p^*$ denotes the best split position in $D$.

$p^*=argmin_{p\in [1, n)} \sum_{l\in \mathcal{L}}\frac{\|\mathcal{L}_{i=l}\|}{\|\mathcal{L}\|} [var(D_{[0, p)}, \mathcal{L}_{i=l}) + var(D_{[p, n)}, \mathcal{L}_{i=l})]$

Once the algorithm decides the best split position of $D$, we can apply divide and conquer! For example, if $p^*$ has been computed, then we recursively apply this mechanism to both $D[0 .. p^*]$ and $D[p^* ..]$. When the split position arrays, $S_i$ and $S_j$, of $D[0 .. p^*]$ and $D[p^* ..]$ return, $S_i$ and $S_j$ will be merged and sorted as final value.

Let's try this algorithm on this small dataset,

Continuous DataLabel
00
20
31
70
150
352
451
471
550
571
612
672
811
920
962
972

Looks good to me! And code goes below.

Continue reading Rust Learning from Zero (25) —— Handle Continuous Features in Decision Tree with Rust

Rust Learning from Zero (24) —— Travelling Salesperson Problem using Evolutionary Approach with Rust

I believe that for almost anyone studying in computer science would know this famous problem below.

The travelling salesperson problem asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?" Wikipedia

I know that there are thousands if not millions approaches that we can use to solve this problem. But just for personal notes and demonstration, I will solve TSP using one evolutionary approach with Rust.

The idea of today's evolutionary approach (EA) is rather simple:

  1. Randomly initialise some solutions and compute cost (described as fitness in EA) respectively.
  2. Mutate one of them, compute the fitness of mutated solution. If the new fitness is worser than the last one, go step 3. Otherwise go step 4.
  3. Reject this mutation and go step 2.
  4. Accept it as a solution, discard the worst solution and repeat step 2.

For $n$ nodes in a path, there are maximum $n!$ (actually, $(n-1)!$) paths to select from. Therefore, if what we want if the global optimal, then this algorithm has to iterate all possible paths, and that gives us $O(n!)$ performance. However, EA could actually gives us a quite good suboptimal in much less time because of the way it works. One use case of EA is when we only have limited time, computation performance and we can accept suboptimal as a solution.

For example, if we have the following adjacency matrix in TSP,

ABCDE
A57415
B53410
C7327
D4429
E151079

Then we solve this problem with EA, the output could be as below.

Initial solution [0]: fitness => 33, seq => CABED
Initial solution [1]: fitness => 32, seq => CADBE
Initial solution [2]: fitness => 34, seq => CDEAB
Initial solution [3]: fitness => 32, seq => ABDEC
Initial solution [4]: fitness => 33, seq => ADEBC
[0] Reject mutation: fitness => 38, seq => DBEAC
[1] Reject mutation: fitness => 34, seq => CDAEB
[2] Accept mutation: fitness => 33, seq => CEADB
[2] Worst solution dropped: fitness => 34
[3] Accept mutation: fitness => 28, seq => EDABC
[3] Worst solution dropped: fitness => 33
[4] Reject mutation: fitness => 33, seq => CBDAE
[5] Reject mutation: fitness => 38, seq => ACDBE
Best solution so far: fitness => 28, seq => EDABC

As you can see, EA found quite a good solution with fitness 28, which is EDABC. Also, this is in fact the global optimal and EA actually found the global optimal in the 3rd mutation!

Continue reading Rust Learning from Zero (24) —— Travelling Salesperson Problem using Evolutionary Approach with Rust