OmniAICreator/Qiita-1.07M huggingface dataset:
文系卒エンジニアがJTC電機メーカーに転職した感想

文系学部卒でスマホアプリを開発していたわたしがJTC (Japanese Traditional Company) ――伝統的日本企業。硬直的・時代錯誤な体質を揶揄する呼称――に転職して5年経ちました。メリット・デメリットを書きます。

- 前職：社員数100人未満でWeb・スマホアプリの受託開発がメイン事業。
- 現職：戦前創業の電機メーカー。売上の2/3が海外。子会社が数十個ある。

# 雰囲気
- 年齢層が高い！
    - 歴史あるメーカーはどこも同じですが平均年齢が40代半ばです。わたしが20代後半で転職した際には100人超の部で一番の若手でした。前職では中堅扱いでリーダー業務も任されていたのでびっくり。年齢が高いため落ち着いている方が多いです。
- 男性が9割超！
    - わたしがいる設計部門は95%が男性です。大学の工学部をそのまま持ってきた性別比です。
- 学歴！
    - 設計部門は全員電気・機械・情報・数学の修士または博士で、まれに物理や化学の方がいるかなという感じです。学部卒・文系卒はわたし以外にいません。学歴に偏りを感じますね・・・・？
- JTC電機メーカーの設計部門は基本的に地方拠点です
    - どの会社も地方の工場併設の開発拠点に設計部門が置かれています。そのため設計の人間はオートマティックに地方在住になります。例外はソニーくらいです。

# メリット
- 給料が高い
    - 設計部門は35歳で年収700万円 + 残業代が標準です。加えて毎月5万円以上の確定拠出年金（日本版401K）が出ています。
    - わたしの前職と比較すると高収入で、20代後半当時は転職するだけで年収が100万円上がりました。メルカリなどの大手ITベンチャーや自動車メーカー・医薬品メーカーと比べると低いですが、上を見るとキリがないですしわたしの経歴の低さのわりに納得できる金額なので一旦満足しています。正直これが最大のメリットです。金はすべてを解決する！
- プログラミングスキルを活かして社内で独自のポジションを獲得できる
    - JTC電機メーカーでは社員が設計し、協力会社がプログラミング・テストを担当する役割分担が基本です。そのため社員とりわけ中堅以上はプログラミングに対する勘がほぼありません。
    - 難易度が高く協力会社の手に余る設計実装・不具合調査で重宝されます。
    - またある種の組み込み開発においてあるあるだと思いますが、組み込み用途のマイナーなOS、ミドルウェアを採用しており、それらOS・ミドルウェア自体の改造や不具合調査で開発元と協力することも結構な頻度であります。
- 開発プロセスが整備されている
    - 我が社ではISO 9001準拠の開発プロセスを採用しておりマイルストーンごとの成果物が定められています。そのためいつ・何を作ればよいかが明確です。
    - プロセスの硬直化・老朽化を指摘する方が多いようですが、ウン千人を超える設計部門が企画・品質・工場と連携して開発を進めるにはある程度固まったプロセスに従う必要があります。そうしないと都度いろいろなことで迷ってしまい時間がかかるので・・・・。
- システム設計の勉強になる
    - わたしはBtoB商品を担当しており10種類以上の機器を接続してひとつのシステムを構成する、という感じの製品を開発しています。各機器の通信方式、機器の追加・除去への対応、将来新商品を接続するための拡張性、などシステム設計固有の考慮事項が勉強になります。また電機機器は突然停電したり物理的に故障することがあるため、システム全体としてのフェイルセーフを入念に検討します。あるサブシステムが止まったら別のサブシステムに通知して止めるとか、安全性に関わる国際規格に準拠した設計をします。非同期なシーケンス設計、状態遷移設計を抜け目なく実施できるようになってきたということです。

# デメリット
- 根性を求められる
    - JTCも最近は浄化されているようですが開発の進捗が悪いと根性（残業）を求められます。過労死認定ラインが業務内容によりますが残業月間80時間か100時間と設定されているのに対し、わたしの残業時間は最大で月間200時間です（平日07:00～24:00、土曜09:00～24:00。土曜は始業時間に温情がある）。残業代が80万円近く支給されましたが、その後1年ほどメンタルが沈みました。
    - 出産後は鉄の意志で残業を拒否していますが（家事育児で忙しすぎるので物理的に無理）、それでも人事評価は下がっていないため、わたしはあのとき何のために残業したのか、また当時の上司のマネジメント能力を疑問に思ったりも・・・？　あと労働組合は何もしてくれなかった・・・・。
- いちエンジニアとして食べていくのも最近は大変
    - 年功序列的に給料が上がればわたしは嬉しいのですが最近はJTCも年功序列の気風が薄れて昇格しないと給料が上がりません。エンジニアが昇格するには専門領域を定めて研鑽する必要があります。係長級（年収700万円）は我が社ではだいたい以下の3点をすべて満たすことが求められます。
        - 技術：ある商品の設計リーダーとして基本設計や重要部分の詳細設計を行う。年間2件の特許出願ノルマをクリアする。
        - コミュニケーション：設計を代表する立場で企画・生産といった他部署への説明責任を果たす。またイニシアティブを持って開発を進める。必要に応じ他社ともコミュニケーションを取る。
        - 育成：下のメンバーに対する技術的な指導を行う
    - 満たせない場合は降格なので人事評価に神経を使うのが嫌です。もっと落ち着いて働きたいのですが。課長まで上がれば降格が無くなるので・・・ずるいですね！
    - 同僚にOSの改造や自社製コンパイラの開発をしている者がおり、低レイヤの開発はハッカーみたいでかっこいいと思っていたのですが、わたしと同じ係長級でした。なおその後わたしも両方やりました。やればできるね。
    - エンジニアの職種のままで課長級に昇るには、有名学会での論文発表経験、単著の執筆経験、大学での客員教授の経験、インパクトの大きな商品設計の経験（売上OOO億円以上）、専門分野の博士号などが複数求められ、わたしにとってはかなりのハードルのため、マネジメントへの方向転換を考えています。

# 最後に
色々とデメリットがありますが安心して生活できる給料をもらえているので転職して正解でした。
隙あらば根性を求めてくるのは嫌なのでわたし個人はなるべく拒否するという草の根活動で風土改善に努めます。
metabaseで頻繁に403 Forbiddenが出る

![スクリーンショット 2024-09-26 11.33.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237077/191c8665-e1b6-e36e-62b6-e06f7d1a8651.png)

metabaseであるときから↑のようなエラーが出るようになりました。
画像は新しい質問を保存するときのものですが、それ以外にも質問の名前変更や移動など、いろんなときに出るようになりました。

それでこちらのissueを見て、WAFの可能性があると思い、AWS WAFの状況を確認してみました。
https://github.com/metabase/metabase/issues/10897

## それWAFの設定かも

CloudWatch logsで確認すると、どうもAWSManagedRulesCommonRuleSetのSizeRestrictions_BODYでブロックされているようでした。

![スクリーンショット 2024-09-26 11.37.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237077/62a8274f-07fb-7ae1-0e68-c6adba44a270.png)

取り急ぎ上記のルールを無効にしたところ、エラーは再発しなくなりました。
完全に無効にするのも危険なので、特定の条件を満たせば無効にするなどの設定をしておくと良いと思います。

あんまりこの手の情報が無かったので取り急ぎ紹介させていただきました。
Mattermostをdocker composeで起動する(SSL対応)

# 概要
Mattermostをdocker composeにて起動するためのセットアップ手順です。
Nginxを構成し、HTTPSでアクセスできるようにします。

# 環境
本手順で取り扱う内容は、次の環境にて確認しています。
マシン：Amazon EC2
OS：Ubuntu 24.04
Docker：27.3.1
Docker Compose：v2.29.7
Mattermost：9.11.1
PostgreSQL：16

# 前提
* Docker がインストール済みであること
* フルチェインの証明書と秘密鍵が準備できていること

# 手順

Gitリポジトリをダウンロードします。
```
$ git clone https://github.com/mattermost/docker
```

ディレクトリを移動します。
```
$ cd docker
```

`.env`ファイルを作成します。
```
$ cp env.example .env
```

ディレクトリを作成します。
```
$ mkdir -p ./volumes/app/mattermost/{config,data,logs,plugins,client/plugins,bleve-indexes}
```

権限を変更します。
```
$ sudo chown -R 2000:2000 ./volumes/app/mattermost
```

証明書を格納するディレクトリを作成します。
```
$ mkdir -p ./volumes/web/cert
```

`./volumes/web/cert`に証明書を格納します。
(証明書はここでは`fullchain.pem`、`privkey.pem`としています。)

```
$ ls -la ./volumes/web/cert
total 16
drwxrwxr-x 2 ubuntu ubuntu 4096 Sep 26 01:33 ./
drwxrwxr-x 3 ubuntu ubuntu 4096 Sep 26 01:32 ../
-rw-r--r-- 1 ubuntu ubuntu 2835 Aug 23 02:02 fullchain.pem
-rw-r--r-- 1 ubuntu ubuntu  241 Aug 23 02:02 privkey.pem

```

格納後、`.env`ファイルを編集します。
編集箇所は次の通りです。
```
DOMAIN=<YOUR-DOMAIN>
TZ=Asia/Tokyo
POSTGRES_IMAGE_TAG=16-alpine #任意のバージョン
CERT_PATH=./volumes/web/cert/fullchain.pem
KEY_PATH=./volumes/web/cert/privkey.pem
MATTERMOST_IMAGE_TAG=9.11.1 #任意のバージョン
```

