OmniAICreator/Qiita-1.07M huggingface dataset:
PHPを任意ユーザー(webapp)で動かす


任意ユーザー（ここではwebappというユーザー）を追加して、そのユーザーでphpを動かす方法について記載します。
環境は AmazonLinux2 で、nginx、php-fpm はインストール済とします。
# 1. webappユーザーの追加の前準備
デフォルトだと webappユーザーを追加する際、ホームディレクトの ``/home/webapp`` の権限が ``700``で作成されてしまいます。
これだと他のユーザーが``/home/webapp``ディレクトリに入れないので、権限を``755``とする為、``login.defs`` の ``UMASK``の設定を変更します。
```
$ sudo vi /etc/login.defs
```
```
# 略
# The permission mask is initialized to this value. If not specified, 
# the permission mask will be initialized to 022.
UMASK           022 <=====この行を077 から 022に変更する
# 略
```
# 2. webappユーザーの追加
以下のコマンドを入力して、``webapp``ユーザーを作成します。
```
$ sudo useradd webapp
```
以下のコマンドでユーザーが追加されているか確認します。
```
$ id webapp
uid=1001(webapp) gid=1001(webapp) groups=1001(webapp) <=====このように表示されればOK
```
念の為、ディレクトリの権限も確認します。
```
$ ls -l /home
略
drwxr-xr-x  7 webapp   webapp   173 12月 14 04:09 webapp <=====権限が755になっています
```
# 3. php-fpm の権限変更
``/etc/php-fpm.d``ディレクトリの```www.conf```を編集します。
```
$ sudo vi /etc/php-fpm.d/www.conf
```
```
略
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache user chosen to provide access to the same directories as httpd
user = webapp <=====ここをwebappにします
; RPM: Keep a group allowed to write in log dir.
group = webapp <=====ここをwebappにします

; The address on which to accept FastCGI requests.
略
```
# 4. php-fpm の再起動と確認
以下コマンドで``php-fpm``を再起動します。
```
$ sudo systemctl restart php-fpm
```
以下コマンドでphp-fpmのプールのユーザーやグループが変更されたかを確認します。
```
$ ps -o user,group,cmd -e | grep -v grep | grep php-fpm
root     root     php-fpm: master process (/etc/php-fpm.conf)
webapp   webapp   php-fpm: pool www   <=====webappになっている
webapp   webapp   php-fpm: pool www
webapp   webapp   php-fpm: pool www
webapp   webapp   php-fpm: pool www
webapp   webapp   php-fpm: pool www
```
# 5. nginx の再起動
忘れがちですが、nginxも再起動が必要です。
```
$ sudo systemctl restart nginx
```
以下コマンドで``webapp``ユーザーになります。また``-``をつけることで、そのユーザーのディレクトリに自動で移動します。
```
$ sudo su - webapp
```
# 6. まとめ
これで``webapp``ユーザーでログインし、``/home/webapp``フォルダにPHPアプリケーションを置く（cloneとかでもってくる）ことにより、ファイル権限も``webapp``になり、動いているphpも``webapp``で動かすことができるようになりました。
phpは吐き出すログファイルなどの権限も``webapp``になるので、整合性がとれるようになります。
フロントエンドコンテナを停止させないようにする(ReactやVue)

# 内容
案件作業でコンテナのことをなんとなく理解した状態でECSの環境構築を行なっていした
その時に、フロントのタスクが開始はするのですが、なぜかすぐ落ちてしまい原因がわからずにいました。

僕みたいにまだコンテナのことをあまり理解していない状態でECSの構築を行なっている人のためになればと思いこの記事を書きます。

# 原因
コンテナを開始してコンテナがやるべき処理が完了しているためタスクが終了してしまっている

この原因で勘違いしてはいけないことは、何かエラーが起きてコンテナが停止してしまっているのではないかと思うことです。
ですが、実際は正常に終了しています。
問題なのはコンテナに処理をし続けさせることです。
そのためにどうすればいいのかというと、webサーバーのイメージをフロントのイメージに入れてあげる必要があります。

## 解決法
コンテナのイメージを構築後、webサーバーのイメージ(proxy)を入れることです。
実際にコードを見た方がわかりやすいと思います
~~~
FROM node:16.13.0-alpine3.12 as builder
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY ./front/package.json /usr/src/app/package.json
RUN yarn install --silent

# ソースを作業フォルダにコピーして、ビル
COPY ./front /usr/src/app
RUN yarn run build

COPY ./health.html /usr/src/app/build

#nodeのイメージの後にnginxのイメージを置く
FROM nginx:1.21.1-alpine
# nginxの設定を削除して、アプリで設定したファイルをコピー
RUN rm -rf /etc/nginx/conf.d
COPY ./docker/react/conf /etc/nginx

# 上記の生成されたアプリのビルド成果物をnginxのサンプルアプリが使用していたフォルダに
COPY --from=builder /usr/src/app/build /usr/share/nginx/html

EXPOSE 3001

CMD ["nginx", "-g", "daemon off;"]
~~~

このようにしてあげればnginxが動き続けるのでコンテナが終了することがありません

また、今回はnginxの設定ファイルは載せていませんが、たくさん設定ファイルの書き方についての記事をあげている方がいるのでその人たちに任せます


## 最後に
後から考えれば当たり前ですが、初めの方はやっぱり難しいですよね〜
この記事でコンテナのイメージをつかんでもらえたらなと思います。
Docker + Kubernetesでコンテナを操作しよう

