技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Marp から乗り換えよう! Markdown スライドのSlidev

自分は個人的に Powerpoint を使いたくない。
なので、ある時期からスライド作成には Marp を使っていたのだが、他にも対抗馬ができたらしいのでやってみた。

Marp とは

Markdown で記述することができるスライドシステム。
実質的に electron で実装されており、要するに JavaScript + HTML5 で実装されている処理系である。

因みに Marp はこちら。 marp.app

VSCode/CLI の他、コアシステムをライブラリとしても利用できる。

markdown で記述し、様々なフォーマットでエクスポートできる。
編集しながら結果出力のプレビューも参照できるので、非常に扱いやすいツールである。

はてさて、Slidev はどうかというと…

Slidev

そして対抗馬となりえるMarkdoenスライドの Slidev について使っていく。
ちょっと使ってみたが、以下の様な特徴があった。

  • vue で拡張できる
  • latex 等の数式サポート

Marp は PDF 化までをきっちりサポートしていたが、意味論的にこちらは PDF はあくまで副次的。
あくまでメインは html 化して web 上のドキュメントとすることを前提としているようだ。

使い分けは必要かもしれないが、個人的にはこれ一本に乗り換えてもいいのではないかというレベルで好感度高かった。

install

npm init slidev すればプロジェクトが開始される。
スライド単位でプロジェクト作っていくスタイルかな?

PS D:\works\sandbox\slidev_sample> npm init slidev
Need to install the following packages:
  create-slidev
Ok to proceed? (y) y

  ●■▲
  Slidev Creator  v0.22.1

√ Project name: ... slidev
  Scaffolding project in slidev ...
  Done.

√ Install and start it now? ... yes
√ Choose the agent » npm
npm WARN ERESOLVE overriding peer dependency
npm WARN Found: vite@2.4.0-beta.2
npm WARN node_modules/vite
npm WARN   vite@"^2.4.0-beta.0" from @slidev/cli@0.22.1
npm WARN   node_modules/@slidev/cli
npm WARN     @slidev/cli@"^0.22.1" from the root project

中略

> dev
> slidev --open



  ●■▲
  Slidev  v0.22.1

  theme   @slidev/theme-seriph
  entry   D:\works\sandbox\slidev_sample\slidev\slides.md

  slide show      > http://localhost:3030/
  presenter mode  > http://localhost:3030/presenter
  remote control  > pass --remote to enable

  shortcuts       > restart | open | edit


[@vue/compiler-sfc] <script setup> is still an experimental proposal.
Follow its status at https://github.com/vuejs/rfcs/pull/227.

[@vue/compiler-sfc] When using experimental features,
it is recommended to pin your vue dependencies to exact versions to avoid breakage.

一通りインストールが終わると、サーバが自動起動する。
f:id:white-azalea:20210701224255p:plain

Ctrl + C で終了します。

続きを読む

Salesforce開発の基礎編8

プラットフォームイベントの基礎

trailhead.salesforce.com

イベント駆動型ソフトウェアアーキテクチャの理解