`docker-compose.nginx.yml`と`docker-compose.yml`のファイルを編集します。
次の行を削除して下さい。こちらはobsoleteとなっている表現です。
```
version: "2.4"
```


コンテナを起動します。
ymlファイルはメインの`docker-compose.yml`と、Nginxを構成するために`docker-compose.nginx.yml`を指定します。
```
$ sudo docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d
```

コンテナが起動したことを確認します。
```
$ docker ps
CONTAINER ID   IMAGE                                             COMMAND                  CREATED          STATUS                    PORTS                                                                                                                     NAMES
7e330a42a9f5   nginx:alpine                                      "/docker-entrypoint.…"   46 minutes ago   Up 46 minutes             0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp                                                  nginx_mattermost
7015f31a8b4f   mattermost/mattermost-enterprise-edition:9.11.1   "/entrypoint.sh matt…"   46 minutes ago   Up 46 minutes (healthy)   8065/tcp, 8067/tcp, 8074-8075/tcp, 0.0.0.0:8443->8443/tcp, 0.0.0.0:8443->8443/udp, :::8443->8443/tcp, :::8443->8443/udp   docker-mattermost-1
5f0888731117   postgres:16-alpine                                "docker-entrypoint.s…"   46 minutes ago   Up 46 minutes             5432/tcp                                                                                                                  docker-postgres-1
```

FQDNでアクセスできるように、DNSの設定を行います。
その後、ブラウザからHTTPSでアクセスできることが確認できたら、セットアップは完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510470/8b473153-ff41-f647-0c02-12ce81cdeadf.png)

# 参考
https://docs.mattermost.com/install/install-docker.html
https://qiita.com/shun_so/items/127904a3482fb8e971fb
SwitchBotの温湿度計のアドバタイズ

ESP32が2Fのモジュールを1Fで受信できなかったので、PIC32MX+USBドングル(CSR)でbtstackを使って実装しなおしてみました。

ESP32は-80dBmより低くなると受信できないようです。

btstackはgoogle codeにあったころの昔のものです。

とりあえずgattのコードをベースにアドバタイズをダンプするプログラムを作ってみました。

```
* adv. event: evt-type 0, addr-type 1, addr XX:XX:XX:31:34:D8, 
rssi -90, length adv 18, data: 02 01 06 0E FF 69 09 D8 34 31 XX XX XX 90 03 04 9B 42 
* adv. event: evt-type 4, addr-type 1, addr XX:XX:XX:31:34:D8, 
rssi -88, length adv 10, data: 09 16 3D FD 54 00 E4 04 9B 42 
```

アドレスのダンプが逆になっています。

二つのイベントがあり、最初の方だけ飛んでくることもあります。

二つ目の方にはバッテリーの情報が含まれますが、一つ目は温度と湿度の情報だけが入っています。

10年位前にPIC32MXにポートしてあったancsのコードをいじって作ってみました。

二つ目のバッテリーの情報を取っておいて、一つ目のイベントでシリアル出力するようにしました。フォーマットはESP32のものと一緒にしました。

アドバタイズを受け取るとシリアル出力して、一時間に200回くらい受け取れてます。

実は当初USBドングルを3.3Vで動かしていたら、あまり調子が良くなく、5Vにしたら元気になりました。

btstackはgithubに引っ越してメンテされているようです。

古いコードを使っているので、ソースは公開しません。

一時間ごとのアドバタイズの受信回数を集計してみました。最後のフィールドが回数です。

```
2024-09-28|00:00:00|26.36|73.82|100.0|185.0
2024-09-28|01:00:00|27.76|69.92|100.0|197.0
2024-09-28|02:00:00|28.62|66.72|100.0|180.0
2024-09-28|03:00:00|29.11|64.55|100.0|190.0
2024-09-28|04:00:00|29.36|64.0|100.0|169.0
2024-09-28|05:00:00|29.19|62.05|100.0|179.0
2024-09-28|06:00:00|28.79|61.94|100.0|189.0
2024-09-28|07:00:00|28.21|62.47|100.0|200.0
2024-09-28|08:00:00|27.47|63.45|100.0|177.0
2024-09-28|09:00:00|26.79|65.0|100.0|170.0
2024-09-28|10:00:00|26.2|65.85|100.0|174.0
2024-09-28|11:00:00|25.72|66.6|100.0|175.0
2024-09-28|12:00:00|25.35|67.48|100.0|182.0
2024-09-28|13:00:00|25.08|68.3|100.0|181.0
2024-09-28|14:00:00|24.86|69.72|100.0|181.0
2024-09-28|15:00:00|24.65|70.8|100.0|177.0
2024-09-28|16:00:00|24.43|71.94|100.0|178.0
2024-09-28|17:00:00|24.22|72.0|100.0|173.0
2024-09-28|18:00:00|24.0|72.0|100.0|176.0
2024-09-28|19:00:00|23.84|72.03|100.0|173.0
2024-09-28|20:00:00|23.69|73.0|100.0|166.0
2024-09-28|21:00:00|23.61|73.69|100.0|172.0
2024-09-28|22:00:00|23.88|74.0|100.0|162.0
2024-09-28|23:00:00|24.14|73.33|100.0|166.0
```

ちょっとアンテナの位置を変えただけで、受信状態が大きく変化するようです。また時間ごとの変動もかなり大きいです。ビーコンなので瞬時に評価できないので、難しいです。
【JS】植木鉢くんの苦行系ワイヤーアクションゲーム【真夏の夜の淫夢】


## 結論

https://mogamoga1024.github.io/uekibati-kun-wire-action-game/?inmu=false

<img width=600 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/ea33bbc5-4362-9564-ea0f-6f6ee5905336.gif>

## 前書き

* スマホじゃ遊べない。悪いね。
* （それなりのボリュームのゲーム作りの）初心者です。
* 音がでます。
* （淫夢要素は）ないです。
* 音がおかしかったらごめん。MyPCの音量システムがイカれてるから正常な音量が分からん…。てかおかしかったら教えて。

## 本文

ワイヤーアクションゲームには直感的に操作できる爽快型と操作とタイミングが難しい苦行型があると思っており、**後者のゲームは絶滅危惧種と化しています（偏見）**。

しかし最近は壺男やJump Kingみたいな苦行ゲームも人気が出ています。

これは便乗せねば！という訳で苦行系ワイヤーアクションゲームを作ってみました。
多分誰もクリアせずに途中で諦められるんだろうなと思っています。
<font color="#ffffff">というか操作方法が分からないまま（書いてあるのに！）、つまんねと投げられるんだろうな。</font>
まあ誰かのインスピレーションに繋がれば嬉しいです。

難易度は海腹川背よりも簡単だと思います[^1]が、
初見だとクリアまで1時間くらいかかると思います。
（慣れれば8分くらい）

https://mogamoga1024.github.io/uekibati-kun-wire-action-game/?inmu=false

<font color="#ffffff">誰かRTAしてくれないかなぁ…</font>

なお、ゲームが全くクリアできない人でもコンソールでパラメータをいじったり関数を実行したりすればクリアできます。
JSだからね。しょうがないね。

以下おまけ
読みたい人だけ読んでください。

## プログラムの解説とか

<font color="#ffffff">どうせ読まんでしょ。こんな長い文章。</font>

本プログラムはゲームエンジンや物理エンジンを一切使用していません。
ただ単にそれらを学習するのが面倒だったらからです。

### シーン管理

シーンとはタイトル画面、ゲーム画面、ヘルプ画面とかのことです。

Sceneクラスを継承したクラスとSceneManagerクラスで管理しています。

AndroidのActivityみたいなもんです。 