# 環境構築
以下の記事で作成した環境を使用します
[PCに仮想化環境を構築しよう](https://qiita.com/yuutom1996/items/34dc5fdd989c1133daf2)

# コンテナの操作
## 手順
- Podを作成（Pod内のコンテナはcentosとnginxのイメージを使用）
- Pod内のコンテナに入りシェル実行
- Podから出る

## Podのマニフェストファイルを作成する
仮想マシンのrootディレクトリ配下にstudyフォルダを作成し、studyフォルダに以下のマニフェストファイルを作成
```pods.yaml
apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: default
  labels:
    env: study
spec:
  containers:
  - name: debug
    image: centos:7
    command:
      - "sh"
      - "-c"
    args:
    - |
      while true
      do
        sleep ${DELAY}
      done
    env:
    - name: "DELAY"
      value: "5"

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    env: study
spec:
  containers:
  - name: nignx
    image: nginx:1.17.2-alpine
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/797651f5-c63b-95f4-8717-3e73186bacb0.png)

## リソースの作成
VSCodeのターミナルから以下のコマンドを実行

- studyに移動
```
[root@localhost ~]# cd study
[root@localhost study]# 
```

- リソース作成
```
[root@localhost study]# kubectl apply -f pods.yml
pod/debug created
pod/nginx created
```

- 確認
```
[root@localhost study]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
debug   1/1     Running   0          47s
nginx   1/1     Running   0          47s
```

## コンテナに入る
- PodのIPアドレスを確認
```
[root@localhost study]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP           NODE                    NOMINATED NODE   READINESS GATES
debug   1/1     Running   0          3m8s   172.17.0.6   localhost.localdomain   <none>           <none>
nginx   1/1     Running   0          3m8s   172.17.0.5   localhost.localdomain   <none>           <none>
```

## debugコンテナに入る
```
[root@localhost study]# kubectl exec -it debug sh
sh-4.2# 
```

## debugコンテナからnginxコンテナにアクセス
```
sh-4.2# curl http://172.17.0.5/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

## リソースの削除
- コンテナから出る
```
sh-4.2# exit
exit
[root@localhost study]# 
```

- リソースの削除
```
[root@localhost study]# kubectl delete -f pods.yml
pod "debug" deleted
pod "nginx" deleted
```
Laravel のログのテスト用ライブラリ Log fake が 2.0 になっていた

Laravel のログのテスト用ライブラリ Log fake が 2.0 にバージョンアップしていたので紹介します。

# Log fake って何？

https://github.com/timacdonald/log-fake

Laravel のログのテスト用ライブラリで、主に以下のようなことができます。
- ログの内容やログレベルに対してアサーションが書ける
- テストでログのファイルが生成されなくなるため気づいたらゴミが貯まっていたということを避けられる

Laravel では`Mail::fake()`を使うと、テストの間はメールが実際に送られることがなくなり、メールの中身をテストすることもできるようになります。
それのログ版だと考えてもらえれば理解が早いと思います。

# 使い方
:::note info
2.0 以降がサポートしているバージョンは以下の通りで、少し新しいですのでその点はご注意ください。
- PHP 8.0, 8.1
- Laravel 9.0
:::

## インストール
まずは以下のコマンドでインストールしましょう。
```
composer require timacdonald/log-fake --dev
```

## 準備
`Mail::fake()`のようにテストの先頭や`setUp()`に以下を書きます。
新しいバージョンでは少しシンプルに書けるようになっていました。
```php
// 旧バージョン
Log::swap(new LogFake());

// 新バージョン
LogFake::bind();
```

## 基本のアサーション
- ログレベル： error
- ログの内容に特定の文字列が含まれている

例えば上記を確認するアサーションを書くと以下のようになります。

```php
// 旧バージョン
Log::assertLogged('error', function ($message) use ($exceptionMsg) {
    return Str::contains($message, $exceptionMsg);
});

// 新バージョン
Log::assertLogged(function (LogEntry $log) use ($exceptionMsg) { 
    return $log->level === 'error'
           && Str::contains($log->message, $exceptionMsg);
});
```
LogEntry というクラスが以下のプロパティ（他にもあります！）を持っています。
- level：ログレベル
- message：ログの内容

以前はログレベルをアサーションメソッドの引数として指定していましたが、新バージョンではコールバック関数の中で上記のプロパティを使ってまとめてチェックするようになっています。
ログレベルは気にしないけど内容だけ確認したい場合などは今のほうがシンプルに書けるかもしれません。

ただ、エラー文の完全一致であれば以前は`assertLoggedMessage()`でシンプルに書けたのでこういう書き方も残しておいてほしかった気もします。
これくらいならラップして独自にメソッドを追加すればいいよねというスタンスなのかもしれません。
```php
// 新バージョンではなくなっているアサーション
Log::assertLoggedMessage('error', $expectedMessage);
```

## 他のアサーション
ほとんどは上記のアサーションで足りると思いますが他の使いやすそうなアサーションを独断と偏見で挙げていきます。

### ログの回数をチェック
特定のログが指定の回数出力されているかを確認できます。
```php
Log::assertLoggedTimes(
    fn (LogEntry $log) => $log->message === 'hogehoge',
    2 // 第２引数で回数を指定
);
```

### チャンネルを指定してチェック
特定のチャンネルに対してのアサーションは、チャンネルを指定した後にチェーンメソッドで続けて書けるようです。
```php
Log::channel('slack')
   ->assertLogged(fn (LogEntry $log) => $log->message === 'hogehoge');
```

## ログ内容を出力する Log::dump()
これが新バージョンで一番便利になった点かなと思ってます！
テストを書いてる最中でアサーションが通らないとき、そもそもログが吐かれていないとか別のエラーで落ちてるなどはあるあるかと思います~~私だけ？~~
そこで`Log::dump()`をすれば以下のようにログの内容を出力してくれるのでデバッグに役立ちます！
```php
array:1 [ // vendor/timacdonald/log-fake/src/ChannelFake.php:52
  0 => array:5 [
    "level" => "error"
    "message" => "エラーが発生しました。"
    "context" => array:1 [
      "id" => 100000000
    ]
    "times_channel_has_been_forgotten_at_time_of_writing_log" => 0
    "channel" => "daily"
  ]
```

# まとめ
ログが意図した通りに出力されているかテストしたい場合に、わざわざログのファイルを取得して〜というのはかなり手間になってしまうと思います。
Log fake を使えば他の Laravel のファサード同様にシンプルにテストできるようになるのでおすすめです！
今回はバージョン 2.0 を紹介しましたが、PHP や Laravel のバージョンが要件を満たしていない場合は 1.X 系を使っても十分に役目は果たせると思いますのでぜひ使ってみてください。
streamlitで外部のAPIを叩く

pythonで使えるフレームワークの一つに、streamlitというものがあります。
URL:

https://streamlit.io/

python初心者が、気軽にいい感じのデザインのwebアプリを作るのに最適なフレームワークです。
株価の可視化アプリとか

https://streamlit-example-app-commenting-streamlit-app-qqwlsm.streamlit.app/

データを簡単に可視化できたり、誰もが分析ツールを使ったりすることができて非常に便利です。

## 自分で単機能のアプリを作った。
僕もこのフレームワークを使って、ゼミで使う二地点間の距離を計算するアプリを作りました。

https://stead08-omisegohanproject-streamlit-app-04qdaj.streamlit.app/

これは緯度経度から直線距離を導出する計算と
googlemapで二地点の車での移動距離をGoogleのAPIを叩いてデータを取得しています。

### ぶつかった壁

使っているAPIのKeyは外部に公開できないものです。
しかし、ソースコードGithubに上げていて、そのリポジトリからこのアプリの更新がされているのでAPIkeyをソースコードに直接打ち込むことができません。

### Streamlit標準機能を使う
streamlit ではprivateな情報を他のユーザに見られないようにしながら、その値をソースコードに適用できる機能があります。（無知なので同様の機能が他のフレームワークにあるのかはわかりません）

![スクリーンショット 2022-12-14 15.16.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687149/54548590-2e9c-882c-49ab-f8af34b1ddcc.png)

ここにAPIキーをあらかじめ保持しておき、
アプリを走らせているときに、その値を呼び出すといった感じです。
ソースコード側は、

```sample.py
#Googleマップで車での移動距離を計算
#google mapライブラリのインポート
import googlemaps
from datetime import datetime
googlemapAPIkey = st.secrets["googlemapAPIkey"]
gmaps = googlemaps.Client(key= googlemapAPIkey)
now = datetime.now()
directions_result = gmaps.directions(shop_selected_longitude_and_latitude,
                                     town_selected_longitude_and_latitude,
                                     departure_time=now)
distance_driving_km = directions_result[0]['legs'][0]['distance']['text']
```

こんな感じにst.secret["secretsで設定したキーの変数名"]をスクリプト上の変数に代入することでapiキーを秘密にしながらAPIを叩くことができます。

共有するような役立つ情報であるかは定かではありませんが、参考になれば幸いです。
CodeBuldの処理開始時に*os.SyscallError: setenv: invalid argument)　というエラーが出た

## 結論
特にbuildspec.ymlに変更を加えていないのにタイトルのようなエラーが出たら環境変数を見てという話

## エラー内容
Codebuldのインストールステージで***os.SyscallError: setenv: invalid argument)**というエラーが出てきました

## 原因
環境変数におかしな定義をしていたためエラーが出たようでした
(だったら環境変数がおかしいよって言ってくれればいいのに…)

## 解決法
環境変数を修正する

私の場合は「〇〇_〇〇=〇〇」というような変数になっていました
(ただのタイポです)

なので=移行を消してあげたら無事エラーが発生することなく処理が進むようになりました
Slack APIでLambda（Node.js）でランダムで絵文字のリアクションをする（reactions.add）

furikaeruという、１日の振り返りを簡単に楽しくできるSlack botを作りました。こちらがその記事です。

https://qiita.com/kakudaisuke/items/18681418cebc3bee93b5

この中で、メッセージに対してLambda（Node.js）を利用して、botで絵文字のリアクションをするという実装をしたのですが、シンプルそうなのにで、あまりサンプルコードにありつけず、ちょいと手こずってしまったのでメモを。

ランタイム: Node.js 14.x

Slack APIの`reactions.add`を使います。
必須パラメータはtoken, channel, name, timestamp。

https://api.slack.com/methods/reactions.add

```js:index.js
const AWS = require('aws-sdk');

exports.handler = async (event) => {
  const eventBody = JSON.parse(event.body);
  const text = eventBody.event.text;
  const channel = eventBody.event.channel;
  const ts = eventBody.event.ts;
  const teamId = eventBody.team_id; // そのコミュニティの絵文字を使いたい場合のみ後々必要

  // いつ絵文字を付けたいかは仕様によると思うのでどうぞよしなに
  await addEmoji(channel, ts, teamId);
}

// 指定したtextに絵文字を付ける
async function addEmoji(channel, ts, teamId) {
  let emoji = selectEmoji(teamId);   // selectEmoji()は絵文字をランダムにしたい場合のみ
  let url = `https://slack.com/api/reactions.add`;

  const data = {
    'channel': channel,
    'timestamp': ts,
    'name': emoji
  };
  
  // 必須パラメータの一つであるtokenはheadersで渡す
  const headers = {
    'Content-Type': 'application/json; charset=UTF-8',
    'Authorization': 'Bearer ' + process.env['SLACK_BOT_USER_OAUTH_TOKEN']
  };
  await sendHttpRequest(url, 'POST', headers, JSON.stringify(data));
}

// 絵文字のバリエーションを増やしたい場合
function selectEmoji(teamId) {
  const fusicTeamId = process.env['TEAM_ID_FUSIC'];
  // ビルトインの絵文字たち
  let names = ["relaxed", "blush", "thumbsup", "sparkles", "sparkling_heart"];
  // コミュニティオリジナルの絵文字たち
  const namesFusic = ["tensaida", "sasuga", "sugoi", "emo", "subara"];
  // 指定したコミュニティからのリクエストであれば、そのコミュニティオリジナルの絵文字たちを入れる
  if (teamId === fusicTeamId) names = names.concat(namesFusic);

  const nameIndex = Math.floor( Math.random() * names.length);

  return names[nameIndex];
}