JavaScript やってるとイベントの概念は分かりやすいかもしれない。

  • イベント駆動型ソフトウェアアーキテクチャの理解
    • イベント駆動は、イベント発生側と受信側に別れ、発生側は適時イベントを垂れ流す。受信側は必要に応じてイベントを受信して処理する。そういう処理モデル
  • イベント駆動型システムのコンポーネント
    • イベント
      ビジネスプロセスにおいて意味のある状態の変化。もしくはそうしたものを扱う情報の単位。
    • イベントメッセージ
      イベントに関するデータが含まれるメッセージ。
    • イベントプロデューサ
      イベントメッセージの公開者。たとえば、発注アプリケーション
    • イベントチャンネル
      イベントを流す場所、イベントのストリーム。
    • イベントコンシューマ
      チャンネル登録者。イベントを受信する側の事。
    • イベントバス
      公開/登録モデルを使用したイベントストリーミングを可能にする通信とストレージのサービス。
  • プラットフォームイベントを使用するケースの例
    • Salesforce ←→ 外部システム のやり取り
      Salesforce 上の製品注文アプリに含まれるトリガが、発注などで発火してプラットフォームイベントを公開する。
      このイベントは イベントバスに流され、登録されてる外部システムがこのイベントを受け取って処理する。
      逆に外部サーバ何等かの通知があればイベントバスにイベントを流し込み、Salesforce 内の対応アプリがイベントバス経由でイベントを受け取る。
    • トリガを利用したイベントメッセージ
      Apex トリガからイベントを publish し、対応する Platform Event Trigger にイベントを通知することもある。
  • プラットフォームイベントの特徴
    • sObject に似てる。カスタム項目を自前で定義できる。
      ただし、これは更新/削除、イベントレコード情報表示といったことができない。
    • ネイティブおよび外部アプリケーションでのプラットフォームイベントの使用
      • イベント公開: Apex, プロセスビルダー, Flow Builder, sObject API (外部サーバ)
      • イベント受信: Apex トリガ, empApi Lightning コンポーネント, CometD (外部サーバ)
  • プラットフォームイベントと他のストリーミングイベントの違い
    他のイベントとして PushTopic イベントや汎用イベントが存在する。
    プラットフォームイベントは汎用イベントに似ているが、より強力なカスタマイズが可能
    • PushTopic イベント : Salesforce レコードの変更をメッセージ受信できる
    • 汎用イベント : 任意のメッセージコンテンツ (ペイロード) を送受信できる
  • プラットフォームイベントは次で利用
    • 事前定義されたスキーマを使用してカスタムイベントデータを送受信する
    • Apex でイベントの公開または登録を行う
    • Salesforce Platform 上かどうかに関係なく柔軟にイベントの公開と処理を行う

プラットフォームイベントの定義および公開

プラットフォームイベントの定義

f:id:white-azalea:20210615211455p:plain f:id:white-azalea:20210615211527p:plain f:id:white-azalea:20210615211629p:plain f:id:white-azalea:20210615211712p:plain f:id:white-azalea:20210615211755p:plain f:id:white-azalea:20210615212116p:plain

  • 「すぐに公開」と「コミット後公開」が選べる。
    すぐに公開は、保存に失敗しようと公開できるが、トランザクションもクソもないので取り消せない。
  • イベントの項かいには Apex からやったり、プロセスビルダーや FlowBuilder からも指定できる。

Apex だとこんな感じでできる。

// Create an instance of the event and store it in the newsEvent variable
Cloud_News__e newsEvent = new Cloud_News__e(
           Location__c='Mountain City',
           Urgent__c=true,
           News_Content__c='Lake Road is closed due to mudslides.');
// Call method to publish events
Database.SaveResult sr = EventBus.publish(newsEvent);
// Inspect publishing result
if (sr.isSuccess()) {
    System.debug('Successfully published event.');
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}

EventBus.publish はListで複数同時送信もできる。
Salesforce API からの場合RESTで

/services/data/v45.0/sobjects/Cloud_News__e/
{
   "Location__c" : "Mountain City",
   "Urgent__c" : true,
   "News_Content__c" : "Lake Road is closed due to mudslides."
}

をPOSTするそうな。

続きを読む

RNN で時系列データの予測をやってみる

この辺の続き

RNN を考える - 技術をかじる猫

要するに次の値を予測してもらうという NN ですな
まずは結果から

正弦波にノイズを与えたデータが学習データ青で、先頭 10 件だけはそのまま、11 件目以降を 10 件づつ与えたデータから予測させて作ったグラフが黄色である。

f:id:white-azalea:20210611011350p:plain

ん、まぁなんとなく正しそうな予感はする。
株価みたいな線形データならやれるだろうか…取り込めるデータは1系統なので、特定銘柄特化でならなりそうな気はするが…。

続きを読む

Salesforce開発の基礎編7

トリガの実行順序

developer.salesforce.com