具体的には[これ](https://github.com/mogamoga1024/uekibati-kun-wire-action-game/tree/main/scene)

### ワイヤーアクション

物理エンジンを利用したほうが間違いなく楽でしょう。

私は難しい計算ができないんで、ワイヤーアクションっぽい挙動になるように適当にコードを書きました。

ほぼこれが全てです。

https://qiita.com/mogamoga1337/items/6a28802ae58f4b0ff1b9

ワイヤーアクションのクソコードを読みたい人は[ここ](https://github.com/mogamoga1024/uekibati-kun-wire-action-game/tree/main/game/player)を見てください。

### マップ

マップはExcelで書いたものをVBAで配列に変えて、それを基にJavaScriptのコードに変換させました。

楽です。（小並感）

### あきらめたこと1

ワイヤー自体の当たり判定処理はかなり難しそうなのであきらめました。

物理エンジンを使えばできるかもしれません。

<img width=600 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/89770f96-b9a3-c19b-8ef3-f8b79b1daa72.png>

#### 考えたほうがいいこと

仮にこれを実装したとして、以下の挙動ができるのか確認したほうがよさそうです。

<img width=600 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/c95cf007-0d6a-c5b2-c9d3-dad32b4b7826.png>

もしできるのなら最高です。

### あきらめたこと2

海腹川背みたいにワイヤーの伸び縮みを利用してジャンプしたり障害物を乗り越えたりしたかったですが、実装が面倒くさそうだったのであきらめました。

物理エンジンを使えばできるかもしれません。

### あきらめたこと3

大車輪を実装したかったですが、なんかバグりそうだからやめました。

<img width=600 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/99d54ed7-939c-8b8d-408b-145ccfe22396.png>

### あきらめたこと4

ワイヤーのスムーズな伸び縮みの実装はあきらめました。
振り子の速度はワイヤーの長さと相関関係があり、それの計算が面倒なのです。

物理エンジンを使えばできるかもしれません。

<img width=600 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/0ef2c59a-e769-7431-60cf-500b5b6ca4c7.png>

終わり。

[^1]: なお海腹川背はエアプです。
Devv AI -- GitHubリポジトリとチャットできるChatGPTを作りました

私たちはChatGPTよりも優れたコーディング体験を提供するAI開発ツールを作成しました:information_desk_person_tone1:：

1. Devv AIは最新の情報を提供し、Stack Overflowを閲覧して質問に答えることができます。ChatGPTの古いライブラリの問題はもうありません。

2. 公開GitHubリポジトリに接続できるので、プロジェクトのコンテキストをより深く理解します。これはオープンソースプロジェクトにとって非常に便利です。

3. コーディングに最適な、私たちが厳選した複数のLLMモデルを使用できます。

4. VScode拡張機能もあります！

5. LLMがあなたのプロジェクトをより良く理解できるよう、パーソナライズされたAIプロファイルをカスタマイズできます。

まだ開発途中であり、競争の激しい分野ですので、フィードバックをいただけると幸いです。

無制限に使用できる無料版もご用意しています。

ぜひお試しいただき、ご意見をお聞かせください！

https://devv.ai/
:point_up::point_up: :3
オプショナルチェーン(?.)について

# オプショナルチェーンとは
オプショナルチェーンとは、JavaScriptのES6以降で使用できる記述方法です。どんなものかといいますと、
 ```javascript
 let family = {};
 alert(family.mother.name);
 ```
 通常こちらを実行すると、
 ```
 Uncaught TypeError: Cannot read properties of undefined (reading 'name')
 ```
 「未定義のプロパティを読み込めません」というエラーが発生すると思います。

 それを**オプショナルチェーン**を利用することで、安全にプログラムが実行できるようです。
 ```javascript
 let family = {};
 alert(family?.mother?.name);
 ```
 こちらを実行すると、プログラム自体は実行され`undefined`というアラートが表示されるかと思います。

 # そもそもなぜこんな書き方をする必要があるの
 先日私の記事にコメントをくださった方にこちらの書き方を教えていただきました。初めてこの書き方をみた私は読解することができず頭を悩ませました。

しかし、これをきっかけに改めて調べてみたところ、なんと便利というか安全に実行できるものなのだと感動しました（**教えてくださった方本当にありがとうございます！！**）

最初のコードでわかる通り、通常JavaScriptでエラーが出るとその時点でプログラムが実行されず止まってしまいます。

例えば、APIを呼び出して何かをするプログラムがあったとします。しかし、ユーザーの環境によって上手く呼び出しが行われなかったとします。その際
```javascript
 let family = {};
 alert(family.mother.name);
 ```
 このような書き方だとエラーが発生してその後のプログラムが実行されません。恐らく止まってしまうと思います。
 そこで、予期せぬエラーを回避するためにもこのような書き方が必要であるということです。

 他にも安全に書く方法はありますが、スッキリとした書き方ではない場合が多いようです。
```javascript
let family = {};
alert(family.mother && family.mother.name);
```
これぐらいですとまだ良いですが、もっと深いオブジェクトを参照する際には多くの記述を要します。

# 使用する際の注意点（全てではないです）
- オプショナルチェーンの使いすぎの注意
    - 存在しなくてもOKな場合のみに使用するものとする。つまり逆をいうと、プログラム上その値が必須となる場合にはオプショナルチェーンを使うべきではないということです（コードが`undefined`のまま実行されてしまうから）
- オプショナルチェーンを使う元のオブジェクトは既に定義されている必要がある
    - 未定義のものには使えない
- 左部分が存在しない場合には使用できない
- 読み取りと削除はできるが書き込みはできない
    - 左辺で用いることはできません

# 以上のことに気をつけて今後使用可能そうな場面で積極的に活用して行きたいと思います（TypeScriptも併せて...）
Vimにプラグインを入れる方法

## はじめに
vimにプラグインを入れる方法です。今回はvimのプラグイン管理ツールのdeinを入れていきます。
PCはmacです。ターミナルを使用しました。

コマンドをぽちぽち打っていきます。
```
$cd ~/.cache
$mkdir dein
$cd dein
$git clone https://github.com/Shougo/dein.vim
```
※gitを入れてない方は最初にgitを入れてくださいね。コマンドは下記。

```
brew install git
```



```
curl -fsSL https://raw.githubusercontent.com/Shougo/dein-installer.vim/master/installer.sh > installer.sh
```

※curlを入れていない方は最初にcurlをインストールしてくださいね。コマンドは下記。

```
$ brew install curl
```
※homebrewが入ってない方はhomebrewもインストールしてください・・・。


```
sh ./installer.sh ~/.cache/dein
```

## 下記が表示されたら一旦完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735736/68ed8b0f-3b91-a7c7-d326-474acd5b07ec.png)

## .vimrcの作成
色々書き方はあるようですが下記のように書いてみました。

```ruby:.vimrc
if &compatible
    set nocompatible
endif

" Required:
set runtimepath+=~.cache/dein/repos/github.com/Shougo/dein.vim
          
" Required:
if dein#load_state('~.cache/dein')
  call dein#begin('~.cache/dein')
             
  call dein#add('~.cache/dein/repos/github.com/Shougo/dein.vim')

" Add or remove your plugins here like this 
call dein#add('Shougo/neosnippet.vim')
call dein#add('Shougo/neosnippet-snippets')
# ここにいれたいプラグインをいれる
call dein#add('elixir-editors/vim-elixir')
    
" Required:
call dein#end()
  call dein#save_state()
endif

" Attempt to determine the type of a file based on its name and possibly its
" contents. Use this to allow intelligent auto-indenting for each filetype,
" and for plugins that are filetype specific.
 filetype indent plugin on
 
" Required:
 filetype plugin indent on
 syntax enable
  
" If you want to install not installed plugins on startup.
  if dein#check_install()
    call dein#install()
  endif

```

今回はelixir-editors/vim-elixirのプラグインを入れてみました。


お疲れ様でした★

## 参考

https://note.com/yama999/n/neb907fe36529

https://qiita.com/MickeyOoh/items/b47ab0b8b5fbbbad3793

https://note.com/noabou/n/naa7ac5460331

https://zenn.dev/oratake/scraps/5593f12189c66f
google.protobuf.Struct のJSON表記がトリッキーだった

１時間くらい溶かしたのでメモる。

# やりたかったこと

Postmanで、grpc でリクエストを送る。
request messageの中に`{"age": 43}`を`google.protobuf.Struct`型のデータとして指定したい。

なお、Postmanではmessageをjsonで指定している。


# 間違えてやっていたこと

Struct型のデータを指定を以下のようにしていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/207cf208-fb52-a269-825e-9e056c88428c.png)



# 正しくはこう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/66a79349-26e3-2f11-a947-62321db18455.png)


# Ref.

https://stackoverflow.com/a/66574109/10233141

https://googleapis.dev/nodejs/spanner/latest/google.protobuf.Struct.html
フローを使って複数選択リストを更新する



テキスト型のコレクション変数に値を追加して、最終的に複数選択リストにセットしようとしましたがテキスト型のコレクション変数が選択できません。

この方法は使えないみたいです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4d787058-50a5-1b88-ba82-1c2a55632121.png)


レコード変数に「次の文字列と一致する」では最後に設定した値だけになった。
「追加」では文字列が連結されてエラーになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0834d08e-ca65-5988-e7c5-5de026c1b016.png)


今までなかったような「項目を追加」を選択してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e8bdd4eb-f408-44e4-0995-28a5aef45868.png)


おおお、機能しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7d3db8c2-1621-ad51-93b7-a3a07633f87e.png)


このような数式で備考欄をチェックしています。

```
CONTAINS({!getContact.remarks__c},"本社拠点(名古屋・特機・ソリューション営業所)")
```
メール送信LambdaをAmplifyで作成

## メール送信LambdaをAmplifyで作成

Amplify で構築した環境で、DynamoDB の特定のテーブルにレコードが追加された際、Amazon SES を利用してメールを送信するLambda Trigger を作成しました。

### Lambda Triggerを作成する
![a2e5ac8e-02b5-4c74-914f-6839ee7b5cc5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/19dbb63c-19d1-0397-3b1b-405b95912062.png)

`amplify add function` を使ってLambda Trigger を作成します。Cloudformation のテンプレートで、対象のテーブルへの権限は自動生成されます。

```
"PolicyDocument": {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DescribeStream",
                "dynamodb:GetRecords",
                "dynamodb:GetShardIterator",
                "dynamodb:ListStreams"
              ],
            "Resource": {
                "Fn::ImportValue": {
                  "Fn::Sub": "${×××GraphQLAPIIdOutput}:GetAtt:(テーブル名)Table:StreamArn"
                }
            }
        }
    ]
}
```
Amazon SES を使うためにポリシーを設定します。
cloudformation-template.json のlambdaexecutionpolicy/Properties/PolicyDocument/statement に以下を追加します。

```
{
    "Effect": "Allow",
    "Action": [
        "ses:SendEmail",
        "ses:SendRawEmail"
    ],
    "Resource": "*"
},
```

ポリシー設定は完了です。Amazon SES のパッケージをインストールします。
`"@aws-sdk/client-ses": "^××"`

