OmniAICreator/Qiita-1.07M huggingface dataset:
SecurityHubのEC2.8(IMDSv2の使用)を設定してみた

# はじめに
SecurityHubに順守する環境構築を行なっている中で、設定項目EC2.8について設定方法や不明点があったので、その際に学習した内容をまとめます。

SecurityHubって何？という方は前回まとめたので、下記ページをご確認ください。
[AWS Security Hubに関して](https://qiita.com/mani___524/items/eb9a37f8a8a88bb16ddf)

# EC2.8の内容

>EC2 インスタンスでは、Instance Metadata Service Version 2 (IMDSv2) を使用する必要があります。

>このコントロールは、EC2 インスタンスメタデータバージョンがインスタンスメタデータサービスバージョン 2 (IMDSv2) で設定されているかどうかをチェックします。コントロールは次の場合に渡されます。HttpTokensIMDSv2 で必須に設定されています。コントロールは、次の場合に失敗しますHttpTokensは、 に設定されます。optional。
>インスタンスメタデータを使用して、実行中のインスタンスを設定または管理します。IMDS は、一時的で頻繁にローテーションされる資格情報へのアクセスを提供します。これらの認証情報を使用すると、機密認証情報を手動でまたはプログラムでインスタンスにハードコーディングしたり、配布したりする必要がなくなります。IMDS は、すべての EC2 インスタンスにローカルにアタッチされます。これは、169.254.169.254.169.254 の「リンクローカル」IP アドレスで実行されます。この IP アドレスは、インスタンスで実行されるソフトウェアによってのみアクセスできます。
引用：[EC2.8](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html#ec2-8-remediation)

要するに、

* インスタンスのメタデータを取得する際に、トークンの要求を必須にする設定する必要があるよ！
* IMDSv1だとトークンなしで、169.254.169.254にアクセスするだけでメタデータを取得できちゃうよ！→セキュリティリスクがある。

ってことだと解釈しました！


# 設定手順

今回は下記３パターンの設定方法を記載します！

[1. 新規インスタンス作成時に設定-マネージドコンソール](#1-新規インスタンス作成時に設定-マネージドコンソール)
[2. 新規インスタンス作成時に設定-AWSCLI](#2-新規インスタンス作成時に設定-awscli)
[3. 既存インスタンスの設定変更-AWSCLI](#3-既存インスタンスの設定変更-awscli)



## 1. 新規インスタンス作成時に設定-マネージドコンソール
新規インスタンス作成時の``ステップ3:インスタンスの詳細の設定``にて、
▼高度な詳細のメタデータバージョンで、V2を選択する。

![スクリーンショット 2022-02-07 13.55.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515983/84735ea6-8115-f689-8c4a-e99bfedc922b.png)



## 2. 新規インスタンス作成時に設定-AWSCLI

下記コマンドで、``--metadata-options``をオプションを記述する。

```powershell
# `--metadata-options` を記述
$ aws ec2 run-instances `
--image-id <イメージID> `
--metadata-options HttpTokens=required,HttpEndpoint=enabled
```

新規インスタンスをAWS CLIで作成する際の手順は下記からご確認ください。
[AWSCLIでEC2 insutance の起動・停止・削除](https://qiita.com/mani___524/items/07752b2d55f0009c7c7e)


## 3. 既存インスタンスの設定変更-AWSCLI
既存インスタンスを変更する場合は、僕が調べた限りAWSCLIのみ可能みたいです。

```powershell
# インスタンス一覧の表示（インスタンスIDを確認するため）
$ aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId"

# IMDSv2の有効化
$ aws ec2 modify-instance-metadata-options --instance-id <インスタンスID> --http-tokens required --http-endpoint enabled

# 変更されていることを確認
$ aws ec2 describe-instances --filters "Name=tag:Name,Values=<インスタンス名>" --query "Reservations[].Instances[].MetadataOptions"

```

実際に、インスタンスメタデータの取得にトークンが必要なことを下記コマンドで確認できます。
EC2インスタンスにSSHか、セッションマネージャーで接続して確認してください。

```ssh
# インスタンスのメタデータ取得→エラーが出ればOK！
curl http://169.254.169.254/latest/meta-data/

# IMDSv2 インスタンスのメタデータ取得→取得できればOK！
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
```


# 参考
[IMDSv2 の使用](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-transition-to-version-2	)
railsのconfig_forで環境ごとに設定を切り替える

# 環境
rails6

# はじめに
開発環境(development)と本番環境(production)で異なる設定値を持たせたい場合があります。むしろその方が一般的だと思います。
それぞれの環境で出力させるパスが違うとか、Titleを変えるとかの場合、いちいちif文を書きたくないですよね。

# ただの設定値として設定させたい場合
```ruby:config/application.rb
module MyApp
  class Application < Rails::Application
     config.hello = "hello"
  end
end
```
以下のように呼び出せます。

```ruby:
Rails.configuration.hello
=> "hello"
````
# 環境ごとに設定を分けたい
#### config_forを有効に
```ruby:config/application.rb
module MyApp
  class Application < Rails::Application
     #以下を追記するとconfig_forが有効になる
     #config_forの引数をシンボルで渡すことでconfig以下のymlファイル全体を読み込む
     #以下の場合、config以下にあるconf.ymlを読み込む
     config.app = config_for(:conf)
  end
end
```
# confファイル
ymlの書式で環境ごとの設定を書きます。この辺はdatabase.ymlと一緒。
shared設定がサポートされており、共通の設定はここに書きます。

```ruby:config/conf.yml
#デフォルト値はここに
default: &default
  app_name: "MyApp"

#各ステージ共通の設定はここに
shared:
  cheat_enabled: false

#開発環境
development:
  <<: *default
  app_name: "MyApp開発"

#テスト環境
test:
  <<: *default
  app_name: "MyAppテスト"

#本番環境
production:
  <<: *default
  cheat_enabled: True
```
# 確認
本番環境のapp_nameはデフォルト値、cheat_enabledは上書きされているのがわかります。

```shell:
###開発環境
$ rails c
> Rails.configuration.app
=> {:cheat_enabled=>false, :app_name=>"MyApp開発"}

###テスト環境
$ rails c -e test
> Rails.configuration.app
=> {:cheat_enabled=>false, :app_name=>"MyAppテスト"}

###本番環境
$ rails c -e production
> Rails.configuration.app
=> {:cheat_enabled=>true, :app_name=>"MyApp"}
```

#rails上での使い方
Rails.configuration.appでハッシュを指定して使用できます。

```erb:
<%= Rails.configuration.app[:app_name] %>
```

# 参考
https://railsguides.jp/configuring.html

https://qiita.com/Garow-oLFlex/items/1866c7b5a4c4b5347b32

https://qiita.com/tohae/items/835147b3569a70f170e0

https://madogiwa0124.hatenablog.com/entry/2021/05/15/200827
AWS 環境構築　参考サイト


###EC2 + RDS
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

###EC2にSQL
https://www.acrovision.jp/service/aws/?p=2387

###DBをEC2運用からRDS運用に変更
https://haloechoes.com/server-operations/ec2-installation-db-operation-changed-to-rds-operational/

###Docker 使用

https://qiita.com/takuyakawaguchi/items/057165b26fac88641ff1

https://qiita.com/soehina/items/91f0c52929d979df59f7

https://laboratory.kazuuu.net/after-creating-a-docker-container-with-centos-7-install-mysql-5-7-and-connect-from-ec2-to-rds/

###terraform 使用

https://takelg.com/aws_create_ec2_terraform/

https://dev.classmethod.jp/articles/terraform-getting-started-with-aws/

https://qiita.com/okdyy75/items/73641a0247bae1fa7f31
Log Parser Studio を使ってみた

このツール，IISのアクセスログ，IISのエラーログ，イベントログ等マイクロソフト製品の分析には使えそうです。
イベントログに関しては，Like検索やGroup by等が使えるので，イベントビューワのXMLクエリーより強力です。
XMLクエリーのように詳細なカラム名の指定ができないので（事前にカラム名を知っている必要アリ），データを広めに検索してしまうことを理解した上で使う必要があります。

# インストール  

1. Log Parser をインストール
2. LPSV2.D2.zipを解凍

# 使い方のコツ１

種類が違うログを同じフォルダに入れているとフォーマットが違う等のエラーになる。
例えば，IISのエラーログとアクセスログはフォーマットが違うので，違うフォルダに入れる。

NGな例
iis_error.log
iis_w3c_access.log
を Add Folder(*.log)で開く

# 使い方のコツ２

イベントログは，イベントID毎にログの中身が変わるので，詳細な情報は結合されて Strings １セルにぶち込まれています。
詳細な解析のためにはイベントビューワとの併用が必要です。

# どこかのCTFで役に立った事例

どこのCTFか忘れたけど，ELECOM製のUSBメモリが挿された日時は？って感じの問題。（シリアルだったかも？）

とにかく，どのイベントログに残るかピンポイントで覚えていなかったので Log Parser Studio で横断検索した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/b4ad00f2-8710-4da5-194f-cc118609cc53.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/d3a99481-8fe3-f763-604b-501bbda43722.png)
Excel帳票をキレイに表示する

システムからExcel出力する。
ヘッダをつけたテンプレートファイルを用意し、出力時にはプログラムで改行コードを含ませながら処理しているが
実際に出力したExcelはガタガタだった。折返しはされないし、幅はその時時によって異なるためテンプレートにも限界がある。

ということでテンプレートファイルに以下を仕込んだ。

コンテンツを有効化した際にすぐにはしるように、ThisWorkBookに下記を記載。

```VB
Private Sub Workbook_Open()

range("C1", "XFD1048576").Columns.AutoFit
range("C1", "XFD1048576").Rows.AutoFit
range("C1", "XFD1048576").WrapText = True
range("C1", "XFD1048576").Columns.AutoFit
range("C1", "XFD1048576").Rows.AutoFit
range("A1", "XFD1048576").HorizontalAlignment = xlLeft
range("A1", "XFD1048576").VerticalAlignment = xlTop
End Sub

```

出力後にExcelを編集したときにも対応できるようにボタンを用意して同じ処理をかいといた。

```VB
Sub 調整_Click()

range("C1", "XFD1048576").Columns.AutoFit
range("C1", "XFD1048576").Rows.AutoFit
range("C1", "XFD1048576").WrapText = True
range("C1", "XFD1048576").Columns.AutoFit
range("C1", "XFD1048576").Rows.AutoFit
range("A1", "XFD1048576").HorizontalAlignment = xlLeft
range("A1", "XFD1048576").VerticalAlignment = xlTop
End Sub

```

1,2行目でたてよこ合わせて、3行目で折り返させる。
4,5行目でもっかいたてよこあわせて、6,7行目で文字列を左上よせに。

以上。
DeepL を使った日本語校正サービスを作った

# 成果物

https://deep-j.vercel.app/

![](https://storage.googleapis.com/zenn-user-upload/37bdbbeae30c-20220205.png)

# 経緯
下記のツイートを見たのがきっかけです。
実際自分で試してみると思った以上に高性能に添削してくれて感動しました。
ただ翻訳する度に日 → 英 → 日とコピペするのが面倒だったのでサービス化しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">DeepL を使って日本語を英語に翻訳し、それを日本語に再翻訳することで日本語の表現をきれいに見せるというライフハックを聞いて感動しました。<br><br>これは上手く使ったら生産性爆上がりなのではないか？以下がこの文の作成に使ってみた例。崩壊気味の文章に秩序が生まれている… <a href="https://t.co/vyD00Xuue2">pic.twitter.com/vyD00Xuue2</a></p>&mdash; 村上智之　働き方のデジタルシフト (@GreenGreenMidor) <a href="https://twitter.com/GreenGreenMidor/status/1439910698461454336?ref_src=twsrc%5Etfw">September 20, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
https://togetter.com/li/1777559

# 使い方
左のテキストエリアに校正した文章をいれて、中央にあるボタンを押すだけです！
かっちりした文章よりかは砕けた文章の方が精度が高い気がするので、ラフに書いてみて下さい！
![](https://storage.googleapis.com/zenn-user-upload/7a9bb1f91535-20220205.png)


# ユースケース
自分の使い方としてはクライアントに送るメール, Slack 投稿前に添削をする、のような使い方をしています。
テレワーク中心の世の中なのでテキスト主体のコミュニケーションがより重要性を増す中、伝わらない文章を撲滅するのに一役買ってるような気がしています(国語力の低い自分の場合)
若干それますが伝わらないテキストは大体が主語がない、助詞が抜けているに起因してる気もしています。

# 構成
**フロントエンド**: Next.js
**ホスティング & Serverless**: Vercel
**翻訳** DeepL

## Next.js
フロントエンドはとりあえず使っとくかの精神で Next.js　を選択。
とにかく機能が少ないので `_app.tsx` と `index.tsx` の2つのファイルで完結しています。
あとはUI ライブラリに　Chakra UI　を使っています。

https://chakra-ui.com/

## Vercel
Next.js を選択した事により半強制的にデプロイは Vercelへ。
後述するDeepL API を Next API routeを使って翻訳を取得しています。

https://vercel.com

## DeepL

https://www.deepl.com/

高精度翻訳サービス。
API も提供していて、50万文字/月まで無料で使える(クレジットカード登録は必須)
バズった場合の対策はrazokuloverさんの記事へ
https://zenn.dev/razokulover/articles/03af7e1c1972fe
上記記事ではバズった場合の対策として、利用ユーザー自身にDeepL APIキーを取得、登録してもらう方法を取っています。本サービスの場合、日 → 英 → 日と一つの文章に対して2回翻訳をかけるので無料枠の消化が激しいですが、
一旦は私が取得したAPI keyのみで運用しています。
ないとは思いますがリミットを超えた場合、上記の運用にしようかと考えています。


DeepL の API を叩く際は下記のライブラリを使った。
オールtypescriptで作られているので型補完してくれる(DeepLのAPI自体がシンプルなので正直使わなくてもいける)

https://github.com/funkyremi/deepl

# 今後
- Glossary(用語集)機能
- 校正履歴閲覧
- ユーザー自身のAPI keyを使用できるようにする

# まとめ
- DeepL を利用した日本語校正サービスを作ったよ！
- 個人開発はなんだかんだ(リリースは)初めてで楽しかったよ！
- 何かフィードバックあったら教えて下さい！
- これを機にTwitter始めたのでフォローお願いします🙏🏻


https://twitter.com/m_develop_m


https://deep-j.vercel.app/
公式ホームページのIntro to Vue 3クラス4 (Conditional Rendering)

# 4. Conditional Rendering

>クラス https://www.vuemastery.com/courses/intro-to-vue-3/conditional-rendering-vue3

VS Codeから該当フォルダを選択して、開きます。その後に、配下のgit部分をクリックして、ブランチをL4-startへ入れ替えてください。

ブランチ切り替え方法
> https://qiita.com/phjg81/items/e6695eb2334d9297a318

今日のポイントは条件による、バインドです。
入っているデータオブジェクトの値により、判定して、バインドされる部分などの調整ができます。

```html:index.html
<p>In Stock</p>
<p>Out of Stock</p>
```

単純な条件の場合は下記のように実装します。

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            product: 'Socks',
            image: './assets/images/socks_blue.jpg',
            inStock: true // new data property //
        }
    }
})
```

```html:index.html
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
```

条件を複数にしたい場合は、下記のようになります。

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            product: 'Socks',
            image: './assets/images/socks_blue.jpg',
            inventory: 100
        }
    }
})
```

```html:index.html
<p v-if="inventory > 10">In Stock</p>
<p v-else-if="inventory <= 10 && inventory > 0">Almost sold out!</p>
<p v-else>Out of Stock</p>
```

今回の課題はonSaleをBooleanデータオブジェクトとして、追加してOn Saleタグを条件により、レンダリングして見てください。

<details>
<summary>課題確認</summary><div>

```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue Mastery</title>
    <!-- Import Styles -->
    <link rel="stylesheet" href="./assets/styles.css" />
    <!-- Import Vue.js -->
    <script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <div class="nav-bar"></div>
      
      <div class="product-display">
        <div class="product-container">
          <div class="product-image">
            <img v-bind:src="image">
          </div>
          <div class="product-info">
            <h1>{{ product }}</h1>
            <!-- solution -->
            <h2>anchor : <a :href="anchorUrl" target="_blank">{{ anchor }}</a></h2>
          </div>
        </div>
      </div>
    </div>

    <!-- Import App -->
    <script src="./main.js"></script>

    <!-- Mount App -->
    <script>
      const mountedApp = app.mount('#app')
    </script>
  </body>
</html>
```

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            product: 'Socks',
            image: './assets/images/socks_green.jpg',
            // solution
            anchor: 'phjg81',
            anchorUrl: 'https://qiita.com/phjg81'
        }
    }
})

```
</div>
</details>
Mecab + mecab-ipadic-NEologd な形態素解析 API サーバーを作った

Mecab を触っていたらいい感じに汎用的な形態素解析 API サーバーができたので GitHub に公開しました。

## 動機

品詞・形態素解析エンジンである [Mecab](https://taku910.github.io/mecab/) と固有表現に強い辞書 [mecab-ipadic-NEologd](https://github.com/neologd/mecab-ipadic-neologd) を、チャットボットを動かしているコンテナにインストールして使っていましたが、辞書のサイズが大きくて取り回しが悪いので、マイクロサービス的に分離してみることにしました。

## 概要

https://github.com/SogoKato/mecab-parser

* 文章を投げると単語ごとに品詞・形態素解析をしてくれます
* コンテナで動きます
  * AMD64 / ARM64 対応
* Mecab の出力結果を key: value の形式に直して返すのでわかりやすい

## 使ってみる

docker run します。

```sh
docker run -p "8080:8080" --rm noroch/mecab-parser
```

別のターミナルを開いてリクエストを投げてみます。

```sh
curl localhost:8080/parse -XPOST -H "Content-Type: application/json" \
  -d '{"texts": ["私はきれいなタヌキです", "あなたはドラえもんに似ているね", "彼はおいしい草を1日3回食べます", "彼女はたまに鹿児島に行きます"]}' | jq
```

レスポンスはこんな感じです（最初の1単語のみ表示しています）。

```sh
{
  "ok": true,
  "results": [
    [
      {
        "annotations": "代表表記:私/わたし 漢字読み:訓 カテゴリ:人",
        "conjugated_form": "*",
        "conjugation_type": "*",
        "input": "私",
        "original_form": "私",
        "part_of_speech": "名詞",
        "part_of_speech_subtyping": "普通名詞",
        "reading": "わたし"
      }
    ]
  ]
}
```

レスポンスのフォーマットは以下の通りです。 [mecab-python3](https://pypi.org/project/mecab-python3/) で mecab-ipadic-NEologd を使った出力結果を key: value の形式に整形してレスポンスを返します。生の出力だとタブ区切り、カンマ区切りの文字列なのでどれがどの情報なのかわかりにくいですが、それを扱いやすくしています。

```
input: str
    テキスト中の単語
part_of_speech: str
    品詞（名詞、助詞など）
part_of_speech_subtyping: str
    品詞（普通名詞、副助詞など）
conjugation_type: str
    活用型
conjugated_form: str
    活用形
original_form: str
    原形
reading: str
    読み
annotations: str
    注釈（代表表記、反義、カテゴリ、ドメインなど）
```

## 今後

* 対応する辞書を増やしたい

フィードバックございましたら随時 GitHub でお待ちしています。

## 謝辞

Mecab および mecab-ipadic-NEologd のプロジェクトに貢献された皆様に感謝いたします。
Flutter: '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'エラーの回避



### 状況

ローカルストレージライブラリ `hive` にJSON形式でデータを保存した場合、Dartの型としては `Map<String, dynamic>`になるが、これをHiveから読み出し→fromJsonでデコードしようとしたところ表題のエラーが発生していた。

もしかしたらFirebaseのsnapshotを受け取る場面でも同様のエラーに遭遇するかも知れない。

```dart
final box = await Hive.openBox('hoge');
// 同じ形式のJSONデータが複数件保存されている前提
// この時点でjsonListはList<Map<dynamic>>
final jsonList = box.values.toList();
// 取得した情報でMapを構築し、そこからHogeオブジェクトを生成しList化
return jsonList
      .map((e) => Hoge.fromJson(e))
      .toList();
```

### 対処

Listに格納された要素をmapメソッドで処理するコードだが、HogeオブジェクトをfromJsonメソッドで作ろうとしたが、`Map<dynamic, dynamic>` から `Map<String, dynamic>`  に暗黙的に変換できないぞ、ということらしい。

うまくキャストしてやれば良いのだが、書き方としてはこうなる。
`Map<String, dynamic>.from(e)`

### 参考
https://github.com/flutter/flutter/issues/16589
pythonで簡単な30分タイマー作ってみた

##とっかかり
整体の先生に
<b>「仕事やゲームに熱中してしまうのは分かるけども30分に1度は胸を張ったり、座りなおしたりする方が良いよ」</b>
と言われた。
最初はスマホのアラームとかやってたけど逐一切ったりするのがめんどくさい。
だったら自分で組んじゃおうか、time.sleep使えば10分くらいで組めるだろ！って思ったので組んだ。
相対パス指定に時間持ってかれて結局43分かかった。
###ファイル構成
タイマー
├─script
│　└30mTimer.py
└─sound
　　└SE.mp3
###コード
(追記：コメントにて@shiracamusさんから教えていただいた書き方に変更)

```30mTimer.py
#もしインストールしてなかったら「pip import ～」でインストールする。
import pathlib #パス関連
import time #時間関連
from playsound import playsound #音関連

#現在のカレントディレクトを取得
here = pathlib.Path(__file__).parent
#pathlib は除算演算子「/」を使った書き方ができる
sound = here.parent/"sound"/"SE.mp3"

#Trueの間ずっと繰り返す→無限ループ。止めたい場合はctrl+cなりコマンドプロンプト落とすなりで止める。
while True:
	time.sleep(1800)#1800秒(30分)待機
	playsound(sound)#SE.mp3を鳴らす

```
###オチ
<b>みんなも体を大切に！</b>
time.sleepの中身はinputで取得して入れたりしてもいいかも。
ボクは面倒だし、30分って最初から決まってたからやらなかったけども。
###参考
https://qiita.com/hisshi00/items/62c555095b8ff15f9dd2
夜の写真を昼にする

#機械学習モデルを使って、夜の画像を昼にします。

![77c483b8-0e4e-4c5c-a791-0c90e06b0ac4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/2c0fbfdf-487a-d525-633e-8ff0bdd77f24.jpeg)

#車載カメラなどの画像を見やすくする
夜の不鮮明な画像を明るくできれば、他のモデルを使った画像認識（例えば車両認識）がスムーズにできそうです。

#AU-GAN
夜の画像を昼の画像にしてくれます。

#使い方
リポジトリをクローンして重みをダウンロード

https://github.com/jgkwak95/AU-GAN

```python
python main.py --dataset_dir bdd100k --phase test --experiment_name bdd_exp --batch_size 1 --load_size 572 --fine_size 512
```

![f53cd000-a75d-4698-bf39-e2b5712e371a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/a952249d-053f-dec6-598b-fe56ebae47f5.jpeg)


🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Carrierwaveでヘッダー指定のURLから画像を取得して保存する

# 概要
Carrierwaveを使用して外部サイトもしくはS3などから画像をダウンロードして保存する。
その際にヘッダーを指定する(今回はRefererのみ)
carrierwave側では画像のcontent_typeをpng/jpg/jpegに限定している。

# 試したけどうまくいかなかったパターン
## open-uriでopenした画像を保存する
```ruby
image_uri = URI.parse(uri) # uriを直接openするとセキュリティ的に問題があるためURI.parseする
file = image_uri.open("Referer" => "https://...")
user.avater = file
```
~~値が入らず断念。tmpファイルに書き出してから行えばうまくいけるかも。~~
#### 2022年6月15日加筆
参考URL: https://docs.ruby-lang.org/ja/latest/library/open=2duri.html
値が入らなかったのはCarrierWaveがcontent_typeを拡張子から判断していたため。
open_uriで開いたファイルはTempfileクラスとして開かれるが、拡張子の命名規則がデフォルトではcontent_typeから類推してくれないことにより
バリデーションエラーが出てしまっていた。
保存するためにはダウンロードしたファイルのファイル名に.jpgなどの拡張子をつける必要があるので今回はCarrierWave::SanitizedFileクラスを利用する。
詳細に関してはこちらを参照ください。
https://github.com/carrierwaveuploader/carrierwave/blob/54f0ef9b1da48f9651f4428e78d19765ab7d3df2/lib/carrierwave/sanitized_file.rb

```ruby
image_uri = URI.parse(uri) # uriを直接openするとセキュリティ的に問題があるためURI.parseする
res = OpenURI.open_uri(image_url, "Referer" => "https://...")
file = CarrierWave::SanitizedFile.new(tempfile: res, filename: res.base_uri.to_s, content_type: res.content_type)
user.avater = file
```



# 上手く行ったパターン
## carrierwaveのremote_#{column}_request_header=(header)とremote_#{column}_url=(url)を使用する
carrierwaveのソースを読むと以下のようなメソッドが定義されているので利用する
columnの部分はモデルの`mount_uploader`で指定したカラム名を使用する
今回はavaterカラムを例に使用
https://github.com/carrierwaveuploader/carrierwave/blob/229594fb2ac7cfa59586162c0b3fc3d0b5bab978/lib/carrierwave/mount.rb#L165

```ruby
image_url = URI.parse(uri).to_s # URIクラスだと受け付けない
user.remote_avater_request_header = {"Referer" => "https://..."}
user.remote_avater_url = image_url
user.save!

```
JavaScriptの変数宣言について

---
【JavaScript】変数の宣言（var, let, const)
---

## 変数宣言
プログラミング言語には、文字列や数値などのデータに名前をつけることで、繰り返し利用できるようにする変数という機能があります。
JavaScriptには「これは変数です」という宣言をするキーワードとして、 const、let、varの3つがあります。
varはもっとも古くからある変数宣言のキーワードですが、意図しない動作を作りやすい問題が知られています。 そのためECMAScript 2015で、varの問題を改善するためにconstとletという新しいキーワードが導入されました。


## ES2015(ES6)とは
ECMASCriptの6th Editionのこと。ECMAScript 6th editionの6を取ってES6と呼ばれていたが、
2015年に標準化されたため正式名称はES2015になった。ここでconstとletが追加されるようになった経緯があった。

## varとletとconst
JavaScriptでは変数の宣言は従来よりvarが使われていたが、ES2015よりletが追加されました。また、同じくES2015よりconstを用いた定数の宣言も可能になった。ECMAScript 2015では、varそのものを改善するのではなく、新しくconstとletというキーワードを追加することで、varの問題を回避できるようにしました。var自体の動作を変更しなかったのは、後方互換性のためです。


**`var`での変数宣言**

```sample.js
var food = 1; 
    food = 2;
console.log(food); //2がコンソールに出力される。
```
1行目において変数は省略されているが、varで宣言されたとみなされている。省略した場合はグローバルな変数(どこにあるコードからでも同じように値の読み取りや書き換えが可能なもの。)になるため避ける。

**`let`での変数宣言**

```js
let food = 'soft';　
console.log(food); // => foodがコンソールに表示される。


food = 'Soft'; // 再代入する
console.log(food); // => Softが表示される。

let food = 'Soft'; // 再宣言するとエラーになる
```
letキーワードでは、値の再代入が可能な変数を宣言できます。 letの使い方はconstとほとんど同じです。
次のコードでは、foodという変数を宣言し、初期値を"JavaScript soft"という文字列であることを定義しています。


**`const`での変数宣言**

```js
const food = 'Soft';
console.log(food); // => Softがコンソールに表示される。

food = 'Soft'; // 再代入するとエラーになる
```
constキーワードでは、再代入できない変数の宣言とその変数が参照する値（初期値）を定義できます。

次のように、constキーワードに続いて変数名を書き、代入演算子（=）の右辺に変数の初期値を書いて変数を定義できます。

#まとめ
### `let`と`const`の使い分け
再代入が必要な変数のみ`let`で宣言し、それ以外は`const`で宣言する。
`var`は利用する理由がないため利用しないこと。
CSRFトークンチェックでエラーになった事。

#先週の行ったことの振り返りとして記述　2022/1/30 〜 2/4 (言語化のための記録)

#行ったこと
・Railsでログインユーザーidをデータベースに保存
・BootStrap5の導入のサインアップ画面の調整

#躓いた点
・サーバー側、event_controlle.rbの create でuser_idを保存したいが、CSRFトークンチェックでエラーになる。

#どのように解決したか
devise_token_authを使いトークン認証を通すことで解決できるが、
今回はskip_before_actionをコントローラーに記述し、エラーをのがれた。

#問題点
skip_before_actionだとセキュリティ上好ましくないので、改めて改修する。
[Xcode]最初に出力するstroryboardの設定の仕方

#はじめに

ビルドした際に一番最初に出力するstoryboardの設定のやり方です。

**Xcode13.2.1 
Swift version 5.5.2**

で行っています。

![Qiita投稿用2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/799f68ae-20db-cb34-8b13-003a28e3a2ed.png)

画面の左のinfoから、storyboardの名前を任意のstoryboardに設定してあげればOKです!!

###ちなみに、
![qiita投稿用3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/bfc0b9a2-2da8-2102-2432-a575fa571c21.png)

Main interfaceを変えてもstoryboardの出力は変わりませんでした。
ここで自分はハマってしまいました。

以上になります!!
paizaレベルアップ問題を紐解く②　アルファベット探し (paizaランク C 相当)

#はじめに
　現在paizaのBランク問題突破を目指して学習中です。今回は、アルファベット探しという問題に関して勉強になったので解法をまとめておきます。
記述方法によってコードが大幅に削減されるという事を実感しました。

こちらの問題です↓↓
https://paiza.jp/works/mondai/prob60/alphabets_large_or_small_9


#問題文
　1行目の英大文字 X から、2行目の英大文字 Y の範囲に3行目のアルファベット C が含まれていれば"true", そうでなければ"false"と出力してください。
X が Y よりもアルファベット順で後ろになる場合(X = 'G', Y = 'F'のときなど)も"false"と出力してください。

入力例1
A
D
C

出力例1
true

問題を要約すると
「１行目と２行目の文字の間に、３行目の文字が含まれていれば"true"と出力させる」
という内容です。

#自分の解答
　まずは自分の回答をまとめます
回答の方針としては

```
①まず３行の標準出力を変数に格納する（その際にordメソッドで文字コードに変換）
②１行目と２行目の間の全ての文字をeach文で出力する
③もしも３行目の文字が含まれていた場合countする。
④最後にcountに従って、"true" or　"false"を出力する。
```

以下が実際のコードです。

```paiza.rb
num1 = gets.chomp.ord
num2 = gets.chomp.ord
num3 = gets.chomp.ord

is_count = false

(num1..num2).each do |i|
    if i == num3
        is_count = true
    end
end

puts is_count
```

これで無事に出力できたので、正解でした。

しかしコードが長い。。

#模範回答
　以下が模範回答でした。

```paiza.rb
string = []
3.times { string.push(gets.chomp) }

puts string[0].ord <= string[2].ord && string[2].ord <= string[1].ord
```

①配列を用意する
②times文の中で、配列に入力値をpushする
③配列[2]が配列[0]よりも大きいかつ、配列[1]よりも小さいときに　"true”と出力する

10行から3行になった。

配列にpushするという発想がなかったです。
また比較の仕方も、if文を使う必要がないという部分は勉強になりました。

#追記　リファクタリングに挑戦　
　編集リクエストありがとうございます！アドバイスをもとにリファクタリングに挑戦します！

**①文字列は比較できるので、ordメソッドは必要ない**
ordメソッドを使わなくても文字列は比較できるということは意外でした。
例えば以下のように使えます。

```paiza.rb
"か".between?("あ","け")　=> true
```
コードを修正すると、


```paiza.rb
puts string[0].ord <= string[2].ord && string[2].ord <= string[1].ord
↓↓
puts string[0] <= string[2] && string[2] <= string[1]
```



**②betweenメソッドを使う**
範囲を比較する場合はbetween?を使うと見やすいですね。

```paiza.rb
puts puts string[0] <= string[2] && string[2] <= string[1]
↓↓
puts string[2].between?(string[0],string[1]) 
```



改めて全体のコードです。

```paiza.rb
string = []
3.times { string.push(gets.chomp) }

puts string[2].between?(string[0],string[1]) 
```

コードが見やすく、シンプルになりました！







#まとめ
　今回は機能としては動くものの、記述方法によって大幅に短くなる。
という事を改めて実感したので記事にまとめてみました。
この調子で効率の良い記述方法など、学んでいきます。
Rails x Reactでapiモードを使うべき理由

##なぜapiモードがいいのか
結論：フロントエンドとバックエンドを完全に分離することができるから。

Rails x Reactで初めてのアプトプットとしてTodoアプリを作ったのですが、apiモードを利用しないとRailsにviewファイルを置く必要が出てきたり、コンポーネントフォルダとかもしっかりとRailsから分離して管理することができずかなり開発しにくかったです。rails newするときは--apiオプションをつけて開発をするといいと思います！！
microsoft365カレンダーに商談予定を入力したら、毎朝忘れずに外出申請書の提出を促すメール発信ツールを作ってみた。

私はスーパーのレジ什器の開発を行う部署にいますが、コロナ禍で取引先との商談やミーティングも大きく変わりました。これまで対面で行われたものがTeamsやZOOMなどのTV会議が主となりました。しかし、試作機の最終ジャッジをするためにはどうしても直接見に行く必要があり、その際には上長のさらに上の上長（本部長）から許可をもらう必要があります。
![許可見本.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/93745c98-37d4-e6e1-55ac-b0b81d20e102.png)

#課題
対面しての商談の日程が決まった時、前日までに申請書を提出することを忘れることが多い。

#やりたいこと
部内メンバーのスケジュール共有で使用しているMicrosoft365カレンダーの中に、商談のスケジュールを入力したら、提出を忘れないように出張の申請書のメールが送られるようにしたい。

#使用した機能
・integromat
・（社内イントラシステム）Microsoft365

#integromat
これまで、[Node-RED](https://qiita.com/forestdoor95/items/60e125d9fd0bf0e38169)や[Teachable Machine](https://qiita.com/forestdoor95/items/a6f817cd31870a7da1f7)などの記事を投稿しましたが、途中までだったり、作成しても失敗に終わったたため、ノーコード・ローコードで何とかできないか、とintegromatを使用してみました。
流れとしてはMicrosoft365 Calenderスケジュールに「商談」「出張」を入れたときに、メールで案内が届くようにします。
![integromat-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/1b8e205a-2704-9f6c-6278-7f9cf0a2a503.png)

##1.Microsoft365カレンダーへの商談スケジュールの入力
![スケジュール貼り付け資料.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/ed3f268b-6f08-67aa-90bb-df236911020b.png)
業務で使用しているMicrosoft365の予定表のsuject欄に必ず「商談」というキーワードを入れるようにします。

##2.【Microsoft365Calendar】から【Search Events】を選択
Microsoft365カレンダーの自分の予定表から「商談」が入力されている日程を探し出します。（たまに「出張」もあるのでそれも検索ワードに入れています。）
![integromat(Mカレンダー１).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/6dbf72c5-8845-6c0d-f481-43dd6b185059.png)
![integromat(Mカレンダー２).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/961bd1f0-c9b0-4428-875e-d211f519fe18.png)

##3.【Google Calendar】から【Seach Events】を選択
Microsoft365 CalenderからGmailやoutlookへの連携がうまく行かないため、Google Calendarからの経由を試みました。
抽出した「商談」のスケジュールからGoogle Calenderで改めて「商談」を探し出します。
![integromat(Gカレンダー１).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/dd015420-f144-3f28-e156-2f6240e713bb.png)
![integromat(Gカレンダー２).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/6fd8f062-d859-0cf1-54ec-fe79dd433116.png)

##4.【Gmail】から【send an email】を選択
こちらもoutlookは管理者権限の壁にぶち当たったためGmailで社内メールへの送信を選択。
抽出した「商談」のスケジュールを私用アカウントのGmailで指定のアドレス（業務で使用している社内メールアドレス）に送信する。
![integromat(Gmail).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/d2dde376-6512-1a43-fa6f-34eb65c49131.png)
メール内容については
スケジュールに記載した内容「subject」、いつ行うのか「Start:Date Time」、何を行うのか「Body Preview」、そして、シェアポイントに投稿されている申請書のURLを記載するようにしました。

##5.1日1回9時に配信する
![rリピート.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/894657bd-4e16-6038-d4a9-6ec278a2ad7d.png)


#結果
Microsoft365カレンダーの予定表に入力した「商談」のスケジュールについて、下記の内容でメールが届きました。
![メール返答.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495333/d9dfae98-0e0e-a031-3d08-209a85251428.png)

#評価
今回、作成したものを同僚に体験してもらいました。
コメントは以下の通りです。
良かった点
・自分も申請書を忘れるから、毎日9時に確認メールが届くのはありがたい。

改善点
・スケジュールを入力したら、すぐにメールは届かないか。
・過去に入力した「商談」が入っているスケジュールも送られてくる。
・送られたメールが読みづらい。（改行してほしい）

#課題と今後
セキュリティの関係で、直接Microsoft365　Emailにつなげることができず、Gmailで送りました。
また、メールが届く、ということは達成できましたが、運用については【Google　calender】の「Start Date」を今日、「End Date」を今日＋１日と設定したのですが、どの部分の「今日」を指しているのか確認と修正が必要です。
(ServiceNow)自動テストでカテゴリ/サブカテゴリといった従属関係あるレコードのテストが通らない場合の解決

## 問題
Automated Test Frameworkで新しいテストを作成。
入力フォームの一方がStringで、それの値に紐づく形でReferenceの入力項目がある場合には以下のエラーが出る。(カテゴリ/サブカテゴリといった従属関係あるレコード)

```
Unable to set field 'subcategory' to value 'laptop'. Value 'laptop' is not currently a valid choice.  
```
有効でない選択肢が表示されている。どうやったらテストが通るのか？

## 解決
この問題は、タイミングにある。カテゴリーがロードされると、サブカテゴリーの値をロードするのに時間がかかるため（ATFの外でも）、ATFがサブカテゴリーを設定しようとしたとき、実際にはまだ空であり、このようなエラーが発生する。

この問題は、値の設定処理を2つのステップに分けることで回避すること。（基本的なカテゴリーとサブカテゴリーを設定した場合）。ステップ1でカテゴリーを設定し、ステップ2でサブカテゴリーを設定します。
→Set variable values(SP)を2ステップにすること。 

### 参考
[Automated Test Framework error](https://tech-software-tokyo.blogspot.com/2022/02/blog-post_7.html)
Android Emulatorのみを起動する

# 概要

アプリを開発してると、少し前のバージョンの動きを確認する際やビルドマシンでビルドしたアプリの動作確認をする際などに、apk/aabをインストールして動作を確認することがあります。
このときに実機にインストールしてもいいのですが、なかなか認識しないことがあるためエミュレーターを使っています。
そんなときにAndroid Studioを起動→プロジェクトをビルド→エミュレーターで確認は少し時間がかかるのとメモリを食ってしまうので、エミュレーターのみ起動する方法を調べていました。

公式のサイトでも十分分かりやすいのですがよく使うオプションなどまとめたかったので記事にしました。

# 方法

## エミュレーター名一覧表示

```
emulator -list-avds
```

## エミュレーター起動

```
emulator -avd avd_name [ {-option [value]} … ]
```

# 例

> たとえば、Mac で実行されている Android Studio 内からエミュレータを起動する場合、デフォルトのコマンドラインは次のようになります。

```
/Users/janedoe/Library/Android/sdk/emulator/emulator -avd Nexus_5X_API_23 -netdelay none -netspeed full
```

# 具体例

私は以下のように実行しています。

```
emulator -avd Nexus_7_API_23 -no-snapshot -no-boot-anim
```

| Options | Description |
|-----------|------------|
| -no-snapshot | 自動読み込みと保存の両オペレーションを禁止し、エミュレータが完全なブート シーケンスを実行してから閉じたときにエミュレータの状態が失われるようにします。 |
| -no-boot-anim | 起動を高速化するため、エミュレータ起動中の起動アニメーションを無効にします。 |

# 参考

https://developer.android.com/studio/run/emulator-commandline
電子レンジの加熱時間を換算する早見表を作りたい

#はじめに

電子レンジ、便利ですね。最近は、在宅勤務中のお昼ご飯も冷凍食品をレンチンです。
おいしく調理するためには、**正しい加熱時間**の設定が大事です。てか、それしかないです。
食品には、例えばこんな表示があります。
![20211224_121119_small3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386900/2afebc50-e60c-0fde-0096-0122dd39c3e9.jpeg)
で、家にある電子レンジが**500W**と**600W**の切り替え式だったりします。
皆さんならどうしますか？
500Wで5分待てばおいしく出来上がりますが、ここは**600Wを使って時短調理**したいところです。
熱量は$ワット数×時間$で求まりますから、

```math
5[分] = 300[秒]
```

```math
300[秒] \cdot\frac{500[W]}{600[W]} = 250[秒]
```

```math
250[秒] = 4[分]10[秒]
```

という計算をすれば、**600Wで4分10秒加熱**すればよいことがわかります。
![cooking_microwave_reitou_small.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386900/3d4d18d2-004a-c89c-79e4-b0956e5be140.png)

#早速アプリを作ろう

と思ったら既にたくさんありました。orz

+ [電子レンジ ワット数変換](https://play.google.com/store/apps/details?id=jp.moshimore.android.microwavewatt&hl=ja&gl=US)
+ [電子レンジのワットを変換！](https://play.google.com/store/apps/details?id=work.tafetafe.microwavewattageconverter&hl=ja&gl=US)
+ [電子レンジ計算機](https://play.google.com/store/apps/details?id=club.lab.kappa_lab.microwave_calculator&hl=ja&gl=US)
+ [電子レンジのワットを変換するやつ](https://play.google.com/store/apps/details?id=jp.xxxxxxxx.lordsilver.microwavewattconverter&hl=ja&gl=US)

などなど、
みんな同じことで苦労してたんですね。

#でも、いつもスマホが手元にあるとは限らないし

いや、**ある**、という人には有益な記事にはなりませんでした。ごめんなさい。

なんか**早見表みたいなのを磁石で電子レンジに張り付けておくイメージ**で利用したい。でも、掛け算割り算が必要なので、単純な早見表ではダメですね。
掛け算割り算ができる早見表みたいなものは、いわゆる**[計算尺[wiki]](https://ja.wikipedia.org/wiki/%E8%A8%88%E7%AE%97%E5%B0%BA)**ですね。

計算尺そのものの説明はwikiを見てくださいね。
ざっくりいうと、掛け算割り算は対数の足し算引き算なので、スライダーを移動させることで、足し算掛け算ができるという仕組みです。
昔の人は、スマホの代わりに計算尺を使っていたそうです（知らんけど）。

#電子レンジのワットを変換する計算尺（その１）

対数目盛を手で刻むのは大変なので、**アプリを作って動作確認をし、画面のプリントアウトを円盤に張り付ける**、という作戦にしました。
ソースコードは**[GitHub](https://github.com/tomoyukioya/MicroOvenCalc)**にあります。
デモページを**[ここ](https://mcalc.blob.core.windows.net/mcalc/index.html)**に置きましたので、内円部分をマウスやタッチでグルグル回してみてください。
冒頭の例でいうと、下図のように**外円の500W**と**内円の600W**の位置が一致するように回してください。
[![スクリーンショット 2022-02-07 110323_small2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386900/9342b2e1-1ead-c539-c427-caf03fb5574d.png)](https://mcalc.blob.core.windows.net/mcalc/index.html)
説明書には**500Wで5分**と書かれているので、同じく内円の5分のところを見ると**実際の温め時間は4分10秒**となり、冒頭の計算と一致しました！！

#電子レンジのワットを変換する計算尺（その２）改良版

何人かにベータテストお願いしたところ、説明書ワット数が外円なのに、説明書加熱時間が内円で、見づらい、との意見をもらいました。
これを解決するには、目盛りを対数の位置に刻むのではなく、逆数の対数の位置に刻めばいいです（計算尺でいうところの、CI尺、DI尺ですね）。
改良版のデモページを**[ここ](https://mcalc.blob.core.windows.net/mcalc/index2.html)**に置きましたので比較して試してみてください。
[![スクリーンショット 2022-02-07 111626.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386900/89d7ad16-2241-326c-0e63-105244e08544.png)](https://mcalc.blob.core.windows.net/mcalc/index2.html)

#物理円盤に実装
あとは、このWebページを画面印刷して、プラバンなどに張り付ければ出来上がりです。
電子レンジの脇に常備しておくと便利です。
![151914334-8e8146e5-3c8e-4983-bad7-a06d7514ba54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386900/29b641f9-4087-9787-77ec-d535ccafe218.jpeg)
(改良前の目盛りです)
M1 Macでde novoアセンブリをしてみよう　〜実行編〜

# M1 Macでde novoアセンブリプログラムが走らない？
[前回の記事](https://qiita.com/bacbac/items/3b3c4d36477c77fd8716)でSPAdesのインストールを行いました。しかし、実際に実行しようとしても動かないのです（笑）

本記事では、その解決方法を紹介します。
## spadesが動かない！！
そもそもSpadesは[k-mer](https://en.wikipedia.org/wiki/K-mer)によって、NGSのリードデータ（[FASTQファイル](https://qiita.com/bacbac/items/6b4634e3feaf84ea1db8)）をアセンブリングするプログラムです。
M1 Macでは普通にコマンドを打ち込んでも、エラー`setrlimit(2) call failed, errno = 22`が発生します。
その対処法は説明します。
ズバリ、オプション`-m 1024`です
```
#コマンド例
`spades.py -1 Read1.fq.gz -2 Read2.fq.gz -o Output_directory -t CORE_number --cov-cutoff auto --careful —debug -m 1024`
```
:::note alert
原理はわかりませんが、Githubの[Q&A](https://github.com/ablab/spades/issues/839)でものこの対処法が紹介されていましたので、M1 Macユーザーはこのオプションを使いましょうね。
:::

# 終わりに
M1 Macでバイオインフォマティクスしようとすると、なかなか不具合が大きいですよね。
今後も対処法を紹介していきます。
エンジニアジョブホッパーの特徴

## ISSUEに単価表の記事を追加しました
https://i-ssue.com/topics/de478ab0-b0d1-4449-a8ff-0d4c8f403896

## はじめに

手に職を持つITエンジニアは身一つで色々な企業で働くことができます。一方で、需要が高く身軽な分ジョブホッパー化しやすいと思います。企業側もエンジニア不足の中、ジョブホッパーかどうかの判断は後回しになってしまうことが多いでしょう。その結果、余計な採用コストをかけてしまう事態が頻発してしまいます。企業の皆様にそんなジョブホッパー気質のエンジニアに引っかからないようにすると共に、エンジニア側も自分がジョブホッパーと捉えられないようにしましょう。

## ジョブホッパーの定義とは

> **ジョブホッパー**とは一般的に、1～2年で転職を繰り返していて、1つの企業に定着しない人材のことを指します。
[参考](https://next.rikunabi.com/tenshokuknowhow/archives/25529/#:~:text=%E3%82%B8%E3%83%A7%E3%83%96%E3%83%9B%E3%83%83%E3%83%91%E3%83%BC%E3%81%A8%E3%81%AF%E4%B8%80%E8%88%AC,%E3%81%AE%E3%81%93%E3%81%A8%E3%82%92%E6%8C%87%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E4%BE%8B%E3%81%88%E3%81%B0%E3%80%81%E3%80%8C%E3%81%BE%E3%81%A020%E4%BB%A3%E5%8D%8A%E3%81%B0,%E5%88%A4%E6%96%AD%E3%81%95%E3%82%8C%E3%82%84%E3%81%99%E3%81%8F%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)

1 ~ 2年で転職を繰り返す人のようですね。ただフリーランスエンジニア(特にWeb)の場合、もう少し短いと思います。具体的には ~6ヶ月くらいかと思っています。即戦力のエンジニアの場合、0→1案件や専門領域の開発などに関してはそれほど時間をかけずともpayできる方が多いためです。

| | 転職までの期間 |
|:-----------|:------------:|
| 正社員       | **1 ~ 2**年        |
| フリーランス       | **~6**ヶ月        |

## ジョブホッパーの本質
ジョブホッパーとはあくまで見え方だと思います。言い回しからネガティブな印象を受けますが、本質としては以下にまとめられると思います。

- 行動力がある
- 責任感がない
- 興味が移ろいやすい
- 組織に馴染めない

行動力があると言うのはむしろ、ポジティブだと思いますが責任感や興味が移りやすいと言う性質を同時に持つとジョブホッパー気質になります。

# ジョブホッパーの特徴
上記を踏まえジョブホッパーの特徴をみていきましょう。

## 1. フットワークが軽い
新しいものを抵抗なく受け入れるタイプです。新規サービスでも少しでも興味を引く、メリットがあると感じると躊躇なく試せるアーリーアダプターな面を持っていると思います。この性質は単体だと仕事面において否定から入らず、まずはやってみようと言える方が多く非常に良い特徴だと思います。

## 2. 正社員として企業に在籍していた期間が1年の経歴が75%以上
例えば現在4社目で、過去3社の在籍期間が1年ほどだった場合間違いなくジョブホッパーです。職場環境が劣悪でもないところなのに在籍期間が短い場合さらに疑い深いです。「次の目標ができたので、転職した」といった前向きな考え方だったとしても、外から見ればジョブホッパーになってしまいます。

## 3. アンテナが高い
情報収集能力が高いので、何事にも優位に立ちやすく常に複数の選択肢を持っています。複数の選択肢があればより良い条件があればそちらに移りやすいです。ただ、こちらもジョブホッパーの本質の中で行動力だけを持ち合わせている方はとても優秀な方だと思います。

## 4. ネガティブな性格
このタイプは組織に溶け込みづらい方が多く、結果人間関係を一新したいという気持ちから職場を変えることがあります。このセクションでいうネガティブな性格の行動例としては、組織やパートナーの悪口を言う、SNS(特にTwitter)で誹謗中傷をする方です。多少の不満はみんな抱えているので、安易には発信しないようにしましょう。

## 5. Noと言えない
[できないエンジニアの特徴](https://qiita.com/sagae_twins_developper/items/399c233ea6b00c8f5734#4no%E3%81%A8%E8%A8%80%E3%81%88%E3%81%AA%E3%81%84)でも登場しました。できないことを安請け合いしてしまいます。成果物をあげられず評価は下がりそれがまた本人のプレッシャーになります。その結果居心地が悪くなり、人間関係を一新しようとします。できないことをできないと言うのは正当な主張でお互いを幸せにすると思います。

## まとめ
ジョブホッパーといえども能力の高く優秀な方もいます。ですのでそんな方には例え短期で抜けたとしても問題ないように、引き継ぎが容易に可能なタスクや常日頃からドキュメントを書いてもらうようにすることがおすすめです

## おまけ
エンジニアの副業やフリーランス、スキルアップについての情報発信してるのでフォローしていただけると励みになります！
@twinsdevelopper

フリーランス・副業時に使える業務委託単価診断もおすすめです！
https://i-ssue.com/surveys
[py2rb] Pandas.DataFrame

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# pandas (Python)
```python
import pandas as pd

val = [[1,2,3],[4,5,6],[7,8,9]]
df = pd.DataFrame.new(val, index=[0,2,4], colums=['d','e','f'])

print(df)
print(df.loc[2])
print(df.iloc[2])
print(df['e'])
```
https://www.shoeisha.co.jp/book/detail/9784798160672

現場で使える！pandasデータ前処理入門 機械学習・データサイエンスで役立つ前処理手法 - 148p
# どうすRuby
```ruby
require 'pandas'

val = [[1,2,3],[4,5,6],[7,8,9]]
df = Pandas.DataFrame.new(val, index=[0,2,4], colums=['d','e','f'])

puts df
puts df.loc[2]
puts df.iloc[2]
puts df['e']

# output
   d  e  f
0  1  2  3
2  4  5  6
4  7  8  9
d    4
e    5
f    6
Name: 2, dtype: int64
d    7
e    8
f    9
Name: 4, dtype: int64
0    2
2    5
4    8
Name: e, dtype: int64
```
https://www.rubydoc.info/gems/pandas/0.3.8

`RubyGems`に`pandas`がありますので、同様のことは可能です。
しかしながら、`new`を付ける必要があることは、ググってもなかなか見つからないようです。
# メモ
+ Python の pandas を学習した
+ 百里を行く者は九十里を半ばとす
Elementorのカラムやセクションにもリンクを付けたい！【Happy Elementor Addons】


Happy Elementor Addons（無料版）の機能を試していたとき、思わぬ便利機能を見つけたので共有です。

##特定の箇所以外リンクが貼れない…

Elementorでページ作成中、この問題で悩んだ人も多いと思います。Elementorは、「見出し」や「画像」などの特定のウィジェットにはリンクを貼ることができますが、ほかの箇所にリンクを設定できないのです。
例えばこんなコンテンツを作ったとします。

![春１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/be7386dc-5542-f0be-f656-4b34af9b090c.png)|
|:-:|

よくあるカード型のコンテンツですね。
作りはこうなっています。

![春2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/2792ec60-4c7c-c320-55fe-66ad52e3e61b.png)|
|:-:|

赤枠がカラムで、水色の枠がウィジェットです。1つのカラムの中に、画像ウィジェット、
見出しウィジェット、テキストエディタウィジェットの3つのウィジェットが入っています。
この3つのウィジェットには各自リンクを設定できます。

![春は-–-new_practice-Google-Chrome-2022-01-20-14-42-15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/1d550101-7ab8-ae4d-d51c-a2413ca67ef0.gif)|
|:-:|

↑こんな感じです。各種ウィジェットの部分がクリック可能になっていることがわかります。
では、**カード全体にリンクを付けたい**場合はどうすればいいのでしょう。現状だと、緑色の部分はクリックしても何も起きません。でもカラムにはリンク設定の項目が無い…困りました。

##Happy Elementor Addonsをインストール
しかし、WordPressには優秀なプラグインがたくさんあります。困ったときはプラグインでだいたいどうにかなります。（サイトが重くなるので入れすぎには注意）
今回は、プラグイン「Happy Elementor Addons」をインストールしましょう。

![newpractice.local_wp-admin_plugin-install.php_s=happy&tab=search&type=term.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/eba97262-4429-2eb6-5337-9cad47cca233.png)|
|:-:|

↑この笑顔が目印

Happy Addonは、２０以上のウィジェットや機能を追加する、Elementor用の拡張プラグインです。有料版と無料版がありますが、無料版でも多数の機能が追加されます。このプラグインの機能の一つ、「**Wrapper Link**」を使います。
Happy Addonを有効化し、Elementorの編集画面を開いてみましょう。
「ウィジェットをここにドラッグ」のところに笑顔のアイコンが追加されていればOKです。

![スクリーンショット 2022-01-20 134631.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/e924f62f-53fb-b66b-ff98-bcb47ac43454.png)|
|:-:|

先ほどのカラムを選択します。Wrapper Linkという項目が追加されていますね。
![スクリーンショット 2022-01-20 135539.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/74f19b39-a129-6db9-8bd9-6fc84d23cbfb.png)

リンクを設定してみましょう。

![スクリーンショット 2022-01-20 135811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/dabd15a8-0a57-ddc8-58f2-87a87f5079e8.png)|
|:-:|

緑色の部分がクリックできるようになっています！

![春は-–-new_practice-Google-Chrome-2022-01-20-14-25-11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/19ad7874-f476-212c-3796-9dac884b8d15.gif)|
|:-:|

このように、ウィジェット以外にリンクを設定することが可能になります。ページ作成の幅が広がりますね。
ちなみに、カラムとウィジェットに両方リンクを設定した場合、**ウィジェットのリンクが優先されます**。一か所だけほかの場所にリンクさせたいときなどは、ウィジェットに個別にリンクを設定しましょう。


##あとがき
いかがだったでしょうか。Happy Addonにはまだまだたくさんの機能がありますので、ぜひ皆さんも触って確かめてみてください。
日記；回すだけIII ③TMCM-CANopenで回す

　TRINAMIC社モータ制御ソフトウェアTMCM-CANopenで、オリエンタルモーターのモータBLMR5100K-A-Bを回します。
![IMGP1005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/688f7479-2eea-bb71-7dfc-e0b1043e332a.png)

　[日記；回すだけII ②GUIツールTMCM-CANopen](https://qiita.com/jamjam/items/592a9d5de02df097540c)ではバージョンが1.5でしたが、2021年年末に1.6に上がりました。
　TMCM-CANopen Revision V1.6.0.0はダウンロード・フォルダで展開（解凍）してあります。
　C:\Users\ユーザ名\Downloads\TMCM-CANopen.1.6のフォルダにUserEdsフォルダを作り、BLVD-KRD_CANopen_V100.edsを入れます。edsファイルはそのモータ固有のオブジェクト・ディクショナリを記述したテキスト・ファイルです。XMLかJSONのようなものです。
　同様に、BeckhoffのCANopen用IO-Link、EPOS2、EPOS4のEDSファイルもいれました。
![2022-02-03 (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/4eb23c89-9672-b90d-3267-1d00638cd1c6.png)

　それぞれのモータは、CANバスにつないでいます。PCとはIXXATのUSB-CANバスでつながっています。
###検出
　TRINAMICのモータのIDは2、EPOS2は5、IO-Linkは7、EPOS4は9、オリエンタルモーターは10を振ってあります。Node IDの検出では、IO-Link以外を見つけてきました。
　画面左のInterface TreeからID10をクリックしました。

![2022-02-07 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/405e135f-1dec-bb85-ea0f-cea39fc7ba52.png)

###運転
　メインのNMTは触りません。
① このモータのID10をクリックしたときに出る画面のGeneralのNMTでStartボタンをクリックします。
② CiA-402 State MachineでCyclic pollingにチェックを入れます。
　Read to switch、Switched on、Operation enabledを連続してクリックしていきます。BLST01のGUIで、リモート運転S-ONをONにした状態になります。じりじりという音が聞こえてきます。

![t102a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/67a0ccae-175a-6c21-3b27-2f6563fc98ab.png)


③ CiA-402 Profile Position Modeをクリックします。このモードは、加速度や速度、動かしたい位置を指定すると、その位置まで内部で計算して加速し、回転し、減速して止まります。
　Cyclic pollingにチェックを入れます。
　回転方向の加速度6083 Profile accelerationと逆回転方向の加速度6084 Profile decelerationにはともに1000が入っています。そのままで使います。
　速度6081 Profile velocityには5000を入れました。すっと動く感じです。500だとじっくり動きます。
　どこまで回転させるか607A Target positionは10000にしました。
　Move absoluteで10000まで回転します。 Move relativeでは10000単位で回転します。


　画面左のInterface TreeからCiA-402 Homing Modeをクリックします。
　6098 Homing methodの37は現在位置をhomeにします。右矢印をクリックすると、下のCiA-402 Profile Position Modeの6064 Actual positionが0になります（画面では-60）。
![2022-02-07 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/a8ffc956-5b0b-c242-9dae-c46a0ead3043.png)

　ほかのmethodは、HP-5143E.pdfの7.4.5 Homing methodに書かれています。

###IDの変更

●TMCM-CANopen
　IXXATConnection　NMTタブ　Start-ResetAppl
　Object Browser　Index2704 CAN Bit Rate　1000　write
　　　　　　　　　Index2706 Store sub-index 1　0x65766173　write
　　　　　　　　　Index2705 Node-ID　3　write
　　　　　　　　　Index2706 Store sub-index 1　0x65766173　write

●Oriental Motor　BLVD-KRD、BLMR5100K-A-B
簡易設定　ノードID　10　　Bitrate　1000kbps　ドライバへ反映クリック

●EPOS4
　DIP switch SW1で設定する。ソフトではできない。ID=5に設定した。

●EPOS2
　DIP switch 1,4をONにして1＋8＝9
Bourne shellスクリプト中でcurlにbodyを渡すときはヒアドキュメントを使うと見通しが良い

タイトル通りの小ネタです。ほぼ個人的な備忘録です。常識だったらすみません。

Web APIの挙動を [cURL](https://curl.se/) を使ってサンプルで示す場合が結構あるかと思いますが、POSTメソッドなどでBodyを取る場合にどうやって表記すると見た目がわかりやすいかと迷っていましたが、ヒアドキュメントを使って書くと比較的見通しが良さそうです。

```sh
curl --request POST --header "$SOME_HEADER" -d@- $URL <<EOM
{
   "some_field": "value",
   "other_field": "$OTHER_FIELD"
}
EOM
```

## ポイント

- `-d@-`: このオプションを付けると標準入力からBODYを取得する。
- ヒアドキュメントの形式で書くと：
    - 変数展開が可能。
    - エスケープをあまりしなくてすむ。
S3バケットをLinuxにマウントするgoofysが良かった

S3をマウントすると遅いという話もあり使っていませんでしたが、容量不足の解決策としてgoofyを使ってs3マウントしてみました。手軽で速度も十分だったのでメモしておきます。本当にストレージを追加したような感覚です。

goofys:
https://github.com/kahing/goofys

##　インストール

ビルド済バイナリーを使うのが早いかと思います。go製なので、シングルバイナリーで動きます。

https://github.com/kahing/goofys#installation

## 設定

AWSのアクセスキーなどを設定します。S3限定の権限が良いかと思います。

```:.aws/credentials
[default]
aws_access_key_id = AKID1234567890
aws_secret_access_key = MY-SECRET-KEY
```

## 実行

単順にbucketとマウントポイントを指定するだけです。

```
goofys <bucket> <mountpoint>
```

## fstab

fstabに設定する事もできます。

```:/etc/fstab
goofys#bucket   /mnt/mountpoint        fuse     _netdev,allow_other,--file-mode=0666,--dir-mode=0777    0       0
```

## データのコピー

データーのコピーが必要な場合、最初はrsyncを使ってマウントした場所にコピーしていたのですが、なかなか時間がかかります。

ということで、aws cliを使ってS3に直接コピーする事で高速に転送する事ができました。

```
aws s3 sync mydir s3://<bucket>/mydir
```

転送後にディレクトリー側で反映されるまでファイル数が多いと少し時間がかかりますが、長時間かかる感じでは無いので十分かと思います。
SFTPコマンドをシェルファイルから使うサンプル

# はじめに

SFTPコマンドを使うとサーバーとファイルのアップロードやダウンロードを行うことができます。
対話式に使うことができるので簡単で便利なのですが、定型的な処理を自動で行いたいこともあります。
この記事ではSFTPを使って、自動で処理を行う方法をお伝えします。

# 概要

シェルファイルからSFTPを呼び出してサーバーとファイルのアップロードやダウンロードを自動で行うサンプルを紹介します。

# 対象者

- macでターミナルを使っている
- ターミナルでファイルの操作が行える
- テキストエディタを使える
- シェルはzsh（最近のmacはデフォルトでzsh：2022年時点）

# 関連記事

- [SFTPを使ってファイルのダウンロード/アップロードする](https://qiita.com/tatsumi_t2/items/73567ff4a1006399969b)	
- [SSH接続をconfigファイルを使ってラクする](https://qiita.com/tatsumi_t2/items/3d88afdaf8d5f7283267)


# 目次

- [サンプル](#サンプル)	
- [実行](#実行)	
- [補足説明](#補足説明)	

# サンプル

sftpへの接続は鍵認証で行う想定です。

- mac側のホームディレクトリに本日の日付のディレクトリを作る
- 作ったディレクトリに移動する
- サーバー側でも、本日の日付のディレクトリに移動する
- サーバー側のそのディレクトリにあるファイルをダウンロードする

sftp_sample.sh

```bash
#!/bin/zsh

# 今日の日付を取得する
today=`date "+%Y%m%d"`

sftp -i 鍵ファイル 接続ユーザー@接続先サーバー << EOF

# mac側：ホームディレクトリへ移動
lcd

# mac側：今日の日付のディレクトリを作る
lmkdir $today

# mac側：今日の日付ディレクトリへ移動
lcd $today

# サーバー側：今日の日付のディレクトリへ移動
cd $today

# サーバーからmacへファイルをダウンロードする
get *

# 終わり
EOF

```

# 実行

```sql
source sftp_sample.sh
```

# 補足説明

sftpコマンドの行末の「<< EOF」はヒアドキュメントと呼ばれるものです。
「<< EOF」からファイル最後の「EOF」までの各行をsftpのコマンドとして送り込みます。
ヒアドキュメントは、シェルの便利な書き方の一つです。
資格試験勉強に対してやる気がでない自分がPython認定基礎試験を勉強したわけ

# 1.はじめに
* この記事について
   * 合格体験記というよりも<b>「資格試験」に対して今回向き合えた自分の心情や、背景などを整理したもの</b>になります。初心大事にしたい派です。
   * あくまで資格試験に対しての個人の感想になるので観点を広げる、動機付けの文言化を進めるという意味で読んでいただけると幸いです。

* 勉強した(している)試験  
   * Python 3 基礎認定試験 - 合格しました！
   * Python 3 エンジニア認定データ分析 - 試験勉強中です！

* 簡単な自己紹介
   * 新卒エンジニア二年目
   * 未経験でスタート
   * Pythonを触り始めて3ヶ月目です。

# 2.資格試験勉強に"やる気"が生まれなかった自分の言い分
* 自分なりの言い分として、<b>「使うことだけ調べて実装できればいいじゃん！」</b>って感じでした(笑)

    >Google先生に聞けば大抵のこと教えてくれるし、（のせてくれている皆さんありがとうございます）
    >自分でプログラミングの試験うけるのって「試験を受けることが目的になっている」感じがして

    >「これって本当に必要な知識・技術なの？」

    >という"邪念"に負けて挫折するのが安定のパターンでした(笑)

* 落ちた時に自分の出来ないやつというレッテルを自分で貼っているような気がして気が進まなかった。

    >大学受験などでも第一志望に落ちたり浪人したけどかなわずだった過去もあるのでトラウマな部分もあるかもです。
    >受ける前から"負けている"という。。。できない理由なんて探したらいくらでも見つけられますが、挑戦しないための理由づくりでしかありませんでした。

# 3.認定基礎試験の勉強をはじめたわけ
</br>
### 端的に言うと、「基礎を固めもっと楽しみたい！！」の一言に尽きます(笑)
基礎を固めたいと思った背景ですが、以下のようなことがありました。

</br>
</br>

* 一番時間がつかいたいところに時間を使えないもどかしさ
    >増えるコードすべてが新しいことだらけ。自分は勉強自体は好きなので「全部楽しい！すごい！こんなこと
     もできるのか！」となるのですが、<b>「ここに時間を使いたいのか？」</b>と二年目になって思うことが増えて
     きました。

    * 例えば、○○の機能を実装したいと思っていても、その機能実装の前に文法について毎回調べていた。。。
    * 継承のルールなどわからずほかの人の書いたコードを読むのに時間が掛かる。。

    >圧倒的に生産性が悪い。。

* これって"良い"コーディング？もっといい書き方があるのではないか？

    * 「もっといい書き方があるのではないか？」と自分で振り返りたい時も<b>良し悪しの判断や改善の方向性が見えない。。</B>
    * ペアプロなどがしてもらえる環境でありつつも、「いつまで教えてもらう立場にいるのか」という焦り
    * Google先生に書いてある通りでしか書けない。<b>なぜそう書いたのかを自分で理解するのにかなり時間を要する。</b>

* 調べてわかった気になっているだけの自分、本当に理解できているのか？
    * その場その場で調べて<b>わかった"気"になっている(たぶんその瞬間では頭では理解できている)</b>が、再現性がないことが多い。
    * 聞かれた時に、「あ、それ前に調べました！、、、、あれ、どうやったっけ？」を連発する。
    * 自分のできそう！ほど信用のない言葉はない(笑)

</br>
</br>
つまるところ...
### 基礎⇒応用のステップを自分で踏めていないのでレベルアップできている感じがしない

</br>
基礎を固めるという意味で最初は遠回りかもしれないけどもやろうと決めて基礎認定試験を取り組み始めました。
</br>

# 4.資格取得の先にあったもの

* 一番時間をかけたいところにかけられている意識が少しずつ持てるようになってきました。
* ライブラリの中身などを見たり、実際に機能を試す時間を圧倒的に増やすことができました。
* 資格勉強中に苦手な箇所も実際に書く中で、理解を深めることができてきました。

    >やはり書かないと覚えれられないです(笑)

* 驕りではない小さな自信がつきました。自信というよりも自分の現在値を知れたというのが適切かもしれません。
>なにが分かっていてどこの部分の知識が曖昧なのかの傾向が掴めたので、苦手な部分などもあいま時間に振り返れます。

# 5.さいごに
自分が好きな言葉に「井の中の蛙大海を知らず、されど空の青さを知る」というものがあります。
ほかの言語はわかりませんが、純粋にPythonという言語で出来ることの多さを目の当たりにしてもっともっといろいろとできるようになりたいです。

試験勉強中は好きとはいえ退屈になる瞬間もありましたが、それでも手を動かして結果を自分で見返しながら行えるのでそこまで嫌にはなりませんでした。

> 好奇心の力って偉大

遠回りかもしれませんが、時間がかかるものと割り切って臨めたのは良かったです。
最近読んだ記事がすごくよかったのも影響しているかもしれません。

><参照>
>プログラミングというより物事が出来るようになる思考法
>https://note.com/simplearchitect/n/n388201603a28

試験は受かったもののギリギリの合格でしたし、まだまだ道半ばですが、日進月歩で楽しんでいきます！

駄文でしたが最後まで読んでいただきありがとうございました！
オンプレミス環境でAmazon SageMakerを動かすための環境構築




オンプレミス環境でAmazon SageMakerを動かすための環境構築をまとめました。



# 環境

- macOS Big Sur 11.1
- Python 3.7.0



# 事前準備

- Docker
Amazon SageMakerが提供するコンテナーを起動する際に使⽤します。macOS で Dockerを使うには、Docker アプリ（[Docker Desktop](https://www.docker.com/products/docker-desktop)）をインストールするか、[Homebrew](https://brew.sh/index_ja)でインストールします。


- Anaconda
機械学習に必要なPythonライブラリは充実しているため、Anacondaの仮想環境にAmazon SageMakerをインストールします。Anacondaのインストール⽅法は[公式マニュアル](https://docs.anaconda.com/anaconda/install/mac-os/)に開設されています。



# Amazon SageMaker⽤仮想環境の作成


condaで仮想環境（`localsm`）を作成します。

```sh
$ conda create -n localsm 
```

作成した仮想環境（`localsm`）に切り替えます。

```sh
$ conda activate localsm 
```

仮想環境に、機械学習に必要なPythonパッケージ（`pandas`, `tensorflow`, `keras`, `pytorch`など）を追加します。

```sh
$ conda install pip pandas tensotflow keras pytorch
```


仮想環境に、`sagemaker`をインストールします。

```sh
$ conda pip install sagemaker
```


Jyupter notebookの環境を構築します。

```sh
$ conda install ipykernel 
$ python -m ipykernel install --user --name localsm --display-name "Python (localsm)"
```


Jupyter Notebookを起動します。

```sh
$ Jupyter notebook& 
```
Webブラウザが起動し、Jupyter Notebookのページが問題なく表示されたら、環境構築は完了です。


# ローカルモードでSageMakerの使用



まず、Amazon SageMakerを実⾏する為のIAMロールを確認します。[AWS CLI](https://aws.amazon.com/jp/cli/)が使⽤できる場合は、以下のコマンドで確認できます。
​


```sh
$ aws iam list-roles | grep SageMaker-Execution 
```

以下のような結果が表示されます。


```
"RoleName": "AmazonSageMaker-ExecutionRole-xxxxxxxxxxxxxx",
"Arn": "arn:aws:iam::602166551063xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
```

この`Arn`の結果は、コンテナを呼び出すときの`role`関数で使います。例えば、Dockerが起動している状態で、SageMakerが提供する`Scikit learn`のコンテナイメージ`SKLearn`を使⽤し、機械学習を実⾏する場合は、以下のように記述します。



```python

from sagemaker.sklearn.estimator import SKLearn

role = 'arn:aws:iam::602166551063xxxxxxxxxxxxxxxxxxxxxxxxxxxx'


# instance_typeは"local"で指定します。
# script_pathは機械学習を実行するスクリプトですです。
sklearn = SKLearn(
    entry_point=script_path,
    framework_version=FRAMEWORK_VERSION,
    instance_type="local",
    role=role, 
)


```
無事にSageMakerが起動できれば、ローカルモードの環境設定は完了です。


# 参考

Train with Amazon SageMaker on your local machine（https://youtu.be/K3ngZKF31mc）