OmniAICreator/Qiita-1.07M huggingface dataset:
Instanaの便利な使い方　第1回　性能改善対象の見つけ方

# はじめに

こんにちは、Airitech株式会社の代表取締役をしている、山﨑政憲と申します。
これからInstanaの便利な使い方や、現場で活躍した事例をいくつか紹介していこうと思います。

# Instanaとは

InstanaはIBMが提供しているObserbavilityツールです。
私は起業した2017年からInstanaを性能改善やトラブルシューティングに活用しており、「早い」「美味い」「安い」と三拍子揃ったInstanaの便利さを日々、実感しています。
Instana好きが高じてIBM Championの認定も受けていましす。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/8dd06a80-9c0e-bead-57bf-fff3bc5357c1.png)


Airitechでは、X上でマンガも掲載しています。
こちらもご覧ください。
https://x.com/AiritechSupport/status/1765633493084893569
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/f3d27c44-a4b1-ede6-1fbf-5765d1bbec2b.png)

# 本題、性能改善対象の見つけ方

さて、みなさん、担当しているシステムの性能改善に取り組む場合、取り組む対象をどうやって選別するでしょうか？
ユーザからクレームが来たり、タイムアウトエラーになっていたら分かり易いですが、それって、かなり不味い状態ですよね。
そうなる前に見つける方法があると便利ですよね。

# Instanaでの見つけ方
### Analytics（分析）画面を使う
Instanaで改善対象を見つけるにはAnalytics（分析）機能を使います。
分析機能は以下のような画面構成で、Instanaが記録したトレースの分類、集計が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/55f4d0e5-9fbc-205a-e4fa-3f13447fdfd0.png)

以下、分析画面を使った改善対象の絞り込み操作の方法を説明します。

### フィルタリング条件を指定する
Analytics（分析）画面では、集計対象のフィルタリングが可能です。
ここで、フィルタでCall Typeを指定し、グループで集計対象を指定します。

#### HTTPリクエストを集計対象とする場合

Call TypeにHTTPを、グループにHTTP Pathを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/a453edcd-e6b3-d9d8-eede-00c5f0a04273.png)

#### SQLを集計対象とする場合

Call TypeにDATABASEを、グループにDatabase Statementを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/9488d681-fc24-16dc-7d0e-c3d9820fa641.png)

### 表示項目を追加する

デフォルトでは、表示項目には、待ち時間（平均値）、エラーのある呼び出し率（平均値）しかありません。
これに、待ち時間（95th）、待ち時間（最大）、待ち時間（sum）を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/ecc63ab9-7e32-1935-9d86-411d2b400605.png)

### ソート条件を指定する

最後に、ソート条件に「待ち時間（合計）」を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/1a1e2161-98ea-a66e-6633-5c78ed835aea.png)

これで準備完了です。

### 改善対象の見極め

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76238/8a09352a-4520-6ae3-070b-58f88d0275fb.png)

これは、あるシステムでの集計結果です。まず、No. 1の処理だけで、25.7%を占めている事が分かります。
この処理を改善することが、システムへの影響が最も大きいということになります。
また、以下の2パターンが存在すると分かります。

a. 呼び出し回数が多く、一回の処理時間が短い
b. 呼び出し回数が少なく、一回の処理時間が長い

基本的には上位のものから改善していけば良いのですが、今回、No. 1がタイプaであることから、No. 1の修正方法が他のタイプaに流用できる可能性も確認すると良いでしょう。
上手くすれば、大半の機能の性能を大きく改善出来るかも知れません。

# 他のObserbavilityツールでは？

他のObserbavilityツールでも同じような分析が可能です。
パフォーマンスインパクトという名称で呼ばれていたりもするので、他のObserbavilityツールを使われている方も探してみると良いでしょう。

# さいごに

いかがでしたでしょうか？
Instanaの使い方、効果に興味を持たれた方はIBMのSoftware Salonでも使い方や事例について解説しているので、ぜひ、ご覧になってみてください。

IBM Software Salon 第10回 (2024/9/19)
トラブル解決でヒーローになろう！障害事例にみるObservabilityツール活用の勘所
https://video.ibm.com/recorded/133995814

また、Instanaユーザコミュニティも、定期的にイベントを行っています。
こちらもぜひ、ご覧ください。
https://instanautsjp.connpass.com/

それでは、今後もInstanaの便利な使い方や事例の紹介を行いますので、よろしくお願いいたします。
【Minecraft】Dynmapをmodブロックに対応させる

## Dynmapとは
Dynmapとは，webブラウザからリアルタイムでマップを確認できる便利なプラグイン/modです．

ここではその導入方法は扱いません．他のサイトを参考に導入してみてください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825073/df2a88e2-534f-8f7d-2e00-02999444c844.png)


## modブロックに対応していない
Forgeでサーバーを立て，Dynmapを導入しました．

しかし，他のmodで追加されたブロックはマップには表示されず，透明になってしまいます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825073/8feb36c1-ca95-694f-d471-b4fde51d5ce0.png)

これは黄昏の森modの森ですが，modで追加された木が表示されていません．


## 解決方法
modで追加されたブロックのテクスチャや状態をDynmapがレンダリングできるようにする必要があります．

手作業でもできるらしいですが，非常に面倒です．

そこで，Dynmap公式が提供している[DynmapBlockScan](https://www.dynmap.us/builds/DynmapBlockScan/)を導入するだけで解決できます．

2024年11月現在，1.20までサポートされており，1.21はベータ版として対応しているようです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825073/ad8aa017-5455-2b53-024f-d0d3be341677.png)


## 最後に
Dynmapにmod対応ブロックを追加することができました．

何かあればご連絡ください．


## 参考
https://www.reddit.com/r/Dynmap/comments/q040h7/dynmapblockscan_updated_includes_addition_of_1165/
https://github.com/webbukkit/dynmap/issues/2062
https://ma.d77.jp/2016/07/10/dynmap%E3%82%92mod%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
【Rails】レコードが見つからない場合におけるfindとfind_byの挙動の違い

## はじめに

Railsの`find`メソッドと`find_by`メソッドはレコードが見つからない時の挙動が異なります。
<br>

どっちがどっちだったかいつも忘れるため、備忘録としてまとめます。

## レコードが見つからない場合におけるfindとfind_byの挙動の違い

レコードが見つからない場合の両者の挙動は次のとおりです。

- `find`メソッド：`ActiveRecord::RecordNotFound`エラーを返す
- `find_by`メソッド：`nil`を返す

## 実際の挙動を確認

実際の挙動を確認して終わります。

### `find`メソッド（ActiveRecord::RecordNotFoundエラーが発生）

```ruby
sample-app> Book.find(99999999)
  Book Load (0.6ms)  SELECT "books".* FROM "books" WHERE "books"."id" = ? LIMIT ?  [["id", 99999999], ["LIMIT", 1]]
/opt/homebrew/lib/ruby/gems/3.3.0/gems/irb-1.14.0/lib/irb.rb:1285:in `full_message': Couldn't find Book with 'id'=99999999 (ActiveRecord::RecordNotFound)
```

### `find_by`メソッド（nil を返す）

```ruby
sample-app> Book.find_by(id: 99999999)
  Book Load (0.4ms)  SELECT "books".* FROM "books" WHERE "books"."id" = ? LIMIT ?  [["id", 99999999], ["LIMIT", 1]]
=> nil
```

## おわりに

完全に記憶に定着するまで、何度でもアウトプットしていきます。
CSSでできる簡単な読込中のぐるぐるの比較

## CSSで読込中のぐるぐるを作成

CSSのanimationプロパティで読込中のぐるぐるを作ってみました。
こんな感じで記述できます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="mdNQPEg" data-pen-title="Untitled" data-user="8787kazuye" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/8787kazuye/pen/mdNQPEg">
  Untitled</a> by 8787kazuye (<a href="https://codepen.io/8787kazuye">@8787kazuye</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

それぞれの設定はCSSのコメントに書いてある通りです。
ChatGPTにお願いしたらささっと作ってくれました。


## ぐるぐるの比較

ぐるぐるをいろいろ作って比較してみました。主にspinのタイミング関数を変更した比較です。少し自分でコードを書いた後に、同じ感じで増やしてくれ、とChatGPTに頼んだら、これもささっとやってくれました。(3行目とbounceはspinではないですが)

<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="WNVgeXX" data-pen-title="読込中のぐるぐる" data-user="8787kazuye" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/8787kazuye/pen/WNVgeXX">
  読込中のぐるぐる</a> by 8787kazuye (<a href="https://codepen.io/8787kazuye">@8787kazuye</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

ぐるぐるをつくるときの参考にしてください。
私はease-in-outがお気に入りです。
ERR_UNSAFE_PORTがEdgeやchromeで出る場合

https://www.ipentec.com/document/software-google-chrome-microsoft-edge-error-err-unsafe-port-accessing-on-port-10080


## Edgeでショートカットを作成する

* 複数ある場合はカンマで区切る

```
--explicitly-allowed-ports=6697,10080
```
クラスとインターフェースの違いをちゃんと理解する

## はじめに
デザインパターンの勉強をしていてこんなことを思いました。
「抽象クラス」と「インターフェース」の違いってなんだ？
どう使い分けしたらいいんだろう？
インターフェースっていらなくね？
以上を踏まえて、今回は「抽象クラス」と「インターフェース」について知らべてみました。

## 抽象クラスとは？
抽象クラスは「継承関係」にあり、実装クラスに「処理の再利用」を行いたいときに使用する。

### 抽象クラスの特徴
- 抽象クラスを継承した場合、抽象クラス内の抽象メソッドのオーバーライドしないといけない
- インスタンス化できない
- 多重継承はできない
- フィールドをもてる

### IS-Aの法則
抽象クラスは「IS-Aの法則」を満たす必要があるといわれています。 例えば、Car（車） は Vehicle（乗り物） であるという関係です（Car is a Vehicle.）。抽象クラスを利用することで、基底クラスの共通機能を継承し、サブクラスにて特定の機能を実装する形が一般的です。
### サンプルコード
``` 
abstract class Vehicle {
    abstract void move();
}