レコードの作成/更新を実行すると、次の順で処理される。

  1. 変更元レコードがあればまず読み込まれる
  2. メモリ上で更新後の値を作成する
    この時標準UIからの更新であれば、UIに設定されてるバリデーション、項目自体に設定された桁数などのチェックが走る。
  3. フロートリガが実行される。
    フローについては Salesforce開発の基礎編4 - 技術をかじる猫 この辺参照。
  4. before トリガの実行。トリガの内容はこの辺参照 Salesforce開発の基礎編5 - 技術をかじる猫
  5. null チェックや桁数チェックが再度起動。これは「before trigger」で値が設定されるためですね。
    多分この辺で数式項目が処理されます。
  6. 重複ルールが実行される。重複ルールはオブジェクトマネージャから設定できる。
  7. データベースに insert される。(transaction commit はまだ実行されてません)
  8. after trigger が実行される。
  9. 割り当てルールが実行されます。
  10. 自動応答ルールが実行される。
  11. ワークフロールールが実行
  12. ワークフローの項目更新があればここで更新
    • 更新が発生すると、before insert, after insert トリガが実行される。
  13. プロセスビルダで指定したフローが実行される。実行順序は保証されない。
  14. エスカレーションルールの実行
  15. エンタイトルメントルールが実行
  16. レコードの保存後に実行されるように設定されたレコードトリガフローを実行
  17. レコードに積み上げ集計項目が含まれる場合、またはレコードがクロスオブジェクトワークフローの一部である場合、計算が実行
    • 親オブジェクトのさらに親の積み上げ集計を実行(だからオブジェクトの親子関係は 3階層までしか持てない)
  18. 共有設定の処理(Summer 21 ではバグで、Process automated/System が所有者だとこの処理が走らない)
  19. トランザクションコミット
  20. メール送信など確定後処理

何か trail 進めようかと思ったけど、今日今時点でなぜか 503 なので、今日はここまで。

夏に美味しいお茶シリーズ

あんまりこういう事を書く機会はなかったのだだけど、僕はお茶が好きだ。
コロナでお茶が売れてきてる…という話は聞くのだけど、なればということでこの時期のおすすめ茶を Lupicia と自前の作成から紹介してみる。

主に、普段はあまりお茶や緑茶を飲まない…苦いだけじゃない?とか思ってる人にもかなり楽しめるお茶を紹介する。

基本的に、夏向けで、いずれも水出しでも十分美味しいものばかりだ。

季節限定茶

Lupicia には多くの季節限定茶がある。
これから暑くなるにあたり、この季節特有の夏に良さげな季節限定茶を挙げよう。

レモン風味のさっぱり感 「ハツコイ」「ナツコイ」

www.lupicia.com

グリーンレモンやレモングラスブレンドした緑茶+紅茶。
安心してほしい酸っぱくはない。ただ風味がレモンの様にさっぱりしているというだけだ。

毎年夏が近づくと販売するお茶である。

柑橘系だがミントも入っててさわやか「ブリティッシュクーラー」

これも水出しがおいしい紅茶だ。

www.lupicia.com

まぁ見出しだけでも風味はなんとなく想像がつくのではなかろうか…

他のフレーバーティー

季節限定…というわけでもないが、これからの季節でおいしいお茶シリーズだ。

桃が香る烏龍茶「白桃烏龍 極品」

桃の風味を冷やして味わう…しかも癖のない烏龍茶。
夏に飲むには最適だろうと思う。

www.lupicia.com

スーッとする緑茶「アラジン」

緑茶にミントを混ぜたフレーバーティ。
風呂上りに冷やして飲みたい逸品である。

www.lupicia.com

ラベンダーで夏らしさを感じようか「コロポックル

店頭で買おうと思たら北海道に行かないと存在しない地域限定茶。
ハスカップとラベンダーが夏らしさを伝えてくれる逸品だ。

www.lupicia.com

夏だ!フルーツだ!

