OmniAICreator/Qiita-1.07M huggingface dataset:
【005_ケプラー予想】コマ大数学科

# 【005_ケプラー予想】コマ大数学科
## 最密度充填問題，パッキングの問題
>直径5cmの缶は縦10cm，横502.5cmの枠に何本入るか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/f8b8c260-3947-282e-bd39-157fa5194701.png)


```latex
\begin{tikzpicture}
  % ==階段，放物線，
  % 線を引く
  \\
  \draw [very thick] (0,0) coordinate (O) rectangle (15,2) coordinate (B);
  \coordinate (A) at (15,0);
  \coordinate (C) at (0,2);
  \draw [very thick] (14.5,2.5) coordinate (O1) circle (0.5);
  \draw [dashed](0.5,0.5) circle (0.5);
  \draw [dashed](1.5,0.5) circle (0.5);
  \draw (0,0) rectangle (0.2,0.2);
  \draw (0,1.8) rectangle (0.2,2);
  \draw (14.8,0) rectangle (15,0.2);
  \draw (14.8,1.8) rectangle (15,2);
  \draw (A).. controls ($(A)!.2!(B)!10pt!270:(B)$) and ($(A)!.8!(B)!10pt!270:(B)$) .. (B) node [midway, sloped, fill=white] {$10$cm};
  \draw (O).. controls ($(O)!.2!(A)!15pt!270:(A)$) and ($(O)!.8!(A)!15pt!270:(A)$) .. (A) node [midway, sloped, fill=white] {$502.5$cm};

\end{tikzpicture}
```
Pardot のリード生成 (Salesforce Classic) ⇒ Pardot のランディングページの使用

１．Pardot でランディングページをホストする利点は何ですか?
２．ランディングページにカスタムレイアウトテンプレートを作成するのはどのような場合ですか?
３．Pardot でドラッグアンドドロップ操作のランディングページビルダーを使用する利点の 1 つに挙げられるのはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/3d6b6ba2-0baa-1bca-01b2-da92d7d6480f.png)
Pythonで学ぶアルゴリズム　第18弾：並べ替え（スタックとキュー）

# #Pythonで学ぶアルゴリズム< スタックとキュー >

##はじめに
基本的なアルゴリズムをPythonで実装し，アルゴリズムの理解を深める．
その第18弾としてスタックとキューを扱う．今回も並べ替えのカテゴリとしているが，スタックとキューは次回の並べ替え（ヒープソート）との比較のため学ぶのであり，決して並べ替えアルゴリズムということではないことを述べておく．

##スタック（stack）
データの格納されたリストにおいて，末尾(最後に入れたもの)から取り出すこと．
スタック(stack)は積み上げるという意味で，その名前の通りである．積荷におけるイメージとリストでのイメージの図を次に示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/9370cfcf-cc67-9fa8-2259-736ac02dc73d.png)

##キュー（queue）
データの格納されたリストにおいて，先頭(先に入れたもの)から取り出すこと．
キュー(queue)は「列」という意味で，その名前の通り入れたものは反対から出てくるというイメージである．先ほどと同様に積荷におけるイメージとリストでのイメージの図を次に示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/ad678981-c97e-cd1a-c2e7-2d89b46c7f68.png)
また，図に示すように，キューにおいてはデータの格納，取り出しに対して，エンキューとデキューという名称がつけられている．


##スタックの実装
以下にスタックのコードとその出力を示す．

#####コード
```python:stack.py
"""
2021/01/12
@Yuya Shimizu

スタック(stack)
"""

List = []

List.append(3)         #stackに[3]を追加
List.append(5)         #stackに[5]を追加
List.append(2)         #stackに[2]を追加

print(List)

temp = List.pop()     #stackから取り出し
print(f"\n取り出し: {temp}\n")
print(List)

temp = List.pop()     #stackから取り出し
print(f"\n取り出し: {temp}\n")
print(List)

List.append(4)         #stackに[4]を追加
print(f"\n追加: 4\n")
print(List)

temp = List.pop()     #stackから取り出し
print(f"\n取り出し: {temp}\n")
print(List)
```

#####出力
```
[3, 5, 2]

取り出し: 2

[3, 5]

取り出し: 5

[3]

追加: 4

[3, 4]

取り出し: 4

[3]
```

##キューの実装
以下にキューのコードとその出力を示す．

#####コード
```python:queue_program.py
"""
2021/01/12
@Yuya Shimizu

キュー(queue)
"""
import queue

q = queue.Queue()

q.put(3)                #キューに[3]を追加
q.put(5)                #キューに[5]を追加
q.put(2)                #キューに[2]を追加

print(q.queue)

temp = q.get()      #キューから取り出し
print(f"\nデキュー: {temp}\n")
print(q.queue)

temp = q.get()      #キューから取り出し
print(f"\nデキュー: {temp}\n")
print(q.queue)

q.put(4)                #キューに[4]を追加
print(f"\nエンキュー: 4\n")
print(q.queue)

temp = q.get()      #キューから取り出し
print(f"\nデキュー: {temp}\n")
print(q.queue)
```

#####出力
```
deque([3, 5, 2])

デキュー: 3

deque([5, 2])

デキュー: 5

deque([2])

エンキュー: 4

deque([2, 4])

デキュー: 2

deque([4])
```
キューに関しては，Pythonにqueueというモジュールが用意されており，Queueクラスを使うことで，putメソッドすなわちエンキュー，getメソッドすなわちデキューを実装することができる．注意としては，``queue.py``という名前ではqueueモジュールが読み込めないことである．

##感想
今回はスタックとキューについて学んだ．直接，並べ替えを学んだわけではないが，データの取り扱いについて，新たなキューというものを知った．また，スタックにおいては，``pop()``を再び扱い，``pop()``の使い方にも慣れて気がする．次回のヒープソートで，今回学んだことよりも優れた方法が学べるということで楽しみである．

##参考文献
Pythonで始めるアルゴリズム入門　伝統的なアルゴリズムで学ぶ定石と計算量
　　　　　　　　　　　　　　　　　　　　　　　　 増井 敏克　著　　翔泳社
【初心者向け】Pythonで作成したライブラリをPyPIに登録する方法

# はじめに
ブログの自動投稿に興味があったのだが、Pythonには使い勝手のいいライブラリがなかったので自作した。せっかくなら`pip install hogehoge`てやりたいのでその方法についてまとめてみた。

# 環境
- Mac OS Big Sur 11.1
- Python 3.8.2
- pip 20.3.3
- Pipenv 2020.11.15
- twine 3.3.0