class Car extends Vehicle {
    void move() {
        System.out.println("Car is moving.");
    }
} 
```
## インターフェースとは？
インターフェースは、クラス仕様としての「型定義」を行うためのものです。インターフェースを通じて、CAN-DO の関係を構築します。

### インターフェースの特徴
- 多重継承が可能
- コンストラクタは不可
- フィールドをもてない

### CAN-DOの関係
インターフェースは、オブジェクトに特定の機能を実装させたい場合に用います。例えば、「車は移動できる」「飛行機も移動できる」という共通の機能をインターフェースとして定義し、それぞれのクラスに実装させることができます。

### サンプルコード
```
interface Movable {
    void move();
}

class Car implements Movable {
    public void move() {
        System.out.println("Car is moving.");
    }
}

class Airplane implements Movable {
    public void move() {
        System.out.println("Airplane is flying.");
    }
}
```
## 両者の違い
| 機能 | 抽象クラス | インターフェース |
|:-----------:|:------------:|:------------:|
| コンストラクタ | あり | なし |
| フィールド | あり | なし |
| 多重継承 | 不可 | 可能 |
| 用途 | 共通の実装や状態を保持 | 型定義、機能の提供 |

## インターフェースのユースケース
- 多重継承が必要な場合
- 実装を持たせたくない場合
- リファクタやAPI設計において、将来の変更に備えたい場合

>例: APIやデータベースの呼び出し先を将来的に変更する場合、インターフェースやそのコントローラー側を修正する必要がなく、実装側の変更だけで済むため、他に影響を与えない疎結合化を実現できる。

## 抽象クラスのユースケース
- 共通の実装や状態を持たせたい場合
- コードの再利用性を高める
- クラス間に強い関係性がある場合

## まとめ
改めて調べることで理解や追加どころはイメージできたけど、
むやみに使いまわすものでもないなと思いました。
小規模なプロジェクトなら使わないほうがむしろいいのかなと。
ご指摘等あればぜひコメントください！
【Swift】30秒で学ぶ多言語対応の方法(String Catalog)

## 1.文字の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/325ff722-8fea-078c-6d92-1e43ecca884e.png)
- ※iOS15以降であれば、`String(localized: "⚪︎⚪︎")`が使える


# 2. 画像の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/e3931b44-a7d1-1e71-09b3-f5a0a32a6a81.png)

# 参考
- https://developer.apple.com/documentation/Xcode/localizing-and-varying-text-with-a-string-catalog
【PHP】事前準備 PHP の開発環境の構築について

まず初めにこの記事は、PHPを使用する人向けの記事となります。
そのために、まず事前準備としてPHPの開発環境を構築していこうと思います。

**使用する環境**
* OS:Winodws11
* XAMPP
* Visual Studio Code
* コマンドプロンプト
* composer
* Laravel
* Node.js


**手順**
1. 「XAMPP」をインストールし、ダウンロードをクリック
2. 「C:\」に解凍
<a href="https://www.apachefriends.org/jp/index.html">XAMPP インストール先はこちら</a>
3. 「XAMPP.exe」を起動し、「Apache」を起動
4. PHP のコードを書くために、「Visual Studio Code」をインストール
<a href="https://azure.microsoft.com/ja-jp/products/visual-studio-code">Visual Studio Code ダウンロード先はこちら</a>
4. 「composer」をインストール
※事前にPHPがインストールされていること
 <a href="https://getcomposer.org/">composer ダウンロード先はこちら</a>
5. 「Windows」のコマンドプロンプトにて下記をたたく
```ruby:コマンドプロンプト
composer --version
```

```ruby:結果
Composer version 2.8.2 2024-10-29 16:12:11
PHP version 8.2.12 (C:\xampp\php\php.exe)
Run the "diagnose" command to get more detailed diagnostics output.
```

7.「Laravel」のインストール
```ruby:コマンドプロンプト
composer create-project laravel/laravel 【作成するプロジェクト名】 --prefer-dist 
```

※エラーが出た場合
```ruby:コマンドプロンプト：エラー結果
git was not found in your PATH, skipping source download
```
* 上記エラーが出たら、Gitをインストールすることでエラーが解消される
<a href="ttps://gitforwindows.org/">Gitダウンロード先はこちら</a>

※gitをダウンロードしてもエラーが出る場合
* 「C:\xampp\php」にある「php.ini」をサクラエディタなどで開き「zip」という単語で検索し、「;」を削除
```ruby:php.ini
962行目;extension=zip
```
* 再度「Laravel」のインストールのコマンドをたたく
→これで「Laravel」のインストールが完了

8.http://127.0.0.1/作成するプロジェクト名/index.php
をたたく
9.下記コマンドをコマンドプロントでたたく
 ```ruby:コマンドプロント
php artisan serve
```
9.「Laravel」のデフォルトの画面が出てきたらOK
10. Node.jsのインストール
<a href="https://nodejs.org/en/">Node.jsダウンロード先はこちら</a>


これで事前準備 PHP 環境構築完了です！
[Scala] Futureのメソッドたち

## メソッド一覧

使ったことがあるものを随時追加していく。

| メソッド名  | Success vs Failure |　型 | メモ |
|:-:|:-:|:-:|:-:|
| map       | Success値へ適応 | TODO | 成功値を成功値へ変換する
| handle    | Failure値へ適応 | TODO | エラー値を成功値へ変換する 
| onSuccess | Success値を受け取る | TODO | 副作用(println等)の処理を行う。-> 値に変更はなし。|
| onFailure | Failure値を受け取る | TODO | 副作用(println等)の処理を行う。-> 値に変更はなし。 |


## 使い方の例

```sc
myRequestFuture
  .onSuccess(logRequestSuccess)        // Future[Response] ⭐️side effect only
  .onFailure(logRequestFailure)        // Future[Response] ⭐️side effect only
  .handle(raiseCustomError)            // Future[Response]
  .map(parseJsonResponse)              // Future[Json]
  .map(Post.buildFromResponseJson)     // Future[Post]
  .onFailure(logCustomError)           // Future[Post]     ⭐️side effect only
```

## Ref.

https://www.scala-lang.org/api/2.13.4/scala/concurrent/Future.html
【AWS】Codepipelineのイベントベースとポーリングベースの違い

## はじめに
実務で、AWSに触れる時イベントベースとポーリングベースのCodePipelineの違いがよくわからなかったので、まとめていきます。

## ポーリングベースとは
Codepipelineの設定。定期的にソースリポジトリをチェックして変更を検出してくれる。

## イベントベースとは
Codepipelineの設定。Amazon EventBridgeを使用して、ソースリポジトリの変更を即時に検出してくれる。

## どっちが推奨されているのか
AWSでは、イベントベースのCodepipelineの設定が推奨されている。ポーリングベースのCodepipelineは以下の理由でAWS公式も推奨をしていない。

>AWS CodePipelineチームは、2023年5月25日より、非アクティブなパイプラインでのポーリングを無効にします。非アクティブなパイプラインとは、過去30日間にパイプラインの実行が開始されていないパイプラインと定義されます。Amazon EventBridgeルール、AWS CodeStar接続、またはウェブフックのみを使用してパイプラインをトリガーする非アクティブなパイプラインは影響を受けません。また、アクティブなパイプラインも影響を受けません。

30日以上利用されていないポーリングベースのパイプラインを無効化してしまう。



## CICDパイプラインの意義からどっちがいいか考える
そもそもCICDパイプラインの存在意義とはなんなのか？

同じ品質で **"早く"** **"安全に"** **"効率的に"** 届けることです。

人間が手動でデプロイすると、何か間違えることもあるし、そもそも人間が足りてないとデプロイすらできないですよね笑

その前提を踏まえると、何かのイベントが発生したら自動で動くように設定する**イベントベース**が好まれるかと思います。

## おわりに
Codepipelineのイベントベースとポーリングベースの違いをまとめてみました。

スピードが勝負のIT業界ならなおさら、イベントベースで使っていきたいですし、承認や許可がいくつも大断してとらないといけない場合は、なおさらデプロイのスピードが落ちてきそうです。

とはいえ、どちらも良し悪しがあると思うので開発の現場に合わせて使っていきたいですね。


## 参考にしたサイト
https://blog.usize-tech.com/aws-codepipeline-change-detection/
Python3: paizaラーニング問題集「部外者をはじけ」を解いてみた

おもしろそうだったのでやってみました。

https://paiza.jp/works/mondai/b_rank_skillcheck_archive/finding_putliers_99

解答例のように個別に距離を測ってもいいんだけど、距離2の平行線の外側って考えると、計算がちょっと軽くならないかな、と思ってやってみる。


```py:
from itertools import combinations
from math import sqrt
from dataclasses import dataclass