// Httpリクエストを送信する。
async function sendHttpRequest(url, method, headers, bodyData) {
  const https = require('https');
  const options = {
    method: method,
    headers: headers
  };
  return new Promise((resolve, reject) => {
    let req = https.request(url, options, (res) => {

      res.setEncoding('utf8');
      let body = '';
      res.on('data', (chunk) => {
        body += chunk;
      });
      res.on('end', () => {
        resolve(body);
      });
    }).on('error', (e) => {
      reject(e);
    });
    req.write(bodyData);
    req.end();
  });
}
```

## 最後に
終わってしまえばやはりシンプルで、なんでハマってたのかも分からないくらい...。

以下、参考にしたもの。

- Slack APIドキュメントの横にあるこのテスト、役立ちました。

https://api.slack.com/methods/reactions.add/test

- クラメソさんの記事。ここにあるJSコードは使いこなせなかった。。

https://dev.classmethod.jp/articles/react-to-message-with-slack-api/
Android Studio・Kotlin・Jetpack ComposeでシンプルなTextfieldを作ろうとしたときに起こったエラー

# 環境
- Android Studio
- サンプルプロジェクトにあるcompose projectを選択

```build.gradle
buildscript {
    ext {
        compose_ui_version = '1.1.1'
    }
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.3.0' apply false
    id 'com.android.library' version '7.3.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
```

# エラー詳細
https://developer.android.com/jetpack/compose/text
テキスト入力を作成するために、ドキュメントのサンプル
```kotlin
@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("Hello") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}
```
をそのままコピーしたところ、**Text**に赤色の下線が表示され、
**None if the following functions can be called with the Arguments supplied** というエラーが表示された。
※エラー解決後に再現しようとしたが再現できなかった。

# 解決方法

```Text("Label")``` を ```Text(text = "Label")```と引数の名前を付けたところ、エラーが解消された。
Azure Logic Apps (ロジックアプリ) / Sentinel プレイブックから自動で ARM テンプレートを生成する

# 1. はじめに
作成したロジックアプリ / Microsoft Sentinel のプレイブックをお手軽に ARM テンプレート化する方法があります。使い方について本記事にまとめておきます。

# 2. 利用するツール / Playbook-ARM-Template-Generator
ツールは Azure 公式 GitHub で提供されている **Playbook-ARM-Template-Generator** を用います。
レポジトリからツールをダウンロードしておきましょう。

https://github.com/Azure/Azure-Sentinel/tree/master/Tools/Playbook-ARM-Template-Generator

# 3. 実際にやってみる
## 3.1 PowerShell 管理者モードで起動する
PowerShell より管理者モードで起動します。ダウンロードしたツールを解凍しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/6da68d3c-18cb-50fc-ecb5-31795c1086fe.png)

## 3.2 Playbook_ARM_Template_Generator.ps1 を起動する
PowerShell の実行権限が無い場合は、以下コマンドで許可を与えておきます。
```Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass```

シェルスクリプトを起動します。Azure Active Directory のテナント ID を聞かれますので入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/831d81fd-b59c-37c8-7b84-12fdc7e1af27.png)

# 3.3 サブスクリプション選択
AAD 認証が通ると、テナント対象化のサブスクリプションを選択する画面が表示されます。
作成したロジックアプリが入っているサブスクリプションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/b7dc8400-0331-a40b-6488-e71dc351cb10.png)

# 3.4 ARM テンプレート化するロジックアプリを選択する
次に対象サブスクリプション配下のロジックアプリが表示されます。
ARM テンプレート化するテンプレートを選択して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/f104438b-af5f-bfde-1dfc-68d8e354850a.png)
自 PC の保存先を問われるので、指定して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/1bff24be-5e17-86b8-0734-c076ddcc5e47.png)

# 3.5 ダウンロードした ARM テンプレートファイルを見てみる
ツールより生成されたファイルは ``azuredeploy.json`` ファイルで生成されます。
VisualStudio Code 等で ARM テンプレートを確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/29553443-93e5-3991-fad3-4d50d83c4838.png)

# 4. 実際にテンプレートをデプロイしてみる
テンプレートが正しく動くかどうか、ARM テンプレートのデプロイを行ってみます。
同一の名前のロジックアプリが作成されないように json を書き換えてテストしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/f4bfd8d9-5f57-5ae5-d8e3-fd7da296e64d.png)
テンプレートを保存して作成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/8a03e84d-eaba-759a-d359-a96d580801c0.png)
テンプレートによって、ロジックアプリが展開出来ていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/bd60c196-a9d5-739f-0d36-de91e474b2b4.png)

# 4.注意点など
生成される ARM テンプレートは、紐づいたリソースの設定情報がそのままエクスポートされるため、同一環境ではなく他環境に展開する場合はカスタマイズが必要になる点にご注意ください。
例えば、他のサブスクリプションやリソースへ展開する場合は、ARM テンプレート内に残る固有情報（サブスクリプション ID、リソースグループ）を変更する必要があります。

# 補足: 参考リンク
本ツールについては、公式ブログ / YouTube にて紹介が有りますので合わせて参考として下さい。

- 公式 Blog

https://techcommunity.microsoft.com/t5/microsoft-sentinel-blog/export-microsoft-sentinel-playbooks-or-azure-logic-apps-with/ba-p/3275898

- Demo YouTube

https://www.youtube.com/watch?v=scTtVHVzrQw
役に立つドキュメントを楽しく書くヒント

:::note info
この記事はLITALICO Advent Calendar 2022のカレンダー2の16日目の記事です:christmas_tree: 
https://qiita.com/advent-calendar/2022/litalico
:::

# はじめに

LITALICOでエンジニアをしている @tomoki-oke です。早いもので入社して4年目になりました。

気付けば担当プロダクトの開発チームでは長くいる方になっており、仕様やコードについて新メンバーに説明する機会が増えてきました。口頭で説明するだけではなく、今後のためにも知識をドキュメント化していかねばと感じ始めています。

そんな中、今年担当プロダクトとSaaSをAPI連携する案件があり、それについての運用ドキュメントを書く機会がありました。
これまでドキュメント書きには苦手意識があったのですが、これまでと書き方を変えてみたところ、納得いく内容を書ききることが出来ました。
中身は割愛しますが、こういった構成のものを書きました。

![toc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132987/75129f74-63b4-2d2e-9965-6fd976c54947.jpeg)

この記事では今回ドキュメントを書くにあたり、試してよかったことを3つご紹介します。

:::note warn
ここでいうドキュメントは開発者がチームの保守運用のためにコードや仕様を説明するドキュメントを指してます。
:::

# 試したこと

## ドキュメントの対象読者を考える
この記事をとても参考にさせて頂いたので、これを引用する形でご紹介します。

https://techlife.cookpad.com/entry/2020/11/27/104826

> 📝メンタルモデルの有無や目的に応じてドキュメントをかき分ける
> ドキュメントを読む人は様々です。そのツールを使い始めようとしている人、特定の使い方を探している人、100%使いこなしたいと思っている人、などなど。そういった読者に合わせたドキュメントを書くことが重要です。

これからドキュメントを読むユーザーは一概に開発者といえども、事前知識が全くない新メンバーかも知れませんし、機能拡張のために実装の詳細を知りたいメンバーかも知れません。
読者によって事前知識の量や欲しい情報は異なっているので、誰が読む想定なのか・その人は何を知りたいのか、を考えるのが大事なんですね。

ドキュメント書きの難しさは「なにを書くのか考えること」にあると思うんですが、この作業を挟むことで書く内容の方向性をはっきりさせることができました。
また対象読者を明確にすることで、自分の中で「このドキュメントは将来マジで役に立つ」と思えるようになり、モチベーションが高まりました:fire: 

参考までに、今回自分はSaaSのAPI連携のドキュメントを書くにあたり、この記事のJasperのドキュメント構成を参考に以下3種類のセクション（読者）に分けました。
* :family:  概要: 新メンバー向け。SaaS自体の説明とAPI連携のかんたんな説明
* :helmet_with_cross:  状況別対応マニュアル: 運用者向け。運用で問題が起きたときの対応マニュアル
* :books: リファレンス: 開発者向け。実装の詳細に踏み込んだ話

## もくじから考える
中身を書く前に全体の構成をざっくりと箇条書きで考えておきます:memo:
もちろん書き進める中で足りてない項目に気付いたりしてどうせ変更は加わるので、軽く考える位がちょうどいいです。

最初にもくじを考えておくと書きたい内容を網羅しやすくなりますし、全体構成の枠があることで失速しがちな終盤も、悩まず書き進めやすくなると思います:red_car: 

もくじが出来たら、その段階でチームメンバーに見てもらえるとなお良いです。この時点で中身は書いてないので書くつもりの内容は補足しつつ、ドキュメント全体の方針をレビューしてもらえると、書ききった後に修正するよりも手戻りが少なく済むはずです。

## コード同様にレビューしてもらう
書き終わったらメンバーへのお披露目です！当たり前かもしれませんが、書いて終わりではなく、やはりドキュメントもレビューしてもらうのがいいです:white_check_mark:

チームメンバーからしてもドキュメントに記載されてる内容をキャッチアップする機会になるので、そういう意味でもレビューを挟むのが良いと思います。

# おわりに
「マジで役に立つだろうな」と思いながらドキュメントを書くのは、結構楽しいものでした。
ドキュメント書きもプロダクト作りと同じく喜ぶユーザー（読者）のことを考えれば、ちょっと楽しくなれる気がします！
楽しく役に立つドキュメントを作っていきましょう:book: 

明日は @nonsaito さんが担当します。お楽しみに:christmas_tree: 最後まで読んで頂きありがとうございました！
【備忘録】数値書式について【Oracle Database SQL】

# 数値書式とは
数値書式は数値を文字列に変換する際のフォーマットです。数値書式に使用できる主な要素は次のとおりです。


|要素|説明|例||
|:---:|:---|:--:|:--:|
|9|指定された桁数の値を表示|999999|1234|
|0|先行0または後続0を表示|099999|001234|
|$|$記号の表示|$99999|$1234|
|L|ローカルの通貨記号の表示(日本語環境は¥)|L99999|¥1234|
|.|指定された位置に小数点を表示|999.999|1.234|
|D|指定された位置に小数点を表示|999D999|1.234|
|,|指定された位置にカンマを表示|999,999|1,234|
|G|指定された位置にカンマを表示|999G999|1,234|
|S|+または-記号を表示|S999999|+1234または-1234|
|V|10のn乗を乗算した値を表示(nはVの後の9の数)|999V999|123400|
|MI|(負の場合)右側に-記号を表示|999999MI|1234-|
|PR|(負の場合)<>で囲んで表示|999999PR|<1234>|

例1)数値12345.67を文字列に変換(有効桁数9桁、桁区切り「,」、小数点「.」)
```
SQL> SELECT TO_CHAR(12345.67, '999,999.999') FROM dual;

