アプリ向け Error monitoring, Crash reporting tools
結構ある
Name | Android | iOS | Flutter | Pricing for individuals | Pricing for teams *1 |
---|---|---|---|---|---|
Crashlytics | ✅ | ✅ | ✅ | $0 | $0 |
Sentry | ✅ | ✅ | ✅ | $0 | $26 |
Bugsnag | ✅ | ✅ | ✅ | $0 | $18 |
Rollbar | ✅ | ✅ | ✅ | $0 | $0 |
Smartlook | ✅ | ✅ | ✅ | $0 | $0 |
Shake | ✅ | ✅ | ⚠️ *2 | $0 | $160 |
Raygun | ✅ | ✅ | ✅ | $40 | $40 |
Instabug | ✅ | ✅ | ✅ | $249 | $249 |
Bugsee | ✅ | ✅ | ✅ | $0 | Custom |
New Relic | ✅ | ✅ | ✅ | $0 | $0~ *3 |
Datadog | ✅ | ✅ | ✅ | $0.31 *4 | $0.93~ |
Dynatrace | ✅ | ✅ | ✅ | - *5 | - |
記事公開時点、✅ は公式 SDK があるかどうか
- Team の定義
- 5 developers.
- 1 app.
- About 100 events/day, 3,000 events/month.
- Crash reporting はまだサポートしてなさそう
- Free plan. 1 Full platform user, 4 basic users.
- Error Tracking ($0.31~).
- むずかし
firebase.google.com sentry.io newrelic.com www.dynatrace.com www.datadoghq.com www.bugsnag.com raygun.com rollbar.com www.shakebugs.com www.instabug.com www.smartlook.com bugsee.com
GitHub Flavored Markdown で Store badges を揃える
App Store, Google Play, Microsoft Apps などの install badge を README などに配置したい時、
Google Play の badge は image 自体に margin があるので、それぞれを揃えて表示するのがとっても面倒。
margin などは使えないので img の width と height で地道に揃える。
まぁあまり置く機会も無いのだけど。
Age of Empires IV で Game Mode の Mod 作るときの tips
小ネタ
Age of Empires IV Mod Workshop
勝敗を決める
Core_SetPlayerVictorious/Core_SetPlayerDefeated を使う
これは新しく Mod 作った時の example code にある
注意点としては、Player が負けて AI が生き残っているような場合を作ると概要が開けず待ちぼうけをくらうことになる
なので、Player が残っていない時点で AI の勝敗も決めておくとよさそう
なお、勝者なしの場合は Core_WinnerlessGameOver を使用する
あと Defeated が呼び出されると Core_IsPlayerEliminated が変わり勝敗が判定できる
勝利条件にもよると思うので変わらなければ Player_IsAlive とかも見るとよさそう
Unit を作成・配置する
UnitEntry_DeploySquads を使う
これも example の通り
もしまだ読み込まれていない Unit (時代が今よりも先, 他国の固有, etc) の場合は、豆腐になるので読み込む必要がある
これには Squad_Precache を使う
第 1 引数は Deploy に渡している Blueprint, 第 3 引数は PlayerID
ここでいう PlayerID は integer ではない、Player_GetID で取得できる値は integer なので注意
他の引数は空でも良い (0 あるいは "")
読み込みが完了したことを検知するには GE_EntityPrecached を使用する、Global Event については下で
Unit の一覧は Content Editor 下部のオブジェクトブラウザから templates > ebps > races 以下を見ればだいたいわかる
Unit の suffix (人種コード)
Player_GetRaceName で得られる人種名は full name なので変換が必要
Race name | Race code |
abbasid | abb |
chinese | chi |
english | eng |
french | fre |
hre | hre |
mongol | mon |
rus | rus |
sultanate | sul |
そのうち Util_ とかで提供されるんじゃないですかね
Unit の殺害 Event
Global Event の中でもよく使いそうな
Unit (Entity) が殺されたことを Event で取得できる
Rule_AddGlobalEvent の第 2 引数に GE_EntityKilled を渡す
function に返る context の中身は
- victimOwner
- 被害者側の player
- victim
- 対象 Unit
- victimSquad
- killer
- victim を殺した Unit
など。killerOwner とかもあったかも
killer と victim が一緒だと自殺 (Player による delete)
Unit が何人残っているか
Player_GetEntityCountByUnitType を使う
この Unit type が何かというと、自分もオブジェクトブラウザから調べる方法を知らない
チューニングパックを作成すると作られる attrib/*.xml で unit を表示して
extensions > type_ext > unit_type_list の中を見ると書いてあるのが Unit type
なので、村人の場合は "villager"、軍事 Unit 全体の場合は "military"
なお、特定の Unit がどの type かを知るためには Entity_IsOfType が使用できる
Console 出力系
Debug に
- Util_PrintIf
- Util_PrintTable
とりあえずまだ Beta なので Document も完全ではなく割と苦労します。頑張りましょう
いくつかデモで作ったので参考までに
Windows PC で BSoD 頻発してたのを直した
Windows PC が BSoD 起こすようになったけど直ったメモ
大まかな構成
- AMD Ryzen 7 5800X
- NVIDIA GeForce RTX 3070
- Driver 30.0.14.7111
- ASRock B550M-ITX/ac
問題としては
このあたりが起動後 10 分以内にほぼ 100% 起きる
- 復元
- Driver 更新
- Clean install
を何回か実行したけど効果なし
Flutter で 2 つの Path を組み合わせる Path#combine
Android における Path#op あるいは Canvas#clipPath のようなことをする Path#combine
以下のような形で Path を組み合わせる
final path = Path.combine( _pathOperation, Path() ..addOval(Rect.fromCircle( center: Offset(centerX - 50, centerY), radius: 100, )) ..close(), Path() ..addOval(Rect.fromCircle( center: Offset(centerX + 50, centerY), radius: 100, )) ..close(), ); canvas.drawPath(path, _paint);
Lua で SQLCipher (lsqlcipher) を使う
lsqlcipher の Install から使うまで
Install
LuaRocks で install します。
$ luarocks install lsqlcipher
私の今の環境 (macOS) だと LDFLAGS で指定されている path に lcrypto がないので sqlcipher の install に失敗します。
$ luarocks install lsqlcipher Installing https://luarocks.org/lsqlcipher-0.9.5-3.src.rock Missing dependencies for lsqlcipher 0.9.5-3: sqlcipher (not installed) lsqlcipher 0.9.5-3 depends on lua >= 5.1, < 5.5 (5.4-1 provided by VM) lsqlcipher 0.9.5-3 depends on sqlcipher (not installed) Installing https://luarocks.org/sqlcipher-4.4.2-2.rockspec ... configure: error: C compiler cannot create executables See `config.log' for more details Error: Failed installing dependency: https://luarocks.org/sqlcipher-4.4.2-2.rockspec - Build error: Failed building.
やり方は色々だと思いますが、symbolic link を貼りました。
$ ln -s /usr/local/Cellar/openssl@1.1/1.1.1k/lib/libcrypto.dylib /usr/local/lib/ $ ln -s /usr/local/Cellar/openssl@1.1/1.1.1k/include/openssl /usr/local/include/
必ずしも原因が同じとは限らないので、error が出た場合は config.log を見るのが良さそうです。
といっても config.log 消えてると思うので、その場合は Source になっている sqlcipher を自分で build して試してみると良いと思います。
Usage
local sqlite3 = require("lsqlcipher") local db = sqlite3.open("./foo.sqlite") db:key("bar") db:exec [[ CREATE TABLE IF NOT EXISTS baz ( id INTEGER PRIMARY KEY ); ]]
あとは lsqlite3 と一緒です
Ktor Client で Twitter の Filtered stream を取得する
小ネタ
HttpClient
このへんはあまり関係ないのでよしなに
val client = HttpClient(CIO) { defaultRequest { url { protocol = URLProtocol.HTTPS host = "api.twitter.com" } header("Authorization", "Bearer $token") } Json { serializer = KotlinxSerializer(json) } }
Add rules
取得する Tweets の rules を POST する
返り値は String でも HttpResponse でも任意に定義した Response でも何でもいいですが、
kotlinx.serialization でそのまま decode する場合は、errors など key がない場合があるので ignoreUnknownKeys = true を指定しておくと良いです
val response = client.post<String> { url { encodedPath = "2/tweets/search/stream/rules" } body = StreamRulesRequest(rules) }
Get tweets
Tweets を real-time に取得する
Ktor Client の doc に書いてある通り、HttpStatement を使用します。
client.get<HttpStatement> { url { encodedPath = "2/tweets/search/stream" } }.execute { response -> val channel = response.receive<ByteReadChannel>() do { val tweet = channel.readUTF8Line() ?: break } while (tweet.isNotBlank()) }
Flow とかで emit すれば扱いやすくなると思います。
もう少し詳しく見たければこちらを
info-provision-bot/TwitterClient.kt at main · CORDEA/info-provision-bot · GitHub