@dataclass
class NumberedPoint:
    n: int
    x: float
    y: float
        
DISTANCE = 2.0

def outsiders(points):
    min_outs = [*points]
    
    for p0, p1 in combinations(points, 2):
        tenp_outs = []
        
        if p0.x == p1.x :
            c_smaller = p0.x - DISTANCE
            c_larger = p0.x + DISTANCE
            
            for p2 in points:
                if p2.x <= c_smaller or p2.x >= c_larger :
                    tenp_outs.append(p2)
                if len(tenp_outs) >= len(min_outs):
                    break
                    
        else:
            m = (p1.y - p0.y) / (p1.x - p0.x)  # 傾き
            c = DISTANCE * sqrt(1 + m * m)     # 中心線に加減して平行線にする定数
            c_center = - m * p0.x + p0.y       # 中心線の定数
            c_lower = c_center - c             # 下側の平行線の定数
            c_higher = c_center + c            # 上側の平行線の定数
            
            for p2 in points:
                p_factor = p2.y - m * p2.x
                if p_factor <= c_lower or p_factor >= c_higher :
                    tenp_outs.append(p2)
                if len(tenp_outs) >= len(min_outs):
                    break
                    
        if len(tenp_outs) == 0:
            return []
        if len(tenp_outs) < len(min_outs):
            min_outs = tenp_outs
            
    return min_outs 
    
    
N = int(input())
points = tuple( NumberedPoint(i
                              , *map(float, input().split(" "))
                              )
                for i in range(1, N + 1)
               )    

minimum_outsiders = outsiders(points)

if len(minimum_outsiders) == 0:
    print("none")
else:
    for p in minimum_outsiders:
        print(p.n)
```

ちょっと速くなったかな?
【ServiceNow】複数のナレッジ記事を一括で公開する方法

# 1. はじめに
みなさんこんにちは、三井情報株式会社です。

今回は業務において既に作成済みのナレッジ記事を一括で「公開」する必要があったため、その方法を紹介します。

# 2. バックグラウンドスクリプトの実行
今回はナレッジベース=人事ナレッジの4つのナレッジ記事を一括で公開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574077/30a4337c-38a8-4cf8-8476-c8275a7963e2.png)

1.「システム定義 > スクリプト：バックグラウンド」を開く。
2.以下のスクリプトを実行する。
```javascript
var now_GR = new GlideRecord("kb_knowledge");
now_GR.addQuery("kb_knowledge_base", "(対象のナレッジベースのSysID）");
now_GR.query();

while (now_GR.next()) {
now_GR.setForceUpdate(true);
now_GR.setValue("workflow_state", "published"); // workflow_stateフィールドを更新
now_GR.update(); // レコードを更新
}
```
3.「ナレッジ > 記事 > すべて」から対象のナレッジベース（今回は「人事ナレッジ」）に絞り込む。
4.記事が全て「公開済み」となっていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574077/d2bc9e81-bfd4-4dc7-8820-a8d2fc73b44f.png)


# 3. まとめ
いかがでしたでしょうか。今回は、複数のナレッジ記事を一括で「公開」する方法について紹介しました。

最後までお読みいただき、ありがとうございました。
SFDC Outbound Messageを使ってInformatica CDIでリアルタイム連携を実現

# はじめに
Informaticaはデータマネジメントクラウドを提供しています。その中で、重要な要素の1つとして、データ連携（Cloud Data Integration、略してCDI）があらゆるデータにアクセスし、連携することが可能です。バッチ連携だけでなく、リアルタイム連携にも対応しています。

本日は、Salesforceへのリアルタイム連携シナリオをご紹介したいと思います。
# シナリオ
今回のシナリオはSalesforceのデータが変わりましたら、そのデータをリアルタイムでOracleに転送します。

上記を実現するため、次のステップが必要です。
１．CDIでマッピングタスクを作成
２．SalesforceにOutboundメッセージを設定
３．SFDC側にデータを変更してテストを行う

## １．CDIでマッピングタスクを作成
CDIでマッピングを作って、Salesforceにある変更対象のオブジェクトをソースにして、転送先のOracleをターゲットにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/367b672b-c1ac-de33-c790-6f0943e67142.png)

マッピングを作りましたら、これを基づいてマッピングタスクを作成します。次は重要なポイントとなり、スケジュールの設定に「Salesforceからの送信メッセージの受信時にリアルタイムで実行します」を指定します。URLをコピーして、後ほどSalesforce側の設定に使われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/650163d8-51ef-7502-ae04-61ec514c1542.png)

## ２．SalesforceにOutboundメッセージを設定
Salesforceにログインして、右上の歯車アイコンをクリックして、設定画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/38efcf60-9e36-1348-81e4-772b7731674c.png)

左のクイック検索ボックスに「アウトバウンドメッセージ」を入力して、アウトバウントメッセージの設定画面を開きます。ここに、メッセージ詳細を設定します。

**名前：** アウトバウンドメッセージの名前を入れます。
**エンドポイントURL：** 前のステップにコピーされたIDMCのマッピングタスクのエンドポイントURLをここに貼り付けます。
**送信する項目：** SFDCからIDMCに送る項目を選んでください。IDMCが選ばれた項目の値しか取れないため、転送したい項目を全部右に移してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/115f90b7-516e-ebcf-7719-f73cb7f28f93.png)

## ３．SFDC側にデータを変更してテストを行う
上記の設定が終わりましたら、Salesforceのデータを変更して、IDMC側にジョブの実行状況を確認しましょう。

下記オブジェクトのCol2の値を変更してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/8de5d4ff-6e1c-c884-ab32-437dbd736e01.png)

そうすると、IDMCのモニター画面に、新しいのジョブが開始されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/8684d64d-e25d-82ba-ec66-4ae58b1ff0a8.png)

インスタンス名をクリックして、詳細を確認すると、１レコードがOracleに成功で転送されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/d20d883f-2749-a38f-ef91-1fd24219c947.png)

# まとめ
いかがでしょう。とても簡単ではないでしょうか。

Salesforceをご利用頂いてる方はリアルタイム連携したい際に、そしてデータの加工変換処理が必要となってCDIをご利用する必要がある場合、Outboundメッセージを活用して、IDMCのCDIジョブをキックしましょう。
35歳の壁

私は2024年11月1日に転職し、3社目になります。

# 1社目
1社目は20名くらいのベンチャーで、自分の活躍以上に評価され、期待されていたような気がします。
ですが、以下のような理由で転職を考えました。
- 社長に見積もり案を出すと、勝手に大幅納期短縮された状態で決定されるため、残業が常態化する
- 請負なのに顧客がマイクロマネジメントをしてくるため必要以上に準備の工数が必要になり遅延が発生し、残業が常態化する
- 過去に開発した案件の保守を並行して行う必要があり、また不具合がどこにあるか分からないというシステムも引き継いでいるため、不具合発生時には開発工数とは別で工数を確保する必要があるが、開発案件の顧客とは契約上一人日MAXで請け負うので、残業で対応する必要がある
- 上司である部長が、顧客との契約内容を伝達しない、自分で言ったことをやらない、質問に対してもちゃんと答えない、といった雑な仕事をする

若手は優秀だったし、社長の手腕もよく業績が良かったし、年収もそれなりに良かったんですが、このまま続けていくと潰れそうという感覚があって、正直年収もそんなに欲しいと思ってなかったので、辞めました。
あとは、もっと先端技術に触れたいなと漠然と考えながら、転職しました。

# 2社目
転職先では残業もかなり少なく、先端技術に触れる機会も多かったし、良かったと思います。
しかし、数年働いている中で、将来の不安がわいてきました。
- 長期のプロジェクトに関わる中で、自分が社会に対して価値を提供できている、貢献している実感が持てない
- 自分が優秀だと感じる人だろうと、言われたことをやっているだけの人だろうと、年次に応じてリーダー格に昇格していく
- 一方で、市場としては35歳で管理職を経験していないと厳しい目で見られると評価される中で、この会社で管理職になるのは大体40歳からで、自分はこのままではチームリーダーすら担うか怪しい
- 年収面も前職の上昇率から比べると圧倒的に低い。近年業績も悪い上に赤字の投資をしまくっているので、上がる可能性が低い
- メインの顧客の業界が衰退業界であり、財布の紐が硬く、収益化が難しい。単価が安すぎる
- 技術力が低く、生産性が低い。技術を知らない人がフィジビリティや費用対効果を考えずにプロジェクトを進めているように感じる

35歳の壁を前にして、「将来のキャリアビジョンをしっかりと持つべきだ」と気付かされ、今後のキャリアに対する考えが深まっていきました。このままでは単に経験を重ねるだけにとどまり、年齢を重ねたときに十分なキャリアパスを築けないという危機感が募りました。
同時に、今いる会社で長期的に抱えている課題があり、それらの解決策がまったく思いつかないようなスキルレベルで転職活動をしてはいけないなと思い、今いる会社でできることをしていかなければならないと強く感じました。

# 転職のトリガー
そんな中、ネットサーフィンとしているとふと**転職ドラフト**が目にとまり、あと3日くらいで次回のエントリー締め切りだったので、急いでレジュメを完成させました。そのレジュメのレビューを通して、自分の直すべき点を知りたいと思っていました。そしたらなぜか一発で通りました。そして年収が1.5倍以上のオファーも２件きました。これが転職活動を始めるトリガーになったと思います。
でも面接がうまくいかず、YouTubeでよく見る**KIKKAKE AGENT**さんを頼り、面接対策なども行なってもらうことにしました。ありがたいことに、転職活動終盤はどんな企業でも全然落とされなくなりました。
※　ちょっとだけ気になっているのは、今入社した会社の代表との最終面接において、エージェント側から当社の説明があったと思うが、と言われましたが、私には特にはありませんでした。おそらく他の候補者には会社の説明があったのだろうと思います。

転職においては、技術力のない人が入りにくい会社を選ぶべきだと考えていました。そういう点で、コーディング試験や技術試験のあるところの企業は好印象でしたし、そういった企業は面接の難易度も総じて高かったのではないかと思います。
※　驚いたことに入った会社では新卒でも同様の選考フローであり、「新卒のレベルが高い」とよく聞くので、これからのお楽しみにしています。

# 3社目
入った会社は透明性が高く、フィードバックもすごく多く、その内容が非常に自分の価値観とも合うと感じました。前回の記事でも触れましたが、一般的に多くの人が良いと認識しているであろう会社さんから多数内定をいただくことができました。それでも、これまでの面接やフィードバック、開示されている情報から非常に興味を持っていたので、今の会社に決めることに、あまり悩むことはありませんでした。
まだ入社して１週間ですが、面白い会社だと感じます。

# まとめ
改めて、今回のキャンペーンは「今年の転職活動で考えたこと、やったことを書き残そう」になるので、まとめます。
35歳の壁を前にこのままではいけないという危機感を覚え、以下のようなことを考え、実践してきました。

## 考えたこと
- キャリアへの危機感
- どういう会社が良いのか、自分にマッチしているのか
- 自分は見合う実力があるのか

## やったこと
- 働き方や将来性を考慮した転職
- 自己認識と改善
Pythonでコサイン類似性(Cosine Similarity)計算のまとめ

# scikit-learn
```python
from sklearn.metrics.pairwise import cosine_similarity 
import numpy as np 