TO_CHAR(1234
--------------
12,345.670
```
例2)数値書式の有効桁数が不足(12345.67に対して整数4桁、少数3桁の書式)
```
SQL> SELECT TO_CHAR(12345.67, '9,999.999') FROM dual;

TO_CHAR(12
------------
##########
```
→***整数部の桁数が不足しているため、「#」で表示されている。***
SSH の X, Y オプションと 「~/.ssh/config」 の　　　ForwardX11,　ForwardX11Trusted　の関係について

opensshの`ssh`コマンドについて

`ssh -X` 　...  X11転送を有効にする
`ssh -Y`　 ...  信頼されたX11転送（Trusted X11）を有効にする

です。次に`~/.ssh/config`での設定との対応関係を見ていきます。

## ForwardX11　のみ  yes

```:~/.ssh/config
ForwardX11 yes
ForwardX11Trusted no
```
だと
`ssh Host`　==　`ssh -X Host`　!=　`ssh -Y Host` になります。
ここで`Host`は `~/.ssh/config`で`Host`の欄に指定した接続名のことです。

## ForwardX11Trusted　のみ  yes

```:~/.ssh/config
ForwardX11 no
ForwardX11Trusted yes
```
だと
`ssh Host`　!=　`ssh -Y Host` になります。ここが **ポイント** です。`ForwardX11Trusted`はあくまでx11転送を有効にしている場合に、その転送された接続が`trusted`な接続になるということを意味します。なので`ForwardX11Trusted=yes`としただけではx11転送は行うことができません。
この設定の場合、`ssh -X Host`　==　`ssh -Y Host` となります。
<br><br>
以上になります、読んでいただきありがとうございました！！ 間違いやご指摘等ありましたら、ぜひぜひコメントお願いいたします:bow_tone1:
<br>
参考資料

https://padraic2112.wordpress.com/2007/07/09/bad-security-201-remote-x-sessions-over-ssh/
チーズはどこへ消えた？　要約

チーズはどこへ消えた？　要約

「変化を嫌う人に幸せは訪れない」

心理学者スペンサージョンソンさん著の本書を自分なりに要約してみました。
登場するものはかなり少なく非常に読みやすいですが、内容は深いものとなっています。

出演
・ネズミ2匹（野生動物らしく行動派）
　スニッフ
　スカリー
　（頭が良くないゆえに即行動、鼻がきく）

・小人2人（現代人よろしく慎重派）
　ヘム（変化を恐れる）
　ホー（変化が必要と頭ではわかっているが行動に移せない）

・チーズ
　チーズは例えであり、人々が求めているもの
　（お金、金塊、ダイヤモンド…etc）

・迷路
 求めているものが存在している場所。即ち、人生

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

第1章「チーズステーションの発見」

　ネズミ2匹と小人2人は、毎日朝から晩まで、迷路へ行きチーズを探し回っていました。
ある時彼らは、「チーズステーションC」と呼ばれる大量にチーズがある場所を発見します。
このチーズステーションCのチーズは減ることはありませんでした。
彼らは、迷路を探索する苦労から解放され、毎日チーズステーションCに通いチーズを食べていました。
　しばらく経つと、2組の生活に違いが出ます。
ネズミチームはチーズステーションCを利用しますが、迷路を探索していた頃と変わらず朝早く起き
迷路での探索を続けていました。チーズに変化がないかチェックも欠かさずしていたようです。
　一方、小人チームはチーズ探しをやめ、チーズステーションCの近くに引っ越していました。
彼らは早起きをやめ、チーズステーションCのチーズを貪るという毎日をすごしていました。

第2章「チーズはどこへ消えた？」

　ある時、チーズステーションCのチーズは無くなってしまいました。
これに対し、ネズミ達は驚くことはしませんでした。彼らは毎日欠かさずチェックをしていたので
チーズが少しずつ減っていることに気づいていました。近い将来なくなることに気づいていたため、
毎日迷路での探索を続けていました。
　一方小人達は驚きを隠せず大騒ぎします。そして彼らは愚かにもチーズを探しに行くのではなく、
なぜチーズがなくなったか原因究明を始めます。
チーズは食べたからなくなったのであり、そこに特別な理由などないのです。
　小人チームは怒りが収まらず、僕たちはあんなにも迷路での探求を頑張ったのに、
どうしてこんな目に遭わなければ行けないのかと文句を言い、
チーズを食べる権利があると主張します。（誰に言ってるんだよ）
更には、迷路へ旅立ったネズミ達にまで「あいつらはバカだ」と当たります。

第3章「ホーの旅立ち」

　変化をしなければいけないと頭でわかっていたホーは、
チーズステーションCに文句を言い続けているだけでは何も変わらないと、意を決して迷路へ旅立ちます。
ヘムは変わらずチーズステーションCに縋りつき、「チーズがなかったらどうするんだ？」とホーに投げかけます。
ホーは本当に迷路へ行くべきか不安になります。それでもホーは「なぜすぐにチーズを探しに行かなかったのか」
と思い、先に進みます。
「もし恐怖がなかったら何をするだろう」
ネズミ達を見ればわかることです。普段から何が起きているか注意して、変化に備えていれば驚くことはなかった。
「恐怖を乗り越えればラクな気持ちになる」
気づけばホーは気分が良くなっていました。
　そしてホーは2個目のチーズステーションにたどり着きますが、そこにチーズはありません。
「もっと早くチーズステーションCに見切りをつけていれば、ここで大量のチーズにありつけたのに」
ホーは折れません。
「早いうちに小さな変化に気づいていれば、やがてくる大きな変化に適応できる」
ホーはポジティブの塊となり、迷路を進みます。

第4章「新しいチーズを見つけよう」

　ついにホーはチーズステーションを凌駕する量のチーズを蓄えたチーズステーションNを発見します。
そこには一足先についていたネズミ達の姿もありました。
　ホーは今までのことを振り返ります。
「変化は必ず来る。変化を予測しなければ行けない」
「小さな変化の気づきは、大きな変化への対応策になる」
「変化すらも楽しむことが必要」
「恐ろしいことばかり考えていてはいけない」

何より、
『最大の障壁は自分自身の中にいるということ』
ホーはヘムが自分自身の手で恐怖を乗り越え、ここに来ることを願い、物語は終わります。
　
しかし、その後のヘムがどうなったか、誰にもわかりません。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

かなり割愛しましたが、物語は以上になります。
終盤ホーに焦点が当てられていましたが、
ネズミ達を見てわかることは、
「何事も早ければ早いほど良い」
ということです。私の上司にも、即実践・即行動をいくつになっても心掛けている方、
速さに取り憑かれたスピード狂の方など、速さに拘る方々がたくさんいらっしゃいます。
そういった方々は私にはとても人生が楽しく、充実しているように映り、とても羨ましいです。

恐らくホーのように頭ではわかっている方、たくさんいると思います。僕もそうです。
わかっていても行動に移せない。
この物語ではチーズを迷路で探すという脳筋のようなテーマでしたが、
みなさんが求めているものって、実際手に入れるのは本当に難しいと思います。
・お金
・時間
・自由
・幸せ....
恐怖に打ち勝つだけではこれらは手に入りませんよね？
狂人のように考え抜いて、行動し尽くさないと手に入らないものだと思います。
めんどくさいですよね？
今のままでいいですよね？
でもそのままだと、きっとヘムのようになって人生はそこで終わりです。

私たち人間にはネズミ・小人達と違い、多くの仲間がいます。
・家族
・同級生
・会社の同僚
そういった方々と力を合わせて変化に飛び込めば、きっと良いことがあるはずです。
日本はますます、変化を嫌う人達を更に底へ落とすような国に代わってきています。
待っていても、誰も助けてなんてくれませんよ。（自分に言い聞かせている）

最後まで読んでいただき、ありがとうございました。
UbuntuにQtをインストール

# はじめに
UbuntuやRaspberyPiにGUIで実装する機会があり、IDEを「Qt」にしました。
Qt初心者向けに詳しく書きたいと思います。

# Ubuntuのインストール
Ubuntuは最新の「22.04」を使用しました。
Qtの記事なので、インストール等の詳細は割愛します。
インストール完了後は、必ずUpdateを行ってください。

# Qtのインストール
## インストール
以下のコマンドをターミナル上で実行します。
```
sudo apt-get -y install qtbase5-dev
sudo apt-get -y install clang
sudo apt-get -y install qtcreator
```
## Version確認
以下のコマンドをターミナル上で実行します。
```
qtcreator -version
```
いっぱい情報が出力されますが、最初の表示した数行をみると、
```
Qt Creator 6.0.2 based on Qt 5.15.3
```
と表示されます。

# Qt(Qt Creator)の起動
「アプリケーションを表示する」から、「Qt Creator」をクリックします。
![Screenshot from 2022-12-14 14-32-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1473918/4ece184d-0131-7260-7173-18c66fb4309d.png)
## 無事に起動できました。

# まとめ
インストールだけですのでまとめることもないですが、普段Windowsを使用している私からだと、「barrier」を使用して、WindowsPCのキーボードとマウスでUbuntuPCを操作したいのですが、「barrier」はUbuntu22.04では上手く動きませんでした(Ubuntu20.04では動いてます)
## 追記
別のPCでUbuntu22.04をインストールしたら、問題無くbarrierが動きました。
使用したPCの差だと思われます。
### barrierが動かなかったPC
CPU:Core i 7 7700T
Mem:16GB
SSD:128GB
グラボ：無し
### barrierが動いたPC
CPU:Pentium G4400
Mem:8GB
HDD:250GB
グラボ：有り(GeForce GTX 750 Ti)
グラボが無いと上手く動作しないんでしょうかね？
※Core2DuoのUbuntuはグラボ無しでもbarrierがちゃんと動作してくれます
AWS AppFlow Salesforceイベント起点の実行ができない

:::note info
この記事は[miriwoお一人様 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/miriwo)の14日目の記事です
:::

# 概要

- AppFlowにてSalesforceのAccountオブジェクトの更新（ChangeAccountObject） 起点でフローを実行しようとしたら実行されなかったので解決方法をメモ的にまとめる。

# 方法

1. AppFlowからSalesforceのイベントだけを登録して終わりではない模様、フローを変更データキャプチャにて当該のオブジェクトを「選択されたエンティティ」に追加する必要があるっぽい。
1. 下記の方法で実施できる。（この作業は当該のオブジェクトのレコード作成、更新、削除、復元の通知が出される様に設定するもの）
    1. Salesforceの右上にある歯車マークをクリック
    1. 「設定」をクリック
    1. 遷移先ページの左サイドバーの「インテグレーション」をクリックし、展開したメニューの「変更データキャプチャ」をクリック
    1. 更新イベントをキャッチしたいオブジェクトを「使用可能なエンティティ」で選択し「▶」をクリックして「選択されたエンティティ」に移動
    1. 「保存」をクリックして状態を保存
日本語のfont-familyを考える

![Mask group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/8fe0c971-1b1f-5311-02d2-1c627e8be613.png)
この記事は「<a href="https://adventar.org/calendars/7794" target="_blank" >【マイスター・ギルド】本物のAdvent Calendar 2022</a>」11日目の記事です。

## はじめに

font-familyに関する記事は多々あり、どの記事を読んでも決定打に欠ける印象です。
そこで正解は求めず、ここでは2023年の個人的指標を決定します。

今回は欧文フォントは置いておき、**日本語ゴシックフォント**に焦点を当てます。
# 各OS主な標準フォント
まずOSに標準搭載されている主な日本語フォントを見てみます。
| Windows | macOS | iOS | Andoroid |
|:-----------|:-----------|:-----------|:-----------|
| ・游ゴシック<br>・メイリオ| ・ヒラギノ角ゴ<br>・游ゴシック（非搭載のOSもあり） | ヒラギノ角ゴ| Noto Sans JP |

# 調査してみた
無作為に20サイトを選び、最優先されているフォントを調査してみました。
| 游ゴシック | メイリオ | ヒラギノ角ゴ | Noto Sans JP |
|:-----------|:-----------|:-----------|:-----------|
| 4サイト| 1サイト | 6サイト| 6サイト |

メイリオが不人気で、他は差がありません。
各サイトのfont-family設定を見てみると
游ゴシック以外を最優先しているサイトは游ゴシックの優先度は一番低く設定しています。
游ゴシックかすれて見える問題を避けていたり、他のフォントと印象が違うからでしょう。
この事から**游ゴシックorそれ以外**という考え方がありそうです。
# 実際に組んでみる
4つのフォントを見比べてみます。

**游ゴシック Regular**
Regularだと細いですね。
![Yu-Re.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/5c9f765e-6f66-6336-b41b-9997f65287ba.png)
**游ゴシック Medium**
使用するならMedium。 字面が小さめでスタイリッシュな印象です。長文も読みやすそうです。
![Yu-Me.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/f44f411e-b6fc-ac8f-72e5-41dfbdaef1f2.png)
**メイリオ Regular**
字面が大きくパキッとしてます。
今回調べた中では不人気でしたが一定数ファンもいるとか。
![Meirio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/b340c5c9-8d70-6ccf-904f-a5c7b9c5800c.png)
**ヒラギノ W3**
ヒラギノはAppleのイメージでしょうか。
ただしAppleのWebサイトはSF Pro JPが使われいてます。
![Hiragino.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/bc1bf3cc-b722-a70e-130a-246b4d3b276f.png)
**Noto Sans JP Regular**
組んだ時の黒みが強い印象を受けます。使いやすいですね。
![NotoSans.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/9a5df62a-22ae-4a7c-4a7d-90c1e9d0b091.png)
# 結論
![Group 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/ec622d8a-7758-1913-f3df-600a1f9a3877.png)
**ZEN角ゴシックNew**
![Mask group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/01c6a0df-71bc-1ed1-ee9b-2dd801cb92f0.png)
調査した20サイトでは使用されてませんでしたが、
GoogleFontsに追加されたのが2021年ですので、これから流行るかもしれません。
クセなく読み疲れしなさそうです。ウェイトも揃っています。
個人的に2023年はZEN角ゴシックNewに決まりました。
ニュースタンダードとなれるか？
KotlinでJunitをするとUnresolved reference: Testエラーが発生する

# はじめに

以下の書籍でテストを学習していたところエラーが発生して止まったのでまとめます

https://www.amazon.co.jp/Kotlin-Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-%E6%96%B0%E3%81%97%E3%81%84%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E9%95%B7%E6%BE%A4-%E5%A4%AA%E9%83%8E/dp/4865940669/ref=sr_1_11?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=10W5IYDWHTDIX&keywords=kotlin&qid=1670989318&sprefix=kotlin%2Caps%2C788&sr=8-11

# 問題

以下のテストを作成して実行しました

```kotlin:JdbcTaskRepositoryTest.kt
package com.example.todolist

import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.jdbc.Sql
import org.springframework.test.context.junit4.SpringRunner

@RunWith(value = SpringRunner::class)
@SpringBootTest
class TaskRepositoryTest {

    @Autowired
    private lateinit var sut: JdbcTaskRepository

    @Test
    fun 何も作成しなければfindAllは空のリストを返すこと() {
        val got = sut.findAll()
        assertThat(got).isEmpty()
    }
}

```

```
$ ./gradlew test
```

すると以下のエラーが発生しました

```

> Task :compileTestKotlin FAILED
e: /app/src/test/kotlin/com/example/todolist/JdbcTaskRepositoryTest.kt: (4, 18): Unresolved reference: Test
e: /app/src/test/kotlin/com/example/todolist/JdbcTaskRepositoryTest.kt: (5, 18): Unresolved reference: runner
e: /app/src/test/kotlin/com/example/todolist/JdbcTaskRepositoryTest.kt: (11, 2): Unresolved reference: RunWith
e: /app/src/test/kotlin/com/example/todolist/JdbcTaskRepositoryTest.kt: (18, 6): Unresolved reference: Test

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileTestKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction
   > Compilation error. See log for more details

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org
```

Junitのインポートがうまくいっていないようなので`build.gradlw.kts`を修正する必要がありそうです

# 解決方法

`build.gradle.kts`のdepenciesに以下を追加しました

```kotlin:build.gradle.kts
	testImplementation("junit:junit:4.12")
```

Junitの4系を利用していたのですが、おそらく5を利用しようとしてエラーになっていました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/d6554557-8d39-9965-0737-870295e6e2f5.png)

# おわりに

あとすこしでこの本も終了するので最後まで頑張って完走したいと思います

# 参考

https://itecnote.com/tecnote/kotlin-how-to-get-the-junit-tests-to-compile-and-run-in-the-kotlingradle-project/
SIer（メー子、デー子、ユー子）

# SESは止めとけ

**メー子** … メーカー（NEC、日立、富士通）子会社。ＩＴゼネコン系列子会社か資本関係がある会社、また、家電メーカ等の関連子会社を指す場合もある。子会社・関連を含め基本的に福利厚生はいいが利益は親会社が吸い取るので給料は親会社より安い場合が多い。（残業の多さで年収ベースでの給料は上回る場合もある） また、メーカ系の上下関係から逃れる事が出来ず激務や技術知識がメーカ方言になることも多い。福利抜群＋薄給。<br />

**デー子** … NTTデータ子会社。残業代全額支給＋福利まぁまぁ＋またーり。<br />
**ユー子** … ユーザー系子会社。ＩＴ業種以外のインフラ系（電気・通信)・商業系（運輸・商業）・金融系（銀行・証券）の子会社か資本関係がある会社。メインの仕事は、親会社の仕事が多く福利厚生等も親基準で安定している（親会社の業績などによって例外もあり）。情報部門が独立して設立された場合が多い。またーり薄給＋親次第。<br />

**独立系** … 激務薄給派遣部隊。基本的に親会社がない。資本関係にベンチャー系大手請負が名を連ねる場合がある。 まれに、外資系ソフト会社提携や独自技術で商売している当たりもあるが大抵はユーザー系・メーカー系の下請けに過ぎない。ユーザー系・メーカー系企業の２次受け・３次受け以下の仕事を同じ独立系で奪い合うが、それを「当社の仕事は全て一次受け」「メーカーと違い様々なハードで仕事が出来るので有利」と主張するのが特徴。 下請けの可能性が非常に高いので給料は安い傾向にある。（大手は普通に高いけど）下流工程が身につくので、それが好きな人にとっては楽しいと思われる。独立で下流を身につけた後、ユーザー系などに転職し経験を積んで「下流も分かるプロマネ」になるというのが理想的なキャリアプランだし、現場もそう言う人材を求めてるはずだが、世　の　中　そ　ん　な　に　甘　く　な　い。一度下に入ってしまうと中々に脱出は難しい。特に派遣系の会社に入ってしまうとそれだけでOUT。冗談抜きで人生が洒落になりません。しっかりと下調べして、どんな事業をしてるのかを見極めるのが寛容。<br />

参考：
<a href="http://money4.2ch.net/test/read.cgi/recruit/1147197228/" target="_new">【デー子】ユーザー系を目指してる奴 16 【狙い目】</a>

![(参考)情報サービス産業における多重下請け構造-by-経済産業省.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157559/6889db0d-5884-b537-ca4a-28336ca3db7f.png)
AWS S3からGCP CloudStorageにデータをコピーする

# はじめに

AWS Glue作ったParquetのデータがあってこれをなんとかGCPにもっていきたかったのでコピーする方法について調べました。

以下はとあるバケットのデータ。Parquetで8.4GB元のテキストデータは70GBくらいですかね。これをGCPのCloudStorageにもっていこうと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/aaa7e946-41d1-fa03-a0dd-90e85e263a08.png)

# AWS IAM Roleを作る

GCPがAWSにアクセスできるようにIAM Roleを作ってあげます。

まずは以下のリンクを開いてGCPプロジェクトのサブジェクトIDを取得します。プロジェクトIDは自身で指定したものを入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/fd6ad0b9-7337-fe17-6519-f5e84e7fc376.png)

AWSのIAMを開き、ロールの作成→ウェブアイデンティティ→Googleを選択します。Audienceには先ほど取得したサブジェクトIDを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/7c916c10-b132-d134-9034-f7921c1b0ced.png)

ポリシーは以下を設定します。（バケット名は適宜修正してください。）

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:Delete*"
            ],
            "Resource": [
                "arn:aws:s3:::uzresk-opendata",
                "arn:aws:s3:::uzresk-opendata/*"
            ]
        }
    ]
}
```

AWSS3toGCPCloudStorageAccessRoleみたいな名前を付けて保存し、ARNをコピーしておきます。

# Data Transferを使ってS3→CloudStorageへのコピー

DataTransferを開き、「転送ジョブを作成」を押して転送ジョブを作っていきます。転送元はS3、転送先はGCPを選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/7ceb1a41-5a0e-1d12-dde2-ec4177935707.png)

ソースのAWSのバケット名、先ほど作ったIAM RoleのARNをコピーを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/f910a81e-ce08-a666-f4f6-cfae5dc97d12.png)

