Twitterでよく見かけるWordle、ニューヨークタイムズが買収したと報道されてましたね。
Wordle 228 6/6
— イナバ (@hollyhockberry) 2022年2月2日
⬜⬜⬜🟨🟨
⬜🟨⬜⬜⬜
⬜🟨⬜⬜🟩
⬜🟩🟨🟨🟩
⬜🟩🟩🟩🟩
🟩🟩🟩🟩🟩
こんな感じのツイートを見かけるたびにGithubのコントリビューショングラフみたいだなぁと思ってたんですが、眺めてるうちに手元にあったseeedのマトリクスLEDに見えてきたので光らせたくなってきました。
何番煎じなのかわかんないですけど、やってみます。
仕組み
Wordleをプレイ後、SHARE
のボタンをクリックすると結果がクリップボードにコピーされます。
通常はTwtterにペーストしてツイートするんですが、代わりに ESP32に渡してLEDを光らせましょう。
ESP32に渡すのはWebServer経由がスマートな気がします。テキストをそのままPOSTで渡せばあとはパースするだけで簡単そうですね!(フラグ)
面倒だった
ESPAsyncWebServerを利用してPOSTされたデータを取得してパースする、ただそれだけ。
server.on("/poi", HTTP_ANY, [](AsyncWebServerRequest *request) { if (request->hasArg("text")) { std::string str(request->arg("text").c_str()); Serial.printf("%s\r\n", str); // この文字列をパースする! } }
いよいよ処理を書こうとしたら手が止まりました。
ああああああああああ!マルチバイトめんどくせぇ!!
— イナバ (@hollyhockberry) 2022年2月1日
考えてみたら当たり前なんですが渡ってくる文字列はマルチバイトでした。
製品カテゴリによるとは思いますが、ドライバ寄りのファームウェアを開発しているとマルチバイトを扱うことが少ないので圧倒的に経験値が足りない!
どうしようかとしばらく考えましたが、string::compare()
を範囲指定でちまちま比較することでなんとかしました。
もっとスマートな方法あるんですかね・・?
// indexの位置に該当の文字があるか判定する関数 int find(const std::string& str, int* index) { const std::string chip[] = { "⬜", "⬛", "🟨", "🟩" }; const int code[] = { 0xff, 0xff, 0x25, 0x55 }; // MatrixLEDのカラーコード for (auto i = 0; i < 4; ++i) { if (str.compare(*index, chip[i].length(), chip[i]) == 0) { *index += chip[i].length(); return code[i]; } } return -1; // 該当なし }
// stringを末尾まで走査してMatrixLEDのデータに変換する bool find(const std::string& str, int line) { if (str.empty()) { return false; } int x = 0; for (auto i = 0; i < str.length(); ++x) { auto n = find(str, &i); if (n < 0) { return false; } score[5 * line + x] = n; } return true; }
妙にめんどくさくて手こずったけど、どうにかできました。
C/C++めんどくさいぜ(でも好き❤️)
できた、Wordleの結果をLEDで光らせるヤツが。WebServerでブラウザからコピペすると光るよ!
— イナバ (@hollyhockberry) 2022年2月1日
問題が解けてなくて恥ずかしい😖 #m5stack #m5atom pic.twitter.com/Vyxtxht3Y1
余白を隠せばもっといい感じになるかな?
ソースコードはこちら↓