### コード実装
実際のLambda のindex.js のサンプルは以下です。

```
const {
    SESClient, SendEmailCommand
  } = require("@aws-sdk/client-ses");
const ses = new SESClient({ region: "ap-northeast-1" });
/**
 * @type {import('@types/aws-lambda').APIGatewayProxyHandler}
 */
exports.handler = async (event) => {
  const command = new SendEmailCommand({
    Destination: {
      ToAddresses: ["送信先のメールアドレス"],
    },
    Message: {
      Body: {
        Text: { Data: "Test" },
      },
      Subject: { Data: "Test Email" },
    },
    // SESのID登録されている検証済みのドメイン・メールアドレス
    Source: "送信元のメールアドレス"
  });
  try {
    let response = await ses.send(command);
    // process data.
    return response;
  }
  catch (error) {
    // error handling.
  }
  finally {
    // finally.
  }
};
```
### テスト実施
テストには以下のようなイベントJSON を渡してみてください。

```
{
  "Records": [
    {
      "eventID": "1",
      "eventName": "INSERT",
      "eventSource": "aws:dynamodb",
      "awsRegion": "ap-northeast-1",
      "dynamodb": {
        "ApproximateCreationDateTime": 1631635465,
        "Keys": {
          // テーブルのフィールドに準拠
          "××": {
            "S": "××"
          }
        },
        "NewImage": {
        　// テーブルのフィールドに準拠
          "××": {
            "S": "××"
          }
        },
        "OldImage": {},
        "SequenceNumber": "12345678901234567890123456789012345678901234567890",
        "SizeBytes": 123,
        "StreamViewType": "NEW_IMAGE"
      },
      "eventSourceARN": "テーブルのARN"
    }
  ]
}
```

これでテスト実行すると、送信先メールアドレスに設定したアドレスにメールが届きます。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策：（最終回100/100）

【100日目】
トピック 10：SAPS/4HANAの能力計画（8/8）

≪問題100≫
製造指図のリードタイム日程計画に関連する時間要素はどれですか。
（２つ選択）
□段取時間
□製造後余裕
□開放期間
□総補充リードタイム

≪解答≫
■段取時間
■製造後余裕
□開放期間
□総補充リードタイム

≪解説≫
◆製造における能力計画では、計画手配や製造指図が作業手順に基づいて登録されます。また、作業区の計算式をもとにリードタイム日程計画が実行され、各作業に対する能力所要量が登録されます。  
◆リードタイム日程計画に含まれる作業に関連する主な時間要素は、以下の通りです。  
（1）製造前余裕、製造後余裕  
（2）開始待ち時間、段取時間、処理時間、片付時間、待機時間、移動時間

≪最後に≫
最低でも８割以上は確実に出題されると思われます。
根気よく学習してください。
有料で過去問を提供しているケースが多いですが、私は営利を求めておりません。
【Blender】【Python】キーフレームをJSON出力する

BlenderでMaterial nodesなどにキーフレームが打ってある場合はglTFでexportできないので、Blenderからキーフレームの値を取得してJSON出力してみました。

## code

```python:exportKeyframesJson.py
import bpy
import math
import json
import os

def exportKeyframesJson(action_name):
    keyframes = {}
    action = bpy.data.actions[action_name]
    fileDir = os.path.dirname(bpy.data.filepath)
    
    if action is not None and action is not None:
        for fcu in action.fcurves:
            transformType = fcu.data_path + '_' +str(fcu.array_index)
            keyframes[transformType] = {}
            for keyframe in fcu.keyframe_points:
                keyframes[transformType][math.ceil(keyframe.co[0])] = keyframe.co[1]
    
    with open(fileDir + '/keyframes.json', 'w') as f:
        json.dump(keyframes, f, indent=2)


selectedObj = bpy.context.selected_objects

# material node action
exportKeyframesJson(selectedObj[0].data.materials[0].node_tree.animation_data.action.name)
```

`exportKeyframesJson`はざっくり言うとキーフレームの情報をDictionary（Pythonのデータ）にして、それをJSONに変換して書き出すという処理の関数です。

その関数にBlenderのaction名を引数で渡します。

```python
# material node action
exportKeyframesJson(selectedObj[0].data.materials[0].node_tree.animation_data.action.name)
```

今回は引数に選択したオブジェクトのMaterial Nodeのaction名を渡しています。

```python
# object action
exportKeyframesJson(selectedObj[0].animation_data.action.name)
```
上記のようにすると選択したオブジェクトのaction名を渡せます。

## 使い方

1. コードをBlenderの`Text Editor`にコピペ or `Open Text`で読み込みする
2. 取得したいキーフレームのオブジェクトを選択する
3. `Run Script`ボタンを押してScriptを実行

すると、blendデータの同階層に以下のような`keyframes.json`が出力されます。

```json:keyframes.json
{
  "nodes[\"Mapping\"].inputs[1].default_value_0": {
    "1": 0.0,
    "57": 2.0
  },
  "nodes[\"Mapping\"].inputs[1].default_value_1": {
    "1": 0.0,
    "57": 0.0
  },
  "nodes[\"Mapping\"].inputs[1].default_value_2": {
    "1": 0.0,
    "57": 0.0
  },
  "nodes[\"Mapping\"].inputs[2].default_value_0": {
    "1": 0.0,
    "57": 1.5707963705062866
  },
  "nodes[\"Mapping\"].inputs[2].default_value_1": {
    "1": 0.0,
    "57": 0.0
  },
  "nodes[\"Mapping\"].inputs[2].default_value_2": {
    "1": 0.0,
    "57": 0.0
  }
}
```

第一階層のKey名（`"nodes[\"Mapping\"].inputs[1].default_value_0"`などの部分）はプロパティ（Location、Rotation、Scaleとか）が入っています。
Key名の最後の数字はプロパティのインデックスを表していて、以下のようにそれぞれ`x` `y` `z` となっています。

| Index | 座標 |
|:-:|:-:|
| 0 | x |
| 1 | y |
| 2 | z |

第一階層の値のオブジェクト（`{"1": 0.0, "57": 2.0}`などの部分）はKey名の方は`フレーム数`、Valueの方はその`キーフレームの値`が入っています。

アニメーションをbakeしてから実行すれば全ての値が取れます🙆‍♀️

おしまい。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（99/100）

【99日目】
トピック 10：SAPS/4HANAの能力計画（7/8）

≪問題99≫
能力計画テーブルでは、計画方針のために以下のどの設定を選択できますか。
（３つ選択）
□固定紐付
□方向
□計画モード
□有限性レベル
□日程計画管理

≪解答≫
□固定紐付
■方向
■計画モード
□有限性レベル
■日程計画管理

≪解説≫  
◆生産日程計画実行アプリの指図一覧では、計画方針の設定に従って指図を差し立てることができます。  
◆計画方針では、次の3つの項目が設定されます。  
（1）計画モード⇒パケット、順序  
（2）日程計画管理⇒スロット検索（有限）、無限計画、作業挿入（有限）  
（3）計画方向⇒順日程、逆日程
Preview 機能の BigQuery Workflows を試してみた

### 前置き

BigQuery Workflows が Preview になりました。

https://cloud.google.com/bigquery/docs/workflows-introduction?hl=en

機能としては公式ドキュメントに次のようなことが書いてあります。

> ワークフローをスケジュールして、指定した時間と頻度で自動的に実行することができます。
> ワークフローを使用して、コードアセットの実行をスケジュールできます。例えば、SQL クエリを毎日実行し、最新のソース データでテーブルを更新するようスケジュールできます。
> 複数のコードアセットを持つワークフローでは、実行順序を定義します。例えば、機械学習モデルをトレーニングする場合、SQLクエリでデータを準備し、後続のノートブックでそのデータを使ってモデルをトレーニングするワークフローを作成できます。

`Workflows are powered by Dataform.` と書いてあり、Dataform のようにクエリのワークフローを組める上に notebook も実行できるようなイメージでしょうか。

僕個人がデータエンジニアとして使うかどうかは怪しいのですが、社内の分析チームにおすすめできそうな気がしたので試してみることにしました。


## 概要

公式ドキュメントに書いてあることを抜粋します。

### できること

- notebook と SQL クエリをタスクとするワークフローの構成
- スケジューリング

notebook が実行できるところが Dataform と差別化されていて良さそうです。

### 制限事項

- 既存の notebook や SQL クエリをワークフローに追加することはできない
- 選択したワークフローへのアクセスを他のユーザーに許可することはできない
- ワークフローは Google Cloud コンソールでのみ利用できる

他のユーザーにアクセスを許可できないのがけっこうしんどそうです。
試しにワークフローを作成したアカウントと別のアカウントで同じ画面を見比べて見ましたが確かにワークフローが表示されませんでした。

workflow を作成したアカウントから見た画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/bf0a56a1-410c-9e07-4e6e-07e6ec6a1703.png)

workflow を作成していないアカウントから見た画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/8d711406-4181-4275-654e-0de9526cb2f3.png)

ユースケースとしてもともとイメージしていたのが、分析チームが作成したワークフローをそのまま渡されて、商用利用できるようにシステム構築するための設計に役立てることだったのですが、そのような用途には使えなさそうです。


## 試してみた


workflows の作り方はこちらのドキュメントにまとまっています。

https://cloud.google.com/bigquery/docs/create-workflows?hl=en

### 依存関係の定義