転送先のCloudStorageのバケットとフォルダを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/1cdf91a7-e0bf-1354-7d07-e6bae2370f94.png)

転送実行モードを選択します。今回は１度だけ起動を選択しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/6085abd5-cd76-ad0d-7ca3-58ce465be473.png)

何を設定したかわかるようにJOBの名前は適当に書いておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/a4605d00-1d25-3a8a-350a-4537d0d2a5cf.png)

保存すると、１分もしないうちに完了するはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/d32c2142-f1f8-7bb1-4d24-fe59f0cf6dd3.png)

転送速度などわかるようですね・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/55ad0511-4438-8106-5ee5-521538d712a4.png)

# さいごに

- AWSのIAMRoleを使ってGCPにデータをコピー可能でありかなりお手軽に利用できました。
- 参考までに合計8.4GB, 1007ファイルで転送時間は32秒、平均転送速度は280MB/Secでした。

# 参考

- https://cloud.google.com/storage-transfer/docs/configure-access#amazon-s3
Github就活・転職2023に向けての方針・抱負

※本稿または本プロジェクトはPDD（ポエム駆動開発）であるため、ポエムはとても重要な位置付けです。

## カリキュラムでオリジナルブログ（サイト）を作ろう
「卒業制作でコピーサイトをチーム開発で作る」という運用をしている事が多いんですが、まずはこれをやめます。
やめます、と言っても私の周囲を動かす事はできないので、私が取り組んでいる範囲についてはやめます。
卒業制作した作品を、卒業後もきちんと使っていける環境を作ることで、スクールでは教えることが難しい「運用」を学んでもらう事ができます。
ポイントは、制作して終わりではなく「自分で使ってみてどう感じるか」を通じて開発を学んでいく事にあります。