# 忙しい人向け
[PyPI](https://pypi.org)ってところに登録するといいよ！
アップロードにはtwineを使ってね！

# 手順
以下はPipenvを使用時のコマンドになりますが[参考](#参考)を見るなりして適宜置き換えてください。

## 0. 前提
- [PyPI](https://pypi.org)、[Test PyPI](https://test.pypi.org)でアカウントを作成していること。
- LICENSE、README.md、setup.pyなどを準備していること。もしまだであれば[こちら](#参考)を参考に作成してください。

## 1. twineのインストール
PyPIへのアップロードは`twine`を使用するため予めインストールしておきます。

```python
pipenv install --dev twine
```

## 2. 登録ファイルの作成
以下を実行すると`dist/`以下に`.whl`と`.tar.gz`が作成されます。

```python
python setup.py sdist bdist_wheel
```

## 3. Test PyPIへアップロード
本番のPyPIへアップロードする前にTest環境のPyPIが使用できます。
絶対に使わなければいけないってことはないですが、慣れないうちは使用する方がいいでしょう。

```python
python -m twine upload --repository testpypi dist/*
```
これでTest PyPIへのアップロードが完了しました。
せっかくなのでTest PyPIからインストールを行なってみましょう。

```python
pipenv install --pypi-mirror https://test.pypi.org/simple/ <PACKAGE_NAME>
```

## 4. PyPIへアップロード
Test PyPIへアップロードしたライブラリの動作確認ができたら最後は本番のPyPIに登録しましょう。誰かに審査されるわけではないのでお気軽にどうぞ。

```python
python -m twine upload dist/*
```
これで本番のPyPIへアップロードが完了しました。
最後に例のやつを試して終了です。お疲れさまでした。

```python
pipenv install <PACKAGE_NAME>
```


# 参考
[Packaging Python Projects](https://packaging.python.org/tutorials/packaging-projects/)
【Rails】created_atを使って「〇〇分前」と表示したい！

# 概要
本記事ではRailsのcreated_atで作成日時を表示する際に、従来の時間表記ではなく「〇〇分前」のように表示する方法を記載しています。
完成イメージは以下の通りです。
![スクリーンショット 2021-01-12 22.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864210/42878dc3-ffdd-d393-8024-61a6ac7f5286.png)


# 開発環境
* Ruby 2.6.5p114
* Rails 6.0.3.4

# 手順

**① 日本語設定をする**

まずは、日本語設定をします。
configのapplication.rbファイルに以下を記述してください

```config/application.rb
config.i18n.default_locale = :ja
```

**② 日本語のyamlファイルを作成する**

次に、どのような日本語表記にするかyamlファイルに設定を書いていきます。
日本語に関するja.ymlはRailsにデフォルトで入っていないため、以下を参考に作成してください。
ja.ymlファイルはconfig/locales配下に作成します。

```ruby:config/locales/ja.yml
ja:
  datetime:
    distance_in_words:
      about_x_hours:
        one: 約1時間
        other: 約%{count}時間
      about_x_months:
        one: 約1ヶ月
        other: 約%{count}ヶ月
      about_x_years:
        one: 約1年
        other: 約%{count}年
      almost_x_years:
        one: 1年弱
        other: "%{count}年弱"
      half_a_minute: 30秒前後
      less_than_x_seconds:
        one: 1秒以内
        other: "%{count}秒未満"
      less_than_x_minutes:
        one: 1分以内
        other: "%{count}分未満"
      over_x_years:
        one: 1年以上
        other: "%{count}年以上"
      x_seconds:
        one: 1秒
        other: "%{count}秒"
      x_minutes:
        one: 1分
        other: "%{count}分"
      x_days:
        one: 1日
        other: "%{count}日"
      x_months:
        one: 1ヶ月
        other: "%{count}ヶ月"
      x_years:
        one: 1年
        other: "%{count}年"
```

**③ ビューで表示する**

最後にビューで表示します。
表示する際は、Railsが用意してくれている`time_ago_in_words`メソッドを使用します。
引数には作成日時を渡します。

```erb:index.html.erb
<p>#{time_ago_in_words(post.created_at)}前にアウトプット</p>

※postの部分は適宜書きかえてください
```

<br>
以上で実装が完了しました！
表示方法を自分好みに修正したい時は`ja.yml`にて修正してください。
SwiftUIのViewを返すプロパティをスマートに定義する

## 異なるViewを返すプロパティ

異なるViewを返すプロパティを定義する際、Viewの型が異なることから無理やりAnyViewなどでWrapする方法が思い浮かびますがどうもスマートではありません…

```swift
var viewProp: AnyView {
    if state {
        return AnyView(Rectangle())
    } else {
        return AnyView(Circle())
    }
}
```

これは`ViewBuilder`attributeを利用することで解決出来ます。
この場合、return文も必要ありません。

```swift
@ViewBilder
var viewProp: some View {
    if state {
        Rectangle()
    } else {
        Circle()
    }
}
```

上記の例だと`ViewBuilder.buildEither`によって単一の型として解決されるために、このような記法が可能になります。

## 条件に合った時だけViewを返すプロパティ

異なるViewを返すプロパティを定義する際、非表示用にEmptyViewを返し、表示用のViewを返す処理を書くことを思い浮かべますがこれらは型が異なるのでAnyViewでWrapするしかありません。
やはりスマートではありません…

この例でも`ViewBuilder`attributeが利用出来ます。

```swift
// Before
var viewProp: AnyView {
    if state {
        AnyView(Rectangle())
    } else {
        AnyView(EmptyView())
    }
}

// After
@ViewBilder
var viewProp: some View {
    if state {
        Rectangle()
    }
    // 条件に当てはまらない時はEmptyViewになる
}
```

上記の例だと`ViewBuilder.buildIf`によって単一の型として解決されるために、このような記法が可能になります。
『OpenCVによる画像処理入門』8章

# 2値画像処理

グレースケール画像やカラー画像から、2値画像（白黒画像）を取り出す処理を2値化処理という。
2値化処理は、ある画像から注目する領域の抽出や、不要な部分を除去するマスクの生成に用いられる。

2値化処理の単純な方法は__閾値処理__で、一定の閾値までは黒、閾値を越えたら白、というように対応づける。

入力画像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/b70c1f6f-5f39-0a94-a2d9-669fceed4f41.png)

閾値(thresh)=100
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/91a081cc-1024-75d4-f3f4-a1087c4426fc.png)

## マスク処理
マスク処理は、不必要となる部分を完全に消去し、必要な領域のみを抽出する処理。
応用例については次章。

## 膨張・収縮処理
風景などを撮影した画像の画素値は一様でなく、ムラがある事が多い。
ムラがある画像に対して2値化処理を行った場合、多くのノイズが入ってしまうため、膨張・収縮処理を施す。
（ノイズ例：微小な孔が開く、複数に分断される、点が残る）

__膨張処理__：注目画素または近傍に白画素があれば、注目画素を白にする。
__収縮処理__：注目画素または近傍に黒画素があれば、注目画素を黒にする。

膨張処理を繰り返すと、分断した領域を結合できる（繰り返しすぎると真っ白になる）
収縮処理を繰り返すと、小さな領域は消去され、最大領域だけ残すことができる（繰り返しすぎると真っ黒になる）

膨張（8近傍、3回繰り返し）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/dd4f4465-03ff-81f0-4899-ba33c693e9ac.png)
収縮（8近傍、3回繰り返し）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/2d88ca32-d7c7-6d0d-f705-0dc0838a0376.png)

膨張・収縮処理は、単独では一方のノイズが増大するため、組み合わせて使用する。
膨張をn回実行した後で収縮をn回実行する処理を__オープニング__、収縮をn回実行した後で膨張をn回実行する処理を__クロージング__と呼ぶ。

オープニング5回、クロージング5回(8近傍)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/23f6795e-bab7-137c-36b7-e58d2334c209.png)

## 形状特徴パラメータ
2値画像内の繋がった要素のことを__ブロブ__と言い、輪郭形状を読み取ることで物体の距離や姿勢の情報が得られる。
ブロブを包含する矩形を__外接長方形__と言い、長方形の2辺の比（縦/横）のことを縦横比という。

ブロブの形状特徴の表し方（形状特徴パラメータ）
・面積：ブロブの大きさを表す。具体的にはブロブ内の白い画素数。
・周囲長：ブロブの輪郭の長さ。
・円形度：対象がどれほど円形に近いかを示すパラメータ

##ラベリング処理
2値画像内に複数のブロブが存在する場合に、各ブロブに一位の識別子を付けて識別する処理を__ラベリング__と呼ぶ。
ラベリングにより、それぞれのブロブを抽出して個別に扱えるようになる。
laraval8 + vue.js2.6で、親子(parent-child)component間の通信について(propsや$emitを使わない場合=>.nativeの使い方)

###この本を書いたきっかけは？何についての記事？
「これから始める、Vue.js実践入門」（山田祥寛/著、SBクリエイティブ株式会社/発行）のリスト4-16あたりをlaravel8のプロジェクト内でやりたかったので、コードを少し改変してみた。
###参考にしたサイトなど
前に挙げた本以外、忘れてしまいました。思い出したら追記するかもです。
###前置きはこれくらいにして
```javascript:MyComponent3.vue
<template>
  <div>
    <div>
      <p>現在値：{{ current }}</p>
    </div>
    <mycomponent4 step="1" v-on:click.native="onclick"></mycomponent4>
    <mycomponent4 step="2" v-on:click.native="onclick"></mycomponent4>
    <mycomponent4 step="-1" v-on:click.native="onclick"></mycomponent4>
  </div>
</template>

<script>
import mycomponent4 from './MyComponent4.vue';
export default {
components: {mycomponent4},
 data: function () {
    return {
        current: 0,
    }
 },
  methods: {
    onclick: function (e) {
      this.current += Number(e.target.childNodes[0].nodeValue);
      //console.log(e);
      console.log(Number(e.target.childNodes[0].nodeValue));
    },
  },
};
</script>
```
.nativeってのがミソで、これがないと動きません。
e.target.childNodes[0].nodeValueってのがボタンに表示されてる値を指すわけですが、
これが正確にどう指定すればよいかはconsole.log(e);してからchromeのdevtoolでeの中身をポチポチ開いていった後に、右クリックで「Copy property path」すると間違いがなくて安心です。


```javascript:MyComponent4.vue
<template>
<button type="button" v-on:click="onclick">{{ step }}</button>
</template>
<script>
export default {
 data: function () {
    return {
        current: 0,
    }
 },

    props: ['step'],
    methods: {
        onclick:function() {
            this.$emit('plus', Number(this.step));
        }
    }
};
</script>
```
```javascript:app.js
require('./bootstrap');
import Vue from 'vue'
import App3 from './components/MyComponent3.vue'
const app3 = new Vue({
    el: '#app3',
    components: {
         App3
    },
});
```
Controllerとか、実際の画面の動きとかはhttps://qiita.com/tarako2/items/942b1c5d9af9bb4bf946
と一緒なので参考にされてください。
ここまで見ていただいてありがとうございました。何かお役に立てれば幸いです。
【Pyhton】MacOS11でtkinterが動かない問題を解消したい


最近MacをBigSurにメジャーアップデートをしたらPythonがGUI系のモジュールが動かなくなったので直した。

brewのPythonは3.9.1にできなかったので公式からインストールする。