a = [2, 15, 3, 25] 
b = [5, 25, 8, 28] 

array_1 = np.array([a]) 
array_2 = np.array([b]) 
cos_sim = cosine_similarity(array_1 , array_2) 
print(cos_sim) 
# 結果: 
# [[0.9753719]] 
```
# NumPy
```python
from numpy import dot 
from numpy.linalg import norm 

a = [2, 15, 3, 25] 
b = [5, 25, 8, 28] 

cos_sim = dot(a, b) / (norm(a) * norm(b)) 
print(cos_sim) 
# 結果: 
# 0.9753719044721808 
```
【git stash】Gitで「git addしていないファイルのみ」をstashする方法

Gitで作業中に「git addしていないファイルのみ」を一時的に退避（stash）させたい場合、通常のgit stashコマンドではインデックスに追加した変更も含まれてしまいます。ここでは、インデックスに追加していない変更だけをstashに保存する方法をいくつかの手順に分けて説明します。

### 手順
**1.インデックスに追加した変更を保持しつつ、未addの変更のみをstashする**
最初に、インデックスに追加していない変更だけをstashに保存したい場合は、git stash push --keep-indexコマンドを使用します。このコマンドを使うと、インデックスに追加されたファイルはそのままで、git addしていない変更だけがstashに保存されます。
```
git stash push --keep-index
```

**2. 追跡されていないファイル（新規ファイル）もstashに含めたい場合**
git stash push --keep-indexコマンドでは、未追跡（untracked）ファイルはstashに含まれません。もし新たに作成したファイルやディレクトリを含めてstashしたい場合は、-u（または--include-untracked）オプションを追加して実行します。
```
git stash push --keep-index -u
```

### コマンドの詳細
* git stash push --keep-index
インデックスに追加されていない（git addしていない）変更のみをstashに保存します。これにより、作業中の変更がstashされ、インデックスに追加された変更はそのまま保持されます。

* -u（または--include-untracked）オプション
このオプションを使うことで、未追跡ファイル（新規作成したファイルやディレクトリ）もstashに含めることができます。

### まとめ
* git stash push --keep-indexでインデックスに追加していない変更のみをstashに保存できます。
* -uオプションを使用することで、追跡されていないファイルもstashに含めることができます。

これで、git addしていないファイルや変更のみを一時的に退避させ、後で元の状態に戻すことができます。stashの内容を戻すには、git stash popを使って復元できます。
TROCCOにて転送元のファイル名称に含まれる日付データをカラムに追加する方法②

TROCCOのカスタマーサクセスを担当しております宮崎と申します。

ファイル名称をカラムに追加する方法についてもう2つめの方法をご説明いたします。
**②ファイル名をカスタム変数として、ワークフロー実行時にファイル名そのものを利用する方法**

## ②ファイル名をカスタム変数として、ワークフロー実行時にファイル名そのものを利用する方法
### ▪️転送設定の設定
#### 転送設定STEP1

ファイル名を取得するためのカスタム変数を作成します。ファイル名取得できるように変数を設定します。ファイルプレフィックスのファイル名に作成した変数を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/c979ae90-fcc0-aeb5-1e16-df6307188f23.png)


#### 転送設定STEP2

次に、カラム定義で新しいカラムを追加します。ファイル名を格納するカラム名を指定し、デフォルト値に**変数**を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/a172c628-cc2a-6ec9-e6ba-2f4d7366a03f.png)

転送設定での設定は以上となりますので、必要に応じてそのほかの設定を追加いただき転送設定を保存してください。


### ▪️ワークフローの設定
#### ワークフローにてループ実行を設定

ワークフローを作成し、転送設定の編集をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/e2e8e394-f9fe-7844-9f48-82c225d61805.png)


カスタム変数で「ループ実行」にチェックを入れ、適切な項目を設定します。

- ループの種類：文字列展開）
- 対象カスタム変数：作成した変数を選択
- 回数：変数に設定するファイル名を指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/25d2c554-4aaa-d1e0-ae8c-a4e76630a3b8.png)

上記の設定を行うと、実行時に変数（ファイルプレフィックス、追加したカラム）が設定され実行されます。
合致したデータがあれば、カラムに日付が追加されデータ転送されます。

### ▪️転送後データ確認

BigQueryにデータが正しく転送されたことを、以下のように確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/0a354177-db90-276f-ac45-5666e5a34e6a.png)

最後までお読みいただき、ありがとうございました。この記事がデータ活用の一助となれば幸いです。
TROCCOにて転送元のファイル名称に含まれる日付データをカラムに追加する方法①

TROCCOのカスタマーサクセスを担当しております宮崎と申します。

今回は、先日お客様からいただいたお問い合わせに関する内容で、同じような問題でお困りの方の参考になればと思い、この記事を書きました。

お問い合わせ内容 転送元がBoxなどのストレージに配置されているExcelファイルなどのファイル名に日付情報が含まれている場合、その日付をカラムに追加する方法についてです。他のツールのように「ファイル名をカラムに追加するオプション機能」が現時点では提供されていないため、少し工夫が必要です。

今回は、以下の2つの方法を提案します。

**①日付データを変数として設定し、ワークフローのループ実行で日付を動的に取得する方法**
**②ファイル名をカスタム変数として、ワークフロー実行時にファイル名そのものを利用する方法**

この記事では、まずBoxからBigQueryへの転送設定を例に、1つ目の方法について説明します。
方法は2つございます。


## ①日付データを変数設定に、ワークフローのループ実行で日付を動的に取得してくる方法
### ▪️転送設定の設定
#### 転送設定STEP1

日付を取得するためのカスタム変数を作成します。ファイル名の日付フォーマットに合わせて、日付を正しく取得できるように変数を設定します。ファイルプレフィックスのファイル名に含まれる日付部分に、作成した変数を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/b7be16fb-4120-cc43-4b0b-0b9f8156f9df.png)

#### 転送設定STEP2

次に、カラム定義で新しいカラムを追加します。日付を格納するカラム名を指定し、デフォルト値に**変数**を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/5aa7833b-1f23-4e8b-9973-d59d2e109f2e.png)

:::note warn
**出力オプションについて**
カラム定義ではデータ型がtimestampとなるため、DATE型でデータを連携したい場合は、出力オプションでDATE型を指定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/f7708773-c6c4-fbd3-aa90-e5b58a9a2e76.png)
:::

転送設定での設定は以上となりますので、必要に応じてそのほかの設定を追加いただき転送設定を保存してください。


### ▪️ワークフローの設定
#### ワークフローにてループ実行を設定

ワークフローを作成し、転送設定の編集をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/15e88f17-c9f3-2b93-534e-fbac89befed4.png)

カスタム変数で「ループ実行」にチェックを入れ、適切な項目を設定します。

- ループの種類：期間（相対指定）
- 対象カスタム変数：作成した変数を選択
- 期間：変数に設定する期間を指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/43823939-c430-24a2-4e52-9a818e6cf32a.png)

上記の設定を行うと、実行時に変数へ下記の日付順に設定され実行されます。（実行日2024/10/25）
合致したデータがあれば、カラムに日付が追加されデータ転送されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/4413c00a-1048-4b71-aad5-e075ac669826.png)


### ▪️転送後データ確認

BigQueryにデータが正しく転送されたことを、以下のように確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860109/b10e0fd7-6375-60ac-45e1-ddb7deff8b0c.png)

②については、また別の記事でご紹介します！

最後までお読みいただき、ありがとうございました。この記事がデータ活用の一助となれば幸いです。
Ubuntu 20.04 複数install PHP切り替えにおける処理

今回Ubuntu 20.04において、標準インストールのPHP8.3から旧バージョン PHP7.3を複数インストールし、バージョン切り替え、とその後 Webサーバ Apache2上でも完全に切り替える処置の覚書を投稿します。
まずは切り替えたいばーじょんの PHP(今回は 7.3)を必要なパッケージ共インストールする。
 ```