説明不要なフルーツ系(風味)烏龍茶!
冷やして飲めや!

www.lupicia.com www.lupicia.com

個人的なおすすめブレンド

ジャスミンティーにミントエッセンスやミントの葉を混ぜて飲むのもお勧め。

RNN を考える

RNN って何かというと Recurrent Neural Network 再起構造型ニューラルネットワークの意味。
再帰構造型の意味って何かというと、前回のニューロンの出力と現在の入力を引数にして「前回の状態を含めて判断する」ニューラルネットのこと。

普通、ニューラルネットを扱うとき、活性関数を  f 学習データを  X とし、重み  W バイアス  B とすると ニューロンの作りは


U = XW + B \\
Y = f(U)

ということになる。
ただしこれはその時点でのデータとしたときの問題で、前の状態が次の状態に影響するようなデータには正常に適用できない。

そこで、RNN ではデータ  X のある時点のデータを  X^{(t)} と仮定して


U^{(t)} = X^{(t)}W + Y^{(t - 1)}V + B \\
Y^{(t)} = f(U^{(t)})

こんな感じに前回のニューロン応答に追加の重み  V を加えて取り込む動作をする。

少し展開するとこんな感じ


U^{(t)} = X^{(t)}W + Y^{(t - 1)}V + B \\
= \left(\begin{array}{xxxx}
    x^{(t)}_{11} & x^{(t)}_{12} & ... & x^{(t)}_{1m} \\
    x^{(t)}_{21} & x^{(t)}_{22} & ... & x^{(t)}_{2m} \\
    ...          & ...          & ... & ...          \\
    x^{(t)}_{h1} & x^{(t)}_{h2} & ... & x^{(t)}_{hm}
  \end{array}\right)
  \left(\begin{array}{xxxx}
    w_{11} & w_{12} & ... & w_{1m} \\
    w_{21} & w_{22} & ... & w_{2m} \\
    ...    & ...    & ... & ...    \\
    w_{n1} & w_{n2} & ... & w_{nm}
  \end{array}\right) + 
  \left(\begin{array}{xxxx}
    y^{(t-1)}_{11} & y^{(t-1)}_{12} & ... & y^{(t-1)}_{1n} \\
    y^{(t-1)}_{21} & y^{(t-1)}_{22} & ... & y^{(t-1)}_{2n} \\
    ...            & ...            & ... & ...            \\
    y^{(t-1)}_{h1} & y^{(t-1)}_{h2} & ... & y^{(t-1)}_{hn}
  \end{array}\right)
  \left(\begin{array}{xxxx}
    v_{11} & v_{12} & ... & v_{1n} \\
    v_{21} & v_{22} & ... & v_{2n} \\
    ...    & ...    & ... & ...    \\
    v_{n1} & v_{n2} & ... & v_{nn}
  \end{array}\right) +
  \left(\begin{array}{xxxx}
    b_1 & b_2 & ... & b_n \\
    b_1 & b_2 & ... & b_n \\
    ... & ... & ... & ... \\
    b_1 & b_2 & ... & b_n \\
  \end{array}\right) \\
= \left(\begin{array}{xxxx}
    \sum^m_{k=1} x^{(t)}_{1k} w_{k1} + \sum^m_{k=1} y^{(t-1)}_{1k} v_{k1} +b_1 & \sum^m_{k=1} x^{(t)}_{1k} w_{k2} + \sum^m_{k=1} y^{(t-1)}_{1k} v_{k2} +b_2 & ... & \sum^m_{k=1} x^{(t)}_{1k} w_{kn} + \sum^m_{k=1} y^{(t-1)}_{1k} v_{kn} + b_n \\
    \sum^m_{k=1} x^{(t)}_{2k} w_{k1} + \sum^m_{k=1} y^{(t-1)}_{2k} v_{k1} +b_1 & \sum^m_{k=1} x^{(t)}_{2k} w_{k2} + \sum^m_{k=1} y^{(t-1)}_{2k} v_{k2} +b_2 & ... & \sum^m_{k=1} x^{(t)}_{2k} w_{kn} + \sum^m_{k=1} y^{(t-1)}_{2k} v_{kn} + b_n \\
    ...          & ...          & ... & ...          \\
    \sum^m_{k=1} x^{(t)}_{hk} w_{k1} + \sum^m_{k=1} y^{(t-1)}_{hk} v_{k1} +b_1 & \sum^m_{k=1} x^{(t)}_{hk} w_{k2} + \sum^m_{k=1} y^{(t-1)}_{hk} v_{k2} +b_2 & ... & \sum^m_{k=1} x^{(t)}_{hk} w_{kn} + \sum^m_{k=1} y^{(t-1)}_{hk} v_{kn} + b_n \\
  \end{array}\right)