適当なサンプルのクエリと notebook を作成して依存関係を定義しました。
作り方は GUI からポチポチやるだけで簡単すぎたので割愛します。


次のように 1 つのノードから複数に分岐することはできますが、複数の分岐から1つのノードに遷移するような依存関係は作れなさそうでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/c54c647c-0db9-9b54-b2af-24f86966379d.png)



### 実行履歴
ワークフローを実行すると実行時間を見ることができます。 Notebook は print するだけでの簡単なコードですがオーバーヘッドがかかるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/2c7fb2f1-eb80-46dc-5e8e-39838d1166ba.png)

### notebook の実行結果

notebook の実行結果は事前に指定したバケットに保存されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/ada1002d-6396-ab6e-ccba-c9f761d8ad2d.png)

こんな感じに実行結果が出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/4e6ce413-5be3-3a0a-b7cc-65b282854595.png)



その他細かいことは公式ドキュメントをご確認ください。

https://cloud.google.com/bigquery/docs/manage-workflows?hl=en

## 感想

notebook を実行できるワークフローを手軽に構築できることは可能性を感じるものの、他のユーザーがアクセスできない点がチームワークするには厳しいと思いました。
現時点では個人開発なら使えそうという感触でした。

まだ Preview 機能なので今後のアップデートに期待します。
(備忘録) LaTeXのemumerate/itemize環境の\parにおいてインデントされないときの対処法

`enumerate`環境や`itemize`環境では`\parindent`が`0`になるので長さを変更すればよい．
```latex
\begin{enumerate}
    \setlength{\parindent}{10pt} % デフォルトは 10pt
    \item あああ\par
        いいい
    \item ううう
\end{enumerate}
```

コンパイル結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2894904/819bcdd1-f584-6af3-c74f-08c122b83607.png)
YKK AP電気錠をスマートロックに変身〜Home Assistant経由でHomeKitに導入

# 背景
こんにちは、今日は YKK APの電気錠をスマートロックに変換する方法を説明します。結果から言うと、iPhone家庭アプリで電気錠の施錠と解錠をコントロールできるようにします。手段としては Home Assistantを経由でHomeKitに導入します。

こちらは去年に新築の戸建を入居しました。建売住宅なので、すでにでYKK APの電気錠が付けらている状態です。型番は`EC-Y7`ですので、スマートキー機能が YKK AP社の`スマートコントロールキー`というスマホアプリで対応します。

スマホでロックをコントロールするのはありがたいですが、毎回操作する時：`スマホアンロック　→　アプリ起動　→ 電気錠との接続待ち　→ 施錠・解錠` の操作フローが長いのでちょっとめんどくさいかと思っていました。

いざアプリでコントロールできるので、プログラムでアプリを制御して Home Assistantに導入できるではないかという考えが浮かんでいました。Home Assistantへの導入ができれば、どこでも利用できるようになるでしょう。