例：
apt install php7.3 php7.3-fpm
apt install php7.3-curl php7.3-gd php7.3-mbstring php7.3-mysql php7.3-pgsql php7.3-xml
インストール後
update-alternatives --config php
上記コマンドより、選択
There are 2 choices for the alternative php (providing /usr/bin/php).

  Selection    Path             Priority   Status
------------------------------------------------------------
  0            /usr/bin/php8.3   120       auto mode
* 1            /usr/bin/php7.3   73        manual mode
  2            /usr/bin/php8.3   120       manual mode

Press <enter> to keep the current choice[*], or type selection number:
php-v バージョン確認
PHP 7.3.33-21+ubuntu20.04.1.....
```
この処理後、systemctl restart apache2　してもApache2上では切り替わっていません。
サイトでphpinfoを確認しても、前のままなので、下記コマンドにてApache上でも認識させる処理をします。
```
 a2dismod php8.3
 systemctl restart apache2
 a2enmod php7.3
 systemctl restart apache2
 ```
 これにより Apache2上でもPHPのバージョンが切り替わります。

 参考サイト:
 https://qiita.com/murakami77/items/a9945f2a8e51ca3791de
 https://qiita.com/berukokoko/items/21a76b1e6e76eda9f5ee
vimの最低限の操作

アウトプット用
最低限のことです。
# vim基本操作
##4つのモード
`esc`: ノーマルモード
`i`: 入力モード
`v`: 選択モード
`:` コマンドモード


## 移動系
### 基本①
`h`左へ移動
`j`下へ移動
`k`上へ移動
`l`右へ移動


### 基本②
`w`次の単語の先頭へ移動
`e`次の単語の末尾へ移動
`b`前の単語の先頭へ移動
`0`行の先頭へ移動
`$`行の末尾へ移動
`gg`ファイルの先頭へ移動
`G`ファイルの最後へ移動
`:数字`数字列へ移動(:10→10行目に移動)


## 保存& 終了系
`vim`vimを起動
`:q!`保存しないで編集終了
`:w`ファイル名:名前をつけて保存
`:w`上書き保存
`:q`編集終了
`:wq!`保存して終了


## 編集&削除系
### 基本①
`i`カーソル直下から編集開始
`a`カーソルの次の文字から編集開始
`o`カーソルの次の行から編集開始
`dd`行ごと削除
`p`貼り付け(ddの後にpをするとddで直前に削除したものを貼り付ける)
`x`カーソル直下の文字削除
`r`カーソル直下の文字削除&変更
`yw`単語コピー
`yy`行コピー
`u`取り消し
`control+R`取消の取り消し

### 検索&置換系
`/単語`上から下に単語を検索(/vim→**vim**という文字を検索)
`?単語`上から下に単語を検索
`:s/old/new`カーソルがあったている部分から最初に見つけた文字だけ置換
`:#,#s/old/new/g`2つの#の間で語句を置換する
`:%s/old/new/g`ファイルの中のすべての検索語句を置換する
Rails で DB から取得するデータに対し order が効かない場合


# 修正前
* 条件に応じてソート方法を分岐させたくて以下のように実装
    * しかし機能しなかった
```ruby:修正前
def search
    result = Post.all.order(created_at: :desc)
    if #-条件-#
        result = result.order(:created_at)
    end
end
```

# 修正後
* 以下のように修正したら機能
```ruby:修正後
def search
    result = Post.all
    if #-条件-#
        result = result.order(:created_at)
    end
end
```

# メモ
* この場合は `Post.all` の時点で「id の降順」になっているので、実質「created_at の降順」であったので余計な order になっていた
npm script で呼ばれたjs内でTerminal側の作業ディレクトリを参照する

```js:runner.cjs
const process = require("node:process");

// これは nodejs の作業ディレクトリ
const CWD = process.cwd();

// こっちは terminal(bash | PowerShell | CMD) の作業ディレクトリ
// PWD - bashから参照可
// INIT_CWD - bash | PowerShell | CMD で参照可
const PWD = process.env.PWD || process.env.INIT_CWD;
```
AsiaRF Wi-Fi HaLow Raspberry Pi HAT Module を日本の周波数で動かす