## 書いた記事をなくさない
私は昔から（小学生の頃から）記事をなんだかんだ書き続けてきて、全部残っていればアフィリエイト用のコンテンツを除いて4000記事ぐらいあったように思えてならないんですね。
同じような経験をしている方は決して少なくないのではないか、と思います。

これだけクラウドが出てきたりしていますが、環境によっては使えなくなったりWordPressに突っ込んでしまってサイトごと消失したり、なんて悲しい事もありましたが、こんな悲しいことはもうナシにしたい。
という目標自体は本プロジェクト発足時点から目標に掲げていたんですが、今のところ安定的に保存はできても、公開や運用に至っていないものばかりです。
特にバックアップが鬼門。バックアップ自体はできるけど、バックアップした後に活用するのが難しいです。

現状は、各サービス毎にオレオレラッパーを作っていましたが、Zennなどマークダウンで書いたものをそのまま手元に残せるサービスも出てきたので、今後は活用面で見ても難度は大きく下がったように思います。

## エージェントが欲しいデータを抽出できる仕組みを整備する
需要があるかは分かりませんが、各社ごとに必要な情報が異なっている事はなんとなく理解しています。
で「欲しい情報が具体的にどれだ」という話が難しいので、結局のところはエージェントの要望あるいは応募したい案件に合わせて、自前で作ったシートを渡しているのが実情です。
というのも、私の場合はキャリアが多いのと広すぎて全部読んでもらおうとするとどれだけ圧縮（文字を削るのは当然として、小さなフォントや行間、余白いっぱいにしてもA4で5ページ）以上は必要になってしまうため、選考としてはそんな長い書類を見たくないわけです。
5ページぐらいなら経験者ならよくある事として読んでいく事はできるんですが、詰めた上に文字も小さい5ページではワケが違います。
私が採用側なら読みたくないです。

これを少しでも解消するべく、欲しい情報をうまく抽出する仕組みを考えたいです。
サイトやブログの検索システムのようなものを、経歴書に置き換えればできますが、問題はフリーワード検索はしないはずなので、検索項目に合わせて書類の情報を整備してデータベースとして活用できるようにする事です。
過去のデータなどは欠損しているものもあるので、検索項目として

## プラットフォームとしてのGithubか、プレゼンテーションとしてのGithubか
要するに、Githubをどうやって使っていくか、というお話です。
具体的には、アカウントの運用です。