[Python Release Python 3.9.1 | Python.org](https://www.python.org/downloads/release/python-391/)

最新のMacじゃないのでIntel版でインストール

 [macOS 64-bit Intel installer](https://www.python.org/ftp/python/3.9.1/python-3.9.1-macosx10.9.pkg) 

公式のGUIインストーラでインストールされるPythonは以下に配置されているので
バージョンを確認して3.9.1になっていればOK

```
$ /usr/local/bin/python3 --version                                                                            
Python 3.9.1
```

venvとかを使っている場合は適宜エイリアスなどでPATHを変えるといいと思う。

#development/Python
Vue.jsのv-ifで画面に表示される内容を切り替える


# 初めに
前回に引き続きVue.jsで学んだことのアウトプットとして投稿します。

# v-if

js ファイルにある `mode` の値を変えることで画面に表示する内容を切り替えることができる。
`key="night-comment"` や `key="mornig-comment"` により、ボタンを押した後、テキスト欄にそのまま文字が残らないようにする。これは以下のように公式ドキュメントにある方法を利用した。


> 一意の値を持つ key 属性を追加する

`v-on` ディレクティブにより js ファイルにあるメソッドを呼び出し `mode` の値を変える。

```html
  <div id="app" v-bind:style="styles">
    <template v-if="mode === 'night'">
      <input placeholder="夜の一言" key="night-comment">
    </template>
    <template v-else>
      <input placeholder="朝の一言" key="mornig-comment">
    </template>
    <button >コメントする</button>
    <br>
    <button 
      v-on:click="toggle"
      v-if="mode === 'night'"
      v-bind:style="buttonStyles">朝へ</button>
    <button
      v-on:click="toggle" 
      v-else
      v-bind:style="buttonStyles">夜へ</button>
  </div>
```

`v-bind` ディレクティブによりスタイルも切り替える。`data` の中に `styles` や `buttonStyles` を入れ、html ファイルの `v-bind` と連携させる。

```js
var app = new Vue({
  el: '#app',
  data: {
    mode: '',
    styles: {
      backgroundColor: 'rgb(240, 210, 220)',
      padding: '50px'
    },
    buttonStyles: {
      margin: '30px 0px'
    }
  },
  methods: {
    toggle: function() {
      if (this.mode === 'night') {
        this.mode = 'mornig';
        this.styles.backgroundColor = 'rgb(240, 210, 220)'
      } else {
        this.mode = 'night';
        this.styles.backgroundColor = 'rgb(10, 10, 30)'
      }
    }
  }
})
```


## 動作結果

- 画面更新後


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/ee1efd08-e442-03e4-df11-a4a1277638a6.png)


- 夜へボタン押下後


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/198c8bfe-ffc6-6cfc-4c41-e1e24aca5b1b.png)


- 朝へボタン押下後


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/f16de5b9-f1ed-b1f2-f2ca-3a8b7b2fce35.png)


# 参考記事
- Vue.js 公式ドキュメント  
https://jp.vuejs.org/v2/guide/conditional.html#v-else-if
アドベントカレンダー36日目：SREを読んでみた「効果的なトラブルシューティング」編④

今回は実践編の最後と実験により否定的な結果がもたらされた場合のアプローチについて、見ていきます。

## 実践
### テストと対応
潜在的な問題をある程度絞った後は、根本原因の調査を行う必要があります。
テストを行う際に注意する点、観点は次の通りです。

* 理想的なテストは問題の原因の仮説を受け入れ、その他の仮説を否認するものです。現実的にはそうなるようにするのは、難しい場合があります。
* 明らかなことから始める。システムに与える影響を考慮しながら、可能性の高い順番にテストを行う。
* 混乱を招く要素により、実験の結果を誤って、認識することがある。（例：特定のIPアドレスを許可するファイアウォール下でテストした場合、自分のワークスペースからは失敗するかもしれない）
* テストが環境に与える影響が大きい時、後のテスト結果が変わる場合がある。
* 結果が決定的なテストだけでなく、示唆的な結果しか与えてくれないテストもある。その場合、妥協が必要な時もある。

#### テストを行うときのドキュメント
* 考えていること、実行したテスト、得られた結果をはっきりと記録する。
* 出来事を正確に記述し、同じステップを繰り返さないようにする。

## 否定的な結果のすばらしさ
否定的な結果とは、実験の結果、期待した結果が得られなかったときの結果のことです。
以下では、否定的な結果へのアプローチを見ていきます。

#### 否定的な結果は、無視したり過小評価するべきではない
はっきりとした否定的な結果は、設計上の問題に回答を与えてくれる場合があります。（2つの案の内、一方に進むことで、もう一方が優れていることを知る）

#### 否定的な結果が出た実験は決定的なもの
プロダクションや設計領域、既存のシステムのパフォーマンスの限界について、確実なことを示します。そして、それらの実験は、独自の設計や実験を行う価値があるかどうかを他者へ伝えることができます。

#### ツールや方法論は、実験そのものよりも長く残り、詳細な作業の助けとなる
最初の結果は、望ましくない結果だったとしても、そこから恩恵を受けるものは多くあります。
また、繰り返し行われる実験の為のツールを作ることは、そのツールにより良い結果が得られなかったとしても、次のアプリケーションでは異なる結果を生むかもしれません。

#### 否定的な結果を公開することは、IT業界のデータ駆動の文化を改善することになる
否定的な結果を説明することでメトリクスにおけるバイアスを下げ、不確実性を慎重に受け入れる例を他者へ示せるようになります。
すべてを公開することで他社にも同じ行動をとることを推奨することになります。

#### 結果を公開する
実験の結果に自分が関心を持っているなら、他人も関心を持っている可能性は高いです。
失敗した結果は、報告することを避けたくなりますが、それはよく考えてリスクをとった結果の一部であり、十分に設計された実験にはメリットがあります。反対にあまり失敗について、言及されていない結果は、懐疑的に見る必要があります。

### 対策
問題の原因が特定できたら、それが本当に原因であるかを確認するために、実際に問題を起こしてみることをするといいですが、難しい場合もあるかもしれません。
その場合は、問題の推定原因しか見つけられないことになります。

また、問題を引き起こした要因を見つけられたら、ポストモーテムを書く必要があります。（システムで生じた問題、問題を突き止めた過程、問題解決方法、再発防止策）

## まとめ
* テストを行う際は、思考の過程などもメモを残し、同じ作業の繰り返しをしないようにする。
* 否定的な結果を無視しない。すべてを公開する。

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　142-143
【初心者でもわかる】1行で複数の値が書けるCSSプロパティ一覧と書き方

#どうも7noteです。transformを複数設定する時など、複数指定する時の方法まとめ

初心者の頃にすぐに書き方を忘れてしまったので、忘れてもいいようにまとめます。
アルファベット順で並べています。


## `background`➡半角スペース[ ]とスラッシュ[ / ]を使う

```style.css
div {
  background: #333 url('background.png') no-repeat border-box left top / contain fixed content-box;
  /* 色　画像　繰り返し　基点　位置左右 位置上下　/ サイズ　スクロール位置　背景領域*/
}
```

**サイズを入れるときにはスラッシュ[ / ]**を入れる。

## `background-xxx`➡カンマ[ , ]でつなぐ

```style.css
div {
  background-image: url("./images/hoge.png"), url("./images/fuga.png");
  /* 背景1, 背景2, 背景3・・・ */
}
```
[hoge.png]が前面、 [fuga.png]が背面になります。
`background-xxx`系は基本的に**カンマ[ , ]でつなぐ**ことができます。

・background-color
・background-image
・background-repeat
・background-origin
・background-position
・background-size
・background-attachment
・background-clip


## `border`➡半角スペース[ ]でつなぐ

```style.css
div {
  border: 1px #ff0000 solid;
  /*太さ 色 種類 */
}
```
※順不同


## `box-shadow`➡半角スペース[ ]でつなぐ

```style.css
div {
  box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
  /* 左右位置 上下位置 ぼかし 広がり 色 内側 */
}
```
「左右位置 上下位置」の2つがあれば動かせます。


## `font`➡半角スペース[ ]とスラッシュ[ / ]を使う

```style.css
div {
  font: italic bold 80%/150% "ＭＳ Ｐゴシック";
  /* スタイル 太さ サイズ / 行の高さ フォントの種類 */
}
```
※スモールキャピタル（font-variant）は省略しています。

行の高さ（line-height）を入れる前にはスラッシュ[ / ]を入れる。

## `font-family`➡カンマ[,]でつなぐ

```style.css
div {
  font-family: Georgia, serif;
  /* フォント１, フォント2, フォント3 ・・・ */
}
```
左側のフォントが優先的に効きます。フォント１がなければフォント2。フォント２がなければフォント3・・・と続きます。



## `margin`・`padding`➡半角スペース[ ]でつなぐ

```style.css
div {
  /* 上下 左右 */
  margin: 10px 20px;
  padding: 10px 20px;

  /* 上 左右 下 */
  margin: 10px 20px 50px;
  padding: 10px 20px 50px;

  /* 上 右 下 左 */
  margin: 10px 20px 30px 40px;
  padding: 10px 20px 30px 40px;
}
```


## `transform`➡半角スペース[ ]でつなぐ