# この記事について
[AsiaRF社製の Wi-Fi HaLow Raspberry Pi HAT Module](https://asiarf.com/product/wi-fi-halow-raspberry-pi-hat-module-mm610x-h06/) を日本で合法に使用するための設定です。
日本仕様で動作させるためのパラメータ値がドキュメント類のどこにも記載されていないため、自分で調べたので、その結果をまとめました。

# AsiaRF Wi-Fi HaLow HAT とは？
名前の通り、台湾 AsiaRF社が販売している、Raspberry Pi 用のWi-Fi HaLow HATです。TELECの認証も通っており、（法的には）日本でも安心して使用できる製品です。
詳細は以下の販売サイトをご確認ください。
https://asiarf.com/product/wi-fi-halow-raspberry-pi-hat-module-mm610x-h06/

# 手順
## 事前準備
製品を購入すると、必要なドライバ等が組み込み済みの Raspberry Pi OS のディスクイメージをAsiaRF社からもらうことができますので、それを使用します。

## HaLow設定
デフォルトだとUS仕様の周波数で動作する設定になっているので、そのまま動かすと電波法的にまずい状況になります。
そのため、以下の設定ファイルを修正します。

### morse.conf
`/etc/modprobe.d/morse.conf`   
→ country_code を `JP` に変更します。

``` /etc/modprobe.d/morse.conf
JP
```

### hostapd-phy0.conf
この HAT を Wi-Fi AP(親機)として動作させる場合は、`hostapd-phy0.conf` を以下の通り設定します。

`/etc/hostapd_s1g/hostapd-phy0.conf`   
→使用する周波数幅・周波数帯と、ssid/passphease 等を設定します。以下のパラメータの値を修正します。
``` /etc/hostapd_s1g/hostapd-phy0.conf
   : 
  前略
   : 
country_code=JP
op_class=65
channel=36
chanlist=36
wpa=2
ssid=my_ssid
wpa_passphrase=my_passphrase
   : 
  後略
   : 
```
パラメータごとの値の意味は以下の通りです。

| パラメータ名| パラメータの意味 | 設定値と意味 | 備考 |
|-|-|-| -|
|`country_code`|国コード|`JP`固定| |
|`op_class` | 周波数帯域幅 | `73` : 1MHz <br> `64` : 2MHz <br> `65` : 4MHz | |
|`channel` | 使用するチャンネル（周波数帯） | `op_class`=1MHzの場合 <br> - `13` : 923.0 <br> - `15` : 924.0 <br> - `17` : 925.0 <br> - `19` : 926.0 <br> - `21` : 927.0 <br> `op_class`=2MHzの場合 <br> - `2` : 923.5 <br> - `4` : 924.5 <br> - `6` : 925.5 <br> - `8` : 926.5 <br> `op_class`=4MHzの場合 <br> - `36` : 924.5 <br> - `38` : 925.5 <br> | `op_class` と `channel` の設定値に矛盾がないようにする |
|`chanlist`| チャンネルのリスト？ | とりあえず `channel` と同じ値をセットしておく | |
|`wpa`| 暗号化 | `2` : WPA2/3 を有効化 <br> `0` : 暗号化なし | |
| `ssid` <br> `wpa_passphrase` | SSID/パスワード | Wi-Fi の SSIDとパスワードの値を設定する | |

### hostapd-phy0.conf
この HAT を Wi-Fi Station(子機) として動作させる場合は、`wpa_supplicant-wlan0.conf` を以下の通り設定します。

`/etc/wpa_supplicant_s1g/wpa_supplicant-wlan0.conf`
``` /etc/wpa_supplicant_s1g/wpa_supplicant-wlan0.conf
country=JP
ssid=my_ssid
psk=my_passphrase
```
パラメータごとの値の意味は以下の通りです。

| パラメータ名| パラメータの意味 | 設定値 | 
|-|-|-| 
|`country`|国コード|`JP`固定| 
|`ssid` <br> `psk` | SSID/パスワード | 親機のSSIDとパスワードの値を設定する | 

## 設定後
いったん reboot してから、`./run_halow_ap.sh`(親機の場合) `./run_halow_sta.sh` を実行すれば、HaLow の無線が動作しはじめます。

# 余談: 他機種との接続性について
2024/11時点で、Wi-Fi HaLow はチップメーカーごと（もしくは機器メーカーごと）の相互接続性がまだ厳しいようです。
このAsiaRFのHATはMorse Micro社製のチップが使われていますが、同じくMorse Microのチップが使われている[センチュリーシステムズ社製MA-S120/LH](https://www.centurysys.co.jp/products/linuxserver/mas120.html) とは接続できました。
対して、Newracom社製チップが使われている他社HaLow機器との接続はできませんでした。

この相互接続性の問題は、現在機器メーカー・チップメーカー側で頑張っているようですので、少し待ちましょう :-)
【初心者向け】 Pythonでやってはいけないこと

# はじめに
この記事ではPythonでコードを書くときなどに、あまりお勧めしないことを紹介します。

## 1.ファイル名をモジュール名と同じにする
```python:tkinter.py
import tkinter as tk

root = tk.Tk()

root.mainloop()

# 実行するとエラーになる
```
僕もPythonをはじめてすぐの時にこのエラーが起きて焦りました

## 2.変数名を日本語、ローマ字にする
```python:main.py
日付 = "2000-01-01"
zikan = 10
```
これはPythonに限った話ではないですが、変数名や関数名などの名前をつける時はわかりやすく英語でつけようということです。

## 3.仮想環境を作らない
全部メインのPythonにモジュールを入れると依存関係でややこしくなることがあります。仮想環境の作り方は、
### venv
```bash
$ python -m venv hoge
```

### anaconda
```bash
$ conda create -n hoge
```

です。
メインのPythonにはよく使うものだけ入れましょう。

# おわりに
最後まで読んでいただきありがとうございました。
コードを書くときにちょっと参考にしていただくと嬉しいです。
PyScript上でopenaiパッケージを使う方法

## 事象
PyScript (2024.10.1)上で`openai`パッケージを使おうとすると、次のようなエラーが出て失敗します：
```
ValueError: Can't find a pure Python 3 wheel for: 'jiter<1, >=0.4.0'
```

## 原因
`openai`パッケージは`jiter`パッケージに依存しているのですが、このパッケージがPure Pythonではない（Rustで書かれている）ため、PyScript / Pyodideで使用できるパッケージに含まれていません。この問題は`openai`パッケージのgithubで[issueとして挙げられている](https://github.com/openai/openai-python/issues/1782)のですが、2024年10月時点では解決していません。

## 解決方法
自力で`jiter`パッケージのwheelを作成し、これをローカルにおいてPyScriptからロードさせます。

[以下のDockerfile](https://gist.github.com/narumichiaki/0cb32c5b6db64493d19066a9ca3aeccb)を`DOCKER_BUILDKIT=1 docker build --file Dockerfile --output out .`等で走らせると、Pyscriptで使えるwheelが出力されます。注意点として、Pyodideのコンパイルに使用されたものと同じバージョンのPythonとEmscriptenを使う必要がありますので、ご自身が用いたいバージョンに応じて変更してください。

```Dockerfile
# wasm32 compiler of jiter-python
# For PyScript 2024.10.1 - Required Pyodide 0.26.3,Python 3.12 and Emscripten 3.1.58
# USAGE: DOCKER_BUILDKIT=1 docker build --file Dockerfile --output out .

FROM python:3.12 AS builder

# Install pyodide-build
RUN pip install pyodide-build==0.26.3

# Install Latest Rust using rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal
ENV PATH $PATH:/root/.cargo/bin

# Add Rust WASM target (Nightly version is required for wasm32-unknown-emscripten)
RUN rustup toolchain install nightly
RUN rustup target add --toolchain nightly wasm32-unknown-emscripten

# Install Emscripten
RUN git clone https://github.com/emscripten-core/emsdk.git
WORKDIR /emsdk
RUN ./emsdk install 3.1.58
RUN ./emsdk activate 3.1.58
# ./emsdk_env.sh (Fails when use emsdk_env.sh directly)
ENV PATH $PATH:/emsdk:/emsdk/upstream/emscripten:/emsdk/node/20.18.0_64bit/bin
ENV EMSDK /emsdk
ENV EMSDK_NODE /emsdk/node/20.18.0_64bit/bin/node
WORKDIR /

# Set environment variables for Emscripten
ENV PYO3_CROSS_PYTHON_VERSION 3.12
ENV PYO3_CROSS_LIB_DIR /usr/local/lib

# Get jiter
RUN git clone --depth 1 https://github.com/pydantic/jiter.git

# Build
WORKDIR /jiter/crates/jiter-python
RUN pyodide venv .venv-pyodide
RUN . .venv-pyodide/bin/activate \
    && RUSTUP_TOOLCHAIN=nightly pyodide build

# Export
FROM scratch AS export-stage
COPY --from=builder /jiter/crates/jiter-python/dist .
```

### pyscript.tomlへの記述方法
完成したwheelをPyScriptを用いたWebアプリと同じフォルダ以下に置きます。<strong>wheelの名前には意味があるので、名前を変更してはいけません。</strong>
例えば`./packages/`に置いた場合、以下のように記述すると`openai`が使えるようになります。
```toml
packages = [
    "ssl",
    "./packages/jiter-0.7.0-cp312-cp312-pyodide_2024_0_wasm32.whl", 
    "openai"
]
```

## 注意事項
<font color="red">PyScriptやPyodideでOpenAI APIを用いる場合、API Keyをユーザから隠すことができないので、API Keyを窃取される可能性が高いです。</font>[Sharepoint環境に置く場合](https://qiita.com/narumichiaki/items/4af1d8d0c45d20dfb7cf)のように、アクセス権限を信頼できるユーザに限定できる場合に限って使用することをお勧めします。

## 参考文献
- https://py.cafe/docs/howto/build

以下は途中経過で参考にしましたが、`jiter`のケースではうまくいきませんでした。
- https://zenn.dev/termoshtt/articles/rust-wasm-wheel-maturin
- https://qiita.com/grafi/items/de804ebff4f50f28577b
- https://blog.pyodide.org/posts/rust-pyo3-support-in-pyodide/

類似のケースで、`openai`のバージョンを`jiter`に依存しない1.39.0まで下げて解決した事例もありました。
- https://qiita.com/naoto_koyama/items/a3af50f858dbd62d63db
ECSで動いているバッチをスケジュールタスクで実行する 〜めちゃ便利〜

## 前提
下記の記事でバッチ処理はLambda契機のHTTP通信で実行するようにしていました。
ざっくりの流れ
EventBridge -> Lambda -> HTTPリクエストでECSのバッチ処理を起動

https://qiita.com/lyd-ryotaro/items/ede118eed0766c7aaf17

しかし、バッチ処理に時間がかかるようになり、CloudFrontのレスポンスタイムアウト30秒内にレスポンスを返せなくなってきて、Lambdaにてタイムアウトエラーが発生するようになってきました。

[![Image from Gyazo](https://i.gyazo.com/465e44e98a65527034cbee2b4c66a6a9.png)](https://gyazo.com/465e44e98a65527034cbee2b4c66a6a9)

ECS内では無事にバッチ処理は完遂していますが、実行元のLambdaにレスポンスだけ返せていないという状況です。
CloudFrontのレスポンスタイムアウトを変更するのはWebアプリケーション全体に影響が出てしまうし、Maxは60秒で付け焼き刃感が否めないので、今回はECSのスケジュールされたタスクというものを使用してみることにしました。

## 全体の流れ
- cron 基準で時間になったらECSタスクが1台起動する
- 仕込まれていたバッチ起動コマンドをECSタスクが実行する
- バッチ実行を完了したらタスクが終了する
- この間web用のタスクは常時起動している
  - バッチ実行中はWeb用とバッチ用でタスクが複数台になるイメージ

## 設定方法
ECS -> クラスター -> スケジュールされたタスク から設定

- スケジュールされたルールの名前：任意
- スケジュールされたルールの説明：任意
- スケジュールされたルール：ON
- スケジュールされたルールのタイプ：cron式
  - e.g. 毎日0:10に起動させる場合：`cron(10 15 * * ? *)`
 
- ターゲットID：任意
- 起動タイプ：FARGATE
- プラットフォームバージョン：LATEST
- タスク定義ファミリー：任意
- タスク定義のリビジョン：最新（空白にすることで最新リビジョンになる）
- タスクの数：１
- VPC：任意（Web用タスクと同じもの）
- サブネット：任意（Web用タスクと同じもの）
- セキュリティグループ：任意（Web用タスクと同じもの）
- パブリックIP：ON
- タスクロール：上書きは特になし
- このターゲットのEventBridge IAM ロール：空白 （ecsEventsRole というルールが自動生成される）
- コンテナの上書き
  - e.g.：`bundle,exec,rails,runner,Batch::Daily.execute`
    - 実行したいバッチ処理を起動するコマンドを入力する

[![Image from Gyazo](https://i.gyazo.com/a0381c2b78c407ae026b003a64fc0788.png)](https://gyazo.com/a0381c2b78c407ae026b003a64fc0788)

## 動作確認
### DBのログ確認
logs テーブルにて日時バッチと15分毎のバッチのログが記録されている。
タスク実行まで cron の時間から2分程度誤差がある模様。リアルタイム性は求めていないので許容範囲でしょう。

[![Image from Gyazo](https://i.gyazo.com/33766264a04cee8a5ac99331a0f42b52.png)](https://gyazo.com/33766264a04cee8a5ac99331a0f42b52)

### アプリケーションのログ確認
アプリケーションログはS3に保管されており、検索にAthenaを使っている。
Athneaでrails用コンテナのログを検索する。
スケジュールタスク用のコンテナが立ち上がってバッチ処理を完遂していることを確認。

[![Image from Gyazo](https://i.gyazo.com/fec720275ac52537aa662edf4ef57b03.jpg)](https://gyazo.com/fec720275ac52537aa662edf4ef57b03)

起動している台数とかも考えなくていいし、スケジュールドタスクめちゃめちゃ便利じゃ！！！！！！🎉🎉🎉
ZEPETOでフォロワーを増やす方法６選!!

![zepetoプロフ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828655/c20d5e45-472d-4b20-97ab-85011b35e739.png)

アカウントの開設からわずか2ヵ月で、フォロワー数が1100人を突破したので、今回は筆者が実際に短期間でフォロワーを増やすために試した方法を6個ご紹介します！
皆さんのフォロワー増加の参考になれば嬉しいです！


## 方法1：スタイル毎日投稿
- **効果**：★☆☆☆☆
- **難易度**：★★★★★
- **オススメ**：★☆☆☆☆

スタイルを毎日投稿し、ファッションセンスに興味を持ってもらいフォローに繋げる手法です。スタイル投稿は3つのスタイルが横並びになるため、背景色とファッション系統を合わせることで統一感を演出してみました！  
効果としては、毎日1~2人のフォロワーが増加しました。  
ただ、毎日アイテムを購入しコーデを考える必要があるため、フォロワー増加を目的とする場合、あまり推奨はしません。

![zepetoスタイル画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828655/e7ab239e-870e-3d1d-3322-443879d023e8.png)

## 方法2：動画や画像の投稿
- **効果**：★☆☆☆☆
- **難易度**：★★★★★
- **オススメ**：★☆☆☆☆

投稿した動画や画像がオススメに載り、フォロワー以外にアプローチしフォローに繋げる手法です。筆者は、流行りの口パクやダンス動画、お気に入りのスタイル画像を作成して投稿してみました！  
撮影と編集技術が必要なため、難易度は高く、オススメに載らなければ視聴回数も増えないため、フォロワー増加を目的とする場合、あまり推奨はしません。

![zepeto投稿.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828655/e3836723-8aa7-ac68-d50c-8a7014728959.png)


## 方法3：他のユーザーとコミュニケーションを取る
- **効果**：★★☆☆☆
- **難易度**：★☆☆☆☆
- **オススメ**：★★☆☆☆

他のユーザーの投稿にコメントをしたり、いいねを押して積極的にコミュニケーションを取り、認知してもらってフォローに繋げる手法です。  
交流を繰り返すことでお互いに仲良くなりフォローに繋がる可能性がありますが、フォロワー増加を目的とする場合、たくさんのユーザーとコミュニケーションを取る必要があります。  
かけた時間に対しての増加率が低いので、効果は薄いと感じました。



## 方法4：クラブを活用する
- **効果**：★★★★★
- **難易度**：★☆☆☆☆
- **オススメ**：★★★★★

お互いにフォローを目的としたクラブが存在するため、そこに加入しクラブ内の投稿でフォロー依頼をする手法です。クラブは人数上限に達していなければ誰でも自由に参加でき、複数のクラブに同時に加入可能です。  
フォロー依頼をすると活発なクラブの場合は、数分でたくさんのフォロー申請が届きましたので手っ取り早くフォロワーを増やすには効果的です！  
筆者もクラブを設立していますので、気になる方は気軽に参加ください(^-^)

![zepetoクラブ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828655/ea18bd8b-4c8e-a3a7-a97a-20a8dfb17874.png)



## 方法5：名前に「フォロバOK」を入れる
- **効果**：★★★★★
- **難易度**：★☆☆☆☆
- **オススメ**：★★★★★

自分の名前の横に「フォロバOK」や「フォロバします」などを入れ、フォローして貰いやすくする手法です。フォロバとは「フォローバック」のことで、相互フォローをすることを指します。  
フォロワーを増やしたいユーザーが多いので、確実にフォローを返してくれると分かるユーザーがフォローされやすい傾向にあります。  
プロフィールからいつでも自由に名前を変更することが出来ますので、オススメの方法になります！

![zepetoプロフ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828655/b6e8a347-6ddf-87b0-ac60-548d896a0653.png)


## 方法6：積極的にフォローをしていく
- **効果**：★★★★★
- **難易度**：★☆☆☆☆
- **オススメ**：★★★★★

フォロバをしてもらえそうなユーザーを積極的にフォローしフォロバを狙う手法です。フォローを待っているだけではなく、こちらからも積極的にフォローすることでフォロバ率が高まります！  
筆者は色々な方法を試してみましたが、この方法が簡単で一番効果的だと思いました！
GA4データ探索機能の活用方法

# はじめに
WEBアプリケーションの受託開発では、GA4の分析結果もクライアントから求められることがよくあります。
これはクライアントが費用対効果を重視しているためです。

GA4の分析結果をレポートする際には、**データ探索**の条件設定を保存して共有することをおすすめします。
データ探索を利用するメリットは以下の通りです。
・条件設定を忘れないようにできる
・条件設定をクライアントに伝えやすくなる
・条件設定を複製し、類似のデータを簡単に作成できる
本記事では、データ探索の基本的な使用方法について解説します。

# ページごとのPV数を表示
具体的にページごとのPV数を表示する方法を解説します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/773e090d-47c6-e350-2118-2310d21b3ad3.png)
1.左メニューから「探索」を選択します。
2.「空白」を選択します。
<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/12778726-8cbf-3c2a-8e88-a8af31989773.png)
3.「ディメンション」に「ページパスとスクリーン クラス」を追加し、「確定」します。
4.「指標」に「表示回数」を追加し、「確定」します。
5.「行」に「ページパスとスクリーン クラス」を追加します。
6.「値」に「表示回数」を追加します。
7.必要に応じて期間を設定します。

設定後の画面は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/30641a9f-a5d5-1eef-784a-5e009c77c133.png)

# 特定のイベント数を表示
前述のPV数に加え、特定のイベント数を表示するタブを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/bfe78814-65a1-2313-f07d-7087c1a5cab3.png)
1.ページ上部のタブ名「自由形式1」を「PV数」に変更します。
2.「＋」ー「自由形式」を選択します。
3.タブ名「自由形式2」を「イベント数」に変更します。

:::note info
「▼」－「複製」でタブを複製して変更することもできます。
:::

4.「ディメンション」に「イベント名」を追加し、「確定」します。
5.「指標」に「イベント数」を追加し、「確定」します。
6.「行」に「イベント名」を追加します。
7.「値」に「イベント数」を追加します。
8.表示するイベントを限定したい場合は、フィルタを設定します。
**フィルタ例**
・先頭が「selected_theme」のイベント名だけを表示する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/1895d6f9-9227-95bf-78f8-7d6d7d759f75.png)

・先頭が「share_」または「click_copy_url」のイベント名だけを表示する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/11e38534-86aa-8740-0321-63d8aa9fd28b.png)

:::note info
フィルタの正規表現は少し複雑です。
詳細は、[こちら](https://support.google.com/analytics/topic/1034375?hl=ja&ref_topic=9228654&sjid=16580573373615087291-AP)をご覧ください。
:::

# その他よくあるデータ集計
その他よくあるデータ集計方法を記載します。(「ディメンション」、「指標」の追加は省略)
・流入数を表示
1.「行」に「ページパスとスクリーン クラス」を追加します。
2.「値」に「総ユーザー数」を追加します。
3.フィルターに「ページパスとスクリーン クラス」、「次と完全一致」、「/」を追加します。

:::note info
「総ユーザー数」はアクセスして、すぐに離脱したユーザー数も含まれます。
これを除外したい場合は「アクティブユーザー」を使用します。
「総ユーザー数」と「アクティブユーザー」はユニークユーザー数です。
ユニークでない（延べの）ユーザー数、つまり同じユーザーが複数回訪問した数を見る場合は、「セッション」を使用します。
:::

・流入元を計測
1.「行」に「セッションの参照元/メディア」を追加します。
2.「値」に「総ユーザー数」を追加します。

:::note info
流入元には[UTMパラメータ](https://support.google.com/analytics/answer/10917952?hl=ja#zippy=%2C%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E5%86%85%E5%AE%B9)を追加してもらう必要があります。
:::

# データ探索の共有
作成したデータ探索は、作成者以外は見られません。
他のユーザーと共有する場合は右上の共有アイコンを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3659381/59128152-142d-e434-bb02-752d4283263a.png)

これで他のユーザーも参照可能になります。
もし他のユーザーが変更しようとした場合は、コピーを作成してから変更するように促されます。

# 最後に
本記事では、GA4のデータ探索機能を使用して、クライアントに求められる主要な指標を効率的にレポートする方法について解説しました。
データ探索の機能を活用することで、設定の共有や条件の再利用が容易になり、分析作業の効率化と報告の精度向上が期待できます。
日々のデータ分析業務の中で、ぜひデータ探索を積極的に活用してみてください。
なぜTypeScriptを学ぶのか

## 初めに
前提として、この記事は「TypeScriptに精通した私が初心者に向けて教える」という趣旨のものではなく、「JavaScriptならちょっと読める」程度の私が備忘録、モチベーションのために執筆したものになります。

したがって、経験則から書かれるものではなく、ネットの記事やQiitaのまとめからの引用がほとんどになりますので、わかりやすさ、正確さを選ぶ方はそちらを見てもらった方がよいかと思います。

同じような初学者の方にとってモチベーションになれば、経験豊富な方には誤った認識をぜひコメントで指摘していただければ幸いです。

 ### 筆者の技術力
 - C,Python (基礎文法~ポインタ、アルゴリズムの授業、研究での使用など)
 - HTML,CSS,JS (大半を生成AIに支援してもらったため読めるが書けない)
 - C++ : (AtcoderのD問題をたまにギリギリ完答できる程度)

## TypeScriptについて
### 特徴
- Microsoftが2012年に開発したオープンソースのプログラミング言語
- JavaScriptのスーパーセット(上位互換)である
- JSと違い型の宣言を可能にした。

### メリット
- 型の指定によりエラーの早期発見が可能
- JavaScriptとの互換性がある
- 作れる物の幅が広い
- 大規模な開発に向いている

### デメリット
- 日本語の情報が比較的少ない（今後改善されていくと予想できる）
- 学習コストが比較的高い（JS知識+型システム+etc..）

https://typescriptbook.jp/

## なぜTypeScriptを学ぶのか
### 学習コストの高さ=覚えられることの多さ
TypeScriptの公式ドキュメントにはこんな文言があります。
>We frequently see the question “Should I learn JavaScript or TypeScript?“.
The answer is that you can’t learn TypeScript without learning JavaScript! 
>出典 : https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

つまり、TSの学習を進めるにあたってJSの学習は避けて通れない道であるということです。これは裏を返せば、TSを学べばJSの大部分も学べると認識してもいいのではないでしょうか。加えてTSでは型システムやジェネリクスの様な追加で学ばなければならないことも多くあります。
　
ということで筆者の様な時間とやる気が有り余っている様な人間は是非学ぶべきです！(と思います。)

 ### 単純にモダンな技術っていいよね
正直私はミーハーです。どうせなら新しい技術を学びたいなんていう浅はかな思いは無限にあります。
  
また、当方学生であり、就活を控えています。下記リンクの様なインターンまとめサイトを見るとどうしてもTypeScriptやReactの様なモダンな技術が目立ちます。そこでどれか一つでも"使える技術"として胸を張って言えるようになりたいと思い、始めることにしました。
  
  https://deep-professor-e3c.notion.site/277c859180bd4f99bc7dd1707a7e9b16?v=b9cbe037a2364cc5a1c62dad9f62fa81


## 今後の学習方針について
- ProgateでJavaScriptの基礎をやり直す
- サバイバルTypeScriptを一通りやる
- TSを使ってwebアプリを一つ作ってみる
- なるべく生成AIは使わず、手を動かす

## まとめ
最後に、かなり主観的な話にはなってしまいますが、先ほど申し上げた通り、私は就活を控えた学生です。授業である程度プログラミングについて学んだものの、エンジニアの就活で戦えるような技術力はまだ持っていないと認識しています。正直焦っています。 不安でいっぱいです。少しでもこれを解消できるようになればなと、思っています。

TypeScriptへの認識や学習方針について、なにかアドバイスできることがありましたらコメントしていただけると幸いです。😸
フローを使ってジョブカン経費精算/ワークフローAPI（β版）を呼び出す

**使っているクラウドなどの小ネタ Advent Calendar 2024 3日目**


まずはpostmanを使って接続できるかを試してみました。ヘッダにトークンを記述するところに罠がありました。フローでも要チェックですね。

+ [ジョブカン経費精算/ワークフローAPI（β版）を使ってみる](https://qiita.com/Keiji_otsubo/items/7805d3fdc976178e2114)

# 指定ログインの登録

設定 --> 指定ログイン情報

以下のように登録します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/38bac620-8799-1429-befd-9573e7e9d8bb.png)

# 外部ログイン情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4f37d189-0fe6-47d4-1fc2-40e1b95c8555.png)

さらに詳細を登録します。ポイントはプリンシパルとカスタムヘッダーです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/27391657-d465-0ec8-c2a9-2c613fcb663b.png)


# 権限セット

外部ログイン情報プリンシパルアクセスで上記プリンシパルを有効にしてユーザに割り当てます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/dfedf006-e477-8487-0864-796375bbd61e.png)


# フロー

今回はボタンからから呼び出したいのでジョブカンのIdを渡せるように変数(request_id)を使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b76efcf1-0bfd-ed72-55f4-50f35e938cab.png)

ただ残念なことに取得できるテキスト型になっているので文字列が長い全てを取れないです。
困った。やっぱりApexの方がいいかもしれませんね。

# 外部サービスの登録

前回はどうやって作ったのかは全く覚えがないな

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8c834c9c-7431-7a0c-fc0a-a34fb6d37a80.png)

確かに違う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c369526b-0e1d-be77-4b4f-129382f51eff.png)

postmanのレスポンスをファイルにしてみたけど、アップローできませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/95288f56-4f6f-7864-c613-a0800c15c6b9.png)

無理やり手動でスキーマを作って登録してみました。こんな作り方ではなかったと記憶していますが...

何だろう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8cc235a4-eeab-f824-ef7c-c88acd5a4856.png)