# その前に
YKK AP社は、IoT製品 Mimottoというものがあります、電気錠の操作はリモートでもできますが、Echonet Liteの対応はできるらしいです。
商品：[ミモット](https://www.ykkap.co.jp/consumer/products/window/mimott)
導入ガイド：[導入ガイド](http://tojimari.ykkap.co.jp/shop/pages/guide.aspx)

[他の記事](https://sympapa.hatenablog.com/entry/2022/05/06/111823)を参照したところかなり値段が高いかと思いました。
> Mimotto用インターフェースユニットの定価は52800円。サブスクは500円/月です。
> 窓のクレセントセンサーでさえ24,200円もします。
> 更に玄関ドアの操作盤付ユニットがMimotto対応のYS-KAG B7でなくてはいけません。標準の操作盤付ユニットYS-KAG B3(HAコネクタ、増設操作盤コネクタ）の定価が15,000円であるのに対しMimotto対応のYS-KAG B7は定価が42,000円で差額27,000円です。
> 半額で見積もっても”Mimotto”を導入するにはイニシャルで40,000円上乗せ、更に500円/月のサブスク、そして同社のドアと窓にのみ対応というなかなかコスパの低いシステムとなっています。

# 前提と必要なもの
- スマートコントロールキーアプリが対応する電気錠（[対応商品参照](https://www.ykkap.co.jp/consumer/support/sck/)）
- Androidスマホ一台（コントロール専用、他用不可。古いものOK、画面割れOK）
- Docker実行環境

# 実現の発想
実現方法を調べた時、[この記事](https://sympapa.hatenablog.com/entry/2022/05/07/065312)の記載者はハードウェアで YKK APの電気錠をコントロールできることがみました、でも筆者はハードウェアのプログラミング知識はあんまりないので、全部ソフトウェアプログラミング範囲内で実現したいかと思っていました。
そのため、下記の流れでできるかなと考えました。

- スマホで`スマートコントロールキー`アプリを常時に開き、実際の電気錠の操作を行います
- プログラミングで MQTT サーバからのメッセージの受信に応じて反応し、`adb`コマンドでスマホアプリをコントロールします
- Home Assistant は頭とブリッジそして全体的の流れのコントロールとiPhoneへの導入をします

図形化したら下記となります。

```mermaid
graph TD
    U((ユーザー)) -->|操作| A[iPhone\n#40;HomeKit#41;]
    A -->|指示| C{Home Assistant}
    C -->|設定| D[MQTTロック定義]
    C <-->|データ交換| E{MQTTサーバー}
    F[Dockerコンテナ] <-->|サブスクライブ/パブリッシュ| E
    F -->|ADBコマンド| G[Androidスマホ]
    G -->|Bluetooth制御| H((YKK AP\n電気錠))
    I[ドア/窓センサー] -.->|オプション| C
    I -.->|状態検知| H
```

*`※ 上図はドア/窓センサーを電気錠につけましたが、オプションなので、もしなければプログラムの繰り返す状態検査ロジックを短めに設定すれば全然仕事できます`*


# リソース
実現の考えがあったら実際の実現は逆に簡単です。必要なソースコードと設定ファイルなどはGitHubにアップロードしたので、ご参照ください。
[GitHub: ykkap-lock-bridge](https://github.com/fisheepx/ykkap-lock-bridge)
- configuration.yaml
コードスニペットをHome Assistant の設定ファイルに追加

- automations.yaml
コードスニペットをHome Assistant の設定ファイルに追加

- docker-compose.yml
Dockerコンテナを作成するファイル

- app_control.py
電気錠を実際にコントロールするプログラムロジック

# 参考した文書
Home Assistantで設定したロックをHomeKitでロックと認識させる方法：[Gate lock and homekit](https://community.home-assistant.io/t/gate-lock-and-homekit/417009)
設定したロックは HomeKit に出ない場合の解決方法：[Homekit integration missing ZWave locks?](https://community.home-assistant.io/t/homekit-integration-missing-zwave-locks/304762/3?u=fis.h)
Android端末のスクリーンをOFFにしてもスリープさせない方法：[GitHub: HunterXProgrammer/DisplayToggle](https://github.com/HunterXProgrammer/DisplayToggle)、[adb+DisplayToggle.dex实现手机屏幕关闭但不休眠](https://meta.appinn.net/t/topic/46361)
ChatGPTに、TDDを説明するスライドをMarpで作ってもらう

新規PJでTDDを導入することになったので、チームメンバーにTDDのメリットを説明するため、ChatGPTにMarpでスライドを作ってもらいました。

## Marpとは
https://marp.app/

Marpは、Markdownを使用してプレゼンテーションスライドを作成するためのツールです。以下にMarpの主な特徴を説明します:

### 主な特徴

- **簡単な使用法**: Markdown記法でスライドを作成できるため、使いやすさが特徴です。

- **自動レイアウト**: レイアウトや書式を自動で整えてくれるので、内容に集中できます。

- **出力形式**: HTML、PDF、PowerPointなど、様々な形式でエクスポートが可能です。

- **カスタマイズ性**: CSSを使用してデザインをカスタマイズすることができます。

### メリット

- スライドの内容作成に集中できる
- 簡潔でスッキリしたスライドを作りやすい
- 見出しや強調などの書式が統一しやすい
- キーボードのみで操作可能

### 使用環境

Visual Studio Codeの拡張機能として利用できるため、Windows、Mac、Linuxなど、OSを問わず使用可能です。

Marpは、特にチーム開発や素早くきれいなスライドを作成したい場合に適しています。ただし、細かなアニメーションや複雑なレイアウトが必要な場合は、従来のプレゼンテーションソフトの方が適している場合もあります。

## やってみる

以下のようなプロンプトを投げました。

```txt
#役割　あなたは、凄腕のソフトウェアエンジニアです
#指示　この度、チームメンバーに、テスト駆動開発について具体的に説明することになりました。テスト駆動開発についての説明と、簡単なサンプルコードを使って、進め方を説明して下さい
上記を、Marpでスライドを作成して下さい
サンプルコードはGoで書いて下さい
TDDのメリットとして、バグが早期に発見されることがあります
これもわかりやすいようにサンプルコードも含めて説明を加えて下さい
```

返ってきた答えをmarkdownファイルにコピーします。

VSCodeの拡張機能[^1]でPDFに変換して完成です！
[^1]: https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

## 成果物

<script defer class="speakerdeck-embed" data-id="9d4b445e8ad548fb82f7273eeb0e54c3" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

## 感想
このスライドは5分くらいで完成しました。
簡単なスライドであれば、生成AIに作らせた方が圧倒的に効率が良いと思いました！
プロンプト次第では、高度な内容のスライドも早く作れると思うので、使いこなせるように頑張ります。
SageMaker JumpStartを使ってテキストの感情分析をやってみた 

# はじめに
この度、ANGEL Calendarの企画に参加してます。TOKAIコミュニケーションズの阿部と申します。
本日は24日目です。
こちらのANGEL Calendarの企画では、AWSに限らず様々な技術記事が投稿されているのでぜひ確認してみてください！！

https://qiita.com/organizations/2024-angel-dojo

# SageMaker JumpStartとは
SageMaker JumpStartは、Amazon SageMaker Studio内で利用可能なサービスで、数回のクリックで事前学習済みのモデルをデプロイして、すぐに推論を行うことができます。さらに、自分のデータセットを用いてモデルを再学習（ファインチューニング）することも可能です。

https://aws.amazon.com/jp/sagemaker/jumpstart/

# 前提
AWSアカウントを持っていること

# 実装 
### １．SageMaker Studioのセットアップ
マネジメントコンソールのSageMakerサービスにアクセスします。その後、左側メニューからStudioをクリックし、SageMakerドメイン作成をクリックします。
![資料1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889582/f358df5f-4e51-5f8f-0518-58701acbe76e.png)

今回はシングルで使用するので左の「シングルユーザー向けの設定（クイックスタート）」を選び「設定」ボタンをクリックします。（スタジオが作成されるまで数分かかることがあるので待ちます。）
![資料2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889582/6803b986-141b-b99e-df8a-6fd248ccfdb2.png)

Studioの設定が完了したら、AWSコンソールのSageMaker Studioページで作成したスタジオのユーザープロファイルを選択し、「Studioを開く」をクリックし起動します。（初期起動時は、環境構築に時間がかかる場合があります。）
![資料3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889582/552d4ab6-7518-7fd8-5f9a-cd0e505a628d.png)

### 2.テキストの感情分析が可能な「Text Classification」を選びデプロイ。
左側のメニューから「JumpStart」を選びます。
![資料4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889582/aa9219cd-67a5-3416-5b96-22a1097eb0d1.png)

今回はテキストベースの感情分析なのでそれに特化したモデルを選んで「デプロイ」をクリックします。
![資料11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889582/8c14c5ff-4364-f8af-4ddb-87582a044e26.png)

### 3.テキスト分類を実行して感情分析
モデルがデプロイできたら、実際に感情分析を行います。SageMaker Studioのノートブックで以下のPythonコードを使ってテキスト分類を実行します。
```python
import boto3
import json

# SageMaker Runtimeクライアントを作成
runtime = boto3.client('runtime.sagemaker')

# エンドポイント名を指定
endpoint_name = 'your-endpoint-name'

# テストするテキストのリスト（ポジティブとネガティブ）
texts = [
    "I love this product!",  # ポジティブ
    "I hate this product!"   # ネガティブ
]

# 各テキストに対して感情分析を実行
for text in texts:
    print(f"Input Text: {text}")
    
    # エンドポイントを呼び出して感情分析を実行
    response = runtime.invoke_endpoint(
        EndpointName=endpoint_name,
        ContentType='application/x-text',
        Body=text
    )

    # 結果を取得して表示
    result = json.loads(response['Body'].read().decode('utf-8'))
    print(f"Model Output: {result}")
    print("\n")

```
このコードでは、SageMaker JumpStartでデプロイしたエンドポイントを使って、感情分析を行います。

### 4.出力結果
実行結果はprobabilitiesフィールドに確率値として表示されます。次のように解釈します。
#### ポジティブなテキストの場合:
```
Input Text: I love this product!
Model Output: {'probabilities': [0.0007346862112171948, 0.9992652535438538]}
```
右の確率（99.93%）が高いので、このテキストはポジティブです。
#### ネガティブなテキストの場合:
```
Input Text: I hate this product!
Model Output: {'probabilities': [0.9935943484306335, 0.006405672524124384]}
```
左の確率（99.36%）が高いので、このテキストはネガティブです。

# まとめ
SageMaker JumpStartは、事前学習済みの多種多様なモデルを活用し、複雑な機械学習タスクを簡単に実装できる強力なツールです。今回紹介した感情分析モデル以外にも、画像認識や物体検出、予測モデルなど、さまざまな用途に対応するモデルが揃っています。特に、機械学習の専門知識がなくても数分でモデルをデプロイし、実際のデータを使った分析が可能です。ぜひ皆さんも試してみてください！

# 参考
https://aws.amazon.com/jp/sagemaker/jumpstart/
初心者だからこそできる限り効率的に作業を進めたい！！

# はじめに
こんにちは。未経験1年目のエンジニアです。
最近、ゼロからコードを作成する機会がありました。普段は、ほぼ完成したコードの修正や追加を行っているため、ゼロからコードを書くことに慣れておらず、かなり時間がかかってしまいました。

時間がかかった原因は、間違いなくコードが汚かったことにあります。
私は「とにかく動けばいい」という考えで、コードの整理をせずにどんどん書き進めてしまいました。その結果、同じコードが何度も繰り返され、自分が修正したい箇所にたどり着くのにも時間がかかる始末。極めつけには、「何が言いたいんだ？」という謎のコードまで完成してしまいました。

さらに、英語が苦手な私は、適当にメソッド名をつけてしまい、同じプロジェクトの方から「これ何？」と言われてしまうこともあり、ご迷惑をおかけしてしまいました。

# コードを綺麗に書かないことで起きた困りごと
### エラー箇所がわからない
コードが整理されていないため、どこでエラーが発生しているのか特定できませんでした。
### 処理がわからなくなる
複雑で冗長なコードにより、どの処理を行ったのかわからなくなってしまいました。
### 修正や追加に時間がかかる
目的の箇所を探すのに時間がかかり、効率が低下しました。

# コードを綺麗に書くことで
綺麗なコードを書くことで、効率が上がり、修正もしやすくなります。
また、どのコードがどの部分に対応しているのかを把握できるので、開発がスムーズに進みます。
綺麗なコードは読みやすく、保守もしやすいため、開発プロセス全体がスムーズになります。同じプロジェクトチームの方たちのためにも、一緒に綺麗なコードが書けるようになりましょう！

# コードを綺麗に書くために心がけること
### 1. コメントを書く
英語が苦手なため、メソッド名だけでは何をしているのか理解できず、わざわざそのメソッドを見に行く手間がありました。適切なコメントを書くことで、自分や他人がコードを理解しやすくなります。期日やチームでの開発を考えると、スピード感も大切です。

### 2. 重複したコードを書かない
同じ処理が何度も出てくる場合は、共通部分を一つのメソッドにまとめましょう。これにより、コードがシンプルになり、修正も容易になります。

### 3. 適切なメソッド名をつける
メソッド名は考えてもわからないことがあります。私のように英語が苦手な方は、翻訳ツールなどを活用して、「こんな感じかな？」と徐々に掴んでいくのも良いと思います。次に同じようなメソッドを作成する際に少しでも思い出せれば、それはもう成長です！

# まとめ
コードを綺麗に書くことで、私自身効率が上がり、コードを書くことがより楽しくなりました。また、私は完璧主義な一面があるので、綺麗なコードを書けるだけで心が弾み、モチベーションも高まりました。
初めは時間がかかるかもしれませんが、その先にあるメリットを考えると、取り組む価値が大いにあると思います。

これからも学びを続け、より良いエンジニアを目指していきたいと思います。
カーソルみたいなものって難しいよね

# 最初に試したこと
最初は`display:flex;`でanimationしてるカーソルの`<span>`を横並びにしていた。
するとあら不思議。
wrapしたタイミングでどんどん`<span>`が縦に伸びていく。
最初のコードはこんな感じ。
```html
<div class="flex">
    <span class="char"></span><span class="cursor"></span>
</div>
```
cssはこんな感じ。
```css
.flex{
    display:flex;
}
.cursor{
    opacity:1;
    background-color:#000;
    animation:backchange 0.5s infinite;
}
@keyframes backchange{
    0%{
        background-color:#000;
    }
    50%{
        background-color:#fff;
    }
    100%{
        background-color:#000;
    }
}
```
私(素人)が頑張ってこんなコードを書いたが、縦に伸びていくばかり。
今思えば横並びにしてるので当たり前。

これを皮切りに二時間格闘。
たとえばcharを書き換えるたびに`<span>`の場所を書き換えたり、果てはJavaScript側でcursorのanimationを無理やり組んだり。
それでも改行したら改行された位置にカーソルが絶対に移動する。
どうしたものか...と困り果てていた時に、あることに気がついた。

**使うのは擬似要素や**

...というわけで。
# 結論 擬似要素を使え

```css
.char::after{
    content: '';
    border-right: 2px solid;
    animation: flashing 0.5s linear infinite;
}
body::-webkit-scrollbar {
    display: none;
}
        @keyframes flashing{
    0%{
        border-color: #000;
    }
    50%{
        border-color: #fff;
    }
    100%{
        border-color: #000;
    }
}
```
HTMLはお察しの通り。

以上っ!
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（98/100）

【98日目】
トピック 10：SAPS/4HANAの能力計画（6/8）

≪問題98≫
製造指図作業に対して作業ステータス"差立済"が設定されている場合は、どのような選択肢がありますか。
（２つ選択）
□製造作業管理アプリで、作業日程を再計画できる。
□計画テーブルの中間点日程計画を使用して、作業日程を再計画できる。
□計画テーブルの有限計画を使用して、作業日程を再計画できる。
□計画テーブルの無限計画を使用して、作業日程を再計画できる。

≪解答≫
■製造作業管理アプリで、作業日程を再計画できる。
□計画テーブルの中間点日程計画を使用して、作業日程を再計画できる。
■計画テーブルの有限計画を使用して、作業日程を再計画できる。
□計画テーブルの無限計画を使用して、作業日程を再計画できる。

≪解説≫  
◆SAP Fioriベースの生産日程計画実行アプリでは、指図の一覧を使用して、複数の指図の差立や割当解除を行うことが可能です。また、複数の指図に対して、日程計画を再調整することもできます。  
◆計画テーブルは、利用可能能力と能力所要量がさまざまな基準に基づいてグループ化され、共通の時間軸上に表示される複数のチャートで構成されています。ユーザは、ドラッグ&ドロップ操作を使って作業のタイムスロットを調整し、作業を再スケジュールできます。有限計画は、有限計画関連区分が設定されているリソースの作業に対してのみ実行されます。差立済作業にはステータス"DSPT"が設定され、再日程計画は有限計画のみで可能です。差立されていないか、有限計画関連区分が設定されていないリソースの作業は、無限で計画されます。
【Revit】Revit起動時、addinファイルで指定したアドインのロードが失敗してしまう際の解消方法

# 概要
Revit起動時にaddinファイルで指定したアドインのdllのロードが失敗し、「外部ツールエラー」ウィンドウでアドインが読み込めない旨のエラーメッセージが表示される場合の対処法について記載しました。

# 以下の現象の解消方法です
Revit起動時、アドインのロードエラーのウィンドウが表示される (物件ファイル選択画面より前に表示されます)
- エラーメッセージのウィンドウのタイトルは「外部ツール - 外部ツールエラー」
- エラーメッセージの例は、「Revitで外部アプリケーションの"〇〇"を実行できませんでした。サポートが必要な場合は～」となっている
- エラーの種類は「System.IO.FileLoadException」
- エラーメッセージの詳細の箇所は、「ファイルまたはアセンブリ"dllまでのパス"、またはその依存関係の1つが読み込めませんでした。操作はサポートされていません。(HRESULTからの例外：xxxxxx)」となっている

# 解消方法
Revitが読み込もうとしているdllが、アクセスブロックになっていて読み込みが失敗している可能性があります。その場合は、以下の方法で解消できます。
1. 読み込もうとしているdllについて、右クリックからプロパティを表示する
1. 「全般」タブの下部の「セキュリティ」で、「許可する」に☑を入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533049/a53ab49d-159e-98eb-b8ed-fe485293ae0e.png)
1. 変更を保存しプロパティを閉じる (完了)

再度Revitを起動すると、アドインのdllは無事ロードできると思います。

# 終わりに
最初にこの現象に遭遇したときは、PGやaddinファイルの定義等を色々調べて解消に時間が掛かってしまいました。他の開発者からモジュールがzipファイル等で連携されたときに起こりやすいです。
※zipファイルをそのまま解凍すると、解凍されたdllは「許可する」に☑が入っていない状態になっているためです。
この場合は、解凍前にzipファイルのプロパティから「許可する」に☑を入れると、解凍後のdllは全て☑が入った状態になります。
DatabricksでMeta Llama 3.2を動かしてみる

こちらのブログにあるように、Metaの軽量かつマルチモーダルモデルである[Llama 3.2](https://ai.meta.com/blog/llama-3-2-connect-2024-vision-edge-mobile-devices/)の発表に合わせて、DatabricksでもLlama 3.2が利用できるようになりました！

https://www.databricks.com/blog/introducing-meta-llama-32-databricks-faster-language-models-and-powerful-multi-modal-models

ビジョンモデルや[Llama Stack](https://github.com/meta-llama/llama-stack)なども気になりますが、まずは動かしてみます。

カタログエクスプローラから`system.ai`にアクセスすると、3.2シリーズが追加されています。
![Screenshot 2024-09-26 at 8.25.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/a56a2722-f229-1bbd-35b1-89a2ebc58fc8.png)

プロビジョニング済みスループットモデルとしてデプロイします。
![Screenshot 2024-09-26 at 8.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/22007279-ea6b-a3fe-8941-b49262574716.png)

![Screenshot 2024-09-26 at 8.27.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f2dade02-2c61-6791-e0b8-c99d14ff5f4a.png)

少し待つとREADYになります。
![Screenshot 2024-09-26 at 8.29.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ded4586b-36c4-aab4-3324-6b3109083c2a.png)

まずは、サンプルでクエリーしてみます。
![Screenshot 2024-09-26 at 8.29.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8b32d4d4-8c3c-5d07-f117-8e0fbc113c12.png)

動きました。
![Screenshot 2024-09-26 at 8.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b405ffc1-8659-e69e-82cb-02f169792a3f.png)

AI Playgroundからもアクセスできます。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/6418b021-5522-b96e-93fa-b0b96bd7b7a1.png)

きちんと日本語を解しますし速いです。
![Screenshot 2024-09-26 at 8.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d0433232-c752-c5d5-987b-6e0b31adf6e6.png)


### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
github actionでDocker imageに対してtrivyで脆弱性スキャンを行う

## 最終ゴール

github actionでtrivyにより脆弱性診断を行い、脆弱性への対応を恒常化させる。
(脆弱性診断をCIに組み込むのは最悪リリースブロッキングになる可能性もあるので、チームの状況によって適宜アレンジして取り込んでください。)

## trivyとは
脆弱性の検知をしてくれるOSS

https://github.com/aquasecurity/trivy

Docker imageに対しても診断可能でOS/libレベルのチェックを行ってくれる

## CIへの組み込み

こちらのライブラリでgithub actionが提供いただいているのでこちらを活用する

https://github.com/aquasecurity/trivy-action

Docker imageのbuildにはこちらを利用

https://github.com/docker/build-push-action

↓ミニマムのサンプル
```yml
name: Scan with Trivity

on: push

jobs:
  trivy:
    runs-on: ubuntu-latest
    env:
      ACTIONS_RUNTIME_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/build-push-action@v6
        with:
          push: false
          load: true
          tags: test-${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "test-${{ github.sha }}"
          exit-code: "1"
          ignore-unfixed: true
          severity: "CRITICAL,HIGH"
```

### 各ステップの説明
#### docker/setup-buildx-action
docker buildxを利用することでキャッシュを使えるようにする

https://qiita.com/_kei_s/items/15c067090d5142648aac

#### docker/build-push-action
* push: false
    * Docker registryへのpushは不要(ローカルスキャンのため)なのでfalseを指定
* load: true
    * ローカルのDockerにimageをロードする(ローカルでDocker imageを参照できるようにする)
* tags
    * 一意の名前を付与する(後述のtrivityで指定するimageと合わせる)
* cache-from / cache-to
    * キャッシュを行うための設定

#### aquasecurity/trivy-action
* image-ref
    * docker/build-push-actionのtagsと名前を合わせる
* exit-code: 1
    * 脆弱性が発生した場合はエラーにする(Securityとして登録するだけなどの場合はなしでOK)
    * デフォルト0で脆弱性が出てもCIが通ってしまうので注意(用途に合わせる)
* ignore-unfixed: true
    * 修正が出ていないものはスキップする
* severity: "CRITICAL,HIGH"
    * 好みに合わせてエラーにする脆弱性レベルを指定


### つまづきポイント
#### ライブラリで修正パッチがまだ出ていないがCIがずっと落ちてしまう
`ignore-unfixed` を指定することで修正パッチが出ていない問題はスキップできる(根本的な解決ではないのでCIとして継続チェックを入れるのであれば必須になりそう)

#### RATELIMIT問題への対応
```
FATAL Fatal error init error: DB error: failed to download vulnerability DB: database download error: oci download error: failed to fetch the layer: GET https://ghcr.io/v2/aquasecurity/trivy-db/blobs/sha256:11c57f2012b2ac112256f94aa404e1feb7e1b7a5787598946b87149115cdb43d: TOOMANYREQUESTS: retry-after:
```
脆弱性のマスターデータ取得の時にratelimitに引っかかる問題が発生する
↓こちらのissueに回避方が書いてあり

https://github.com/aquasecurity/trivy-action/issues/389

envで `ACTIONS_RUNTIME_TOKEN` にGITHUB TOKENを入れると回避できるらしい(今の所発生していない)
[WARNING]: ! Unable to write cache: {"code":"ERR_BAD_REQUEST","message":"Request failed with status code 404"})}の解決方法


## はじめに

amplifyでいつものようにデプロイを行うと、なぜかデプロイが転けてしまい、
解決に時間がかかったのでまとめます。

## 問題と原因

CDを走らせると以下のような警告が出ました。

```bash
[WARNING]: ! Unable to write cache: {"code":"ERR_BAD_REQUEST","message":"Request failed with status code 404"})}
```

原因としては、すでに削除したリモートブランチと同じ名前のローカルブランチを作成し、
プッシュしてPRを立てると、リモートブランチ側との整合性が取れなくなり、キャッシュエラーが起きたみたいです。

## 解決方法

シンプルにAmplifyのGUIにある、プロジェクトキャッシュ削除をするだけで解消しました。
amplify.ymlに`envCache --set stackInfo ""`を書いてもいけるみたいです。

## おわりに

こういうエラーは大元のコードがどういう処理をしているかが見えないのでデバッグしづらいですね。
ほなまた。

## 参考資料
 
https://github.com/aws-amplify/amplify-cli/issues/13572
康煕部首を検索するブックマークレット

[康煕部首とは](https://ja.wikipedia.org/wiki/%E5%BA%B7%E7%85%95%E9%83%A8%E9%A6%96)
webサイト制作時、支給原稿などによく混ざっているので最終webブラウザで確認時にも検索できるようブックマークレットを作成しました。
\u2F00-\u2FDFがハイライト表示されるようになります。

![スクリーンショット 2024-09-26 082316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322108/9ef59a05-eb39-c89e-a3a0-0da8fc982283.png)

~~~javascript
javascript:(function(){var regex=/[\u2F00-\u2FDF]/g;var text=document.body.innerHTML;var kanjis=text.match(regex);var kanjisSet=new Set(kanjis);var kanjisArray=Array.from(kanjisSet);var highlighted=text;kanjisArray.forEach(function(kanji){highlighted=highlighted.replace(new RegExp(kanji,'g'),'<span style="background-color:yellow;">$&</span>');});document.body.innerHTML=highlighted;if(kanjisArray.length>0){alert(kanjisArray.length+"個の康煕部首が存在します。");}else{alert("康煕部首は存在しません。");}})();
~~~
【Rails】blank?とempty?は空白文字とnilの扱いが異なる

## はじめに

`blank?`と`empty?`の違いがよくわからなくなりました。

そこでこの記事では、空白文字と`nil`を切り口に両者の違いを整理します。

## `blank?`と`empty?`は空白文字とnilの扱いが異なる

空白文字と`nil`を順番に確認します。

### 空白文字について

- `blank?`メソッド: `true`と判定
- `empty?`メソッド: `false`と判定

```ruby
rails> " ".blank?
=> true
rails> " ".empty?
=> false
```

### `nil`について

- `blank?`メソッド: `true`と判定
- `empty?`メソッド: `NoMethodError`の例外発生

```ruby
rails> nil.blank?
=> true
rails> nil.empty?
/opt/homebrew/lib/ruby/gems/3.3.0/gems/irb-1.14.0/lib/irb.rb:1285:in `full_message': undefined method `empty?' for nil (NoMethodError)

nil.empty?
   ^^^^^^^
```

## ちなみに`exists?`はどうか？

`exists?`はデータベースの中身を確認しに行くメソッドです。

そのため、空白文字・`nil`に対してメソッドを呼び出すとどちらも`NoMethodError`が発生します。

```rails
rails> " ".exists?
/opt/homebrew/lib/ruby/gems/3.3.0/gems/irb-1.14.0/lib/irb.rb:1285:in `full_message': undefined method `exists?' for an instance of String (NoMethodError)

" ".exists?
   ^^^^^^^^
rails> nil.exists?
/opt/homebrew/lib/ruby/gems/3.3.0/gems/irb-1.14.0/lib/irb.rb:1285:in `full_message': undefined method `exists?' for nil (NoMethodError)

nil.exists?
   ^^^^^^^^
```

## おわりに

存在を確認するメソッドは色々あってややこしいです。

備忘録としてまとめてみました。

内容に誤りがありましたらコメントにて教えていただけますと幸いです。

### 参考資料

https://github.com/rails/rails/blob/main/activerecord/lib/active_record/relation.rb#L355

https://github.com/rails/rails/blob/main/activerecord/lib/active_record/relation.rb#L1267

https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-blank-3F

https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-empty-3F
Pythonのzip()関数

# はじめに
Pythonのzip()関数を使うと、複数のイテラブル（リスト、タプル、辞書、集合のように繰り返し可能なオブジェクト）から要素を取り出し、対応する要素をまとめることができます。
# zip()関数の使用例
例えば、キーと値が別々のイテラブルであっても、dict()関数とzip()関数を使うことで簡単に辞書を生成することができます。
~~~Python:zip_dict.py
drink = 'milk', 'tea', 'coffee', 'juice' # キーのイテラブル
price = 160, 210, 150, 250 # 値のイテラブル
dict(zip(drink, price))
# {'coffee': 150, 'juice': 240, 'tea': 220}
~~~
# zip()関数を使用する場合の注意点
異なる長さの複数のイテラブルにzip()関数を使用すると、zip()関数は**短いほうのイテラブルに合わせて処理を終了してしまう**ので、長いほうのイテラブルに**処理されなかった要素が存在することを警告してくれません**。
# どうすればいいのか？
**Python 3.10から、zip()関数にstrictオプションが追加された**ので、複数のイテラブルの長さが異なる場合は、ValueErrorを発生させるようにしましょう。
~~~Python:zip_strict.py
drink = 'coffee', 'juice', 'tea', 'milk'
price = 150, 240, 220
for x, y in zip(drink, price, strict=True):
    print(x, y)

# この例では、イテラブルの長さが異なるので次のエラーが発生します。
ValueError: zip() argument 2 is shorter than argument 1
~~~
# zip_longest()を使う
zip()と似たzip_longest()という関数を使うこともできます。**zip_longest()はzip()と異なり、長いほうのイテラブルに合わせてイテレータを作成します**。 短いほうのイテラブルで、長いほうのイテラブルの長さを超えた場合の要素はデフォルトではNoneを返します。zip_longest()を使うには**itertoolsをインポートする必要**があります。
~~~Python:zip_longest1.py
import itertools
for x, y in itertools.zip_longest('aiu', '12'):
    print(x, y)

# 出力結果
a 1
i 2
u None
~~~
None以外の値を返したい場合は、fillvalueという引数で指定します。
~~~Python:zip_longest2.py
import itertools
for x, y in itertools.zip_longest('aiu', '12', fillvalue='N/A'):
    print(x, y)

# 出力結果
a 1
i 2
u N/A
~~~
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（97/100）

【97日目】
トピック 10：SAPS/4HANAの能力計画（5/8）

≪問題97≫
グラフィック計画テーブルで作業区の特定の時点に作業を挿入しようとしています。計画方向は順方向です。希望する差立時刻は、以前に差立てた作業と重なります。この挿入はどのように実行されますか。
□新規作業が希望の時刻に挿入され、以前に差立てた作業は後ろ倒しされる。
□新規作業が希望の時刻に挿入され、以前に差立てた作業は前倒しされる。
□以前に差立てた作業の時刻は変更されず、新規作業が差立ててある作業の後に挿入される。
□以前に差立てた作業の時刻は変更されず、新規作業が差立ててある作業の前に挿入される。

≪解答≫
□新規作業が希望の時刻に挿入され、以前に差立てた作業は後ろ倒しされる。
□新規作業が希望の時刻に挿入され、以前に差立てた作業は前倒しされる。
■以前に差立てた作業の時刻は変更されず、新規作業が差立ててある作業の後に挿入される。
□以前に差立てた作業の時刻は変更されず、新規作業が差立ててある作業の前に挿入される。

≪解説≫  
◆日程計画で特定の時刻に作業を挿入する場合、方針プロファイルで作業挿入に関する設定を行う必要があります。  
◆希望する差し立て時刻がすでに別の作業と重なっている場合、新しい作業は、計画の方向（順方向または逆方向）に応じて、その作業の前または後に差し立てられます。すでに差し立てられている他の作業があれば、それに合わせて計画の方向にシフトされますが、もし計画期間を超える場合、その作業の差し立ては取り消されることがあります。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（96/100）

【96日目】
トピック 10：SAPS/4HANAの能力計画（4/8）

≪問題96≫
SAP S/4 HANAで能力計画のために表形式の計画テーブルを利用できるのは、以下のどのチャートタイプですか。
（２つ選択）
□指図（プール）チャート
□指図（差立済）チャート
□作業区能力チャート
□能力所要量チャート

≪解答≫
□指図（プール）チャート
□指図（差立済）チャート
■作業区能力チャート
■能力所要量チャート

≪解説≫
◆表形式の計画テーブルを使用して、作業区の負荷平準化を行うことができる。
◆表形式の計画テーブルは、上下2つのチャートで構成される。上のチャートでは、選択した作業区の残存能力が期間分割に表示される。下のチャートには、選択した作業の能力所要量が表示される。
◆表形式の計画テーブルでは、作業の能力所要量が期間に差し立てられるが、期間内の差立済作業に対して特定の順序を登録することはできない。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（95/100）

【95日目】
トピック 10：SAPS/4HANAの能力計画（3/8）

≪問題95≫
能力計画における作業区階層とは何ですか。
□優先順位別の階層レベルに構造化される、生産の代替作業区グループ
□生産の順序で使用される生産ライン内の作業区グループ
□生産の累計利用可能能力を提供する代替作業区グループ
□生産数量の分割および同時作業に使用される平行順序内の作業区グループ

≪解答≫
□優先順位別の階層レベルに構造化される、生産の代替作業区グループ
□生産の順序で使用される生産ライン内の作業区グループ
■生産の累計利用可能能力を提供する代替作業区グループ
□生産数量の分割および同時作業に使用される平行順序内の作業区グループ

≪解説≫  
◆特定のタスクを複数の代替作業区で実行可能な場合、これらの作業区に対して作業区階層を登録できます。  
◆能力評価の際には、代替作業区の能力所要量と利用可能能力が階層作業区に累積されます。  
◆もし特定の作業区で過負荷が発生した場合でも、代替作業区に対して能力所要量を再計画することで、代替作業区の所要量と利用可能能力が階層作業区に累積され、過負荷の解消が期待できます。