```style.css
/* 例） **位置変更**と**回転**を同時に書く */
.trans {
  transform: translate(-50%, -50%) rotate(45deg);
}
```

`translate`と`rotate`の間に半角スペースを空けることで複数指定することができます。

## まとめ

`margin`  `padding`とかはよくつかうので、覚えられますが忘れやすいものも多いので書き方をまとめました。
参考になれば幸いです。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
Salck APIとを使用してC#でテキストファイルを投稿する

# はじめに
C#でSlak APIを利用する際に、  
Webhookを使用した記事を用いたメッセージ投稿のプログラムは 
よくみるものの、 
Tokenを使用したプログラムはあまり見られなかったので、 
自分への備忘録も兼ねて記事を書きます。
# Slack APIについて
基本は使用したいAPIの公式ドキュメントを見てください。
そこに全ては書いてあります。
今回は"files.upload"を使用するので、
以下URL先のドキュメントをしっかりよむ。
https://api.slack.com/methods/files.upload
# C#側のコード
以下、今回紹介するソース全文

```C#
//外部ファイルより、投稿したいChannelとTokenを取得
string channel = System.Environment.GetEnvironmentVariable("Channel");
string token = System.Environment.GetEnvironmentVariable("Token");

//パラメータにTokenとChannelをセット
var parameters = new NameValueCollection();
parameters["token"] = token;
parameters["channels"] = channel;

var client = new WebClient();
client.QueryString = parameters;

byte[] responseBytes = client.UploadFile("https://slack.com/api/files.upload",Filename);

//結果を取得
String responseString = Encoding.UTF8.GetString(responseBytes);

ReturnValue Return = JsonConvert.DeserializeObject<ReturnValue>(responseString);

Console.WriteLine(Return);
```

```C#
class ReturnValue
{
  public bool ok { get; set; }
  public String error { get; set; }
  public SlackFile file { get; set; }
}
        
class SlackFile
{
 public String id { get; set; }
 public String name { get; set; }
}
```

## 外部ファイルより値の取得
System.Environment.GetEnvironmentVariable()では
外部ファイル（今回はAzure Functionで作成したので”localsetting.json”から）
TokenとChannel（正確にはChannelID）から値を引っ張ってきます。
Tokenの取得は以下、
https://dev.classmethod.jp/articles/search-messages-with-slack-api/
ChannelIDの取得は以下を参考にするとわかりやすい
https://qiita.com/unsoluble_sugar/items/603e51106d9632f3ea4f

```C#
//外部ファイルより、投稿したいChannelとTokenを取得
string channel = System.Environment.GetEnvironmentVariable("Channel");
string token = System.Environment.GetEnvironmentVariable("Token");
```

## APIに渡す引数のセット
次に、NameValueCollection()をもちいて、
先ほど取得した
"parameters"にTokenとchannels(Slack APIに渡す引数)をセットする。

```C#
//パラメータにTokenとChannelをセット
var parameters = new NameValueCollection();
parameters["token"] = token;
parameters["channels"] = channel;
```

## クエリを作成し、WebClientで送信する
WebClientのクエリとして"parameters"をセットした後に、
"client.UploadFile"でSlack APIにクエリを投げかけます。
(変数"Filename"に投稿したいファイルパスが格納されています)

byte[] responseBytes にはSlack APIからの返信がバイトで格納されます。

```C#
var client = new WebClient();
client.QueryString = parameters;

byte[] responseBytes = client.UploadFile("https://slack.com/api/files.upload",Filename);
```

## 結果をコンソール出力
最後に、送信結果をコンソールに出力すると、便利かも。
(okのパラメータがTrueなら投稿できているはず)

```C#
//結果を取得
String responseString = Encoding.UTF8.GetString(responseBytes);

ReturnValue Return = JsonConvert.DeserializeObject<ReturnValue>(responseString);

Console.WriteLine(Return);
```

# 最後に
今回で、Slcak APIについて色々わかってきたので、
他も触っていきたいと思う今日この頃
またしてもFiddleの利用中にGCにメモリ領域を回収されてまった話

Fiddleの構造体のメンバーを何回も呼び出すと値が変わってしまうことがあります。
意気揚々としてisssue報告をしたのでしたが…

下、1000回呼び出すとだいたい値が変化する…

```ruby
require 'fiddle/import'

module A
  extend Fiddle::Importer
  S = struct [
    'int8_t* hoge',
    'int8_t* fuga']
end

s = A::S.malloc
s.hoge = [*1..10].pack('c*')
s.fuga = [*1..10].reverse.pack('c*')

a1 = s.fuga[0,10].unpack('c*')

1000.times do
  s.fuga[0,10].unpack('c*')
end

b1 = s.fuga[0,10].unpack('c*')

if a1 == b1
  puts "OK"
else
  p a1, b1
end
```

ところが、これはバグではなく、文字列がGCによって回収されてしまうのだそうです。
以前にも[Fiddle::Closure::BlockCallerがGC回収されてしまう記事](https://qiita.com/kojix2/items/aeb496ec9b31b2cb4e7d)を書きましたが、これも全く同じパターンでして、

```ruby
s.hoge = [*1..10].pack('c*')
s.fuga = [*1..10].reverse.pack('c*')
```

この `=` の右側の文字列は、何の変数にも代入されていないので、無慈悲にもGCに回収されてしまうのです。
回避策としては

```ruby
s.hoge = memo1 = [*1..10].pack('c*')
s.fuga = memo2 = [*1..10].reverse.pack('c*')
```

のように変数に入れておくというのがあります。

FFIを利用してプログラミングを行う際には、よほどGCに注意しなければならないということを再確認しました。

この記事は以上です。
多相バリアントを使って構文木の定義を使いまわす

抽象構文木（AST）みたいなものを作っていると、構文木としては同じ構造なのだけど、各ノードに付加情報を付けたいことがある。

例えば、エラー処理をする段階ではソースコードの位置情報が付いていて欲しいが、後段になると位置情報は捨てて、また別のメタ情報を付けたい、といったような場合だ。

そのような場合、素直にやると同じような定義を繰り返すことになる。

```ocaml
module SyntaxTree = struct
  type t = (* いい感じのASTの定義 *)
end

module TreeWithPosition = struct
  type t = (* SyntaxTree.t とほぼ同じだけど位置情報がついた構文木 *)
end

module TypedTree = struct
  type t = (* SyntaxTree.t に型情報がついた構文木 *)
end
```

どうにかして構文木の定義を使い回せないか……。

## 多相バリアントを使った定義

ということで、以下のような位置情報をASTに付与することを考える。

```ocaml
module With_position = struct
  type 'a t =
    { value : 'a
    ; start : Lexing.position
    ; end_ : Lexing.position
    }
end
```

ASTは [再帰的多相バリアントそぞろ歩き - Qiita](https://qiita.com/dico_leque/items/e1cde3898c89541923b5) のS式の定義を使い回すことにする。

先に欲しいものを確認しておくと、位置情報なしの場合は以下のようにし、

```ocaml
type 't atom =
  [ `Symbol of string
  | `Vector of 't array
  ]

type t =
  [  t atom
  | `List of t list
  | `DottedList of t list * t atom
  ]
```

位置情報ありの場合は以下のようにしたい。

```ocaml
type p =
  [  t_with_position atom
  | `List of t_with_position list
  | `DottedList of t_with_position list * t_with_position atom With_position.t
  ]
and t_with_position = p With_position.t
```

`atom` の定義は使い回せるとして、 `` `DottedList`` の末尾部分と他の再帰部分はさらに分けないといけなさそうだ。

まとめるとこんな感じだろうか。

```ocaml
type 't atom =
  [ `Symbol of string
  | `Vector of 't array
  ]

type ('t, 'tl) t_ =
  [ 't atom
  | `List of 't list
  | `DottedList of 't list * 'tl
  ]

type t = (t, t atom) t_

type p = (t_with_position, t_with_position atom With_position.t) t_
and t_with_position = p With_position.t
```

単純に自分自身を参照すると定義が拡張できなくなってしまうので、型パラメーターで穴をあけておいて、最後に定義を綴じ合わせる。

## 使ってみる

構文木から位置情報を取り除く `t_with_position -> t` な関数を定義してみよう。

その前に、パターンマッチの都合で `t_with_position` のアトム部分の型を分けておくと便利なのでそのようにしておく。

```ocaml
type patom = t_with_position atom
```

さらに、アトムの `` `Vector`` 以外（再帰しないケース）も型を分けておく。

```ocaml
type atom_ =
  [ `Symbol of string
  ]

type 't atom =
  [ atom_
  | `Vector of 't array
  ]
```


これらを使うと、構文木から位置情報を取り除く関数は以下のように定義できる。

```ocaml
let rec strip (x : t_with_position) : t =
  let strip_atom = function
    | { With_position.value = #atom_ as v; _ } ->
      v
    | { With_position.value = `Vector arr; _ } ->
      `Vector (Array.map strip arr)
  in
  match x with
  | { With_position.value = #patom; _ } as v ->
    (strip_atom v :> t)
  | { value = `List vs; _ } ->
    `List (List.map strip vs)
  | { value = `DottedList (vs, t); _ } ->
    `DottedList (List.map strip vs, strip_atom t)
```