本来は開発者然としてGitの細かい制御や開発をしながら、データハブとして使うのが元々のGit関連のサービスが想定しているものです。
が、Githubに限った話をすると、色々な機能があり、ユーザーがいじれる範囲が広くてやりごたえがあります。
元々のGithub就活・転職プロジェクトも、こういったGithubの仕様をうまく使いながらポートフォリオを作成し、Githubにあげたソースをスコア化して応募したり、スカウトをいただいたりしていたのが発端でした。
が、近年はGithubを使ったスカウトより発信者のアカウント（Twitterやその他SNSなど）を経由して情報を収集する動きが多く見られるようになったため、Githubに注力するのは効果が薄くなってしまっている傾向を感じています。

であれば、Github（Git）に力を入れるよりは、発信力を高める方法を検討していった方が良いだろう、というのでGithubの使い方を検討しています。

## Githubを使わない就活・転職はプロジェクトと称するべきか？
困った話ですが、メインとなる場所がGithubではなくなってしまう可能性が出てきたので、Github就活・転職プロジェクトという名前に違和感が生まれてしまっています。
Githubを使ったスカウトがなければ、Githubでの就活も転職もないので、そもそもプロジェクト自体が破綻ーエンジニア転職としてそぐわないのではないか、という気がしないでもないです。

この辺りは実際にエージェントの方に聞いてみたくもありますね。
自社サイト等で求人を出している以外に応募者を募る方法って広告以外にあるかな？という段階なので、この辺りは自分で求人を出してみたり採用側になってみてからですね…。

## Github就活・転職2023
現状は積極的にGithubを使うというより、Githubをプラットフォーム/プレゼンテーションツールとして考えて活用していく方針です。
目的が不明瞭なので、現状で重要度が高いのは、書いたデータをなくさない・活用できるようにフォーマットを整える方ですね。
良い情報が分かり次第シェアしていきたいと思います。