ここをチェックしてみる？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b04b633a-b175-28f8-fd39-c62e8c24f800.png)

おおお、少し変わった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c79ce248-27e6-4c42-3f4b-a243a91cfeeb.png)

このサイトでhttp://json-schema.org/draft-04/schema#"を無理やり変換

https://douni.one/jp/json-schema-to-openapi-schema


無事に組み込めました。Apexを使ったらうまくいきませんでしたが、この方法なら機能しそうです。
しかし、スキマーはハンドで作るのは大変ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/69fd6165-db5a-c8c2-aaac-6166e9b7ca71.png)

# 関連するエラー

+ [HTTPコールアウトをフローで実行すると全くうまくいきません](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KAR7h)

:::note alert
Missing required input parameter: body Required field is missing value: body
:::
MIT App Inventorで電卓作ってみたぁ！

## はじめに
ここでは，Mit App Inventorを使用して電卓を作った方法を記載します．まぁ，電卓アプリはストア探せばいっぱいあるから，自作する意味はないけど，趣味なので！

## Designer画面
![Designer画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/1d84aa3e-a3df-9efc-b016-7e518abcfdb6.jpeg)

・Button
1~9，足し算，引き算，掛け算，割り算．AC-C
ButtonはTableArrangementでレイアウトしています．

## Blocks画面
### 変数
・ナンバー１
数字ブロック．初めに入力された数値を記録する変数．
![変数: ナンバー１](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/e48348d5-490d-0e63-5403-6a8153a8d7e3.png)