ここで `strip_atom` を分けておくのは、 `` `DottedList`` の末尾部分がアトムであることを型レベルで忘れないようにするためだ。また、 `strip_atom` の結果型は `t atom` ≠ `t` なので、OCamlでは `(strip_atom v :> t)` のようにアップキャストが必要になる。 `#atom_` に関しては、今回はなくてもよいのだけど他のアトムができたときのために型を分けておく。

という感じで、表現力の豊かな型機能にありがちな感じで、定義に少し工夫が必要になってしまった。

ここには現れていないけれど、書いているときには構造的な型にありがちなエラーの読みにくさもあった。

ここからさらにパーサーを拡張可能にして構文木も拡張可能にしたりすると恰好よさそうだけれど、定義がかなり禍々しいことにはなりそうではある。

# 余談

こんな感じの方針で、位置情報のあり/なしでバリアントタグを使い回したり、字句解析器のトークンと構文木とでバリアントタグを共有したり、さらにエラー情報を `result` 型 + 多相バリアントで表現する趣味のS式パーサーを[leque/scheme-datum.ml](https://github.com/leque/scheme-datum.ml)として公開している。

趣味のパーサーなので実用性はあまり考えていないのだけれど、もうすこし大きな例として興味がある人はどうぞ。
Docker上でGrafanaとInfluxDBを接続しようとしたらBad Gatewayが出た

![screencapture-localhost-3000-datasources-edit-6-2021-01-12-20_21_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231123/7ca32a91-b11e-f54f-9a73-8a4fbfdcfc07.png)

「Grafana InfluxDB Docker」とググってみて出てくるチュートリアルをやってみたら上記のようなBad Gatewayに悩まされたお話。
結論としては、URLとAccessの組み合わせを正しく理解していなかったためでした。

# 実施環境
ローカルPCのDocker上にGrafanaとInfluxDBのコンテナを立ち上げ、GrafanaのData SourcesからInflxDBを設定しようとしました。
以下のようなDocker-compose.ymlを書いて、実行します。

```
version: "3"
services:
  influxdb:
    image: influxdb:latest
    ports:
      - "8086:8086"
    volumes:
      - ./data/influxdb:/var/lib/influxdb

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - ./data/grafana:/var/lib/grafana
    depends_on:
      - influxdb
```
volumesはフィジビリする上では好みですが、今回はdocker-compose.ymlと同階層に「data」フォルダを作成し、その下に「influxdb」フォルダと「grafana」フォルダを作成しておきます。

InfluxDBにdockerコマンドでアクセスして、新規データベース(ここではsample)とメジャーメントを作成しておいてから、Grafanaに`「http://localhost:3000」`でアクセスをして、ConfigurationのData SourcesよりInfluxDBを追加するために情報を入力して、「Save & Test」を実行までしたところ、冒頭のような「InfluxDB Error: Bad Gateway」が発生しました。

# 解決策① AccessをServer→Browserに変更する(非推奨)
こちらは、いろいろ設定を弄っているうちに接続できるようになった、という解決策です。
その後の意味合いを理解すると、この①は非推奨で、後述の②を実施すべきですので、参考程度の記載となります。
![スクリーンショット 2021-01-12 20.54.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231123/5d9fb8f0-081b-85ad-a991-9808a203588d.png)
URLを`「https://localhost:8086」`のまま接続を確立したい場合はAccessを**「Server」**から**「Browser」**に変更することで、「Save & Test」後、「Data source is working」となり接続されるようになりました。

ところで、このAccessとは何なんでしょうか？
右にある「Help」を選択すると以下のような記載が表示されます。
![スクリーンショット 2021-01-12 20.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231123/5384b47d-917f-da65-5905-8ccb48122dd0.png)
要約すると、以下のように理解しました。
- **Server**はGrafanaのバックエンドを経由してアクセスを試みる(内部通信)
- **Browser**はブラウザ上から直接アクセスを試みる(外部通信)

つまり、今回つまづいた理由は**Server**のときにURLを「localhost:8086」としてるので、**Grafanaコンテナ上の8086ポートにアクセスしようとした**ため、Bad Gatewayが発生したということになります。

それが、解決策①では内部通信ではなく、外部通信として、localhost(ローカルPC自身)をアクセスしにいくようになったため、接続できるようになったということになります。
しかし、実際のケースではInfluxDBのようなデータベース層を外部からアクセスできるような状態になっているケースは殆ど無く、DBへは内部通信でアクセスできるようにしたくなります。

そのため、今回は以下のような解決策で、アクセスできるようにしました。

# 解決策② URLを内部通信向けの名前(アドレス)に変更する
今回は、Docker composeよりGrafanaコンテナとInfluxDBコンテナを起動しているため、`docker-compose.yml`の記載やディレクトリ名に依存しますが、今回は一例として以下のような状態となります。

```
 $ docker-compose ps
           Name                      Command           State           Ports
-------------------------------------------------------------------------------------
influxdb_grafana_grafana_1    /run.sh                  Up      0.0.0.0:3000->3000/tcp
influxdb_grafana_influxdb_1   /entrypoint.sh influxd   Up      0.0.0.0:8086->8086/tcp
```

上記の場合、InfluxDBのコンテナ名は「influxdb_grafana_influxdb_1」となります。
docker-composeでは、networkよりデフォルトでお互いのコンテナ名で名前解決ができるため、この「influxdb_grafana_influxdb_1」をURL名とすることでAccessが**Server**でも接続ができるようになります。
今回の例だと、URLを`http://influxdb_grafana_influxdb_1:8086`とします。

![screencapture-localhost-3000-datasources-edit-6-2021-01-12-21_13_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231123/2e0d9ffb-74e6-1198-2e2c-c6eceea5c768.png)
【Android】背景色を透過する方法(備忘録)

#プログラミング勉強日記
2021年1月12日
Android Studioで開発をしているときに、背景の色を透過することにてこずったのでその方法を備忘録として記録する。


#背景色を透過する方法
 CSSではtransparentやrgbaで指定する。Androidでのレイアウトでの背景色透過の方法をまとめる。

##1. 8桁の色指定で設定する方法
　8桁での色指定では<b>上位2桁が不透明度</b>で、最初の6桁がRGBの指定である。上位2桁の不透明度は、`00(透明)~FF(不透明)`の相対値で指定する。
　

```
android:background="#00000000"
```

##2. Viewのalpha属性で指定する方法
　alpha属性に少数で指定する。Alpha値は0.00(透明)~1.00(不透明)の範囲で相対的に設定できる。

```
android:alpha="0.25"
```
ProgateでHTML,CSSを学んでみた（1日目）

#概要
Web開発に興味が出てきたのでとりあえず一通り必要そうなものを触ってみることにしました。
ただ触るだけだと忘れてしまいそうなのでメモとして学んだことを書いてみます。
ここにあるコードはほぼ全てProgateで出てきたものです。

##HTMLの仕組み
HTMLはタグと呼ばれる印をつけることでテキストに意味付けをする言語。
###見出し
以下のように囲むと見出しという意味になる。
    
    <h1>Hello World</h1>
見出しは全部で6段階ある。
    
    <h1>Hello World</h1>
    <h2>Hello World</h2>
    <h3>Hello World</h3>
    <h4>Hello World</h4>
    <h5>Hello World</h5>
    <h6>Hello World</h6>

試しに上のコードをqiitaのエディタに貼り付けてみると文字の大きさが変わることを確認できた。
<h1>Hello World</h1>
<h2>Hello World</h2>
<h3>Hello World</h3>
<h4>Hello World</h4>
<h5>Hello World</h5>
<h6>Hello World</h6>

###見出し以外の文字
見出し以外の文字には\<p>をつける（pはparagraphの意味）。

###コメント
コメントは<!--と-->で囲む。

###リンクの作成
以下のように\<a>で囲むとリンクを貼り付けることができる。

    <a href="https://prog-8.com">Progateへ</a>
qiitaのエディタにそのまま貼り付けてみると以下のようになった。
<a href="https://prog-8.com">Progateへ</a>

###画像の表示
画像の表示は\<img>タグでできる。テキストを囲むことはないため、終了タグは必要ない。

    <img src="https://prog-8.com/images/html/beginner/wanko.jpg">
qiitaのエディタにそのまま貼り付けてみると以下のようになった。
<img src="https://prog-8.com/images/html/beginner/wanko.jpg">

###リスト
リストを作成するには以下のように書く。
\<ul>で囲むと黒丸\<ol>で囲むと数字がつく。

    <ul>
        <li>hoge</li>
        <li>fuga</li>
    </ul>
<ul>
    <li>hoge</li>
    <li>fuga</li>
</ul>


    <ol>
        <li>hoge</li>
        <li>fuga</li>
    </ol>
<ol>
    <li>hoge</li>
    <li>fuga</li>
</ol>

##CSSの仕組み
CSSはwebページをデザインするための言語。
HTMLの要素に文字の色や配置を与えることができる。
HTMLとは別ファイルに記述する。
以下のように書くと、h1の要素の色を赤に変えることができる。
\#ff0000はカラーコードと呼ばれる。
googleで検索するとたくさんの色が見れる。
例：https://www.colordic.org/
　：https://html-color-codes.info/japanese/

    h1 {
      color:#ff0000;
    }

###フォント、背景色、サイズを指定

    h1 {
      font-size: 20px;
      font-family:"Lucida Grande";
      background-color:#f3f372;
      height:80px;
      width:200px;
    }
RX6800 で Linux で OpenCL を使うメモ

追記: ROCm 5.0 で RDNA2 がしっかりサポートされったぽいようですので, 今後は OpenCL ではなく HIP(CUDA っぽいやつ)が推奨になっていくと思われます. OpenCL もある程度はサポートが続くとは思われます(内部的には OpenCL -> HIP asm? にコンパイルされるのかな)

RDNA2 で OpenCL で GPGPU 計算とか機械学習とかマイニングしたい.

OS: Ubuntu 20.04
GPU: RX6800 (RDNA2)
Driver: amdgpu(-pro) 20.45

https://math.dartmouth.edu/~sarunas/amdgpu.html

を参考に, OSS 版 amdgpu カーネルの上に OpenCL driver(こちらは pro 版でクローズドソースっぽい) を入れます.
引数とかがちょっと変わっています.
(また, 20.45 では amdgpu-pro-install では `--no-dkms` を選択できない)


```
# unpack amdgpu package
$ cd <amdgpu-package>
$ ./amdgpu-install --opencl=legacy,rocr --headless --no-dkms
```

(legacy はなくてもいいかもしれません)

Pro(クローズドソース版)は基本的にはゲーム用や, 古い GPU 用かと思われます. 一応 Pro 版でも動くとは思います.


Ubuntu 20.04 の場合は `render` group にユーザーを追加しておきましょう.

clinfo してうまく認識していれば OK です!

```
Number of platforms                               1
  Platform Name                                   AMD Accelerated Parallel Processing
  Platform Vendor                                 Advanced Micro Devices, Inc.
  Platform Version                                OpenCL 2.0 AMD-APP (3188.4)
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_icd cl_amd_event_callback 
  Platform Extensions function suffix             AMD

  Platform Name                                   AMD Accelerated Parallel Processing
Number of devices                                 1
  Device Name                                     gfx1030
  Device Vendor                                   Advanced Micro Devices, Inc.
  Device Vendor ID                                0x1002
  Device Version                                  OpenCL 2.0 
  Driver Version                                  3188.4 (HSA1.1,LC)
  Device OpenCL C Version                         OpenCL C 2.0 
  Device Type                                     GPU
  Device Board Name (AMD)                         AMD Radeon RX 6800
```

## Vulkan ray tracing 拡張?

amdgpu-pro 20.45 の Vulkan のメモ
https://qiita.com/syoyo/items/c66c0a46cd6ad584dacb

amdgpu(-pro)ではまだ対応はされていません.

AMDVLK(RADV 入り?) 

https://github.com/GPUOpen-Drivers/AMDVLK

`v-2021.Q1.1` のバイナリ入れてみましたが, こちらも `VK_KHR_ray_***` 関連ありませんでした.

Linux で AMD GPU で Vulkan ray tracing はしばらく待つ必要があります. :cry:
ラズベリーパイで気温・湿度監視モニターの作成


## 事前準備

[RasPi＋FastAPIを使う](https://qiita.com/dev_greentea/items/3d3d34b26d14e22ab76d)
[RasPi＋PythonでDHT22を動かす](https://qiita.com/dev_greentea/items/e74363b9e7ae0ed96d0b)

## ファイル構成

| ファイル | 説明 |
|--------|------|
| templates/index.html | HTMLファイル、JavaScriptで５秒ごとにデータを取得する |
| dht_server.py | Pythonサーバ、DHT22のセンサー処理を含む　|

## html code

Pythonサーバからfetchを使用して５秒ごとに気温と湿度情報を取得する。

```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <title>気温・湿度監視モニター</title>
</head>

<body>
    <div>
        <div class="container">
            <h1>気温・湿度監視モニター</h1>
            <h2 id="time">time</h2>
            <h2 id="temperature">temperature</h2>
            <h2 id="humidity">humidity</h2>
        </div>
    </div>
    <script>
        var sensor_read = function () {
            fetch("/data", {
                method: 'GET'
            }).then((response) => {
                return response.json();
            }).then((data) => {
                console.log(data);
                var time = document.querySelector("#time")
                time.innerHTML = data.time
                var temperature = document.querySelector("#temperature")
                temperature.innerHTML = `気温：${data.temperature}度`
                var humidity = document.querySelector("#humidity")
                humidity.innerHTML = `湿度：${data.humidity}％`
            }).catch((err) => {
                console.error(err);
            });
        };

        setInterval(sensor_read, 5000);
    </script>
</body>

</html>
```

## Python code

/dataへアクセスした時にDictで気温・湿度データを渡す。

```python:dht_server.py 
import uvicorn
from fastapi import FastAPI
import RPi.GPIO as GPIO
import MyPyDHT
from starlette.templating import Jinja2Templates
from starlette.requests import Request
import datetime

app = FastAPI()

templates = Jinja2Templates(directory="templates")
jinja_env = templates.env

GPIO.setmode(GPIO.BCM)
DHT_PIN = 4 
GPIO.setup(DHT_PIN,GPIO.OUT)

@app.get("/")
def root(request: Request):
    return templates.TemplateResponse('index.html',
                                      {'request': request})

@app.get("/data")
def data():
    try:
        today = datetime.datetime.now().strftime ("%Y/%m/%d %H:%M" ) 
        humidity, temperature = MyPyDHT.sensor_read(MyPyDHT.Sensor.DHT22, DHT_PIN, use_cache=True)
        if humidity is not None and temperature is not None:
            dat = {"time": today, "temperature": temperature, "humidity": humidity}
            print(f"json: {dat}")
            return dat
    except MyPyDHT.DHTException as e:
        print(f"err: {str(e)}")
    return None


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

```

## サーバを起動する。

ラズベリーパイのIPを調べて、ブラウザでアクセスする。
0.0.0.0はラズベリーパイ上でifconfigなどで調べて置き換えてください。

```bash
 $ python dht_server.py 
INFO:     Started server process [5720]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
```
Androidで、タイトル付きの日付選択スピナーを作成する

意外に記事がなかったのでメモ

以下のようにダイアログをカスタムし、

```java

package com.example.buttonsandbox;

import android.app.DatePickerDialog;
import android.content.Context;
import android.widget.DatePicker;

class MyDatePickerDialog extends DatePickerDialog {
    public CharSequence title;

    public MyDatePickerDialog(Context context, int style, String title, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
        super(context, style, callBack, year, monthOfYear, dayOfMonth);
        this.title = title;
        setTitle(title);
    }

    @Override
    public void onDateChanged(DatePicker view, int year, int month, int day) {
        super.onDateChanged(view, year, month, day);
        setTitle(title);
    }
}
```

スピナーのスタイルを与える。

```xml

// styles.xml
// SpinnerDatePickerStyle
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="SpinnerDatePickerStyle" parent="android:Theme.Material.Dialog">
        <item name="android:datePickerStyle">@style/SpinnerDatePicker</item>
    </style>

    <style name="SpinnerDatePicker" parent="android:Widget.Material.DatePicker">
        <item name="android:datePickerMode">spinner</item>
    </style>
</resources>
```

そして呼び出す。

```java
new MyDatePickerDialog(this, R.style.SpinnerDatePickerStyle, "Set birthday", dateSelectedListener, 1990, 0, 1).show();
```
django-sesで「No handler was ready to authenticate」エラー



# 事象

```sh
No handler was ready to authenticate. 1 handlers were checked. ['HmacAuthV3Handler'] Check your credentials
```

- EC2では動く
- ECS（Fargate）で上記エラー
- IAM Roleには正しく設定されている（AdminRoleを設定しても解決されない）

# 解決策

このエラー自体はRoleの設定ミス等の他の原因でも発生するのですが（そのため調査に時間がかかりました・・）、ライブラリのバージョンが古いと発生する可能性があります。

[django\-ses is unable to use ECS task roles, uses instance role instead \(boto3 required?\) · Issue \#124 · django\-ses/django\-ses](https://github.com/django-ses/django-ses/issues/124)


具体的には、`django-ses` が1.0未満（0.X）の場合に、認証ライブラリのbotoが古いために（botoではなくboto3である必要がある）、ECSのRoleをうまく扱えずにエラーが発生します。
他のライブラリでも、ECS環境で認証エラーが発生した場合は疑ってみてください。
社会人エンジニアがatcoderで茶色を目指す#完結

#茶コーダへ
abc188にて念願の茶コーダーへ到達しました。
コンテスト参加した回数は３０回。
よく続けたなと自分でも思います。
![ErYIbN7VoAAFb6h (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626801/ac314d32-b664-4084-3eb6-2b4c2a247a7d.jpeg)

##始まり
2020/05/04からQiitaにてAtCoderの茶コーダーになるために積み重ねてきた勉強内容を記事にしてきました。
abc188にて茶コーダーになった為に競技プログラミングのみの記事を更新してきましたが一区切りをつけようと思います。

#勉強内容
2020/05/04からQiitaにて更新してきた全ての記事が茶コーダーになるまでに記載したプログラムです。
灰色コーダーの方達の為にどんなコードを記載してきたか残しておきます。

##APG4b
[AtCoder Programming Guide for beginners (APG4b)](https://atcoder.jp/contests/APG4b)

AtCoderを始めるならここから学ぶ。

##AOJ
###[AIZU ONLINE JUDGE](http://judge.u-aizu.ac.jp/onlinejudge/finder.jsp?course=ITP1)

レッスンコースはプログラミングの基本が学べてとても助かりました。

##けんちょんさんの記事
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067#5-%E9%81%8E%E5%8E%BB%E5%95%8F%E7%B2%BE%E9%81%B8-10-%E5%95%8F)

初期にとてもお世話になりました。

##E869120さんの記事
[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【初級編：競プロを始めよう】](https://qiita.com/e869120/items/f1c6f98364d1443148b3)
[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編：目指せ水色コーダー！】](https://qiita.com/e869120/items/eb50fdaece12be418faa)

今もまだ勉強中です。

##数学
伸び悩むエンジニアは基礎学力という壁に気づきます。

###[高校の数学I・Aが1冊でしっかりわかる本](https://www.amazon.co.jp/%E9%AB%98%E6%A0%A1%E3%81%AE%E6%95%B0%E5%AD%A6I%E3%83%BBA%E3%81%8C1%E5%86%8A%E3%81%A7%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E3%82%8F%E3%81%8B%E3%82%8B%E6%9C%AC-%E5%B0%8F%E6%9D%89%E6%8B%93%E4%B9%9F/dp/476127364X/ref=sr_1_6?dchild=1&qid=1610407270&refinements=p_n_feature_eleven_browse-bin%3A2364118051&s=books&sr=1-6)

二次関数、集合、確率、整数問題の勉強をしました。
偏差値４０用の初心者用の参考書です。

#競技プログラミングのレートをあげる為に一番大事な事

伸び悩み、試行錯誤し何回か心が折れかけました。
最後は数学という原点の勉強へ辿り着きました。
数学の参考書を勉強する事で最後の壁を突破できました。
全てのプログラミングの基本、基礎学力がプログラミングで一番大事です。

#ありがとう、AtCoder
数学を勉強する機会、無料でプログラミングを勉強する機会をくれたAtCoderには感謝。

#未来の茶コーダーへ
AtCoderのレート分布を見ると５０％以上が灰色です。
灰色である事を悲観する必要はありません。
試行錯誤し勉強を続ければ必ずレートは上がります。
一番大事なのは楽しむこと！
よきプログラミングライフを！！
削除してしまった「アナウンスメント」フォーラムの復旧

# 注意
以下の記事は，Moodle 3.9 についてのみ有効性を確認しています．
その他のバージョンではどうかというのは確認できていません．

# 「アナウンスメント」の機能
* コースを登録しているユーザに対して一斉メールを送信できる便利機能．
* デフォルトでは「アナウンスメント」と表示されているのみで何に用いるのか分かりづらく，削除されてしまうことが多い．
* 後に一斉メールが必要になってから「Moodle，一斉メール」などの検索ワードで調べてみて初めてアナウンスメントの大切さに気づく．

# つまづき所
元に戻したい，と考えてまず最初にやってみるのは`活動またはリソースを追加する`という選択肢だろう．しかしながら，追加できるコンポーネントをいくら探しても__「アナウンスメント」は見つからない__．

# 復旧方法
1. 削除から14日以内の場合，`コース管理＞ゴミ箱`から`リストア`
2. 削除から14日以降の場合，以下の2つの方法で復旧できる

## 方法 1. 「ブロックの追加」を用いる方法（簡単）
1. `ブロックを追加する＞最新アナウンスメント` を選択
2. `最新アナウンスメント` ブロックが表示される
3. ブロック内の `新しいトピックを追加する` をクリック
4. `フォーラムに投稿する` もしくは `キャンセル` を押すと，トップページ最上部のセクションに自動的に`アナウンスメント`が復旧される

参考ページ：[UMass Amherst Information Technology | UMass Amherst](https://www.umass.edu/it/support/moodle/courseannouncementsmoodle#Replace%20a%20Deleted%20Announcements%20Forum) (University of Massachusetts Amherst)

## 方法 2. 他のコースからインポートする方法
こちらの方法は筆者には複雑に見えたため，確認作業をしていません．
詳しい手順は外部リンクに委ねることにします．

参考ページ：[Waseda Moodle 利用マニュアルについて｜削除してしまったコンテンツを復元したい](https://www.wnpspt.waseda.jp/teacher/wsdmoodle/?p=4010) (早稲田大学)
Twitter api とLine api使ってみた

###はじめに
apiの勉強をしたいと思い、テストで作ってみました。
Twitterのトレンド（1～5位）を取得して、Lineで通知するbotを作ります。

###環境構築


```
pip install line-bot-sdk //Line apiを使うライブラリー
pip install requests requests_oauthlib//twitter apiを使うためのライブラリー
```
それぞれをインストールする。






```csharp

import json
from requests_oauthlib import OAuth1Session
from linebot import LineBotApi
from linebot.models import TextSendMessage

CONSUMER_KEY='*****'
CONSUMER_SECRET='*****'
ACESS_TOKEN='*****'
ACESS_TOKEN_SECRET='*****'
twitter=OAuth1Session(CONSUMER_KEY,CONSUMER_SECRET,ACESS_TOKEN,ACESS_TOKEN_SECRET)//自分のapikeyを入力してください

url='https://api.twitter.com/1.1/trends/place.json'
params={'id':23424856}　//日本のidの値を設定する。
res=twitter.get(url,params=params)
json=res.json()
trends=json[0]['trends']
names=[]
urls=[]
for i,trend in enumerate(trends):
  if i>=5:
    break
  name=trends[i]['name']
  url=trends[i]['url']
  names.append(name)
  urls.append(url)

CHANNEL_ACCESS_TOKEN="*****"
line_bot_api=LineBotApi(CHANNEL_ACCESS_TOKEN)
texts=[]
number=0

def main():
    USER_ID="*****"
    for i in range(len(names)):
      texts.append(str(i+1)+" "+names[i]+"\n"+urls[i])
    line_bot_api.push_message(USER_ID, TextSendMessage(text=texts[number]+'\n'+texts[number+1]+'\n'+texts[number+2]+'\n'+texts[number+3]+'\n'+texts[number+4]))

main()

```

###終わりに

APIの利用はなれたらとても簡単にできると思います。
##わからないところがあれば、気軽に言ってください！！
この記事に関することなら、なんでもお答えします！！
##ダメなところなどもあれば言ってください
DataPortal: 新機能さかのぼり（行ごとに複数のメールアドレスでフィルタする）

DataPortalのまだ知らない使えそうな機能を求めて、新機能の一覧を遡ってみました。

[行ごとに複数のメールアドレスでフィルタする](https://support.google.com/datastudio/answer/9888200?ref_topic=7219787)
> データの統合機能を使用して、多対多のメールフィルタを作成する方法を説明する記事を追加しました。

早速試してみます。

## やること

今回は、アクセス制御リストを利用することで、管理者には全ての売り上げを開示し、店舗ごとの担当者にはその店舗の売り上げだけ開示するようなレポートを作成します。

#### ACL作成
スプレッドシートでアクセス制御リストを作成します。
![ACL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/45bb3089-f4a8-abaf-091c-9d708bb5116a.png)

#### データテーブル作成
スプレッドシートでデータテーブルを作成します。
![Data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/7991d9ce-38da-ca6a-6653-640f7bc07f08.png)

#### ACLとデータテーブルの混合データ作成
各スプレッドシートをデータソースとして取り込みます。
ACLはメールアドレスでフィルタします。
![ACLテーブルメアドフィルタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/20e5131f-b7bb-aa4c-73a6-c1f845b12f17.png)
![メアドフィルタ設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/d1847eb7-7fde-3ca6-ae40-f4c35c41306b.png)

ACLに対してデータテーブルを結合し、混合データを作成します。
![ACL-Data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/9a7390f1-2df8-4e6c-8d20-e6f733349fa3.png)

#### レポート作成
各データを表コンポーネントとしてレポートに配置します。
管理者アカウントには全ての店舗の売り上げが開示されました。
![管理者画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/cc48c301-2266-af6a-2de5-b657f91355fb.png)

店舗担当者アカウントには自身が担当する店舗の売り上げのみ開示されました。
![担当者画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/05d091eb-79e2-bd9a-d2b9-52faabad7b12.png)

#### ついでに
データテーブルに対してACLを結合する混合データだと、メールアドレスフィルタが機能せず、担当者アカウントにも全てのデータが開示されてしまいました。
![Data-ACL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/a1ace827-f734-6ff1-6ed7-323a18d9fcd1.png)
![担当者画面-data_acl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/629021ba-36bf-2aaa-0f3e-dc223b0aa78a.png)

## まとめ
閲覧権限を設定して、アカウントに応じて表示内容を切り替えられました。
とても有用な機能ですが、混合データの作り方には注意がいりそうです。
Nuxt / Laravel(Docker) / AWS(EC2)で作るシンプルなCRUDアプリ

(ポートフィリオの紹介になります。)
タイトルの通り、フロントはNuxt、バックエンドはLaravel(Docker)でシンプルなCRUDアプリを制作、
Nuxtはheroku、Laravel(Docker)はAWS(EC2)*にデプロイしました。
NuxtはSSR(ユニバーサル)、API認証にsanctumを使用しています。
それぞれの具体的な解説は別の記事にまとめていきたいと思っています。

*当初はLaravelもHerokuにデプロイしたのですが、後にAWS(EC2)にリプレイスしました。

[制作したアプリケーション](https://nuxt-laravel--nuxt.herokuapp.com/)
*現在、SSL証明書の期限が切れ表示されません。対応中です。

![スクリーンショット 2021-01-12 16.19.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501141/f42b90fb-d57d-e42e-7ab5-1e75b87376b3.png)



## 機能
- バリデーション:  コメントを投稿したユーザー(本人)のみ編集と削除ができる
- いいね機能:  自分がいいねしたボタンは色が黄色に変化する。再び押すと取り消される。



## 課題
- エラーハンドリング
     - 前までは動いていたはずなのに、ケアレスミスでいつの間にか動かなくなっている、という状況が発生。
修正することはできたが、テストの重要性を感じた。
それぞれの機能を疎結合にしてテストしやすくしたい。
- Nuxt
 - 非同期の理解を深め有効に活用したい。
 - 監視プロパティーを活用し、よりインタラクティブな処理を書きたい。
 - Dotenvが急に機能しなくなったので、現状はURIのフルパスで記述しています。



## 参考
<details><summary>Dockerデプロイ</summary>
 - [git pushでDocker環境をHerokuにデプロイする](https://qiita.com/stepiko135/items/24c462c0a065e6f579a6)
  - [docker + Laravelアプリをherokuにデプロイする](https://www.gintonix.xyz/post-254/#toc4)
 - [【超入門】20分でLaravel開発環境を爆速構築するDockerハンズオン](https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4)
</details>


<details><summary>Nuxt</summary>
 - [Nuxtを使ってPromise, async/awaitのコードを書く](https://qiita.com/yasudadesu/items/3262784bd4e45df57314)
 - [JavaScriptで一定時間待ってから処理を開始する方法](https://laboradian.com/js-wait/)
 - [Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (16) エラーハンドリング Part.2](https://www.hypertextcandy.com/vue-laravel-tutorial-error-handling-part-2)
</details>

<details><summary>Laravel</summary>
 - [Laravel 粘着質なcacheを削除しよう！](https://qiita.com/A-Kira/items/5fd039217ba992481267)

</details>

<details><summary>Auth</summary>
 - [Nuxt.jsでAuth Moduleを使ってログイン機能を実装する](https://qiita.com/itouuuuuuuuu/items/1dc6401022e0d771c757)
 - [【Laravel + Vue】 Laravel Sanctum を使ってAPI認証を構築してみる](https://qiita.com/ntm718/items/ada07bad631a39ca30b9)
 - [nuxt.js + auth使用時のFATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory解消法](https://qiita.com/RikuKomiya/items/9543770f6b0a9ea1936e)
 - [【Nuxt.js】ログイン前後のリダイレクト処理をミドルウェアで実装する](https://blog.cloud-acct.com/posts/u-nuxt-redirect-middleware/)
 
</details>

<br>


## メモ
- 基本的にはシンプルなCRUDアプリなので、上記の参考と公式を見たらできると思う。あまりまとめる事柄が無い..?
- CRUDだがshowのページを作っていない。そのためfor文を使って全投稿を表示している。削除や編集の時はクエリをパスにプッシュすることで個別の投稿データを取り出している。
- AWSは初挑戦だったので、まず公式のチュートリアルを見てLaravelとWordPressをデプロイすることから始めた。VPCなど基本的な事柄を学べるので、初心者におすすめ。



<br>
<br>
JavaScriptのメールアドレスのバリデーションサンプル

#やること
入力されたメールアドレスの形式をチェックし、NGならアラートを表示してフォームは送信しない

```html
<form name="form">
  <input id="email" type="email">
  <input id="submit" type="submit">
</form>
```

##ステップ1
入力されたメールアドレスの値を取得する。

```js
const email = document.form.email.value;
```

```js
const email = document.getElementById('email').value;
```

どちらでも取得可能です。今の書き方だと後者ですね。

##ステップ2
「メールアドレスの形式」とみなす条件を決定する。

例えば、

「任意の文字1文字以上」「@」「任意の文字1文字以上」「.」「任意の文字1文字以上」
をメールアドレスの形式とみなすのであれば、正規表現にすると

- 「任意の文字」→ `.`
- 「1文字以上」→ `+`
- 「.」→`\.`

と変換し、つなげると

```js
.+@.+\..+
```

となります。

「半角英数1文字以上」「半角英数または._-のいずれか0文字以上」「@」「半角英数または_-のいずれか1文字以上」「半角英数または._-のいずれか1文字以上」
をメールアドレスの形式とみなすのであれば、正規表現にすると

- 「半角英数」→`[a-zA-Z0-9]`
- 「1文字以上」→`+`
- 「半角英数または._-のいずれか」→ [a-zA-Z0-9\\.__-]
- 「0文字以上」→`*`

と変換し、つなげると

```js
[a-zA-Z0-9]+[a-zA-Z0-9\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\._-]+
```

となります。

どこまで厳しいバリデーションにするかを考え、まずは日本語で整理してみましょう。
その後正規表現の書き方に変換します。

##ステップ3
入力されたメールアドレスと「メールアドレスの形式」とみなす条件を比較する。

入力されたメールアドレス = `email`
「メールアドレスの形式」とみなす条件 = `.+@.+\..+`
です。
比較には`match`を使います。

```js
const email = document.getElementById('email').value;
if (!email.match(/.+@.+\..+/)) {
  window.alert('メールアドレスをご確認ください'); 
}
```

これで、入力されたメールアドレスがメールアドレスの形式でない場合はアラートが出るようになります。

##今回やらないこと
ハイフンを置換する。

```js
const email = document.getElementById('email').value.replace(/[━.*‐.*―.*－.*\-.*ー.*\-]/gi, '');
```

取得したメールアドレスの値に対して、置換をかけています。
replaceのかっこ内の１つ目の引数は変更前の「ハイフンらしきもの」、２つ目の引数は変更後の空欄です。
「ハイフンらしきものを空欄に置換する」という書き方になります。

なぜやらないかというと、ハイフンを空欄に変換してから比較すると、変換前の入力が正しかったのかわからなくなるためです。例えば、

```js
0-8-0-1-2-3-4-5-6-7-8
```

のような入力も通ってしまいますよね。

そのため、入力を置換するのではなく、入力された値のまま「メールアドレスの形式」とみなす条件、「電話番号の形式」とみなす条件と比較するべきです。

###参考リンク
https://www.tagindex.com/javascript/form/check3.html
https://its-office.jp/blog/js/2017/08/19/telmatch.html
[備忘録]本番環境への更新(AWS EC2)

# 前提
- Railsでアプリケーションを作成している
- AWSの初期設定が完了しており、EC2のインスタンスなども起動し、既にアプリケーションをデプロイしている
- Capistranoによる自動デプロイ設定が完了している

# 本記事の目的
- 作成したアプリケーションにローカルで変更を加えたので、AWSで本番環境にも変更を反映させたい
- AWS EC2のプッシュ方法をいつも忘れてしまうので、備忘録代わりに投稿しておきたい

# 手順
1.ローカル環境での変更をgithub上のmasterブランチへプッシュ

2.EC2へログイン

```:terminal
~ % cd .ssh
.ssh % ssh -i example.pem ec2-user@更新したいアプリケーションのElastic IP
```

3.EC2内のアプリケーションのリポジトリへ移動

```:terminal
[ec2-user@ip-○○○-○○-○○-○○ ~]$ cd /var/www/アプリケーション名
```

4.現在動いているサーバーを落とす

```:terminal
[ec2-user@ip-○○○-○○-○○-○○ リポジトリ名]$ ps aux | grep unicorn
↓
「unicorn master -c」の文字があるプロセスIDを探す
↓
[ec2-user@ip-○○○-○○-○○-○○ リポジトリ名]$ kill プロセスID
↓
exit を実行し、EC2インスタンスからログアウト
```

5.ローカルの更新したいアプリケーションのディレクトリにて自動デプロイを実行

```:terminal
アプリケーション名 % bundle exec cap production deploy
```

6.Elastic IPよりアクセスし。変更が反映されているか確認

以上。