Suburi
Suburiという素振りをするプロジェクトを作りました。
基本的にはUIコンポーネント集みたいになりそうですが、Twitter等で見かけた実装をこのアプリで片っ端から実装しよう。というコンセプトです。
直近ではCICDを回すことにしました。 Xcode16から、swift-formatが内蔵されるようになったので、それを利用する形でワークフローを組みました。
挙動としてはPRの作成に反応してformat、差分がコミットされる、というものです。
GithubActionsを使ったことがそこまでなかったので、ハマった内容などを残しておきます。
- コミットさせる場合はActionsの設定からWrite権限を設定しないとコミットが拒否される。
- ユーザは
[email protected]
とすると既知のBotとしてコミットされる。 qiita.com
今後も気になったらCIは調整する。 実装issueは以下 github.com
競プロ精進録
8/10に競プロをやり始め、Rustと戯れること苦節2ヶ月弱、ようやく本番で3完できました。
今回のCは簡単すぎてなんだ?と思っていました。
正直Rustじゃなかったらもっと伸びてるやろ、とは思いますが、とはいえもうそろそろ慣れてきて基本的な実装はできるようになったかなと思います。
自分の成績だけ見ているとまだまだやるだけ伸びるいいゲームだなー
やってたこと
典型90問とかよく聞きますが一旦これだけやってました。そういうレベルじゃなかったと思うので。 といいつつ46題しかやっていない。
でもそろそろやろうかと思っています。 という記録。
備考
↓
Creative UIs with SwiftUI (Vol.2)
続き。
最終的にPxに変換しているので値をそのまま描画したらいい感じに同じ図形が描画できた。当たり前と思うかもしれないが・・・
最終系がこんな感じ。 SwiftUIとComposeの違いとしてmodifierの影響範囲が違うことがわかった。
Composeと同様にbackGroundを設定してからClipするとSwiftUIでは期待したようにClipされなかった。
SwiftUIではメソッドチェインされたものは順にViewが渡されて処理されるので、Clipを最後にするとその矩形で最終的にClipするようだ。(感覚的にはこちらの方がわかりやすい。)
Composeでは.clipはあくまで大元のViewに対してのClipであって.drawBehindした内容には影響がない。(多分)
Pathは同じような記述で良いのは面白かった。やってることはSVGと同じなのでそれはそうかというところだが。
あとがき
これ以降少々込み入ったレイアウトの話になってしまっていて互換どうこう、という感じではなさそうだった。方針は同じでいいんだろうけれど。 時間ができたらまたやってみようと思う。
あとセッションの動画が公開された。
Creative UIs with SwiftUI (Vol.1)
droidkaigiに参加している同期から面白い発表があったと紹介された。 内容的には、
- 現代では標準的UIが確立しておりメリットを多く享受しているが、その一方でデザイン的には面白みに欠ける。
- 過去のアプリ、PCソフト、またゲームのような、四角形をただ並べるだけではないレイアウトをJetpackComposeではどう組み立てるのか。
- ペルソナ風チャットアプリを題材に作成していく。
といったところだと思う。(アーカイブが公開されたらこの辺りの齟齬は修正する)
昨今ではKMPやSkipの隆盛めざましいが、SwiftUIにもっと慣れるために紹介されたUIをSwiftUIで組んでみようと思う。
今回は簡単な背景から。
background
https://speakerdeck.com/chrishorner/creative-uis-with-compose-droidkaigi-2024?slide=41
とりあえず背景とアイコンをレイアウトしてみた。
Swift側で縦積みを再現するのにZStackを利用したがalignmentが.center
になっていた。
Androidと指定を合わせる意味で、ZStackのAlignmentを
.topLeading
に設定してみた。
追々コードはGithubで共有する。
素数判定(<sqrt(n))
これを解いた時に素数判定をする必要があった。
愚直に2以上の数で割っていき、割れなければ素数、割れれば合成数。
nの合成数は全てsqrt(n)以下の数なのでsqrt(n)
まで調べれば、素数かどうかは判別できる。
競プロで以下の判定式を書くならどのみち結果が出るのがsqrt(n)までの間というだけなのであまり意味のある知識ではなさそうなものだけど 面白かったのでメモ
fn is_prime(n: isize) -> bool { if n == 2 { return true; } else if n % 2 == 0 { return false; } let mut i = 3; while i <= (n as f64).sqrt() as isize { if n % i == 0 { return false; } i += 2; } return true; }
なんでシンタックスハイライトが効かないんだろう。
しばらくはここでやっていくというハナシ
GithubPagesでホストしている技術ブログが存在する。 元々自分でホストしたブログでやっていきたいなぁという気持ちがあって立ててみて数回更新はしてみたのだがなんとなく書きづらい。
mdファイルを作ってgit push
すればなんとなく動いて記事は公開されるものの、携帯でみた時の見た目などがやや気に入らないので、直したいが時間もそう掛けられないので一旦こっちでまめに書こうと思う。
いずれ解消したらホストしたいと思っているのでダメポイントを挙げていく。
微妙な点
- 画像のリンクがうまくない
- モバイル表示時の左右Paddingが0で見づらい
- Laprasのクローリングで拾えない
未来で解消したら移行する。
Vobot Mini Dockで遊んでいる
https://www.kickstarter.com/projects/vobot/vobot-mini-dock-screen-equipped-dock-portal-to-infomation
先日KickStarterでBackしたVobotMiniDockが到着したので記録。
▼クリックで配送記録を表示
Date and Time | Status | Description |
---|---|---|
2024-07-08 01:00:00 | Transit | Departed 【JP】 processing center |
2024-07-08 00:59:00 | Transit | JingWaiJinKou Customs clearance |
2024-07-07 09:00:00 | Transit | JingWaiJinKouHaiGuanLiuCunDaiYan(DengDaiTiJiaoGeiBianJingJiGou/AnQuanBuMen) |
2024-07-07 08:59:00 | Transit | Send to overseas import customs |
2024-07-07 00:43:00 | Transit | Arrive at destination ChuLi ZhongXin |
2024-07-06 00:31:00 | Transit | Arrive at destination |
2024-07-05 22:25:00 | Transit | FeiJiJinGang |
2024-07-05 17:25:50 | Transit | Airline in transit to next facility |
2024-07-05 10:56:21 | Transit | Airline JieShou |
2024-07-05 00:31:00 | Transit | Arrive at destination |
2024-06-30 10:20:00 | Transit | Shenzhen,YiJiaoChengYunShangYunShu |
2024-06-30 08:28:50 | Transit | Shenzhen, YouJian Departed from【GuangDongSheng Shenzhen GuoJiHuHuanJu】, ZhengZai sent to Next stop |
2024-06-30 02:27:40 | Transit | Shenzhen, 【GuangDongSheng Shenzhen GuoJiHuHuanJu】 Departure from outward office of exchange |
2024-06-30 02:27:10 | Transit | Shenzhen, ChuKou customs / FangXing |
2024-06-29 23:48:55 | Transit | Shenzhen, SongJiaoChuKou customs |
2024-06-29 22:10:55 | Transit | Shenzhen, YouJian Departed from 【Shenzhen GuoJiGongSiZhiShuDaLangYingYeBu】, ZhengZai sent to 【Shenzhen international】 |
2024-06-29 22:10:52 | Transit | Shenzhen, YouJianYiZai【Shenzhen GuoJiGongSiZhiShuDaLangYingYeBu】WanChengFenJian, ZhunBeiFaChu |
2024-06-29 21:24:24 | Transit | Shenzhen, China YouZheng YiShouQuYouJian |
2024-06-30 20:57:48 | Sent | Creator uploaded the tracking information |
本体仕様(公式引用)
- Screen: 2 inches with resolution 320x240 and 16M colors
- Connection ports: including USB-C, USB 3.0, HDMI, Ethernet interface, compatible with fast charging and data transmission
- Size and weight: Compact design, easy to carry and place in working environment
2インチの画面を持ったデジタル時計+Dockという感じ。 HDMI端子やtype-Cの端子が2つ、USB-Aが1つ、PD用のtype-Cが1つ。
価格
今購入する際は下のリンクから。 Mini Dock – Vobot Online Store
セール中表記だが確かKickstarter時の表記だと$69.99が基本価格だった。 Kickstarterでの$55で購入した。本発売で$79.99なら4000円程度安く買えた計算になるので自分としては得した気分。 これに送料が乗ってなんだかんだ1万円くらいになる。円安が憎い。
所感
- Dock欲しさに買ってみたものの、これ一つに全て刺すと机がごちゃついてしまってコレジャナイ・・・となった。まあこれは買う前から予想できたことだが
- この2インチディスプレイに常に情報が出ているというのはなかなか良い。基本自分は天気を表示している。
- 他の内蔵アプリでいうと
- NowPlaying: フォントが日本語対応していないので微妙に使えない。英語表記であれば十分。
- Pomodoro: シンプルなポモドーロタイマー。これは良い。ビープ音がかなり安いけど。
- Calender: 月表示のカレンダー。これはこれで良いがGoogleCalenderの週予定を表示できた方が嬉しい
- Weather: 天気、気温、湿度、などを表示できて内蔵アプリの中では一番表示がリッチだと思う。
- Stock, Cryptocurrency: 株価,暗号通貨価格が表示できる。これは割とシンプルなTable表示で良い。
- Screen Mirroring,Game Emulator, H/W Monitoring: 未使用。何やら設定がいるらしい
- アプリの設定は一部、設定状態に入った端末に他の端末からブラウザでアクセスするタイプ。これが結構良い。
- 背面の光表示 いらないかも。何基準で光っているのかがわからないので賑やかしかな?
アプリ開発
個人的にこれを買った理由は、内蔵アプリのようなアプリケーションを自前で書けることにある。
手始めにローカル端末にPingを飛ばして死活確認をするようなアプリケーションを作った。
対応言語はMicroPython,GUIにLVGLを利用。
コード部分
個人的に詰まったのはPythonのモジュールインポート。
. ├── README.md ├── __init__.py └── ping_utils.py
こういうファイル構造にした時ping_utils.pyをinitからimportするには
from .ping_utils import ping
と書くと認識された。色々試したんだけど残していない・・・
個人的に気に食わないのはlabelなどUI周りをコードにつらつら買いているところで、なんかこう上手い書き方がありそうだな〜
ロジックはほぼないのでただAPIを叩いて返答を画面に反映する、それだけのものなのでチュートリアルとしては適切なサンプルだったと思う。 ただPingを飛ばす部分は外部ライブラリを利用できなかったので自分で書く必要があったがこれを利用することで動いた。
µPing: Ping library for MicroPython · GitHub
Pingを3つに飛ばすという仕様を作ったので、このままだと画面がフリーズしたままだった。 なので、このpingをasync対応したところひとまず期待の動作になったというわけである。
設定画面
このVobotMiniDock独自仕様としてget_settings_jsonという関数を作ることで設定画面が生成される。
def get_settings_json(): return { "title":"Ping to your local devices", "form": [ { "type": "input", "default": "1", "caption": "PingFrequency:", "name": "frequency", "attributes": {"maxLength": 5, "placeholder": "Ping your device every {input} minutes."} }, { "type": "input", "default": "", "caption": "Device1:", "name": "device1", "attributes": {"maxLength": 15, "placeholder": "Enter device ip(192.168.0.0)"} }, { "type": "input", "default": "", "caption": "Device2:", "name": "device2", "attributes": {"maxLength": 15, "placeholder": "Enter device ip(192.168.0.0)"} }, { "type": "input", "default": "", "caption": "Device3:", "name": "device3", "attributes": {"maxLength": 15, "placeholder": "Enter device ip(192.168.0.0)"} }] }
こんな感じになる。ドキュメントにも書いているのであえて書く必要もないか。
LVGL
LVGLについても、Python版フォークということもあり若干自分の想定した記法で動かずメールで泣きついたら丁寧に教えてくれた。Vobotスタッフには感謝である。
From your code, to achieve alignment, you only need to change
lv.screen_active().set_flex_flow(lv.FLEX_FLOW.COLUMN)
toscr.set_flex_flow(lv.FLEX_FLOW.COLUMN)
In addition, for other ways to align controls, you can use the
align
function or thealign_to
function, such aslabel2.align(lv.ALIGN.BOTTOM_LEFT, 0, 0)
orlabel2.align_to(label1, lv.ALIGN.OUT_BOTTOM_LEFT, 0, 0)
概ねあっていたようだがscreen_active()は提供されていないようで、scrに直接設定すればよかったようだ。あるlabel起点での配置の仕方も教えてくれた。
怠惰なプログラマなので、その細かいレイアウトについてはよしなにやって欲しい派。 なのでobjを利用して中のラベルは勝手に整列するようにした。最終的な画面コードはこんな感じにした。
数字付きラベルは良くないが一旦動けば良いのだ精神。
... container = lv.obj(scr) container.set_size(lv.pct(100), lv.pct(50)) container.set_flex_flow(lv.FLEX_FLOW.COLUMN) label1 = lv.label(container) label2 = lv.label(container) label3 = lv.label(container)
まとめ
なんとなく購入したが結果的には面白いものを手に入れたように思う。 もう少しPythonへ習熟すれば自前でもいいウィジェットが作れる気がするが今の所何を作るか思いついていない。
この手のデバイスはアプリの充実度で評価が変わってくるので、充実してより広まって欲しい気持ちである。 完成系とそのコードも上手い人のが見たいし。アプリ公開用ストアも追々できるらしいので興味があれば是非。