## 次の記事
- [(24日目) ](https://qiita.com/nomurasan/items/)
- [カレンダーページ](https://qiita.com/advent-calendar/2022/oreno_nomurasan2022)
セグメンテーションで分けられた部分ごとに透過png画像を生成する

# １.きっかけ
[前の記事](https://qiita.com/ksmkzs/items/f3555b9bdd0a372894aa)の続き

### 元画像の例  
###### RGB画像
![21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/9165cbbb-9e49-3876-7ea6-26cfa81e4831.jpeg)
###### セグメンテーション画像  
![semantic-segmentation-deep-learning-review-500x375.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/f75287cf-39ac-9e96-adc0-46b5c1fb1b1f.png)


# ２.実装

```Python
from PIL import Image
import numpy as np
# 画像ファイルを読み込む
img = Image.open("hoge_segmentation.png")
img_rgb = Image.open("hoge_rgb.jpg")

# パレットモードかどうか判定する
if img.mode != "P":
    print("画像がパレットモードではありません")
    exit()

# パレットを読み込み出力用画像を生成
palette = img.getpalette()
img_output = Image.new("RGBA", size=img.size)


# 色を取得
w, h = img.size
colors = set()
for y in range(h):
    for x in range(w):
        colors.add(img.getpixel((x,y)))
print(colors)


# outputに色ごとに出力
pixels = img_rgb.load()
for color in colors:
    for y in range(h):
        for x in range(w):
            color_pixel = img.getpixel((x, y))
            if color_pixel != color:
                r ,g, b = pixels[x,y]
                img_output.putpixel((x,y),(r, g, b, 0))
            if color_pixel == color:
                r, g, b = pixels[x,y]
                img_output.putpixel((x,y),(r, g, b, 255))

# 画像の保存
      img_output.save(f"output_sample_{color}.png")

```

### 出力結果
![sample_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/f193acc5-247b-7492-8fee-8b07f2405947.png)
![sample_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/d5a32489-f271-ce86-60b7-125b4e02052c.png)
![sample_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/ffcfa3cd-c4a6-3ceb-d5e0-7bb4f80cb903.png)
![sample_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3066359/30951cdc-62b3-271f-4ed2-c93a15961643.png)
Ubuntuでネットワークブリッジを構成する

### 環境
* Ubuntu 20.04.5 LTS

## Ubuntuでネットワークブリッジを構成する
PCに搭載した2つのNICをL2スイッチのように振る舞わせるための設定です。

まずはnetplanを使って、ブリッジの構成を作ります

```yaml:/etc/netplan/50-cloud-init.yaml
network:
    version: 2
    ethernets:
        enp0s25:
            dhcp4: no
        enp5s0:
            dhcp4: no
            # mtuを設定する場合はここで指定する
            # mtu: 9000
    bridges:
        br0:
            interfaces:
                - enp0s25
                - enp5s0
            dhcp4: no
            addresses:
                - 192.168.99.1/24
            gateway4: 192.168.99.254
            nameservers:
                addresses: [8.8.8.8,8.8.4.4]
            parameters:
                forward-delay: 0
                stp: no
            optional: true

```

### 適応
```console
$ sudo netplan apply
```

### プロミキャスモードの設定
このままでは2つのNICを跨いだ通信ができないため、両方のNICをプロミキャスモードにします。
```console
$ sudo ip link set dev enp0s25 promisc on
$ sudo ip link set dev enp5s0 promisc on
```

### プロミキャスモードの永続化
プロミキャスモードを永続化するためにサービスを作成します。
以下のファイルを作成します。
```unit-file:/etc/systemd/system/bridge-promisc.service
[Unit]
Description=プロミキャスモードを有効にするためのサービス
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/ip link set dev enp0s25 promisc on
ExecStart=/usr/sbin/ip link set dev enp5s0 promisc on
TimeoutStartSec=0
RemainAfterExit=yes

[Install]
WantedBy=default.target
```

サービスを起動時に呼び出すように登録します。
```console
$ sudo systemctl enable bridge-promisc
```

### 確認
nicに `PROMISC`のフラグが立っているか確認します。
```console
$ ip a

2: enp0s25: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether d0:60:59:65:b1:30 brd ff:ff:ff:ff:ff:ff
3: enp5s0: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 9000 qdisc mq master br0 state DOWN group default qlen 1000
    link/ether 14:8c:92:7a:5a:52 brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 24:8a:07:7a:0b:50 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.1/24 brd 192.168.99.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::bc80:f4ff:fe21:cf94/64 scope link
       valid_lft forever preferred_lft forever
```


#### 参考
https://askubuntu.com/questions/1355974/how-to-enable-promiscuous-mode-permanently-on-a-nic-managed-by-networkmanager
TypeScriptでMessagingAPIを使う際にMessageを別ファイルで定数として用意する方法

## はじめに
本記事ではタイトルの通り，TypeScriptでMessagingAPIを使う際にMessageを別ファイルで定数として用意する方法を紹介します．
紹介するのはそれだけです．MessagingAPIの使い方だったり，TypeScriptの書き方を紹介する訳ではないので悪しからず．
既にMessagingAPIがTypeScriptで動作している前提です．

## 外部ファイルにMessageを用意
まず，外部ファイルにメッセージを定数として用意します．

```Messges.ts
import { TextMessage } from '@line/bot-sdk';

export const templateTextMessage = (): Promise<TextMessage> => {
    return new Promise((resolve, reject) => {
        const params: TextMessage = {
            type: "text",
            text: "text"
        };
        resolve(params);
    });
};

// もし引数を取りたい場合は以下のように宣言
export const templateTextMessage = (text: String): Promise<TextMessage> => {
    return new Promise((resolve, reject) => {
        const params: TextMessage = {
            type: "text",
            text: text
        };
        resolve(params);
    });
};


```

もし，FluxMessageやTemplateMessageなどを使いたい場合はコード内のTextMessageをそれに変えれば使えます．
## Messageを呼び出してリプライ
あとは前項で用意したtemplateTextMessageをimportして呼び出すだけです．
```index.ts
import { templateTextMessage } from "./Messages"

...
async function handleEvent(event: any) {
    const templaMassage = await templateTextMessage()
    await client.replyMessage(event.replyToken, templaMessage);
}
...

```
これで別ファイルに用意したMessageを使ってメッセージを送ることができました．
Pythonでじゃんけんゲームを作ってみた

最近Webスクレイピングの興味からPythonの勉強を始めました。
使っている教材でじゃんけんゲームを作ってみようという課題があり、若干詰まりながらもなんとか作成することができたので、この場でアウトプットをしていきます。

## 全体のコード

まずは全体のコードから。

```python
import random

#リストにじゃんけんの手を格納
list=["グー","チョキ","パー"]

#プレイヤーの手をインプット
player = input("あなた：")

#リストから手を出す
com = random.choice(list)
print("相手:{}".format(com))

#プレイヤーと相手の手で勝敗を決める
#勝敗もプリント
if player == com:
    print("あいこです。")
elif player == "グー":
    if com == "チョキ":
        print("あなたの勝ち")
    elif com == "パー":
        print("あなたの負け")
elif player == "チョキ":
    if com == "グー":
        print("あなたの負け")
    elif com == "パー":
        print("あなたの勝ち")
elif player == "パー":
    if com == "グー":
        print("あなたの勝ち")
    elif com== "チョキ":
        print("あなたの負け")
```

## コードの流れ
流れとしては以下のような感じです。

リストに「グー、チョキ、パー」を格納
↓
自分の手をインプット
↓
リストから相手の手をランダムに出力
↓
If文で勝敗を決めて出力。

というような感じ。
コードは結構シンプルで単純。

## 解説
というわけで行ごとに解説していきます。

今回はrandom モジュールを使います。
random モジュールはリスト内や数値、文字などをランダムに出力してくれる優れものです。

randomをインポートしてリストにじゃんけんの手を格納します。

```python
import random

#リストにじゃんけんの手を格納
list=["グー","チョキ","パー"]

#プレイヤーの手をインプット
player = input("あなた：")

#Listから手を出す
com = random.choice(list)
print("相手:{}".format(com))
```

そしてinputでプレイヤーの手をインプットします。
Inputした文字はPlayerに変数として格納されます。

その後randomでListの中の手を出力します。
いわばrandomはじゃんけんでいう相手ですね。
ちなみに相手の手はcomとして変数に格納されます。

次は勝敗をIf文で定義します。
```python
#プレイヤーと相手の手で勝敗を決める
#勝敗もプリント
if player == com:
    print("あいこです。")
elif player == "グー":
    if com == "チョキ":
        print("あなたの勝ち")
    elif com == "パー":
        print("あなたの負け")
elif player == "チョキ":
    if com == "グー":
        print("あなたの負け")
    elif com == "パー":
        print("あなたの勝ち")
elif player == "パー":
    if com == "グー":
        print("あなたの勝ち")
    elif com== "チョキ":
        print("あなたの負け")
```

”あいこ”の場合は、Player=com
ようはListの中身の文字とInputで入力した文字と一緒の場合は”あいこ”になります。
似たような要領で勝敗を決めていきます。
先程のInputで入力された文字（変数のPlayer）と相手が出した文字（変数のcom）をIf文で定義します。

これで完成になります。

## 詰まったポイント

私はIf文で詰まりました。

初めは相手の出す手と自分の出す手を変数にしてIf文で勝敗を決めるように設定しようと試みましたが全然動かず。。。
```python
x = "グー"
y = "チョキ"
z = "パー"
list=["x","y","z"]
player = input("あなた：")
a = "グー"
b = "チョキ"
c = "パー"
com = random.choice(list)
print("相手:{}".format(com))

if x == a:
    print("あいこです。")
elif x == b
        print("ちょきの勝ち")
#以下省略
```
↑のようにListの中身の手を変数に指定、自分の手を変数に指定して変数同士で勝敗を決めるIF文で作ろうとしたのですが、うまく動かず。
わざわざ変数に指定する必要なくね？と頭によぎり変数指定を取りやめることで完成しました。

変数同士を条件にIF文って作れないのだろうか。。。
暇なときにでもまた考えてみます。
pyperclipがインストールしたのに使えない！　NameError: name 'pyperclip' is not defined 

「pipでインストールしたのに使えねぇ」と思ってるようじゃが

```
NameError: name 'pyperclip' is not defined 
```

# 顔も知らないのに悩んでるそこの君ぃ！
```
import pyperclip as pc
```

こうじゃないよ！

```
import pyperclip
```

こうだよっ！

```
pyperclip.copy("hoge")
```

これで使えるよ！
Github の Pull request にて変更ファイルの一覧を取得したい

該当 Pull request の Files changed タブを表示して、Chrome の デベロッパー ツール > コンソールにて下記を実行するとファイルパスの一覧が取得出来る
```javascript
[...document.querySelectorAll('.file-info>.Truncate>a')].map(x => x.title)
```

取得例

https://github.com/httpie/httpie/pull/1398/files

```javascript
[...document.querySelectorAll('.file-info>.Truncate>a')].map(x => x.title)
(16) ['extras/completion/completion.bash', 'extras/completion/completion.fish', 'extras/completion/completion.zsh', 'extras/completion/templates/completion.bash.j2', 'extras/completion/templates/completion.fish.j2', 'extras/completion/templates/completion.zsh.j2', 'extras/httpie-completion.bash', 'extras/httpie-completion.fish', 'extras/scripts/completion/__init__.py', 'extras/scripts/completion/bash.py', 'extras/scripts/completion/completion_flow.py', 'extras/scripts/completion/generate_completion.py', 'extras/scripts/completion/zsh.py', 'httpie/cli/definition.py', 'httpie/cli/options.py', 'httpie/output/ui/rich_help.py']
```
NFTはなぜ難しいのだろう？

はじめに
---
これは、[株式会社 RetailAI X Advent Calendar 2022](https://qiita.com/advent-calendar/2022/retail-ai-x) の 14日目の記事です。
昨日の記事は、 @esoul さんの[『Reactでよく使われるprops』](https://qiita.com/esoul/items/f699b7e40766bba92e76)でした。

本日は、『NFTはなぜ難しいのだろう？』について書いています。

自己紹介
---
新卒入社3年目のMikeyです。
・関連会社のマーケティング部
・関連会社のネットスーパー立ち上げ
を経て、
現在はRetail AI Xで様々な業務に携わっています。
(経営管理・総務・社内チャットボットの開発/運用・未来戦略準備　等)
ネットスーパー立ち上げの際にエンジニアとしてのキャリアがスタートし、
半年ほどFlutterに触れていました。
現在は社内チャットボットの開発/運用業務のためにgolangの勉強をしております！

先日、未来に向けた準備ということで、
NFTという技術について調査して社内で発表する機会がありました。

そこで感じたことについて今回は発信していきます。
駆け出しエンジニア目線での発信として温かい目で見守っていただけると嬉しいです:relaxed:

分かるようでわからないNFT
---
この記事を読んでくださっている方々の多くは
NFTという言葉をご存知でしょうし、
さらには技術的な実体についても把握されている方が大勢いらっしゃるのではないかと思います。

しかし私自身は、
「NFTについて調べてみて！」と言われたときは、
・NFTがうちの会社とどう関連するの？
・調べたとして、発表の場で何を伝えればいいの？
・そもそもNFTってなんだっけ？
と、頭の中がクエスチョンマークだらけでした。

なぜNFTが分かりづらいか？
私なりに理由を振り返ってみると
・NFTといえば、NFTアートみたいに売り買いするものだよね？！
・NFTってブロックチェーン技術も関連しているの？！
・イーサリアム？スマートコントラクト？なにそれ！
というように感じており、
NFTに関連した情報が多すぎるな、と思っていました。

そうです、NFTは関連する情報量が多いがゆえに、
人によっては「アート作品のこと」と捉えたり「仮想通貨のこと」と捉えたりするのだと思いました。
だから分かるようで分からないんですね。

NFTの正式名称
---
改めてですが、NFTは
**Non-Fungible Token**
の頭文字を取ったものであり、
日本語では
**非代替性トークン**
と訳されたりします。

ここまで調べて、
そうだ！
そういえば「トークン」(token)のことをよく理解していないんだ！
ということに気付かされました。

そこで英和辞典で"token"を調べてみると、
「しるし」「証拠」が元々のメインの意味だということがわかります。
それが「お金として価値を持つことを示す証拠」「資産であることを示す証拠」というように派生していき、
やがては「仮想通貨」という意味まで持つようになります。

このtokenという言葉や、
巷で言われるNFTの特徴を踏まえて、
社内で発表するときは
NFT=あるデジタル資産が「この世に1つだけ」だと示す電子証明書
という意訳をお伝えさせてもらいました。

調査/発表準備で気をつけたこと
---
実際の資料にはさまざまな情報を入れていますが、
それを「小学生でも分かるように」伝えることは至難の業です。

まずは私自身が理解を深めるために下記の手順を踏みました。
1.NFTという言葉を直訳する
2.NFTという言葉を自分がわかるように意訳する
3.NFTという言葉から連想されるものをブレストする
4.会社が進もうとしている方向性をブレストする
5.3.4.のブレスト結果を結びつける

NFTに関連する情報が多いからこそ3.のブレスト作業を通じて
**情報同士のつながりを理解する**ことが大事ですし、
それを会社の戦略に落とし込む上で4.　のブレストや5.の作業も大切です。
今回の調査/発表を通じて、
「わからないなりに手を動かすこと」が大事だと気付かされました。

最後に
---
今回はコーディングとは関係ない話題になりましたが、
私自身もエンジニアとしてのキャリアアップを目指すうえでわからない概念がたくさん出てくると思います。
「不明点を聞ける人が周りにいる」という環境があるのでRetail AI Xは恵まれていると思いますが、
人に聞く前に「わからないなりに手を動かす」という手順をコーディングにおいても重視していきます。

最後まで読んでいただき、ありがとうございました！

次回は@risei　さんによる[「迅速な開発Go Adminについて」](https://qiita.com/risei/items/499e357f8864e1dc71d2)という記事です。
いつも私達のサービスのBackendを支えていただきありがとうございます:star:
みなさま、お楽しみに！

参考
---
[トークンとは 概要や仕組みを2分で入門](https://cloud-ace.jp/column/detail343/)
[NFTの動向整理](https://www.caa.go.jp/policies/policy/consumer_policy/caution/internet/assets/internet_committee_220715_08.pdf)