・計算
計算方法を記録する変数．
![変数: 計算](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/617b1c40-1b6d-18aa-30cb-706f8ce608be.png)

### 数字ブロック
・Button_0がクリックされたとき
![blocks (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/1edde916-b957-6210-7cf9-14b43e128765.png)

・Button_1がクリックされたとき
Button_2~9は以下のブロックの[1]をそのButtonの数値に変更します．
![blocks.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/9cf2609f-abb5-7fe5-44af-07f434b809bb.png)

### AC-Cクリックされたとのブロック
![blocks (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/8239c5de-17be-56dc-4243-27b55c8dce6b.png)

### 足し算，引き算，掛け算，割り算がクリックされたときブロック
以下は足し算のブロックだが，ほかのブロックでは[足し算]を引き算などに変更します．
![blocks (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/57adbc26-7b44-1535-f6af-8fad8b003a3d.png)

### Button_イコールがクリックされたとき
![blocks (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928359/291437c5-b88c-cad4-2d7f-3f7e8fe8eb48.png)

## おわりに
小数点も実装できたら面白そうです．特定の計算を行うだけのアプリがあれば研究や仕事の効率化で使えそうですね！
3Dモデルのフォーマット変換（pyvista+meshio）

PyVistaとmeshioを用いて3Dモデルを変換します

# コード
```python:model_transfar.py
import pyvista as pv
import meshio

in_filename = 'input.stl'
out_filename = 'output.vtk'
reader = pv.get_reader(in_filename)
mesh = reader.read()

pv.save_meshio(out_filename,mesh)
```
1 : pv.get_reader()でフォーマットに合わせた読み込み関数を呼び出し
2 : reader.read()でメッシュを読み込みmeshに格納
3 : pv.save_meshioでmeshioモジュールを介してフォーマットに合わせて書き込み

# 対応拡張子
入力側
'.obj''.stl''.vtk'など[2]

出力側
meshio対応のファイルフォーマット[4]

# 参考
[1]https://tutorial.pyvista.org/index.html
[2]https://tutorial.pyvista.org/tutorial/02_mesh/solutions/e_read-file.html
[3]https://docs.pyvista.org/api/readers/_autosummary/pyvista.objreader
[4]https://www.rccm.co.jp/icem/pukiwiki/index.php?meshio