OmniAICreator/Qiita-1.07M huggingface dataset:
EfficientnetをCore MLに変換する【変換済みモデルあり】

<img width="600" alt="スクリーンショット 2020-08-11 12.40.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/354ba0ee-3ce5-3156-911e-9f4ae0fc8d54.png">
画像分類の最新モデルをCore ML形式に変換します。

**[変換済みCoreMLModel(GitHub)](https://github.com/john-rocky/CoreML-Models)**
###TensorFlow Hubのモデルコレクションからダウンロードしてモデルを構築。


```python
m = tf.keras.Sequential([
    hub.KerasLayer("https://tfhub.dev/tensorflow/efficientnet/b0/classification/1")
])
m.build([1, 224, 224, 3])
m.summary()
```

###クラスラベルを読み込んでおきます。

(今回はImageNetの１０００クラスでそのまま使用。TensorFlowHubには転移学習のできるバージョンも公開されています。)

```python
import urllib
label_url = 'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt'
class_labels = urllib.request.urlopen(label_url).read().splitlines()
class_labels = class_labels[1:] # remove the first class which is background
assert len(class_labels) == 1000

# make sure entries of class_labels are strings
for i, label in enumerate(class_labels):
  if isinstance(label, bytes):
    class_labels[i] = label.decode("utf8")
```


###CoreMLTools4.0で変換します。

```python
import coremltools as ct

image_input = ct.ImageType(shape=(1, 224, 224, 3,),
                           scale=1/255)

mlmodel = ct.convert(m,
                     inputs=[image_input],
                     classifier_config=classifier_config,
                     )
mlmodel.save('./efficientnet.mlmodel')
```

<img width="951" alt="スクリーンショット 2020-08-11 12.40.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/54eee8a0-91ac-4edd-54e5-01bbab9a1019.png">


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

[Twitter](https://twitter.com/JackdeS11)
[MLBoysチャンネル]
(https://www.youtube.com/channel/UCbHff-wfjTnB3rtXIP6y0xg)
[Medium](https://medium.com/@rockyshikoku)

[相棒](https://twitter.com/oka_yuuji)
[note](https://note.com/oka_yuuji)
Deploy Keyを使ってEC2からGitlabのリポジトリをクローンする



## 1.EC2側
EC2にSSH接続後

```shell:EC2
cat .ssh/id_rsa.pub 
```

### 鍵がない場合は作成する

```shell:EC2
ssh-keygen -t rsa
cat .ssh/id_rsa.pub 
```
表示された文字列をコピーしておく

## 2.GitLab側

### Deploy Key登録

#### プロジェクトのSettings > Repository
<img width="217" alt="スクリーンショット 2020-08-11 12.22.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/5cd5b38f-90a1-5d59-d765-4d0cbc28a80c.png">
Deploy Key項目を探す

#### Deploy Keyを登録する
Title　：　適当
Key　：　EC2でコピーしたもの（id_rsa.pubの中身）
<img width="971" alt="スクリーンショット 2020-08-11 12.23.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/762744fb-0585-250a-f76e-9d6c4475d59e.png">

## 3.EC2側

### クローンする

```shell:EC2
git clone {Gitlabのプロジェクトでcloneボタンを押したら出てくるgit@~}
```

## ※ 別のプロジェクトも同じEC2にクローンする場合（Gitlab側）

### Gitlabで登録済みのDeploy Keyを有効化する
#### プロジェクト > Settings > Repository > Deploy Key
<img width="1362" alt="スクリーンショット 2020-08-11 12.06.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/1e3679ad-d952-5edb-3b1b-6408f34c8d39.png">

#### 有効化前
<img width="879" alt="スクリーンショット 2020-08-11 12.34.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/59bda0c2-8486-01ee-8e90-e542fc41a87a.png">
#### 有効化する
Privately accesslible deploy keys タブをクリックし、登録済みのDeploy Key横にある「Enable」ボタンを押す
<img width="875" alt="スクリーンショット 2020-08-11 12.34.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/1c84be6c-c5e1-cdc2-89f3-3802446ed07a.png">

#### 有効化後
<img width="704" alt="スクリーンショット 2020-08-11 12.31.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125006/b089d66d-a2f1-53b7-29b4-ffe11bfbeeea.png">

#### クローンする（EC２側）

```shell:EC2
git clone {Gitlabのプロジェクトでcloneボタンを押したら出てくるgit@~}
```
【Rails5】gem gonの使い方 ~RailsからJSに変数を渡す方法~

##実装した機能

####開発環境
```text
ruby > 2.6.5
rails > 5.2.4.2
gon > 6.3.2
```

今回はシンプルに、RailsのControllerで定義した変数をJSに渡してhtmlに表示します。
Railsに標準搭載されている`hoge.js.erb`形式や`coffeescript`で書いたほうがスムーズだったりしますが、うまく表示できないときの回避策としても使えるGemかなと思ったのでご紹介します。

**※注意**
Gemの仕様上、htmlソース内に変数自体が表示されるので、セキュリティ的に隠す必要があるものには使わないほうが良いです。

##導入方法

まずは、Gemfileに追加

```ruby:Gemfile
gem 'gon'
```

そして、インストール

```terminal:Terminal
$ bundle install
```

RailsのView内にコードを記述
今回は全ページで使う想定ですが、必要なviewに記述されていればOKです。
JSを読み込むのと同じく、読み込みのタイミングによって挙動が異なるので読み込み順には注意しましょう。

```ruby:application.html.erb
・・・
<%= include_gon %>
<%= javascript_include_tag "application" %>
・・・
</body>
```

これで準備完了です。

##変数を渡す

RailsのControllerでGon用の変数を定義します。
といっても、変数の頭に`gon.`をつけるだけです。

```ruby:Users.erb
def show
  @user = User.find(1)
  gon.username = @user.name #これをJSに渡します
end
```

JSに変数を渡してhtmlに表示します。

```ruby:index.html.erb
・・・
<p id="name"></p>
・・・
```

```javascript:application.js
・・・
let name = gon.username
$('#name').html(name);
・・・
```

このように表示されればOKです。

```html:index.html
・・・
<p id="name">こうへい</p>
・・・
```

####html内の表示について

冒頭で「html内に変数が見えちゃう」という話をしましたが
実際にはこのように読み込まれています。
良くも悪くもわかりやすい構造になっていますね笑

```html:index.html
・・・
  <script>
    //<![CDATA[
      window.gon={};gon.username="こうへい";
    //]]>
  </script>
</body>
・・・
```

##その他機能

単純に変数を渡す以外にも

- 配列、ハッシュを渡す
- 変数をすべて読み込む

などの使い方もできるようです。
むしろ、Gemの役割としてはこっちのほうが大きいのかもしれませんね。
詳しくは公式ページをご確認ください。

**Gon公式**
https://github.com/gazay/gon
AWSアカウントへのログインをセキュアに省略する

# AWSアカウントへのログインをセキュアに省略する

前記事(別に見なくても良い)

* [Macからログイン画面経ずにAWS Management Console行くで！
](https://qiita.com/uji52/items/c779ceb447cd5c3b3a0f)
* [Macからログイン画面経ずにAWS Management Console行くで！(CLIワンライナー編)
](https://qiita.com/uji52/items/7fc0e4d4b54ee99d9098)

自宅の開発環境もWindowsになったのでWindows環境向けの第3段

## やること

「AWSで開発してるけど毎回ログイン面倒だなぁ」ってときにログインをショートカットする。

## 前提

* AWS Credentialを設定している人
* Async/Awaitの使えるNodejsが走る
* jqコマンドがインストールされている

## 動作確認環境

* Windows 10 WSL2 CentOS 7
* Nodejs 10.20(12.18.3を使うとnpm install時にエラー有り)

## 使い方

基本的には[ここ](https://github.com/uji52/aws-login)参照。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103725/19db8241-e6ca-7ed8-5705-a05d21b72d81.png)

1. AWSアカウントで必要な権限を持ったLinux環境(WSLも可)に上記Gitの環境をClone
2. npm install実行
3. npm run setupを実行し、自身のAWSアカウントID(12桁の数値)を入力
4. npm startを実行
5. ブラウザで`http://localhost:5201`にアクセス
6. 以上！

## 追加でできること

* 中のファイルを書き換えたら、権限絞れるし期限もイジれる。
* この環境を社内サーバに立ててBasic認証必要にするなどして社員ならこのリンク押すだけでログイン、とかもできるんじゃないかな。
* 修正とか機能追加とかプルリクいただければ喜んで取り込みますよー
react-hook-formの基本的な使い方

Reactで入力フォームを開発する際に便利なライブラリである[react-hook-form](https://github.com/react-hook-form/react-hook-form)の基本的な使い方についてまとめておきます。

[公式ドキュメント](https://react-hook-form.com/)が丁寧に用意されていますので、網羅的に機能を知りたい方はそちらをご覧ください。

## 実装手順
### 基本
以下のようなフォームに値を入力させて、submitする想定で改修を加えていきます。

```tsx
import React from 'react';

function App() {
    return (
        <form>
            <input name="title" />
            <textarea name="content" />
        </form>
    );
}

export default App;

```

### ライブラリのインストール

ライブラリをインストールします。

```bash
npm install react-hook-form

or 

yarn add react-hook-form

```

### refの登録
次にライブラリが各フィールドを参照できるよう、registerメソッドをそれぞれのrefに追加します。
TypeScriptの場合は予め、useFormに対して各フィールドを持った型を渡しておきましょう。

```tsx
import React from 'react';
import { useForm } from 'react-hook-form';

type Post = {
    title: string;
    content: string;
};

function App() {
    const { register } = useForm<Post>();
    return (
        <form>
            <input
                name="title"
                ref={register({ required: true, maxLength: 30 })}
            />
            <textarea name="content" ref={register} />
        </form>
    );
}

export default App;
```

react-hook-formには基本的なバリデーションも用意されており、このregisterを追加する際に設定することが可能です。

利用できるバリデーションについては以下を参照ください。

https://react-hook-form.com/get-started/#Applyvalidation

### バリデーションエラーについて

設定したバリデーションでエラーが発生した場合はreact-hook-formが用意しているerrorオブジェクトを利用してハンドリングすることができます。

```tsx
import React from 'react';
import { useForm } from 'react-hook-form';

type Post = {
    title: string;
    content: string;
};

function App() {
    const { register, errors } = useForm<Post>();
    return (
        <form>
            <input
                name="title"
                ref={register({ required: true, maxLength: 30 })}
            />
            {errors.title && <span>タイトルは必須です。</span>}
            <textarea name="content" ref={register} />
        </form>
    );
}

export default App;

```

### submit

そして、formタグに対して、コールバックを渡したhandleSubmitを設定します。

```tsx
import React from 'react';
import { useForm } from 'react-hook-form';

type Post = {
    title: string;
    content: string;
};

function App() {
    const { register, handleSubmit, errors } = useForm<Post>();
    const onSubmit = (data: Post) => {
        console.log(data);
    };
    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <input
                name="title"
                ref={register({ required: true, maxLength: 30 })}
            />
            {errors.title && <span>タイトルは必須です。</span>}
            <textarea name="content" ref={register} />
        </form>
    );
}

export default App;
```

これでフォームが送信アクションが発生した際に、入力した値がonSubmitに渡されるようになります。
JavaScriptの制御構文(1)〜if命令とswitch命令〜

# はじめに
こんにちは！
今日から時間をかけて、1度ある程度読んだJavaScriptのテキストの復習をしていこうと計画したので、ついでにこちらに投稿して備忘録として残してみようと思います！
まず、最初のテーマは、制御構文です！

# 制御構文
制御構文って色々ありますよね！
<ul><li>if命令</li>
<li>switch命令</li>
<li>while/do...while命令</li>
<li>for命令
(for命令の中でも、配列なのかオブジェクトなのかによって使い分けもあります。)</li></ul>

この中で、今回は、if命令とswitch命令について投稿します。
この2つの共通点としては、**処理を「分岐する」こと**です！

# if命令
処理を分岐するための命令には、if命令とswitch命令の2つがあります。

```
if (条件式) {
	trueの場合の処理
} else {
	falseの場合の処理
}
```

```
let x = 75;
if (x >= 60) {
  console.log('合格');
} else {
  console.log('不合格');
}

/* 変数xの値は、60以上であるため、条件式はtrueになるので、consoleには、
「合格」が表示される。*/
```
上記のような構文を用いて、if命令を実行し、処理の分岐を実現できます。
また、else以降のfalseの場合の処理を省略して、trueの場合のみ、処理を指定することも可能です。

また、trueかfalseの2つに処理を分岐させるのではなく、複数分岐させることもできます。

```
if (条件式1) {
	条件式1がtrueの場合の処理
} else if (条件式2) {
	条件式2がtrueの場合の処理
} else {
	全ての条件式がfalseの場合の処理
}
```

```
let x = 77;
if (x >= 90) {
  console.log('Aです。');
} else if (x >= 75) {
  console.log('Bです。'); 
} else if (x >= 60) {
  console.log('Cです。');
} else {
  console.log('不合格です。');
}

/* 変数xの値は、77であり、75以上、90未満である。したがって、consoleには、
「Bです。」が表示される。*/
```
else ifを必要な数だけ書き、分岐させます。
しかし、条件式を適切な順番で記述しないと、思わぬところで条件が一致し、処理が終了してしまうので、注意が必要です。

# switch命令
if命令は、条件によっては、同じような形式で条件が並ぶので、冗長な(長ったらしい)記述になってしまいます。。

例)

```
if (rank === 'A') {
	console.log('Aランクです。');
} else if (rank === 'B') {
	console.log('Bランクです。');
} else if (rank === 'C') {
	console.log('Cランクです。');
} else {
	console.log('ランク外です。');
}
```
上記のような、コードが存在したとすします。条件式をそれぞれ見てみると、rank ===  ‘A’や、rank === ‘b’というように、「rank ===」という形式の条件が複数連なっています。
しかし、このような、長ったらしい、同じような条件の分岐命令も、switch命令を利用すれば、見やすく改善できます。

```
switch (式) {
	case 値1:
		式 = 値1の場合の処理
		break;
	case 値2:
		式 = 値2の場合の処理
		break;
	case 値3:
		式 = 値3の場合の処理
		break;
	default:
		式の値が全て一致しなかった場合の処理
		break;
}
```
このswitch命令には1つ注意点があり、それぞれのcaseの処理の最後には、break命令の記述を忘れないことです。switch命令は、条件式に合致するcaseに移動するだけで、そのcaseの処理を終えたとしても、switch命令自体が終了するわけではないため、そのまま、合致したcase以降のcaseの処理も次々と実行してしまうのです。そうならないために、breakを忘れないように気をつけましょう。

# 意図的にbreak命令を記述しない時はある。(フォールスルー)

```
let rank = 'B';

switch (rank) {
	case 'A':
	case 'B': 
	case 'C':
		console.log('合格');
		break;
	case 'D':
		console.log('不合格');
		break;
	default:
		console.log('ランク外');
		break;
}

/* 変数rankの値は、Bであるため、consoleには、
「合格」が表示される。*/
```
上記では、変数rankの値が、Aの場合、Bの場合、Cの場合では、全て同じ処理をしようとしています。この場合、case ‘A’とcase ‘B’、case ‘C’の間にbreak命令を挟んで、終わらせる必要はありません。
仮にbreak命令を記述してしまうと、そこでswitch命令自体が終了してしまうため、適切な処理が行われなくなってしまいます。(行うべき処理があるにも関わらず、case 'A'やcase 'B'の場合に、何も処理が行われない)
ただし、処理内容の詳細を記述している、case ‘C’やcase ‘D’、defaultの後には、break命令が必要になってきます。


以上！！今日のif命令・switch命令のまとめでした！
理解不足による不備等ございましたら、コメントをお願い致します。
## 参考文献

山田祥寛著『[改訂新版]JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで』(2018)
※第1刷は、2016年。
[Rails]コントローラでUserAgentを取得する

##UserAgentとは？
UserAgentとはHTTPリクエストヘッダーに含まれるWEBの使用環境に関する情報です。
ブラウザの種類、ブラウザのバージョン、端末のOSの種類などの情報が含まれています。


##HTTPリクエストヘッダーとは？
HTTPリクエストヘッダーとはWEBサイトにアクセスされた時にブラウザからWEBサイト側に送られるリクエスト情報と一緒に送られる付加的な情報です。
UserAgent、Referer（リンク元URL）、Authorization（認証情報）などの情報があります。


##RailsにおけるUserAgentの取得方法
 Railsのコントローラにはrequestオブジェクトを指すアクセサメソッドが用意されており、
それを利用することでコントローラにおいて、以下のように簡単にUserAgentを取得することができます。

```
request.user_agent
```

##UserAgent以外にも色々と取得できるrequestオブジェクト
requestオブジェクトを利用すると以下のようにリクエスト情報を簡単に取得することができます。

```
request.url           # リクエストで使われるURL全体
request.remote_ip     # クライアントのIPアドレス
request.query_string  # URLのクエリ文字
```


<br>

（参考）
[Railsガイド：requestオブジェクトとresponseオブジェクト](https://railsguides.jp/action_controller_overview.html#request%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A8response%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)
Tableau サムネイルとYoutube動画の表示

### Tableau サムネイルとYoutube動画の表示

最近ダッシュボードのアクションを使用してwebサイトの表示方法に学んだのでここにやり方を残しておきたいと思う。

まず、ダッシュボードに移動し「webページ」を選択し赤枠を作成します。その後「ダッシュボード」→「アクション」を選択します。
![2020-08-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/73579f59-cb62-ee8c-d288-51d3b676e3c8.png)

「アクション追加」→「urlに移動」
![2020-08-11 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/ecedfd96-6b6b-dc3a-7af2-b950dea799c3.png)

黄色の「アクションの実行対象」のところでどのような操作で表示されるのかがわかります。オレンジ色の「url」のところでURLを指定すると指定したURLを検索する仕組みです。今回は「Thumbnail Link」がURLで構成されているカラムがあるのでそのカラムを指定しています。
![2020-08-11 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/7306dc3d-ee60-ccde-f3b8-7ecb15dff85f.png)

完成したら下図のようになり、titleにカーソルを持ってくると自動的にサムネイル画像が表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/4a3a1945-0da7-7178-c3b0-925b4eab39e2.png)

次に動画も表示させていきたいと思います。Thumbnail Linkには「https://i.ytimg.com/vi/0_1IMZmJe-U/default.jpg」
のようなURLがはいっています。Youtubeの動画を検索するにはこのurlから「0_1IMZmJe-U」ここの部分を取得しなければなりません。このように文字列の一部を取得するには計算フィールドを使用することで解決することができます。今回はsplit関数を使用しました。

![2020-08-11 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/0d3f5cab-233a-306f-efc7-951121f4297d.png)

オレンジ枠のところでURLアクションの追加を選択し図のようにURLを追加します。
![2020-08-11 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/dfb2108c-f825-ecbb-37a3-8de8ba320516.png)

完成品が下図のようになります。
![2020-08-11 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676443/00d111e5-4fc8-eb7f-fc07-29428ef2b531.png)

このようにURLを使用するとできることも幅広くなってくるためデータにURLがある場合は活用していくのもいいかと思います。
GuzzleHttpでのレスポンスをモック化してテストする

# まえがき

GuzzleHttpを利用してHTTPリクエストをしている処理のユニットテストを書きたい。
GuzzleHttpにはレスポンスをモック化する機能が用意されているようなので、こちらを利用してみることにします。

# 実装例

```php:HogeTest.php
<?php

use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Client;

class HogeTest extends \Codeception\Test\Unit
{
    /**
     * @group guzzletest
     */
    public function testGuzzleTest()
    {
        /* Arrange */
        $response = new Response(200, [], 'Response Body');
        $mock = new MockHandler([$response]);
        $handler = HandlerStack::create($mock);
        $client = new Client(['handler' => $handler]);

        $url = 'http://localhost:8080/';
        $params = [
            'token' => 'hogehoge'
        ];

        /* Act */
        $res = $client->post($url, ['form_params' => $params]);

        /* Assert */
        $this->assertEquals('Response Body', $res->getBody());
    }
}
```

```:実行結果
$ vendor/bin/codecept run unit --group guzzletest -c common/
Codeception PHP Testing Framework v3.0.2
Powered by PHPUnit 8.2.4 by Sebastian Bergmann and contributors.
Running with seed: 

[Groups] guzzletest 

Common\tests.unit Tests (1) -----------------------------------------------------------
✔ HogeTest: Guzzle test (0.04s)
---------------------------------------------------------------------------------------


Time: 1.96 seconds, Memory: 32.00 MB

OK (1 test, 1 assertion)
```

- 上記例では、テストコードで直接クライアントを作成している
- GuzzleHttpを利用しているServiceクラスやcomponentのテストを行う場合、setClient()などを実装していれば、MockHandlerで生成したClientをテストコードからセットしてレスポンスをモック化する



つまりGuzzleはとても便利。。
Alteryx DesignerでRedmineにユーザーを一括登録

Redmineのテスト環境にユーザーを一括登録する際、Alteryx Designerではまりました。解決策をメモしておきます。

環境は以下の通りです。

* Alteryx Designer：2020.2.3
* Redmine：4.1.1.stable

# Alteryxワークフロー
このワークフローの目的は、Redmine本番環境の特定のプロジェクトのメンバーをテスト環境に登録することです。

1. Redmine本番環境の全ユーザーのデータをJSONで取得
2. Redmine本番環境の特定のプロジェクトのメンバーをJSONで取得
3. これらを結合して特定のプロジェクトに属するメンバーのJSONデータを作成（login, firstname, lastname, mailフィールドのみ）
4. Redmineテスト環境に上記を登録

以下のスクリーンショットは４の部分です。

![REST-API_workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/0b2b22c3-0844-9c02-88b1-ec2c8be9ff27.png)

# Alteryxダウンロードツールの設定

「ペイロード」タブでは、フィールドからJSONデータを取得するよう設定します。
![payload.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/1bcfd6dc-a576-4811-0b61-2695649d33ec.png)

「ヘッダー」タブでは、AuthorizationとContent-Typeの2つのHTTPリクエストヘッダーを指定します。
![header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/85146b56-6678-44ae-246b-97055f9b706f.png)

* Authorizationヘッダの値として「Basic _credential_」を指定

_credential_は、アカウントとパスワードをコロンで連結した文字列をBASE64でエンコードしたものです。（そのためスクリーンショットではモザイクをかけています。）
BASE64エンコードは、Alteryxの「Base64エンコーダー」ツールを使って実行できます。

「接続」タブでログイン情報を指定した場合、HTTPレスポンスが401 Unauthorizedとなってワークフローが停止してしまいます。

* Content-Typeには「application/json」を指定

このMIMEタイプを指定しないとエラーになります。

（2020/08/12追記）
APIキーを利用した場合には、Authorizationヘッダの代わりにX-Redmine-API-Keyヘッダを使うこともできます。

# おわりに

分かってしまえばなんということはないのですが、今回は認証とコンテントタイプでだいぶ時間を浪費してしまいました。何かの参考になりましたら幸いです。
【目次】知識ゼロからコンピュータとソフトウェアの概要を理解する【作成中】

# この記事を書くに至った背景と目指すところ

コロナ禍などによる景気低迷の影響で、不採算部門から慢性的人手不足であるIT部門（組み込みソフト含む）に異動になる非エンジニアの方々が今後増えてくるのではないかと思います。
異動される方も受け入れ部署も文句を言ってても仕方がないので、お互いハッピーになれるよう、短時間で戦力になってもらうべきと考えます。
まずは非エンジニアの方々がソフトウェアエンジニアの話す内容を理解できるようにしていきたいと思い、記事を書いてみました。あとは実務を積みながら慣れてもらうしかない。
※本気でソフトウェアエンジニアを目指すのはこの記事の範疇外なので、過度な期待はしないでください。[^1]

[^1]: プログラミングそのものは小学生でも始められるほど簡単だが、安心して使ってもらえるプロダクトを作るのはとてつもなく困難な仕事であることを忘れてはいけない。基礎知識と経験と想像力がなければ、妥当な設計はできない。

# 基礎編

## 1. コンピュータの常識
■想定レベル

- テキストファイルとバイナリファイルってなんのこと？
- 2進数とか16進数ってなに？

■コンテンツ

　[知識ゼロから始めるソフトウェア ～ コンピュータの基礎の基礎【非エンジニア向け】](https://qiita.com/kob58im/items/4fdfd5544cda4931cc2b)


## 2. Windowsの常識
■想定レベル

- インストールって何？

■コンテンツ

　[超入門 - 知識ゼロから OS (Windows) の常識を知る](https://qiita.com/kob58im/items/47d031ed46ed635fc19c)

## 3. コマンドプロンプトを使う
■想定レベル

- コマンドプロンプトって何？
- ※2章の内容は知っている前提

■コンテンツ

　[超入門 - 知識ゼロからコマンドプロンプトをつかう](https://qiita.com/kob58im/items/64dfc4d97272398a63af)


## 4. プログラムを書いて動かす環境を整える
■想定レベル

- ※2章と3章の内容は知っている前提

■コンテンツ（といいつつ他力本願）
　Windows7, 10 ならインストール不要のC#を使う。
　参考サイト [コマンドプロンプトからC#をコンパイル](https://qiita.com/Stosstruppe/items/bdffc4e133db3abf8961) を参照ください。


<font color="red"><b>以下、作成中</b></font>

## 5. テキストエディタを使う

memo: ここ以降については、上記までで前提知識が足りていそうか見直す

■注意事項

・<font color="red"><b>ソフトのインストールに関しては、各職場のルールに従ってください。個人で勝手にインストールすることが禁止されている場合があります。</b></font>

■想定レベル

- ※2章の内容は知っている前提

■コンテンツ（といいつつ他力本願）

　参考サイト [HTMLファイル作成にも役立つ！サクラエディタの使い方【初心者向け】](https://techacademy.jp/magazine/4722) を参照ください。

■補足

- なぜメモ帳ではなくテキストエディタを使うのか？<br>主なメリット：
  - 「元に戻す」機能を使える回数が多い。
  - 検索機能や置換機能が使いやすい。
  - 特定のキーワードをハイライトしたり、カスタマイズできる。
  - 空白文字や改行位置が見やすい。
- エディタの選定について
  - ガチでプログラミングするのであれば、Visual Studio Code が最もおすすめ。<br>（使い方などについては、書籍はすぐに陳腐化するので、ネットで調べたほうがよい。）<br>ただ、サクラエディタは矩形選択やgrepが使いやすいので、併用するのもあり。

## 6. 文字コードについて

【作成中】
日本語を取り巻く文字コードの問題について

## 7. プログラムを書いて動かしてみる

 - [Visual Studio要らずで始める C# ～ Windows向けお手軽ツール開発 （かきかけ） - Qiita](https://qiita.com/kob58im/items/97ef8c65c4cbea68d879)


# 応用編

## A. GUI

【後回し】

## B. コンピュータのアーキテクチャ - CPUと機械語とメモリの話

【構想検討中】
・CPUと機械語・命令コードとメモリ

## C. 組み込みソフト開発

【構想検討中】
・電子回路
・パソコン と 組み込み系（マイコンを中心としたECU）の対比
　・コード領域とRAM領域
　・マイコンとレジスタ
・機械語とC言語
・コンパイル
・motファイル
・ソフトの書き込み

# 参考サイト

- [なぜ大学生はプログラミングが上達しないのか](https://qiita.com/ike_7010/items/b7e016a70ff143722a3c)
- [コマンドプロンプトからC#をコンパイル](https://qiita.com/Stosstruppe/items/bdffc4e133db3abf8961)
- [HTMLファイル作成にも役立つ！サクラエディタの使い方【初心者向け】](https://techacademy.jp/magazine/4722)
- [新人さんに知ってほしい「文字コードのお話」](https://qiita.com/yuji38kwmt/items/b3a7820b4d3b544da4ff)
スケール○○の違いについて

#本記事について
スケール〇〇っていろんな種類があってあまり理解していなかったのでまとめます。

まず以下の四つがあります。

 - スケールイン
 - スケールアウト
 - スケールアップ
 - スケールダウン

#違いについて
##スケールイン
スケールをインする、つまり小さくすることを指しています。
サーバの台数を減らすことがこれに当たります。
##スケールアウト
インの逆でアウトですね。意味も逆で、サーバの台数を増やすことです。
最初は「インだからサーバがインして増えてるんだな！アウトだからサーバが出て行ってるから減ってるんだな！」って勘違いしてました。
##スケールアップ
スケールをアップします。これはサーバの台数ではなく、サーバのスペックを上げることを意味しています。
##スケールダウン
アップの逆です。スペックダウンのことです。
サーバ増減以外にもスケールする方法があることを理解しておかないと、「スケールアップとスケールアウトの違いは？」って聞かれた際に混乱するので注意してください。
フランス人マダムの紅茶をAlexaで入れる

ちょっと何を言っているのか？というタイトルですが、Alexaの定型アクションをこんな風に設定してみたという内容です。

# フランス人マダムの紅茶

さる界隈で流行ってるらしいです（知らんけど）

[フランス人マダムに教えてもらった、世界一おいしいアイスティーの作り方](https://dot.asahi.com/dot/photoarticle/2019080800076.html)

## 教えてもらった、マダム式氷を使わないアイスティーの作り方

1. できればやかんではなく、鍋に2リットルの水を入れ、沸かす。
2. 沸騰したら火を止め、ティーバッグを3包入れてふたをし、21分蒸らす。
3. ふたをはずし、菜箸などでそっとティーバッグを取り出す。
4. 粗熱が取れるまで放っておき、粗熱が取れたらピッチャーやジャグなどに移し変え、冷蔵庫でひと晩冷やす。

## 課題

2.の工程の21分蒸らしを実施するために、Alexaのタイマーを使っていました。
タイマーでは発話が長く、毎回時間を伝えるのがめんどくさいという問題提起があり、少ない発話で紅茶を作れるようにしたいという要望がありました。
（我が家だけの事情だと思います）

# Alexaの定型アクションを設定する

下記画面のようにAlexaの定型アクションを設定しました。

![IMG_0232.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33417/d9f9cc28-bceb-2391-4bf4-7510e7f39cd5.jpeg)

## ポイント

- タイマー機能を定型アクションで設定できない様子だったので、「待機」アクションを使いました
- 「待機」アクションでは、任意の時間設定（21分）が設定できませんでした。選択可能な時間から2つ「待機」を設定して21分の蒸らしを実現しました
- 実行条件を発話後、Alexaがアクション実行を開始したかを教えてくれません。自分でアクションを受け付けたメッセージを「Alexaのおしゃべり」で「承知しましたと言う」と設定しました
- 「シールドアップを再生する」は、「サウンド」から設定しています
- 最後は、「メッセージ」から「アナウンスを送信」を使って任意の言葉（「紅茶ができました」）をしゃべるように設定しました

# Appendix. 定型アクション「目薬」

目薬3種類を5分間隔で点眼するやーつも作りました。

![IMG_0233.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33417/81acfb94-1d5d-7acd-2578-8e306a3f587a.jpeg)
ゼロトラストの基礎知識

### “セキュリティ”の為にみんなが今までやってきた事と、これからすべきことの基礎知識

**ゼロトラストを導入しようとしても境界防御に慣れた多くの人にとってなかなか説明が難しく、ましてや導入のために社内説明（技術者以外の人を含む）をするのは至難の業で苦戦します。
そこで、ゼロトラストを素人の人にも、技術者にも分かり易く説明をするための資料を作成しました。**

**（関連知識）**
**ゼロトラストとは**
“米国国立標準技術研究所（NIST）の定義とその意訳**
https://qiita.com/masaaki-murakami/items/6a7f56079aa95f44119d
**ゼロトラスト / IdaaS + CASB の設計例**
ゼロトラスト　/　“内部の情報漏洩”対策　>>> IdaaS ＋ CASB
https://qiita.com/masaaki-murakami/items/87d9bdc3fc0deb01ffcd
**ゼロトラスト / MDR = EPP+EDR+SOCの設計例**
“外部からの攻撃（身代金、搾取等）”対策【 PC・スマホ 】>>>「MDR = EPP + EDR + SOC」
https://qiita.com/masaaki-murakami/items/0f952c10b17c3dba3815




##セキュリティで「今までやってきた事」と「これからすべき事」
####　(1)今までやってきた事/境界防御
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/24f18d28-2695-4678-5dfc-7e1b1392a538.png)
####　(2)これからすべき事/ゼロトラスト防御
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/432353fc-f419-08a2-b3e0-295c1c7c9a76.png)
###### A. 「Nさんの信用」を担保する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/558202d9-dbf4-3070-e948-0032b2fb5416.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/5c6b231c-cd55-1088-6af8-c601061996d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/d51ed4b7-b677-46a7-6470-3f1e025db92a.png)
###### B. 「クラウドXの信用」を担保する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/564012cb-63e9-8b04-8c2b-97f33a22cb63.png)
###### C. 「信用を裏切られた場合」に備える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/ad3532f7-ea84-4f90-0d2e-cdcfb0d9f813.png)
SQL　データ加工の基礎的な方法Ⅰ

◆DISTINCT（カラム名）
指定したカラム名の重複するデータを除くことができる。

◆四則演算
SELECTで取得するカラムに使用する

例）
price*1.1 消費税を計算する

合計
SELECT SUM(カラム名)

SUMはWHEREと併用ができる

例）
SELECT SUM(price)
FROM purchases
WHERE character_name = "たまご";

たまごの金額の合計取得することができる

◆平均
AVG(カラム名)

AVGはWHEREと併用ができる

例）
SELECT AVG(price)
FROM purchases
WHERE character_name = "たまご";

卵の金額の平均を取得できる

◆データの数を数える
COUNT（カラム名）

通常nullはカウントされないが、nullも含めて
カウントしたい場合は、

SELECT COUNT(*)
FROM parchases;

とすると、全部のデータをカウントする。

例）
SELECT COUNT(price)
FROM purchases
WHERE character_name = "たまご";

たまごのデータの数をカウントできる

◆最大・最小を求める

最大
MAX(カラム名)
最小
MIN（カラム名）

例）
SELECT MAX(price)
FROM purchases
WHERE character_name = "たまご";

たまごの最大金額を選べる

◆データをグループ化する

GROP　BY カラム名

例）
SELECT SUM（price),purchased_at
FROM purchases
GROP BY purchased_at

日付毎にグループ化を行い、日付毎に料金を合計する

◆複数のカラムをグループ化する方法

GROUP BY　カラム名,カラム名

例）
SELECT SUM（price), purchased_at, character_name
FROM purchases
GROP BY purchased_at, character_name;

◆WHEREを使ったグループ化

SELECT　集計関数
FROM テーブル名
WHERE 条件
GROUP BY カラム名,カラム名

①WHEREでカテゴリーのレコードを検索する 
②日付とキャラクターでグループ化する 
③集計関数で集計するという順番になります。

◆HAVING
GROUP BY カラム名 
HAVING 条件

※HAVINGはグループ化したものを更に取り出したいときに
使う。

例）
SELECT SUM（price), purchased_at
FROM purchases
GROP BY purchased_at
HAVING SUM(price)>1000;

1000円より合計が大きいものが日付ごとに算出される
画像を真っ二つにするスクリプトを書いた

#はじめに
AtCoderでPythonの勉強をしていました。
少しずつ書き方を覚えたので、そろそろ実用的なスクリプトを書いてみたいなと思い、自分が必要としているものを作ってみることにしました。

#環境
OS：Ubuntu 20.04LTS
言語：Python3.8.2
Pillowのバージョンは7.0.0です。

#目的・用途
横長の画像を縦半分に分割したいときに使う。
スマホで見開き資料を読むときなんかに活用。

#コード
```python:imagehalf
import glob
from PIL import Image
import os

files = glob.iglob('/home/user/images/*.jpg')

for f in files:
    img = Image.open(f)
    x, y = img.size

    box = img.crop((0, 0, x//2, y))
    title, ext = os.path.splitext(f)
    box.save(title + 'half1' + ext, quality=75)

    box = img.crop((x//2+1, 0, x, y))
    title, ext = os.path.splitext(f)
    box.save(title + 'half2' + ext, quality=75)

    os.remove(f)
```

#コードの説明
ホームディレクトリ上に『images』というディレクトリを作成し、そこを作業用とします。
imagesに格納されている、拡張子が.jpgのファイルを全て検出します。
画像の左上を起点とし、x軸方向の中間座標を取得し、画像を半分に分割します。
半分に分割した画像の左側を、『元のファイル名+half1+拡張子』として保存します。
半分に分割した画像の右側を、『元のファイル名+half2+拡張子』として保存します。
元の画像を削除します。

※注意
スクリプトファイルは、作業用ディレクトリと同階層かつ、ホームディレクトリ上に置くと動作すると思います。
分割する元となった画像ファイルは、ゴミ箱ではなく削除になります。復活できません。

#おわりに
初めて作成したスクリプトなので、書き方やそもそもの環境設定がおかしいかもしれません。
もっとスマートな書き方があれば、ご指摘をお願いいたします。
なお本スクリプトによる責任はご容赦ください。
IQ Bot：ラーニングインスタンスの削除

IQ Botで作成済みのラーニングインスタンスを削除する方法です。

##削除の手順

###1. ラーニングインスタンスタブから、削除したいインスタンスを選択する
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/09564f46-5cf1-f036-8a12-eead4abf200a.jpeg)

###2. インスタンスの詳細画面で、「編集」をクリック

「編集」ボタンが押せない場合は、図の矢印の先にあるトグルの状態を確認してください。

このトグルがオレンジ（プロダクション状態）だと編集ボタンが押せません。
→　その場合は、トグルをクリックしてグレー（ステージング状態）にし、編集ボタンを押します。
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/6ad3d1f2-8709-cd7d-0b09-2b04ed9347f8.jpeg)

###3. 「インスタンスを削除」をクリック
![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/52eec15f-8347-91b3-2112-e4c9348d275f.jpeg)

###4. 確認のために、インスタンス名を入力させる画面が出てきます。
![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/664fce4f-b7c1-aba4-2c45-df151a43bbc8.jpeg)

###5. インスタンス名を入力（画面上でコピペも可能）すると、「はい、削除します」ボタンが押せるようになるので押します。
![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/f5b1d5a3-0985-376b-c282-107d87f6fb9f.jpeg)

###6. 削除完了！

画面右上に、削除が完了した旨のメッセージが表示されます。
![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/1497fcb8-eef8-4793-2500-00c9302636b3.jpeg)


削除の手順は以上です。

##注意事項

ラーニングインスタンスを画面上で削除しても、**<font color=red>削除済みのインスタンスと重複する名前のインスタンスを再作成することはできません。</font>**

データベースからはインスタンスの中身の情報が削除されますが、インスタンス名の情報は削除済みのインスタンスを含めて残るためです。
リモートサーバでcondaを使ってJupyter Notebookを使えるようにする

## はじめに

リモートサーバでの環境構築はローカル環境とはだいぶ違ったので忘れないようにメモ．

### 1. 仮想環境の構築

pipenvの代わりにcondaを使う．

```
$ conda create -n [仮想環境名] python==[バージョン]
```

仮想環境に入ってから2.以降の操作を行う．

```
$ source activate [仮想環境名] 　# 仮想環境に入る
$ source deactivate           　# 仮想環境から出る
```

pip自体をアップデートしておく．

```
$ pip install --upgrade pip
```

### 2. パッケージのインストール

初回のみ以下を実行．

```
$ conda config --append channels conda-forge
```

これによりパッケージのインストール成功率（見つかりやすさ）が上がる．

```
$ conda install [パッケージ名]==[バージョン]
$ pip install [パッケージ名]==[バージョン]　# どうしても見つからない時（非推奨？）
```

### 3. Jupyter Notebookの設定

まずはパッケージのインストール．

```
$ conda install jupyter jupytext
```

以下を順に入力していく．

```
$ ipython

In [1]: from notebook.auth import passwd

In [2]: passwd()
Enter password: [パスワードを入力]
Verify password: [パスワードを再度入力]
Out[2]: 'sha1: [ハッシュ化されたパスワード]'　　# 後から使うのでコピー

In [3]: exit

$ jupyter notebook --generate-config
$ vi ~/.jupyter/jupyter_notebook_config.py
```

viエディタが開くので末尾に以下を追加．

```
# jupyterの設定
c = get_config()
c.IPKernelApp.pylab = 'inline'
c.NotebookApp.ip = '*'
c.NotebookApp.password = 'sha1:[ハッシュ化されたパスワード]'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888

# jupytextの設定
c.NotebookApp.contents_manager_class = 'jupytext.TextFileContentsManager'
c.ContentsManager.default_jupytext_formats = 'ipynb,py'
```

これでJupyter Notebookが使えるようになった．

```
$ jupyter notebook　　# http://[IPアドレス]:8888/ からログイン
```

## 参考文献

[conda コマンドの使い方メモ](https://qiita.com/yasushi-jp/items/7ce0975db7a7e9ac7991)
[リモートサーバでjupyter notebookを起動させローカル環境で使う
](https://qiita.com/syo_cream/items/05553b41277523a131fd)[Pipenvを使ってJupyter Notebookを導入する方法]
(https://qiita.com/SUZUKI_Masaya/items/76b927b9812d77d33e57)
Airflowのマクロがうまく動かない場合に確認すること

# 背景

以前こんな感じの質問を受けた。

```
{{}} の中に書けるマクロがあるかと思いますが、書いてもプリプロセスしてくれなくて。
何かおまじないや、設定追加が必要なものなのでしょうか。
```

これに関してメモ。

# まず、Airflowのマクロとは

#### [Airflow Document# Macros reference](https://airflow.apache.org/docs/stable/macros-ref?highlight=macro)

Airflowのマクロとはテンプレートで挙動する変数
例えば、 `{{ execution_date }}` を呼び出すと、実行時間をPendulumクラスのインスタンスで取得できる。


# 動く場合と動かない場合

ドキュメントにもあるが、このMacro は Jinja Templates内で有効なものである。

例を示す。

動く例↓

```py:動く例
t1 = BigQueryOperator(
    task_id="example",
    sql="./sql/example.sql",
    use_legacy_sql=False,
    destination_dataset_table="pj.mart.example${{ execution_date.strftime('%Y%m%d') }}", # イケる！
    write_disposition="WRITE_TRUNCATE",
    allow_large_results=True,
    time_partitioning={"type": "DAY"},
    dag=dag
)
```

動かない例↓

```py:動かない例

ds = {{execution_date}}.to_date_string # ここでエラー
BigQueryOperator(~略~)
```

Operatorの、とある引数フィールドであればMacroは使用することができる。

# じゃあ、どのOperatorのどの引数でmacro使えるのか？

### [Jinja Templating](https://airflow.apache.org/docs/stable/concepts.html#jinja-templating)


> You can use Jinja templating with every parameter that is marked as “templated” in the documentation. 


ドキュメント見て、 `templated` って書いてある項目ならイケるらしい。


例えば、

### [airflow.contrib.operators.bigquery_operator](https://airflow.apache.org/docs/stable/_api/airflow/contrib/operators/bigquery_operator/index.html)

をみると、`sql` や `destination_dataset_table` に `templated` と書いてあるので macroを使用できることがわかる。
ルート権限の無いCentOSにPython-3.8.5を野良ビルドする

# はじめに
root権限の無いCentOS7.3＆GCC-4.8.5の環境に野良ビルドした[GCC-9.3.0](https://qiita.com/yonedat/items/78baf03597fe2341fbf8)と[OpenMPI-3.1.6](https://qiita.com/yonedat/items/d4a764a9a527364ac954)を基に，今回は，Python-3.8.5を野良ビルドで構築し，さらに並列化のためにmpi4pyを入れたいと思います。

# 準備
Python，OpenSSL，libffiをダウンロードしておきます。

-https://sourceware.org/libffi/
-https://github.com/openssl/openssl
-https://www.python.org/downloads/source/

今回用いたバージョンは，libffi-3.3，openssl-1.1.1g，python-3.8.5です。
Python-3.8.5のビルド自体はlibffiとOpenSSLを事前にビルドしていなくてもできたのですが，pipの際にOpenSSLのエラーが生じます。"pip OpenSSL"などで検索すると色々でてきますが，Python3.7からOpenSSLの新しいバージョンが必要なようです。
また，新しいOpenSSLをインストールすることで，numpyなどはpipで入る様になりますが，mpi4pyはpipの際に”ModuleNotFoundError：No module named ‘_ctypes'”のエラーが生じます。これは，libffiをインストールしておくことで解消する様なのですが，Python-3.8.5をそのままビルドするとlibffiとリンクできないバグがあるようです。

# OpenSSLのビルドとインストール
GCC-9.3.0でOpenSSLをビルドしようとしましたが，なぜかエラーになってしまったので，とりあえずデフォルトのGCC-4.8.5でビルドしました。

```
tar xzvf openssl-OpenSSL_1_1_1g.tar.gz
cd openssl-OpenSSL_1_1_1g
./config --prefix=$HOME/tools/OpenSSL-1.1.1g shared zlib enable-tls1_3
make -j 24
make install
```
OpenSSLのインストール後，.bash_profileに以下を追記します。

```
PATH=$HOME/tools/OpenSSL-1.1.1g/bin:$PATH
LD_LIBRARY_PATH=$HOME/tools/OpenSSL-1.1.1g/lib:LD_LIBRARY_PATH
```

# libffiのビルドとインストール
こちらも，OpenSSL同様にGCC-9.3.0でビルドしようとするとエラーが出てしまいました。おそらくパスの設定などに問題があると思うのですが，後で考えることにします。取りあえず，標準で入っていたGCC-4.8.5でそのままビルドしてみます。

```
tar -zxvf libffi-3.3.tar.gz
mv libffi-3.3 libffi_work
cd libffi_work
mkdir build
cd build
../configure --prefix=$HOME/tools/libffi-3.3
make -j 24
make install
```
libffiのインストール完了後，.bash_profileに以下を追記しました。

```
export LD_LIBRARY_PATH=$HOME/tools/libffi-3.3/lib64:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=$HOME/tools/libffi-3.3/lib/pkgconfig:$PKG_CONFIG_PATH
```
# Python-3.8.5のビルドとインストール
上記でも述べたように，OpenSSLとlibffiを事前にインストールしておかないと，Pythonインストール後のpipの際にエラーが生じるのですが，さらにPythonビルド時にlibffiとリンクできないというバグもあるようです。Pythonの解凍後のトップディレクトリにある，Makefile.pre.in，configure，configure.ac，setup.pyの[4つのファイルに対する修正](https://github.com/python/cpython/pull/20451/commits/62384c971db4a8c309e2a95764f06e7bf601c014)がありましたので，その通りに修正して上書き保存します。
あとは，以下の手順にてインストールを行います。

```
tar Jxfv Python-3.8.5.tar.xz
mv Python-3.8.5 py_work
cd py_work
mkdir build
cd build
../configure --prefix=$HOME/tools/Python-3.8.5 --enable-shared --with-openssl=$HOME/tools/OpenSSL-1.1.1g --with-ensurepip LDFLAGS=-Wl,-rpath,$HOME/tools/Python-3.8.5/lib CC=$HOME/tools/gcc-9.3.0/bin/gcc CPP=$HOME/tools/gcc-9.3.0/bin/cpp CPPFLAGS="-I$HOME/tools/gcc-9.3.0/include -I$HOME/tools/OpenSSL-1.1.1g/include -I$HOME/tools/libffi-3.3/include"
make j 36
make install
```
インストール完了後，以下を.bash_profileに追記します。

```
PYTHON_HOME=$HOME/tools/Python-3.8.5
PYTHONPATH=$PYTHON_HOME/lib/python3.8/site-packages
PATH=$PYTHON_HOME/bin:$PATH
export PYTHON_HOME PYTHONPATH PATH
```
以下の様に，シンボリックリンクを作成してみました。

```
cd ~/bin/
ln -s ~/tools/Python-3.8.5/bin/python3.8 python38
```
また，numpyとmpi4pyも入れてみます。

```
cd ~/tools/Python-3.8.5/bin
pip3 install numpy
pip3 install mpi4py
```
以上で，GCC-9.3.0とOpenMPI-3.1.6をベースにしたPython-3.8.5までを野良ビルドで構築できました。一応，numpyとmpi4pyも問題無く動くようです。
Laravel6.x以上にBootstrapを導入

###Laravel6.x以上にBootsrapを導入
ターミナル上で以下のコマンドを打つ必要あり



```:ターミナル
$ composer require laravel/ui
$ php artisan ui bootstrap
$ npm install && npm run dev
```

###インストールされたか確認
####CSS
publicの下にcssのフォルダが作成されていたら成功！

```css:public/css/app.css

/*!
 * Bootstrap v4.5.2 (https://getbootstrap.com/)
 * Copyright 2011-2020 The Bootstrap Authors
 * Copyright 2011-2020 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 */

```
入ってますね。

####Javascript
publicの下にjsのフォルダが作成されていたら成功！
app.jsというファイルが入っているはずです。


###head情報に読み込むためのコードを埋め込む
```php

<link href="{{ asset('/css/app.css') }}" rel="stylesheet">

```
`asset('ファイルパス')はpublicディレクトリのパスを返す関数。`

ということは、
publicの直下なら
`asset('/app.css')`

publicの下にcssというディレクトリを作ってその中にcssファイルを入れるなら
`asset('/css/app.css')`

```javascript

<script src="{{ asset('/js/app.js') }}"></script>
```
Railsアプリケーションの立ち上げ方【初学者向け】

##新しいRailsアプリケーションを作成
以下のコマンドを実行して、新しいRailsアプリケーション「My App」を作成しましょう。
※もちろん名前は「My App」じゃなくてもいい。

```ryby:ターミナル
# projectsディレクトリの作成
$ mkdir ~/projects

# projectsディレクトリに移動
$ cd ~/projects

# Railsのバージョン5.2.3を用いて、「my_app」を「-d」オプションでMySQLを指定して作成。
$ rails _5.2.3_ new my_app -d mysql

# 「my_app」ディレクトリに移動
$ cd my_app

# 現在のディレクトリのパスを表示
$ pwd
```
上記の操作を行って、/Users/ユーザー名/projects/my_appと表示されれば一旦は成功です。

:warning:最後にエラーが出る場合
もし、アプリケーション作成段階でエラーが生じた場合は、以下のような赤字の文章が表示されます（必ずしも同じ文面ではありません）。
【例】

```ryby:ターミナル
Installing mysql2 0.5.3 with native extensions

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory: /Users/user_name/Programs/web/foobar-repo/vendor/bundle/ruby/2.5.1/gems/mysql2-0.5.3/ext/mysql2

/Users/user_name/.rbenv/versions/2.5.1/bin/ruby -r

(中略)

An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3'` succeeds before bundling.
```
エラーが表示されている場合は、以下のコマンドを実行してください。

```ryby:ターミナル
$ bundle config --delete build.mysql2
$ bundle config --global build.mysql2 --with-opt-dir="$(brew --prefix openssl)"

$ cd ~/projects/my_app
$ bundle install
```
##正しく関連ファイルが読み込まれているか確認
以下のコマンドを実行して、関連ファイルが読み込まれているか確認しましょう。

```ryby:ターミナル
# Users/ユーザー名/projects/my_appと表示されることを確認する
$ pwd

# 関連ファイルが読み込まれていることを確認する
$ bundle install
```
##データベースを作成しましょう
```ryby:ターミナル
# データベースを作成
$ rails db:create

# 以下のような表示がされれば成功
Created database 'my_app_development'
Created database 'my_app_test'
```
##サーバーを立ち上げて確認しましょう
正しくアプリケーションが作成できたか、サーバーを立ち上げて確認しましょう。使用するコマンドは、rails sコマンドです。以下の通りに実行しましょう。

```ryby:ターミナル
# サーバーの起動
$ rails s
```
http://localhost:3000 にアクセスして、Railsのデフォルト画面が表示されれば成功です。
:warning:サーバーを終了させる際はcontrol+c

#####テキストエディタ（VS Code）を開いて、comand+oで作成したファイルを開いてコードを書きはじめましょう！!
AWS の Windows 2019 Server のインスタンスで日本語に変更できない

# はじめに
AWS の Windows Server 2019 で「Add a language」 で日本語を入れても「Windows display language」のプルダウンメニューから日本語が出てこないが、何とかして日本語化したいので調べてみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/3b0cba8e-02ed-f409-6e50-e88e7de01707.png)


通常では、以下の URL を参考に日本語を追加すると言語変更できるのだが、なぜか AWS の Windows Server 2019 のインスタンスではできない(選択できない)
https://blog.trainocate.co.jp/blog/azure_setting_024

# 日本語化手順
AWS の Windows Server 2019  で日本語化する手順の概要はこちら。

1. ISOイメージのダウンロード
2. ISをマウント
3. ISOイメージに入っている言語をインストール
4. [言語変更](https://blog.trainocate.co.jp/blog/azure_setting_024)
5. 再起動

先に「4.」の手順を行ってからでも日本語化できます。
※)「4.」 の手順をしているのにも関わらず「日本語」がでなかったので調べてみたのでした。


## マルチランゲージのパッケージをダウンロード

以下のページのまんなかあたりにある ISO のダウンロードの「here」をクリック。

https://support.microsoft.com/en-za/help/4466511/cannot-configure-language-pack-for-windows-server-2019

<img width="400" alt="ダウンロード先" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/c4512960-489a-6235-ddf1-2ef226680536.png">


直接ダウンロードしたいときは以下のURLでダウンロードできる。
https://software-download.microsoft.com/download/pr/17763.1.180914-1434.rs5_release_SERVERLANGPACKDVD_OEM_MULTI.iso


## ダウンロードした ISO をマウント

ダウンロードしたファイルを右クリックし「Mount」をクリック
<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/ec7a2676-d22e-f2ac-ebd3-f40f2aa547eb.png">


マウントすると、以下のように出てくる。(赤枠で囲ったランゲージをインストール)
<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/77c2df82-3b13-1e5d-59aa-f06629597f72.png">


## インストール

管理者モードでコマンドラインを起動し「lpksetup.exe」を実行
<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1f6219ab-61c1-6459-22b9-d3ca4c47ade8.png">

以下の画面が起動するので「Install display languages」を選択

<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/63ba9589-715d-e7ac-e6de-c47fc4dd73c2.png">


「Browse」で「Microsoft-Windows-Server-Language-Pack_x64_ja-jp」を選択して「Next」をクリックしてインストールする。

<img width="400" alt="日本語の言語パッケージをインストール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1971b6f0-d846-873e-4e87-56d260998edf.png">


インストール完了

<img width="400" alt="インストール完了" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/6f2946dc-8d70-6507-508f-b8e6158589c5.png">


# 言語の設定
「日本語」が出てきた！

<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/a7f67219-5917-a2c7-69ee-80b6c17d03e8.png">

変更して、再起動すると日本語化された
<img width="400" alt="ISOファイルをマウント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/c5854a1c-6918-a9d0-18b1-6ab96b9caf4a.png">



# おわりに
日本語化するとなんかOSの処理速度落ちたような気がするのは気のせいなのか？？
PHP array_key_exists関数

# 目的

- 便利そうな関数だったので自分用に使い方をざっとまとめてみる

# 前提情報

- 下記のサービスを用いて関数の振る舞いを確認した。
    - [https://paiza.io/ja](https://paiza.io/ja)

# 機能

- 指定した文字列が指定した配列に格納されていることを判定する関数である。

# 例

- 下記にarray_key_exists関数の例を記載する。

    ```php
    //配列に文字列が含まれているかを確認する処理、含まれていればtrueが返される。
    array_key_exists(文字列, 配列);
    ```

# 具体例

- 配列`$array`に「str_1」というインデックスが存在していることを判定する処理を記載する。
- 格納されている場合trueを、格納されていない場合falseを返す。

    ```php
    array_key_exists('str_1', $array);
    ```
- 下記の様な処理が実行された場合「str_1の要素が存在します」と出力される。

    ```php
    $array = [
        'str_1' => 1,
    ];

    if (array_key_exists('str_1', $array)) {
        echo 'str_1 の要素が存在します';
    }
    ```

# 参考文献

- [https://www.php.net/manual/ja/function.array-key-exists.php](https://www.php.net/manual/ja/function.array-key-exists.php)
JupyterLabの初期ディレクトリを外付けHDDにマウントしたGoogleDriveにする

JupyterLabを開くと左側のツリーにはCドライブのuser下が表示される。
自分は他のドライブ(D:\)の下に作ったGoogle Drive「バックアップと同期」（※Google drive file streamではない）のフォルダを作業に使うので、初期で表示されるツリーをそこにしたい。

# JupyterLabの初期ディレクトリを変更する
[次の記事](https://qiita.com/k-serenade/items/af8701101fe50397d8aa)を参考にした。
上のリンク先の記事はJupyter notebookのものだが、これをJupyterLabとして使用した。
まずAnaconda promptを起動して,

```
jupyter lab --generate-config
```

とすると、`C:\Users\username\.jupyter\jupyter_notebook_config.py`ってのができた。
これの266行目に

```
## The directory to use for notebooks and kernels.
#c.NotebookApp.notebook_dir = ''
```
というのがあったので、

```
## The directory to use for notebooks and kernels.
c.NotebookApp.notebook_dir = 'D:\GoogleDrive'
```

としたらうまくいった。
jupyter notebookとほぼ一緒。
ベイズ推論でモデルの作り方（概念編）

##ベイズ推論のモデルの作り方

####Pythonで体験するベイズ推論より
[「Pythonで体験するベイズ推論」](https://github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers)

ベイズ推論でどうモデル作るのか！？の概念編です。

[「メールの受信数のベイズ推論」](https://qiita.com/motoyuki1963/items/d4d59d320dbd58a68df6)の時にどうモデルを作ったかを書いてます。

0)まず自分が全知全能の神となって、データセットをつくる方法を想います。

1）ベイジアンモデリングの出発点として重要なのは、「計測したデータにあう確率変数はどれか」と考えることです。データがどのように生成されたかについて考えることです。ポアソン分布は、カウントされているデータを表すのに良い確率変数なので、メールの受信数はポアソン分布からのサンプルだというモデルを立てます。[「ベイズ推論の考え方（２）・・ベイズ推定と確率分布」](https://qiita.com/motoyuki1963/items/904d8c8ecb340a801ebb)


2)次に、「OK、メールの受信数がポアソン分布であるとすると、ポアソン分布に何が必要か？」さて、ポアソン分布にはパラメーター$λ$が必要です。

3)$λ$の値は、何がよいのか、わかっているのか？いや、わからないが、2つの$𝜆$値があり、前半と後半の２種類あると予想した。この変化がいつあるかはわからないから、その変化点を$τ$とした

4)２つの$λ$を表すための確率分布は何が良いだろうか？$λ$は正の実数なので指数分布がよさそうだ。指数分布にもパラメーターがある$α$だ。

5)パラメータ𝛼がいくつかわかっているか？いや、わからない。ここでも$α$の確率分布を考えることもできるが、もうやめよう。$α$の影響は無視できる程度だろうし、$λ$の値に対する信念（「$λ$は途中で変化する」「たぶん１０から３０の間だろう」）はもっているが、$α$の値に対する信念があるわけではないのだ。だから受信数に対する、モデリングで終わりである。
　それでも、$α$も設定しないといけない。$λ$に対する信念「たぶん１０から３０の間だろう」があるので、小さい値を$α$にすると大きな値の確率が高くなるので、よくないだろう、逆もだめそうだから、何が良いだろうか？良い作戦は、$λ$の平均値が観測データの平均値と等しくなるようにするというので、これは[[「ベイズ推論の考え方（３）・・pymc3による実際の計算」](https://qiita.com/motoyuki1963/items/d4d59d320dbd58a68df6)で計算した方法です。

6)$𝜏$が何日目かもアィデアがない。だから$𝜏$は一様分布であるとかんがえた。

この関係を図で表すとこうなる。
![0811beyse.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/21aa6e6d-ad27-cc49-2338-795e33a244b4.jpeg)

ここまで読んでどう感じたか、ほぼほぼ自分の主観的な意志でモデルを作っている。だから自分が全知全能の神となるしかありません。

[「メールの受信数のベイズ推論」](https://qiita.com/motoyuki1963/items/d4d59d320dbd58a68df6)では、この順番でモデルを作ってきたが、逆にすると予測ができるのである。

つまりこの`Python`スクリプトで予測ができます。

```
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

#1. DiscreteUniform（0,80）からサンプリングして、ユーザーの動作が切り替わるタイミングを指定します。
tau = np.random.randint(0, 80)
print(tau)

#2.指数分布 Exp（𝛼）から𝜆1と𝜆2をサンプリングする。。
alpha = 1./20.
lambda_1, lambda_2 = np.random.exponential(scale=1/alpha, size=2)
print(lambda_1, lambda_2)

#𝜏より前の日については、ユーザーの受信したメール数を、ポアソン分布Poi（𝜆1）からサンプリングし後の日をポアソン分布Poi（𝜆2）からサンプリングします。
data = np.r_[stats.poisson.rvs(mu=lambda_1, size=tau), stats.poisson.rvs(mu=lambda_2, size = 80 - tau)]

#結果を描画します。
plt.bar(np.arange(80), data, color="#348ABD")
plt.bar(tau-1, data[tau - 1], color="r", label="user behaviour changed")
plt.xlabel("Time (days)")
plt.ylabel("count of text-msgs received")
plt.title("Artificial dataset")
plt.xlim(0, 80)
plt.legend()
plt.show()
```
結果は、元のデータとは同じになりません。
３回計算を繰り返して予測したグラフを載せましたが、また繰り返しても、いろいろなパターンの予測になります。

このように予測できるということが、後々重要になってくるようです。

![0811predictFigure 2020-08-11 100358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/097c9312-a1a4-1bb4-3b23-65bcc7cac53a.png)
![0811predict_2_Figure 2020-08-11 100358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/b4fcbad1-9093-e0a6-c531-3adc0cc42009.png)
![0811_3_predictFigure 2020-08-11 100358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/2a844e59-1b87-1943-777d-1029f22e8447.png)
【Wordpress】標準テーマの Powered by Wordpress を書きかえる

Wordpressの標準テーマはシンプルで使いやすいですが、企業のウェブサイトで利用する場合など、フッターの「Powered by Wordpress」を削除したい場合が多々あります。

# CSSでパワードバイを非表示にする

これまでは、アップデート時の影響を考慮してテンプレートを直接編集することは避け、追加CSSに以下を記述して非表示にしていました。

```
.powered-by-wordpress {
    display: none;
}
```

# プラグインでパワードバイを書きかえる

上記の方法だと、非表示にするだけ自由に編集はできません。
また、HTML上には Powerd by Wordpressの文字が残ったままになります。

そこで、パワードバイを書きかえるプラグインを作成しました。
[Elvez Edit Powered By（プラグインのダウンロードページ）](https://wordpress.org/plugins/elvez-edit-powered-by/)


<img width="500" alt="screenshot-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38978/4b37bf5e-4159-bc28-eeff-525b8283a8bb.png">

設定画面でテキストとURLを入力すると、パワードバイを書きかえてくれます。
何も設定しない場合は非表示になるので、パワードバイの表記が不要な場合にも対応できます。



プラグインの機能はシンプルですが、書きかえるテキストを保存したり、javascriptに値を渡したりと、いくつか実装で工夫をしています。こういう実装もできるというのがあれば、ぜひ教えてください。


他にも社内で利用しているソースコードの一部を、無料プラグインとして公開しています。
https://elvez.co.jp/wordpress/
使ってみて役に立つと思ったら、ぜひ寄付など応援をお願いします。
ArduinoにおけるATtiny1616とATtiny1617のポート制御

### ポート制御
Arduinoで使える、ATtiny1616とATtiny1617のポート制御についてです。
通常のpinMode,digitalWriteの設定では無くて、直接制御を行いたいと思いまとめました。

### PortA
・PA1をON/OFFする通常の書き方です。

```c++
void setup() {
  pinMode(PIN_PA1, OUTPUT);
  digitalWrite(PIN_PA1, LOW);
  digitalWrite(PIN_PA1, HIGH);
}
void loop() {
}
```

・PA1をON/OFFする方法１、レジスタを読み出してAND/ORする方式

```c++
#define PA1 1
#define LED (1<<PA1)

void setup() {
  PORTA.DIR = PORTA.DIR | LED; 
  PORTA.OUT = PORTA.OUT & ~LED;  
  PORTA.OUT = PORTA.OUT | LED;  
}
void loop() {
}
```

・PA1をON/OFFする方法2、直接ビット操作をする方式

```c++
#define PA1 1
#define LED (1<<PA1)

void setup() {
  PORTA.DIRSET = LED; 
  PORTA.OUTCLR = LED;
  PORTA.OUTSET = LED;
}
void loop() {
}
```

### PortB
・PB1をON/OFFする通常の書き方です。

```c++
void setup() {
  pinMode(PIN_PB1, OUTPUT);
  digitalWrite(PIN_PB1, LOW);
  digitalWrite(PIN_PB1, HIGH);
}
void loop() {
}
```

・PB1をON/OFFする方法１、レジスタを読み出してAND/ORする方式

```c++
#define PB1 1
#define LED (1<<PB1)

void setup() {
  PORTB.DIR = PORTB.DIR | LED; 
  PORTB.OUT = PORTB.OUT & ~LED;  
  PORTB.OUT = PORTB.OUT | LED;  
}
void loop() {
}
```

・PB1をON/OFFする方法2、直接ビット操作をする方式

```c++
#define PB1 1
#define LED (1<<PB1)

void setup() {
  PORTB.DIRSET = LED; 
  PORTB.OUTCLR = LED;
  PORTB.OUTSET = LED;
}
void loop() {
}
```


### PortC
・PC1をON/OFFする通常の書き方です。

```c++
void setup() {
  pinMode(PIN_PC1, OUTPUT);
  digitalWrite(PIN_PC1, LOW);
  digitalWrite(PIN_PC1, HIGH);
}
void loop() {
}
```

・PC1をON/OFFする方法１、レジスタを読み出してAND/ORする方式

```c++
#define PC1 1
#define LED (1<<PC1)

void setup() {
  PORTC.DIR = PORTC.DIR | LED; 
  PORTC.OUT = PORTC.OUT & ~LED;  
  PORTC.OUT = PORTC.OUT | LED;  
}
void loop() {
}
```

・PB1をON/OFFする方法2、直接ビット操作をする方式

```c++
#define PC1 1
#define LED (1<<PC1)

void setup() {
  PORTC.DIRSET = LED; 
  PORTC.OUTCLR = LED;
  PORTC.OUTSET = LED;
}
void loop() {
}
```

### 参考
https://qiita.com/chromia/items/367726f949ecce1a6241
【Excel】ExcelでIMAGE関数を使う

この記事は、Excelでセル内のURLを参照して画像を表示する自作関数の記事です。

#SpreadSheetにあってExcelにない関数
URLを受け取ってセルに画像を表示する

`=IMAGE("URL")`

という関数がGoogle SpreadSheet にはあります。
![IMAGE.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441999/4162f3b8-7875-1cb0-251f-4cc8c77b09b1.png)

同じような機能をExcelでつくってみました。
![IMAGE2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441999/a670cbc8-b44b-ff46-2fa5-2e08013ea965.png)

##どんなときに使うの？
たくさんの商品の管理などをされている方に役立ちます。

シートにサムネイル画像の列をつくって**データの視認性を上げる**と
・商品などを探すスピードがアップ
・色違いの商品の発注ミス低減
といった効果があります。

一方で、画像の縦横比は無視されるのでビジュアル映えする印刷物を作成するには不向きかもしれません。

#ExcelでIMAGE関数を使うには？
標準モジュールに下記コードをコピーペースト。
<details><summary>:grey_question: 標準モジュールがわからない方はコチラ</summary>
① ｛Excel アプリケーション｝>｛開発タブ｝>［Visual Basic］でVBEditorを開く。
　　※開発タブが表示されていない方はご自身でお調べお願いします。
② ｛VBEditor｝>｛プロジェクトのウィンドウ｝>［VBA Project ("ブック名")］>［右クリックメニュー］>［挿入］>［標準モジュール］をダブルクリック
![スクリーンショット 2020-08-11 08.33.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441999/70a0788c-8f74-61c9-0d4f-74f1625f65c9.png)
③　｛コードのウィンドウ｝>［適当な箇所］をクリックしてアクティブ状態にする。VBAコードをコピーアンドペーストする。
![スクリーンショット 2020-08-11 08.34.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441999/b9a4fba3-d0ff-db23-55b4-739060fc85d4.png)
</details>


```VB:qiita.rb
'====================================================================
'サムネイル画像を表示するワークシート関数
'=IMAGE(A1)などでそのセルに画像を表示する
 Function IMAGE(Optional URL = "")
    With Application.ThisCell
    '現在の状態をチェックして負荷軽減に役立てる
    Dim shp As Shape
    For Each shp In .Parent.Shapes
        If shp.Type = msoLinkedPicture Then
            If shp.TopLeftCell.Address = .Address Then
                If shp.name = URL Then
                    IMAGE = ""
                    Exit Function
                End If
            End If
        End If
    Next
    '新しいシェイプ画像をつくる
    If URL <> "" Then
        Set rg = Application.ThisCell
        On Error GoTo NotFound
        Set shp = .Parent.Shapes.AddPicture(URL, True, False, rg.Offset(, 0).Left, rg.Offset(, 0).Top, rg.Offset(, 0).Width, rg.Offset(, 0).Height)
        shp.name = URL
        On Error GoTo 0
        shp.Placement = xlMoveAndSize
        shp.Fill.ForeColor.RGB = RGB(255, 255, 255)
    End If
    End With

    IMAGE = ""
    Set shp = Nothing
    Exit Function
NotFound:
    IMAGE = "Not Found"
    Set shp = Nothing
End Function

Sub btn_DelIMAGE()
    With ActiveSheet
    '現在の画像を探して消す
    Dim shp As Shape
    For Each shp In .Shapes
        If shp.Type = msoLinkedPicture Then shp.Delete
    Next
    End With
End Sub
```

・たとえばのセルに`=IMAGE(A1)`と記述して、A1セルに入れたURLを参照して使いましょう。
・参照せず値を直接入れるときは`=IMAGE("http://example/hoge.png")`など「"(ダブルクォーテーション)"」をお忘れなく。

#このコードの欠点(未解決)
・マウスポインタを重ねて「+」をドラッグして同じ関数で埋める機能が画像シェイプが邪魔で触れなくなる点
→この問題は@takahasinaoki さんによる以下の提案があります。

>Ctrl+6 キーを押してみてください
画像シェイプが非表示になります。
　　　　　↓
再度画像を表示するには、もう一度 Ctrl+6を押します。
https://www.i-skillup.com/lecture/EXCEL/key/2016/c61.php?skey=c_6

・マウスポインタを重ねて「+」をドラッグして同じ関数で埋める機能が画像シェイプが邪魔で触れなくなる点
　　画像のシェイプのみとりあえず削除


・縦横比無視して配置する点


一旦これにて記事は閉じます。
Excelでセル内のURLを参照して画像を表示する自作関数の記事は以上です