RNN の活性関数には  tanh をよく使われてる。
これはこんな関数らしい


y = f(u) = \frac{ exp(u) - exp(-u) }{ exp(u) + exp(-u) }

もう少しシンプルな書き方で一般化して


u^{(t)} = \sum^m_{k=1} x^{(t)}_{k} w_{k} + \sum^m_{k=1} y^{(t-1)}_{k} v_{k} + b \\
y^{(t)} = f(u^{(t)})
続きを読む

Salesforce開発の基礎編6

データベースと .NET の基本

trailhead.salesforce.com

.NET は忘れていい。というか引きずると超ハメられる。
決して .NET 程リッチなつくりではないのだから…。

SQL から SOQL への移行

  • SOQL はあくまで検索機能しかない (insert, update 等は DML であって SOQL ではない)
  • SOQL は標準的に SELECT * はできない(ことになっている)。
    調べれば分かるが summer 21 アップデートで FIELDS が入るので、事実上の * はできるようになる。(制限として 200 行以下縛りがある)Salesforce Spring '21の新機能、SOQLのFIELDS()関数について - TerraSkyBase | テラスカイを支える人とテクノロジーの情報を発信する基地局
    通常は必要なフィールドを全部列挙する。
  • クエリの作成は ワークベンチ を使うこともできる。てーかめんどくさくて普通の開発では使わないけど。
  • LIKE 等は普通に使える。ORDER BYLIMIT 等も普通に使える。
  • JOIN はできない。CONTAIN も存在しないし、サブクエリも実質存在しない(SQL使いにしてみれば F〇CK YOU! と叫びたくなる)
  • has-a 関係やリレーション項目が存在していれば、そこを経由して検索することができる。
    SELECT Name, (Select FirstName, LastName FROM Contacts) FROM Account

SOSL クエリの作成

全文検索クエリが使える。SOSL 基盤には Lucene が使われている。
ただしインデックスがどう使われるかは開発者が操作できない…

FIND {"grand*"} IN ALL FIELDS RETURNING Account(Name), Contact(LastName, FirstName, Email)

まぁ割と見たまま過ぎて突っ込むこともないよね。

効率的なクエリの作成

クエリ自体はバックエンドが Oracle なんでオプティマイズはその辺任せ。
デフォルトでは以下の項目にインデックスができる。
インデックスは DB が高速に検索するための設定

  • Id
  • Name
  • OwnerId
  • CreatedDate, SystemModStamp
  • RecordType
  • 主従項目、参照項目
  • unique 制約を入れた項目
  • 外部ID項目

クエリプランは開発者コンソールから

f:id:white-azalea:20210525200819p:plain
f:id:white-azalea:20210525200847p:plain
f:id:white-azalea:20210525201006p:plain

で出てくる

DML を使用したレコードの変更

開発者コンソールからガンガン行ける。

f:id:white-azalea:20210525201153p:plain

もしくは insert などのDML句を使おう。Database クラスからでも操作できる。

// Add Account
Account acct = new Account(
    Name='Test Account',
    Phone='(225)555-8989',
    NumberOfEmployees=10,
    BillingCity='Baton Rouge');
Database.SaveResult[] results = Database.insert(acct, false);
続きを読む