OmniAICreator/Qiita-1.07M huggingface dataset:
Wordpressで複合検索（絞り込み検索）をプラグインなしで実装する方法

Wordpressのデフォルトではキーワード検索しかできないため、カテゴリやカスタムフィールドなどで絞り込むことができない。

複合検索（絞り込み検索）を実装するには独自にフォームを作ってクエリを実行する。

## 複合検索のためのフォームを実装する
検索フォームはHTMLで自由に作れるので、検索したい項目を作成すればOK。

ここでは、検索キーワード、カテゴリ、カラーというカスタムフィールドを検索する。

`name`に入れる文字はクエリの作成で使うのでわかりやすい文字を入れておく。

フォームは、`search-form.php`のようなテンプレートとして作って、サイドバーなど好きなところから呼び出す。

```php
// search-form.php
<form method="get" id="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
	<label for="s">キーワード</label>
	<input type="text" class="field" name="s" id="s" placeholder="検索キーワード" />
	<label for="category">カテゴリ</label>
	<select name="category" id="category">
		<?php 
			$cateogry_list = get_terms( array(
				'taxonomy' => 'category',
			) );
			foreach( $cateogry_list as $category ) {
				if( $category->parent == 0 ) {
						echo '<option value="'. esc_attr( $category->term_id ) .'">
										'. esc_html( $category->name ) .'</option>';
				}
			}
		?>
	</select>
	<label for="s">カラー</label>
	<select name="color" id="color">
		<option value="red">Red</option>
		<option value="blue">Blue</option>
		<option value="yellow">Yellow</option>
	</select>
	<input type="submit" class="submit" value="検索" />
</form>
```

## 複合検索の表示方法
検索結果を表示するには、`WP_Query`にクエリを渡すだけ。

クエリを作るために必要な検索キーワードや選択項目を取得するには`$_GET['name']`を使う。

`name`の部分にはフォームのname属性に入れた文字を入れる。`name`が`s`なら`$_GET['s']`となる。

```php
// search.php
<?php
$args = array(
  's' =>  $_GET['s'], // 検索ワード
  'cat' => $_GET['category'], // カテゴリID
  'meta_query'  =>  array(
    array(
      'key'     => 'color', // メタキー
      'value'   => $_GET['color'], // 値
    ),
  )
);
$wp_query = new WP_Query( $args ); ?>

<?php 
if ( $wp_query->have_posts() ) : 

  /* Start the Loop */
  while ( $wp_query->have_posts() ) :
    $wp_query->the_post();

    // 投稿内容を表示

  endwhile;

    // ループ終了後の処理、ページネーション表示など
    the_posts_navigation();

else :

  // 投稿がない場合の表示

endif;
?>
```

検索結果の表示は`pre_get_posts`を使う方法もあるのでどちらか好きな方で実装する。
git初心者がgitを使いこなすためのメモ

###（１）初期設定

```
git config --global user.name "名前を入れる"
git config --global user.email メールアドレスを入れる
```

###（２）gitリポジトリを作成する
リポジトリを作成したいディレクトリに移動して、下記コマンドを実行。

```
git init
```
・リポジトリ：ファイルやディレクトリの状態、変更履歴を記録する場所。

###（３）gitの基本的なワークフロー
####①ファイルの変更をステージングエリアに追加する

```
git add ファイル名　　　　　←入力したファイルを追加
git add . 　　　　　　　　　←すべてのファイルの変更を追加
git rm ファイル名          ←削除したファイルを記録
```
####②ローカルリポジトリにコミットする

```
git commit -m "コメントする"
```
####③リモートリポジトリにプッシュする
まずリモートリポジトリに登録する

```
git remote add origin 登録gitのURL
git push origin master
```
Laravel 6.Xで新しくなったログイン認証を導入した話

こちらは、
`KPI 項目B：「Laravelの勉強をする」`
のアウトプット記事です。

# 本編
今回はLarave 6.0で新しくなった認証機能を試しました。

# 準備
Laradockで環境の用意。
今回は以下の環境。

|パッケージ|バージョン|
|---|---|
|Ubuntu| 16.04.6|
|PHP| 7.3.15 |
|PostgreSQL| 9.6.17 | 
|Laravel | 7.2.2 |

### Node.jsのインストール 
Dockerのコンテナ内で`npm`が使えるようにNode.jsをインストールします。

Laradockの環境設定を変更し

```sh:.env
WORKSPACE_INSTALL_NODE=true # DockerへNode.jsをインストールする。
```

コンテナの再ビルド

```sh
docker-compose build stop
docker-compose build workspace
docker-compose up -d --build workspace
```

## 認証機能のコマンド実行
何はともあれ`Workspace`コンテナへログイン。

```sh
docker-compose exec --user=laradock workspace bash
```

先にUsersテーブルのマイグレーション。

```sh
php artisan migrate:refresh --seed
```

composerを使って、`laravel/ui`ライブラリをインストール後、Artisanコマンドを実行。

```sh
composer require laravel/ui
php artisan ui vue --auth
```
## NPMでモジュールのインストール

```sh
npm install 
npm run dev
```

## 登録画面
ベースデザインは以前と変わらないよう。
SCSSやVUEといった要素が使われるようになっていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338551/bcfad6d3-bb47-57cf-0957-b8f0231d3668.png)



# 参考
[Authentication(Laravel - Official)](https://laravel.com/docs/7.x/authentication)
[Laravel 7.x 認証](https://readouble.com/laravel/7.x/ja/authentication.html)
ハッシュ関数・進数変換備忘録

#ハッシュ関数・進数変換備忘録

##一方向性ハッシュ関数
###SHA256
特定の文字列をSHA256アルゴリズムでハッシュ化する

```
# echo -n ABCDEFGHIJKLMN | sha256sum
93c5f007220b38ab257456a0e96540d148d4425cf91569dbcdfe6b72685538a4  -
```

###HMAC-SHA256
特定の文字列をSHA256アルゴリズム(HMAC付き)でハッシュ化する

```
#  echo -n "ABCDEFGHIJKLMN" | openssl dgst -sha256 -hmac "secret_key"
(stdin)= 3398f37e84ec13d8f62e33c8d0e708af2a12847fae9ba1a45b027c1654156537
```

###SHA1
特定の文字列をSHA1アルゴリズムでハッシュ化する

```
# echo -n ABCDEFGHIJKLMN | sha1sum
6238bf61dd8df8f77156b2378e9e39cd3939680c  -
```

###MD5
特定の文字列をSHA1アルゴリズムでハッシュ化する

```
# echo -n ABCDEFGHIJKLMN | md5sum
47e441c9bbd571f97fc86c5be32f6cc0  -
```

##進数変換
###16進数化
特定の文字列を16進数化する

```
# echo -n ABCDEFGHIJKLMN | xxd -p
4142434445464748494a4b4c4d4e
```
rootユーザーのssh接続禁止設定

#手順

#1.  /etc/ssh/sshd_configを開く。

次のコマンドを実行する。
vi /etc/ssh/sshd_config

#2.  rootユーザーssh接続を禁止に設定する。

/etc/ssh/sshd_configの次の部分の"yes"を"no"に変更する。
PermitRootLogin yes    →    PermitRootLogin no

#3.  sshdを再起動し、設定を反映する。

次のコマンドを実行する。
service sshd restart

#まとめ

sshd_configを編集してrootユーザーのログインを禁止にし、sshdを再起動して、設定を反映する。
活動記録(2020.3.22)

#今週やったこと

・学習を始めた頃にザッとやってしまったフロントエンド周りの知識がダメすぎるという事に気付き、復習と『これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん』を読み進める。
ポートフォリオに組み込めるか分からないが、JavaScript方面も勉強したい。

・エラー祭りでGit周りの運用に不安があったため、Slackのサロンで質問。「なるべくタスクの粒度を細かく分けてブランチを作成すべき」等、非常に参考になるご回答を得た。

・Docker環境下での開発の敷居が高い(理解の浅いDocker周りのエラーが多い)ため一旦ローカルでの開発に切り替え。また、エディタをAtomからVScodeに戻して色々と拡張機能を入れたが、理解が進んだこともあってか超快適に思える。


#課題・不明点
・データベース周りの知識が不足している。
・テスト環境の理解が浅い。rubocopを導入すれば自動で警告文が出るらしい。RSpec、Jenkinsについても調べておく。
・ルート、ポート、DNS等ネットワーク周りの知識が弱い→基本情報技術者テキスト
・AWSは公式のレクチャーを見るべき。
・デプロイはCircleCIではなくGitHubActionsを採用するのもいいかも。
【Laravel】投稿日時を「X秒前」「X分前」「X時間前」というように相対表示させたい

##はじめに
TwitterなどのSNSのように投稿日時が下記のように相対表示するように、日時を変換する処理を記述していたのですが、Carbonライブラリでは既に`diffForFumans()メソッド`が用意されていたので、ご紹介します。

```
0秒 ≦ X < 60秒 の場合 => 「X秒前」
60秒 ≦ X < 3600秒 の場合 => 「X分前」
3600秒 ≦ X < 86400秒 => 「X時間前」
86400秒 ≦ X < 604800秒 => 「X日前」
604800秒 ≦ X < 2764800秒 => 「X週間前」
2764800秒 ≦ X < 31536000秒 => 「Xケ月前」
31536000秒 ≦ X => 「X年前」
```


##実装
```
$content->created_at->diffForHumans();
```

##最後に
以上です。
プライベート関数でcreated_atを引数にとって、条件分岐で経過時間を相対表示できるように処理を記述していたのですが、`diffForFumans()`で代用できるなんて便利ですね！！

他にも色々とカスタマイズできるので、詳しくは[公式ドキュメント](https://carbon.nesbot.com/docs/)を確認してみてください。
PHPでQiitaのRSSを読み込む方法

#初めに
プログラミング学習を独学で続けてきて、これは忘れそうだなと思いましたので、備忘録として記載します。

##RSSとは
RSSは「Rich Site Summary（リッチ・サイト・サマリー）」の略です。
ブログ等でこのようなアイコンを見たことがあると思います。
<img width="300" alt="スクリーンショット 2020-03-22 23.25.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529982/4658578e-b5e0-2bcb-fa9c-6d134cfa388d.png">
これがRSSのマークです!!

では、このRSSはどういった技術なのでしょうか?

それは、**ブログやニュース記事など、日々更新されていく新しい情報をキャッチするために用いられる技術**です。

これを使うと、自分が見たいニュースやブログ記事を、一つのwebサイトに集約できるポータルサイトを作ることが可能です。

##使い方（RSSのURLを取得する）
それでは、PHPでRSSを読み込む方法について見ていきます。

まずは、自分が調べたいもののRSSのURLを取得しましょう。
今回は、QiitaのPHPに関するRSSのURLを取得します。

Qiitaでphpに関するRSSを読み込むには、URLに
`https://qiita.com/tags/php/feed`
と入力すればオッケーです。

実際に開いてみると、XML形式で記事が更新されていることがわかります。

ここに書いてあるタグですが、大まかにはどのwebサイトも書き方はほぼ同じです。
（タイトルが記載されてるタグには`<title>`、記事のURLが記載されているタグには`<link>`のような）

##使い方（実際にコードを書く）
実際にコードを書いてみます。
以下、実際に使用したRSSのURLです。
<a href="https://qiita.com/tags/php/feed">https://qiita.com/tags/php/feed</a>

今回取得したものは、最新順での記事ごとのタイトルとその記事のURLです。
こんな感じです。

```php:php.read-rss
 　　　　　　　　　　　<?php
                      $url = simplexml_load_file('取得したいURLを記述');
                     ?>
                        <a href="<?php print($url->link); ?>">
                            <?php print($url->description); ?></a>
                        <br>
                   <?php
                     foreach ($url->entry as $entry) :
                    ?>
                            ・<a href="<?php print($entry->url); ?>">
                                <?php print($entry->title); ?></a>
                            <br>
                   <?php endforeach; ?>
```

コードについて説明します。
まず、取得したいRSSのURLを変数$urlに代入します。

その後、`<a>`タグを使ってどこの記事なのかを明らかにするために記事全般が集められてるURL`（$url -> link）`、そこの見出し`($url -> description)`といった感じで取得します。

その後、記事のURLとタイトルを`foreach`文を使って取得します。

#最後に
以上が、PHPでQiitaのRSSを読み込む方法でした。
まだまだ勉強途中で、間違っている部分や、説明不足な点もあるかと思いますが、勉強を続けていく中で、更新していこうと思います。
Atcoder 生活　3日目

[前回]
(https://qiita.com/flandrescarlet237/items/a97d9ba0cf2fff5afb0d)

#3日目
今回はABC0４２＿B,ABC043_Bをやり、さらに今日開催されたABC159に挑戦しました。

##ABC042_B
[文字列大好きいろはちゃんイージー](https://atcoder.jp/contests/abc042/tasks/abc042_b)

```c++
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int N, L;
  cin >> N >> L;
  vector<string> S(N);
  for (auto& e : S) {
    cin >> e;
  }          
  sort(begin(S), end(S));
  for (const auto& e : S){
	cout << e;
  }
}
```

sortという存在をこれでまなびました.
昨日は、Aしか解いてなかったので、Bの難しさを知りました


#ABC043_B
[バイナリハックイージー]
(https://atcoder.jp/contests/abc043/tasks/abc043_b)

```c++
#include <bits/stdc++.h>
using namespace std;

int main(){
    string S, S_ = ""; 
  	cin >> S;
    for(int i = 0; i < S.size(); i++){
        if(S[i] == '0') S_ += '0';
        else if(S[i] == '1') S_ += '1';
        else if(S[i] == 'B') if(S_ != "")S_.erase(S_.size()-1); 
    }
    cout << S_ << endl;
}
```

これでやっとforの使い方を理解することができました。

#ABC159

[A-The Number of Even Pairs]
(https://atcoder.jp/contests/abc159/tasks/abc159_a)

```c++
#include <bits/stdc++.h>
using namespace std;
int main(){
	int N,M;
  	cin >> N >> M;
	if(N > 1 && M > 1)cout << N*(N-1)/2 + M*(M-1)/2 << endl;
	else if(N <= 1 && M > 1)cout << M*(M-1)/2 << endl;
    else if(N > 1 && M <= 1)cout << N*(N-1)/2 << endl;
  	else cout << 0 << endl;
}
```

これしか解けなかった、、
やっぱA問題とB問題は格が違うと思う

明日もB問題解くため練習だ！
【Unity(C#)】TrailRendererの頂点座標を取得する方法

##TraliRenderer
TrailRendererを使えば簡単なお絵描き機能がサクッと実装できます。

【参考リンク】：[【Unity(C#)】ハンドトラッキングで簡易版VRお絵かきアプリ](https://qiita.com/OKsaiyowa/items/b5045fc240d1d9a57880)

今回はTrailRendererの頂点座標を取得していきます。

最終的には頂点座標をシリアライズしてJson形式で保存、
セーブデータとして外部リソースに保存したのち、
デシリアライズしてロード、、、までやります。


##デモ
今回行ったデモはこちらです。

![PaintTest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/46233e4f-11e7-1306-f0a7-ee778e857da2.gif)

中央のボタンを押すと、各TrailRendererの頂点にオブジェクトが生成されます。


##コード

``` C#

using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// お絵描き機能　適当なオブジェクトにアタッチ
/// </summary>
public class Paint : MonoBehaviour
{
    [SerializeField] private Transform _paintObjParent;

    [SerializeField] private GameObject _paintObjPrefab;

    [SerializeField] private GameObject _vertCube;
    
    private GameObject _tmpPaintObj;
    
    private void Update()
    {
        //スクリーン座標をワールド座標に変換
        Vector3 worldClickPos = Camera.main.ScreenToWorldPoint(Input.mousePosition +  Camera.main.transform.forward);
        
        //マウス押した瞬間
        if (Input.GetMouseButtonDown(0))
        {
            _tmpPaintObj = Instantiate(_paintObjPrefab, worldClickPos, Quaternion.identity);
            _tmpPaintObj.transform.parent = _paintObjParent;
        }

        //マウス押し続けている間
        if (Input.GetMouseButton(0))
        {
            _tmpPaintObj.transform.position = worldClickPos;
        }
    }

    /// <summary>
    /// 全てのTrailRendererの全頂点を取得　Buttonに登録
    /// </summary>
    public void GetVert()
    {             
        foreach (Transform child in _paintObjParent.transform)
        {
            TrailRenderer tr = child.GetComponent<TrailRenderer>();
            int posCount = tr.positionCount;
            Vector3[] posArray = new Vector3[posCount];

            //全ての頂点を取ってくる
            int vertCount =  tr.GetPositions(posArray);
                        
            //描画した頂点座標を確認
            for (int i = 0; i < vertCount; i++)
            {
                Debug.Log(posArray[i]);
                Instantiate(_vertCube, posArray[i], Quaternion.identity);
            }
        }
    }
}
```

今回の記事内においては本質ではないので詳細には触れませんが、
クリック時にTrailRederer付きゲームオブジェクトを生成しています。

~~そのせいで、Listを使って若干複雑になっていますが、
下記リンク内で詰まっていた、
消しゴム機能(Undo,Redo)の実装時に役立ちます。
Save,Load時に活用します。~~


【参考リンク】：[【Unity(C#)】ハンドトラッキングで簡易版VRお絵かきアプリ](https://qiita.com/OKsaiyowa/items/b5045fc240d1d9a57880)
##GetPositions

TrailRendererコンポーネントに実装された、
`GetPositions`メソッドを使用して頂点を取得しています。
引数に`頂点座標分の数だけ要素が存在する配列`を渡してあげれば、
すべての頂点を取得できます。

##まとめ

今回の頂点の取得により、TrailRendererのシリアライズの準備が整いました。

次回はシリアライズから、デシリアライズまで一気に進めようと思います。
LineNotifyを使ってメッセージ、画像を送信する

#LineNotifyを使って Fortniteの画像とメッセージを送ってみる。
まず、LINE Notifyのサイトでログインしてトークンを発行する。
https://notify-bot.line.me/ja/

・Mac
・python

（１）ディレクトリ構成
imagesの中に、gazo.jpegを保存。

```
test
├test.py
└images
  └gazo.img
```

（２）test.pyを記述
コードは以下の通り。

```.py:test.py
#coding:UTF-8
import requests,os



#------画像を送る場合----------------------------
def main_gazo():
    url = "https://notify-api.line.me/api/notify"
    token = "*********************************"
    headers = {"Authorization" : "Bearer "+ token}

    message = 'Fortnite！'
    payload = {"message" :  message}
    #imagesフォルダの中のgazo.jpg
    files = {"imageFile":open('images/gazo.jpeg','rb')}
　　#rbはバイナリファイルを読み込む
    post = requests.post(url ,headers = headers ,params=payload,files=files)


#------メッセージを送る場合----------------------------
def main():
    url = "https://notify-api.line.me/api/notify"
    token = "*********************************"
    headers = {"Authorization" : "Bearer "+ token}

    message = 'Fortnite！'
    payload = {"message" :  message}

    r = requests.post(url ,headers = headers ,params=payload)


if __name__ == '__main__':
    main_gazo()#画像を送るmain_gazo()を動かしてみる（メッセージの場合はmain()）
Pythonで毎日AtCoder #13

### はじめに
[前回](https://qiita.com/taxfree_python/items/baf8266aa4a2be7f9110)
今まではAtCoderProblemsのレコメンド問題を解いていましたが、より基礎的な力が足りないと思ったので[これ](https://qiita.com/drken/items/fd4e5e3630d0f5859067)をやります。


### #13
さすがにA問題1題だけだと物足りないので、A問題をふたつ解きます。

[ABC086-A](https://atcoder.jp/contests/abc086/tasks/abc086_a)
[ABC081-A](https://atcoder.jp/contests/abc081/tasks/abc081_a)

**考えたこと**
ABC086-Aは$a*b mod(2)$するだけ

```python
a, b = map(int,input().split())
if a*b % 2 != 0:
    print('Odd')
else:
    print('Even')
```

ABC081-Aはsの中の'1'をcountするだけ

```python
s = list(str(input()))
print(s.count('1'))
```

### まとめ
今日のABCで悔しい思いをしたのでとりあえず過去問精選を解く。
では、また
AtCoder Beginner Contest 159 参戦記

# AtCoder Beginner Contest 159 参戦記

## [ABC159A - The Number of Even Pairs](https://atcoder.jp/contests/abc159/tasks/abc159_a)

3分半で突破. 奇数のペアか、偶数のペアが答えになる. <sub>k</sub>C<sub>2</sub> = k(k-1)/2 が分かっていればあとは書くだけなのだが、A問題にしては難しいね、これ.

```python
N, M = map(int, input().split())

print(N * (N - 1) // 2 + M * (M - 1) // 2)
```

## [ABC159B - String Palindrome](https://atcoder.jp/contests/abc159/tasks/abc159_b)

12分で突破. 時間かかりすぎた orz. 回分チェックルーチンを書いて、後は 1-indexed を 0-indexed に変換しながら、言われたとおりにチェックしていくだけ. B問題にしては難しいね、これ.

```python
S = input()


def is_palindrome(s):
    return s == s[::-1]


N = len(S)

if not is_palindrome(S):
    print('No')
    exit()

if not is_palindrome(S[:(N - 1) // 2]):
    print('No')
    exit()

if not is_palindrome(S[(N + 3) // 2 - 1:]):
    print('No')
    exit()

print('Yes')
```

## [ABC159C - Maximum Volume](https://atcoder.jp/contests/abc159/tasks/abc159_c)

2分で突破. A問題の間違いじゃないの、これ?

```python
L = int(input())

print((L / 3) ** 3)
```

## [ABC159D - Banned K](https://atcoder.jp/contests/abc159/tasks/abc159_d)

10分で突破. 当然 k 番目のボールを除いた場合の数を毎回全部計算し直していたら TLE. とりあえず抜かない場合の数を計算して、k 番目の値の場合の数だけ調整して答える.

```python
N = int(input())
A = list(map(int, input().split()))

d = {}
for a in A:
    if a in d:
        d[a] += 1
    else:
        d[a] = 1

s = 0
for k in d:
    s += d[k] * (d[k] - 1) // 2

for i in range(N):
    t = d[A[i]]
    print(s - t * (t - 1) // 2 + (t - 1) * (t - 2) // 2)
```

## [ABC159E - Dividing Chocolate](https://atcoder.jp/contests/abc159/tasks/abc159_e)

敗退. 累積和でホワイトチョコの数え上げを *O*(*HW*) から *O*(*H*) に軽減して、再帰関数で総当りしたが、TLE & WA でした. 総当たりなのに WA なのでどこか実装がバグってますね…….
PythonでABC159を解きたかった

### はじめに
今回は問題が簡単だったのでA~Cは解けましたが、Dまで解けるべきでした。

### A問題
[問題](https://atcoder.jp/contests/abc159/tasks/abc159_a)

**考えたこと**
偶数を作るには、偶数+偶数、奇数+奇数しかないのでNとMのそれぞれで$_nC _r$、$_mC _r$しています。コンビネーションの計算は自分で実装してもいいですが、scipyにあるのでそれを使いました。

```python
from scipy.misc import comb
n, m = map(int,input().split())

ans = comb(n,2,exact=True) + comb(m,2,exact=True) #exact=Trueで整数値が返される
print(ans)
```

### B問題
[問題](https://atcoder.jp/contests/abc159/tasks/abc159_b)

**考えたこと**
回文の問題が苦手でA解いた後に放置していました。Sが回文であるのなら、s.reverse()==sになることを利用して解きました。強い回文の条件はsをスライスして、上と同じことをしました。n

```python
s = list(str(input()))

checker = 0
n = len(s)
new_s = list(reversed(s))
if s == new_s:
    checker += 1


split_s = s[0:(n-1)//2]
new_s = list(reversed(split_s))
if new_s == split_s:
    checker += 1


split_s = s[(n+2)//2:n]
new_s = list(reversed(split_s))
if new_s == split_s:
    checker += 1
if checker == 3:
    print('Yes')
else:
    print('No')
```

### C問題
[問題](https://atcoder.jp/contests/abc159/tasks/abc159_c)

**考えたこと**
体積が最大になるのは、立方体になるときなので$(L/3)^3$で終わり。精度が怖かったけどなにもしなくても通った。

```python
l = int(input())
print((l/3)**3)
```

### D問題
[問題](https://atcoder.jp/contests/abc159/tasks/abc159_d)
1WA、4TLE

**考えたこと**
解けなかった
for文で$A_i$を抜いたAでコンビネーションを計算しようとしたけど、TLEが出て死んだ。

```python
from scipy.misc import comb

n = int(input())
a = list(map(int,input().split()))
a_s = set(a)
for i in range(n):
    l = a[i]
    a[i] = 'X'
    ans = 0
    for j in a_s:
        ans += comb(a.count(j),2,exact=True)
    print(ans)
    a[i] = l
```


### まとめ
勉強不足なのとBを解くことをあきらめてしまったことが敗因。
おやすみなさい。
eslintとprettierの競合を解消する

競合とは、eslintとprettierが互いに別のコードフォーマットを適用して、コードが修正されない状態を言います。

その解決法は`.eslintrc.js`に`eslint-config-prettier`を加えるだけです。

```js
{
  "extends": [
    /* 他の設定 */
     'eslint-config-prettier' //必ず最後に加える
  ]
}

```

`eslint-config-prettier`は、必ず最後に加える必要があります。なぜなら後に書かれた設定の方が優先順位が高いからです。


[参考]

- [eslint-config-prettier
](https://github.com/prettier/eslint-config-prettier)
laravel 7.xでmake:authの代わりに打つコマンド

# 結論：代わりに↓をコマンドラインに打ってください

```
composer require laravel/ui

php artisan ui vue --auth

laravel new blog --auth
```
##ソース
[laravel公式ドキュメント-該当ページ](https://readouble.com/laravel/7.x/ja/authentication.html?header=%25E3%2582%25A4%25E3%2583%25B3%25E3%2583%2588%25E3%2583%25AD%25E3%2583%2580%25E3%2582%25AF%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3)

### きっかけ：`php artisan make:auth`と入力したら「そんなコマンド無いよ」とlaravelがエラーメッセージを返した
今まで使ってたのが5系で、初めて7系で認証機能付けようとしたら↓のエラーが出ました。

```
 Command "make:auth" is not defined.
```

「あれ」と思って公式ドキュメント見たらmake:auth機能なくなってたことに気付きました。
Laravelのbladeにて、多重のforeachを使って複数の配列を元にhtmlを表示する


# 実現したいこと

例えば不動産システムを例にした時に、複数の配列の情報を元に、
「物件情報のjsonを参考にリストで表示し、isLivedがtrueのものだけ 背景の色をグレーにしたい」
に近いことがしたいと思った時、$loopがとても便利だったのでメモ。


```sample.json
                "price": [{
                    "place_1": 60000,
                    "place_2": 85000,
                    "place_3": 90000,
                    "place_4": 80000,
                    "place_5": 80000,
                    "place_6": 100000
                }],
                "isLived": [{
                    "place_1": null,
                    "place_2": null,
                    "place_3": null,
                    "place_4": null,
                    "place_5": null,
                    "place_6": true
                }]

```


# 実装例

```sample.blade.php
        @foreach ( $sample['rental_apartments'] as $rental_apartment )
          <div class="h40 w-100 border">
              <div class="d-flex flex-wrap">
                @foreach ($rental_apartment["isLived"][0] as $rental_apartment_isLived)
                  @if ($rental_apartment_isLived !== null)
                  <div class="bg-grey">
                    @foreach ($rental_apartment["depth"][0] as $rental_apartment_price )
                      @if ($loop->parent->index === $loop->index)
                          {{ $rental_apartment_price }}
                      @endif
                    @endforeach
                  </div>
                  @elseif($rental_apartment_isLived === true)
                  <div>
                    @foreach ($rental_apartment["price"][0] as $rental_apartment_price )
                      @if ($loop->parent->index === $loop->index)
                          {{ $rental_apartment_price }}
                      @endif
                    @endforeach
                  </div>
                  @endif
                @endforeach
              </div>
          </div>
        @endforeach
```


アプローチとしては、
多重のforeachの中で、
`$loop->parent->index === $loop->index`

を突き合わせることで、同じ順番の要素の時だけが判定されるようにしている。

そもそもjson構造はこうあるべきでないとか、書き方が冗長なんじゃないかとか、、もっとループの計算量は少なくできるんじゃないかとか、色々と余地がありそうだが一旦公開してみる。



# 参考記事

[【Laravel】foreach文における$loop変数に感動した](https://qiita.com/r_fukuma/items/710edce04e64324f5f4c)
機械学習におけるPrecision, Recall, F値の気持ちを解釈してみる

(※もし間違った認識をしている点がありましたら、編集リクエスト・コメントなどご指摘お願い致します。)

その他の[Precision, Recall系の記事のまとめページ一覧はこちら](https://qiita.com/dl_from_scratch/items/1b6e0b7a60aa881b1930)。

## Precision, Recall, F値の定義

機械学習における分類性能指標: Precision, Recall, F値の定義は、

>引用: https://qiita.com/conjugate_box/items/e568909df734cf0b200d
>参考: https://en.wikipedia.org/wiki/Precision_and_recall#Definition_(classification_context)
>
>| 真のラベル | 予測ラベル | 表記
>|---|---|---
>| 正 | 正 | True Positive (TP)
>| 正 | 負 | False Negative (FN)
>| 負 | 正 | False Positive (FP)
>| 負 | 負 | True Negative (TN)
>
>上記の記号を用い，PrecisionとRecallを次で定義する．
>
>$$ Precision=\frac{TP}{TP+FP},　Recall=\frac{TP}{TP+FN} $$
>
>簡単のため以降ではP=Precision, R=Recallとする．
>この時，次で定義される値がF値(もしくはF1値)と呼ばれるものになる．
>
>$$ F=2\frac{P∗R}{P+R} $$

## Precision, Recall, F値の解釈

どういう意味/どういう違い/どういうニュアンスなのかを、機械学習くんとりんごで解釈してみます。

### 1. Precisionは、
例えば、機械学習くんがたくさん絵を見た時に、「これはりんごだ」と言った100回を集めてきて、そのうちいったい何回分が正しいりんごの絵だったか＝正解だったか、を表しているに等しい。**「機械学習くんがたくさん予測してりんごを言い当てようとしてくれるんだけれど、機械学習くんがりんごって言った時にその発言って毎回どれぐらい正しいと思っておけばいいの?」という気持ち**。機械学習くんがりんごと言った時にそれが正解である確率。**機械学習くんの発言の正しさ、機械学習くんの発言を信頼できる度合い**。全体(分母)を機械学習くんがりんごと予測した回数とした時の正解率、母数は機械学習の予測側。

これは、すなわち、**機械学習くんの発言の正しさを表し、正しさ＝Precisionと名付けている**のかと、思います。

Precision=0.9であれば、機械学習くんがりんごって100回言った時、そのうち90回は本当のりんごの絵だ、ということ。

りんごの絵・レモンの絵・ぶどうの絵...のように、複数の識別クラスがある場合は、それぞれのクラスに対して1つずつPrecisionを用意して、りんご発言の正しさ＝りんごPrecision・レモンPrecision・ぶどうPrecision...と出来る。

### 2. Recallは、
例えば、機械学習くんが事前にたくさん絵を見て学習したんだけれど、その記憶力を見るために、正しいりんごの絵を100枚用意して見せた時に、何回分をりんごの絵と回答できるか＝正解できるか、を表しているに等しい。**「機械学習くんに正しいりんごの絵を見せた時に、果たして毎回どれぐらい正解できるものなのか?」という気持ち**。機械学習くんにりんごの絵を見せた時に正解する確率。機械学習くんに「これは何でしょう」とりんごの絵を出題した時の正解できる確率、すなわち、りんご記憶力テストの正答率。**機械学習くんの思い出す能力の度合い、機械学習くんの記憶力テストの結果**。全体(分母)を正しいりんごの絵の枚数とした時の正解率、母数は真値側。

これは、すなわち、**機械学習くんの思い出す能力の高さを表し、思い出す＝Recallと名付けている**のかと、思います。

Recall=0.9であれば、機械学習くんにりんごの絵を100回見せた時、そのうち90回はりんごと言える(＝残り10回はレモンとかぶどうとか言って間違える)、ということ。

これも同様に、りんごの絵・レモンの絵・ぶどうの絵...のように、複数の識別クラスがある場合は、それぞれのクラスに対して1つずつRecallを用意して、りんごに対する記憶力＝りんごRecall・レモンRecall・ぶどうRecall...と出来る。

### 3. F値は、
Precisionの値とRecallの値を1つにまとめて、1つの値で性能を見る用に。PrecisionとRecallは、両方見ておかなくてはいけないが、それを何とか1つの値で見ることで、数十種類を超えるいろいろな機械学習くんが居ても、性能を1つの値で表しておけば、すべてを一覧表に並べて比較・順位付け出来るようになるし、棒グラフも描けるようになるから便利なのだろうと。

これも同様に、複数の識別クラスがある場合は、それぞれのクラスに対して1つずつF値を用意。

# 参考：表を用いてPrecision, Recallを具体的な数値で計算してみる例

https://qiita.com/dl_from_scratch/items/e6f615b7b50833e2fd4a

# 参考：Precisionが大きくRecallが小さい状態の解釈

Precisionが小さくRecallが大きい状態とはどういうことなのか?、Precisionが大きくRecallが小さい状態とはどういうことなのか?、について解釈してみた記事があります。

https://qiita.com/dl_from_scratch/items/309f98c11156b4ab6b52

# 参照

recall,precisionなど:

https://qiita.com/taro_kawasaki/items/64e7536e41f3c698592c

Accuracy/Recall/Precisionってややこしくない??:

https://qiita.com/K5K/items/5da52e99861483cae876

具体例で考える、Recall / Precisionの使い分け:

https://qiita.com/yohei7328/items/f7943507986634411476

【入門者向け】機械学習の分類問題評価指標解説(正解率・適合率・再現率など):

https://qiita.com/FukuharaYohei/items/be89a99c53586fa4e2e4

Accuracyだけに頼れない理由:

https://qiita.com/unohisa/items/00d94f5cfe3f2e5d03b9
Fortniteの画像を100枚スクレイピングする

#Fortniteの画像を、Yahooから100枚スクレイピングしてみた。
・Mac
・python3

#（１）環境構築、ディレクトリ構成
デスクトップにディレクトリfortniteを作成。
ディレクトリ内にimagesフォルダ（画像保存用）と、scraping.pyを作成。

```
fortnite
├scraping.py
└images
```

ディレクトリ内で仮想環境構築。

```
python3 -m venv .
sorce bin/activate
```

必要なパッケージ、モジュールをインストール

```
pip install beautifulsoup4
pip install requests
pip install lxml
```

#（２）scraping.pyを記述
Fortniteの画像スクレイピングは、Yahooの画像検索結果を使う。
https://search.yahoo.co.jp/image/search?p=%E3%83%95%E3%82%A9%E3%83%BC%E3%83%88%E3%83%8A%E3%82%A4%E3%83%88&ei=UTF-8&b=1
1ページあたり10枚画像あり、次ページ以降を合わせると100枚以上はあることが確認できる。
ここからスクレピングして、imagesフォルダに格納する。

```.py:scraping.py
from bs4 import BeautifulSoup
import lxml
import requests
import os
import time


def main():
    #１ページあたり20個の画像、次ページをスクレイピングするための変数
    page_key=0

    #保存した画像をナンバリングするための変数
    num_m = 0

    for i in range(6):
        URL = "https://search.yahoo.co.jp/image/search?p=%E3%83%95%E3%82%A9%E3%83%BC%E3%83%88%E3%83%8A%E3%82%A4%E3%83%88&ei=UTF-8&b={}".format(page_key + 1)
        res = requests.get(URL)
        res.encoding = res.apparent_encoding
        html_doc = res.text
        soup = BeautifulSoup(html_doc,"lxml")

        list = []
        _list = soup.find_all("div",class_="gridmodule")
        for i in _list:
            i2 = i.find_all('img')
            for i3 in i2:
                i4 = i3.get('src')
                list.append(i4)


        for i in list:
            i2 = requests.get(i)
            #絶対パスを指定して保存
            with open(os.path.dirname(os.path.abspath(__file__)) + '/images' + '/{}'.format(num_m)+'.jpeg','wb')as f:
                f.write(i2.content)
            num_m += 1
            #画像が101枚目となったら保存処理を停止（for文停止）
            if num_m == 101:
                break

        #内側の保存処理のfor文が停止した場合、外側のfor文も合わせて停止する処理
        else:
            continue
        break


        #サーバー負荷防止のため１秒間隔を開ける
        time.sleep(1)

        page_key+=20

if __name__ == '__main__':
    main()
```

###補足説明
・GoogleChromeの”検証”を使い、画像URLのありそうな場所を探した結果、divタグのclassがgridmoduleの部分にあることを確認。そこからimgタグの部分をスクレイピング。
・get('src')で、imgタグのsrc属性の値を取得する。
・取得したimgタグのsrc属性はurlではあるものの、str型となっているので、requestsでレスポンス情報を格納したレスポンスオブジェクトを取得する。レスポンスオブジェクトには、text、encoding、status_code、contentが含まれる。contentはレスポンスボディをバイナリ形式で取得するために必要。（参考）[Requests の使い方 (Python Library)
](https://qiita.com/sqrtxx/items/49beaa3795925e7de666)・ファイルで絶対パスを指定して、wbモードで書き込む（参考）[
Python、os操作について](https://qiita.com/nooonchi/items/ed883d39b9d7c8308f46)
・for文で100枚保存したら内側のfor文と外側のfor文を中止する。[Pythonのforループのbreak（中断条件）](https://www.headboost.jp/python-for-break/#2_forbreak)

###実行すると、imagesフォルダに画像を保存できたことが確認できる。
遊興競技依存症拮抗

遊興競技(game)依存症の経緯を記録し、
いかに依存症による弊害を軽減できるかを考える。

 <この項は書きかけです。順次追記します。>

 


# 解決策０　自分で管理する
誰かに規制されたり、誰かに監視されても効果は怪しい。
自分で、自分の健康と仕事が両立できるような原理を考え、
自分で管理することが、解決策の第一歩


# 軽減策１　遊ぶ方から創る方へ

遊んでいるから依存症が問題になる。
創る方に回れば、依存症の弊害を少しでも減らすことができるのではないかと考えた。

創るだけでなく、ついつい試験以外の目的でもやってしまうという現象は現れる。


# 解決策２　遊ぶ時間も創る時間も労働時間として扱う。

労働基準法
https://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=322AC0000000049
>第三十二条　使用者は、労働者に、休憩時間を除き一週間について四十時間を超えて、労働させてはならない。
○２　使用者は、一週間の各日については、労働者に、休憩時間を除き一日について八時間を超えて、労働させてはならない。

に基づき、創る時間と遊ぶ時間の合計が１日８時間、週４０時間を超えないように、することが大事。

遊ぶのは労働時間に入れないとう選択肢は悪魔の選択だということ。

労働時間が１日１６時間くらいになることがあるかもしれない。
その場合には、週で４０時間を超えないように、代休などの方策を取ると良い。

# 解決策３　午前中は起動しない。

午前中からついついやってしまうと、１日の時間をすぐに超えてしまう。
仕事もそっちのけになってしまうかもしれない。

午前中は絶対に起動しないことが大事。

# 解決策４　休憩時間、休息時間、休日にはしない

労働時間として考えることの一つの派生。
休憩時間、休息時間、休日には立ち上げないことが大事。

# 解決策５　病気、体調不良の時にはしない

体の調子が悪いと、仕事が捗らない。
ついつい、立ち上げてしまう。

それを防ぐには、病気、体調不良の時にはしないことが大事。

# 参考資料

プログラマが落ち入らない方が良さそうな依存症群調べ(一部自己対策含む)
https://qiita.com/kaizen_nagoya/items/4d00b3fc2d9f649e0a18

１年ゲーム断ちして　

https://qiita.com/kaizen_nagoya/items/a29748da55ef1e1fe6cd

SNS依存症の分類 

https://qiita.com/kaizen_nagoya/items/f8d99ee9c654dc27807b

ゲーム依存症から脱却するために 

https://qiita.com/kaizen_nagoya/items/c952d6291fb881eb0985

遊興競技依存症拮抗 

https://qiita.com/kaizen_nagoya/items/934b65ea3282f7e863fe

仮説（154）「GAFA断ち」

https://qiita.com/kaizen_nagoya/items/5fb95a9df523721377f6

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞


### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
「テスターちゃん」で学ぶソフトウェアテスト①

#1. 「テスターちゃん」とは:thinking:
初心者(新人)向けに描かれたソフトウェアテストの漫画
作者さんも現役の方らしい
たまたまJSTQBについて調べていた時に見付けたブログの記事がきっかけで読むようになりました
[JSTQBを取るメリット5選](http://testerchan.hatenadiary.com/entry/2018/02/15/001117)

元々(紙の本・電子書籍共に)同人誌として発売されているが、[書籍版](https://www.amazon.co.jp/exec/obidos/ASIN/4863543026/milk0824-22/)としても発売されることが決まっている
※因みに書籍版には同人誌版1～5巻までの内容が入る(大人の事情により書籍版には収録出来ない内容も一部あるとのこと)ため、同人誌版の1～5巻は紙・電子書籍共に販売を完了しているらしい
現在の同人誌版は英語版の1巻のみ購入可能となっている

実は自分が唯一通読した仕事関係の本:sweat:
とは言え、完結した作品ではないのですが

対象読者層は初心者や作者の方も言っているように開発側の人だが、しかしながら個人的にはバリバリ設計等もこなしている経験者や管理者側の人間が読んでも新たな発見が出来ると思う
むしろそう言った立場の人が初心を忘れないように積極的に読むべきでは？

これから「テスターちゃん」を読んで学んだことをまとめて行こうと思います

#2. LOG
「テスターちゃん」で学ぶソフトウェアテスト① :point_left_tone1:イマココ
[「テスターちゃん」で学ぶソフトウェアテスト②](https://qiita.com/156Musik/items/3c1a91126dc15bd2bf40)
[「テスターちゃん」で学ぶソフトウェアテスト③](https://qiita.com/156Musik/items/1a9450a15aa3607fe2d5)
[「テスターちゃん」で学ぶソフトウェアテスト④](https://qiita.com/156Musik/items/77d4471ae21aac937f78)
[「テスターちゃん」で学ぶソフトウェアテスト⑤](https://qiita.com/156Musik/items/b89e104010dfcced3fd0)
[「テスターちゃん」で学ぶソフトウェアテスト⑥](https://qiita.com/156Musik/items/ebb1d2339c3a256f8ec9)
[「テスターちゃん」で学ぶソフトウェアテスト⑦](https://qiita.com/156Musik/items/94a036beb46c2dc68a86)
[「テスターちゃん」で学ぶソフトウェアテスト⑧](https://qiita.com/156Musik/items/fb1aa75351660c1150f8)

#3. QAとは何か
QA＝Quality Assurance
日本語で言うと<font color="red">品質保証</font>のこと
プロダクトがユーザーにとって満足の出来る品質に至っていることを保証する

#4. テストとは何ぞや
プロダクト(アプリ・Web等)を実際に動かして<font color="red">問題がないこと</font>を確認する

##4.1 テストの確認の基本
###１．バグの確認
テストとは、バグを含めて出来るものが出来ないこと、あるものがないこと＝<font color="red">意図しない動き</font>を確認する

ソフトウェの動きは以下の４つ
>・入力
・計算
・出力
・データ保存

そこに注目する

###２．性能の確認
ユーザーに影響のあるバグが見付からなくなったとしてもそのプロダクトが大丈夫だとは限らない

〔EX〕
とても挙動が遅い、とか

なので、<font color="red">性能の確認</font>も必要である

性能系は基本部分が多いので、早めに確認する
→作り直しになる可能性がある

###３．ユーザー視点での確認
ユーザーとしてそのプロダクトが使い易いかも見る必要がある

企画通りでも使ってみて<font color="red">改善した方がいいこと</font>も確認する
<font color="red">ユーザーは絶対こう使う</font>と言う思い込みもあるので、それに縛られないことが必要

##4.2 気付くのって大変
QAが最後の砦と言われているのは、開発・企画が気付かなかったことに気付いて食い止めるから

とは言え、**何かおかしい**と言うのに気付くのは大変なこと
>・プログラムの間違い易いところ
・端末のくせ
・データがどうやって保存されるのか……等

結構幅広い知識が必要となってくるようだ

#5. マイヤーズの三角形
##5.1 課題
>以下のプログラムで、**テストケース**を全て述べよ
>【プログラム】
　１．このプログラムは、３つの整数を入力出来る
　２．この３つの値は、それぞれ三角形の３辺の長さを表すものとする
　３．プログラムは三角形が以下のどれかを決めるメッセージを印字する
　　・不等辺三角形
　　・二等辺三角形
　　・正三角形

##5.2 確認してみる
###出来ること
正常系確認
・不等辺三角形になるか
・二等辺三角形になるか
・正三角形になるか

###出来ないこと
異常な入力値
・０を入力
　→全部の辺が０の場合
　→どれかの辺が０の場合
・マイナス値
　→全部の辺がマイナス値の場合
　→どれかの辺がマイナス値の場合
・小数点を用いた値
　→全部の辺が数点を用いた値の場合
　→どれかの辺が数点を用いた値の場合
・整数以外での確認
　→文字(かな・カナ・漢字・記号・絵文字等)
・入力しない(空欄にする)

【見落とし易い？】
・A+B<Cの場合
　→ちゃんとした整数でも1つの辺が他の辺の合計より長い場合は三角形にならない

##5.3 マイヤーズの三角形のまとめ
・まず正常値は必要
・二等辺三角形はそれぞれの辺についても確認する
・三角形の性質(テスト対象)をわかっていないと出ないテスト観点がある
　→盲点となっているところがあるかも
　→しっかり頭を回転させて考える必要がある

#6. 続く
一つの記事で同人誌版1巻まとめようとしましたが、結構内容が濃いので、巻数を気にせずまとめていきます:sweat_smile:
AWS認定ソリューションアーキテクト - アソシエイト 1回落ちて2回目で合格

AWS認定ソリューションアーキテクト - アソシエイト 受験の感想です。

## はじめに

今まで、AWSを使う機会は全く無かったのですが、
転職を機会きっかけにAWSに関わることが増えたため、知識の底上げとして受験することにしました。

実は、半年くらい前に一度受験したのですが、その時は落ちてしまい、再受験の機会を伺っていました。
そんな時、新しいバージョン(SAA-C02)が、2020/3/23から始まるとのことで、急遽受験することにしました。

## 1回目（落ちた）

#### 勉強
みなさまの合格記録を参考に勉強をはじめました。

- [黒本](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E2%80%93-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8/dp/4295005495/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr= "黒本")を３〜４周
- 公式のサンプル問題
- 公式の模擬試験

模擬試験は、問題をキャプチャ、正解はわからないので、黒本で確認、わからなければググる。
不安はあったものの、大枠、理解出来てる感はあったので、受験してみました。

#### 振り返り
サービス名と内容の把握は出来ているものの、
具体的なアプリケーションやシステム構成に落とし込んだ場合についての理解が甘かったのだと思います。
実際、回答にかなりの時間を要し、見直す時間はない状況でした。


## ２回目（受かった）

#### 勉強
１回目の振り返りを元に、各サービス/機能を

- どのように使用するのか
- どう選ぶのか

を理解するため、以下に頼りました。

- [Udemyの「これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（初心者向け22時間完全コース）」](https://www.udemy.com/course/aws-associate/ "Udemyの「これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（初心者向け22時間完全コース）」")
- [AWS WEB問題集で学習しよう](https://aws.koiwaclub.com/ "AWS WEB問題集で学習しよう")

ハンズオンで使い方のイメージを固めつつ、試験問題で復習するという形で進めていきました。
うちの会社は、AWSが使い放題なので、そこは非常に助かりました。勉強に対する支援、ホント素晴らしいです！！

当初、１ヶ月後に再受験と考えていたものの、予定が合わず一旦キャンセル、いつ受けようか悩んでいたところ、
新バージョンの話が出てきて、急遽、２週間後に再受験することにしました。
ハンズオンは一通り終わっていたので、２週間は、ひたすら試験を解いて過ごしました。

#### 振り返り
１回目と違い、半分ほどの時間を残して回答が終わり、残りは全て見直しに使うことが出来ました。
慣れもあるかもしれませんが、今回は、問題が求めているものをしっかり読み取り、スムーズに回答出来ました。

#### おまけ
２回目の勉強期間中、社内の勉強会で「ABD（アクティブ・ブック・ダイアローグ）で黒本を読む」という機会があり、
非常に良い復習になりました。最初にこの機会があれば、機能理解はもっとスムーズ進んだことと思います。

## 最後に
資格が全てではないものの、やっぱり合格出来て嬉しいです。
資格を持っているだけにならないよう、学んだ知識を仕事で活用していこうと思います(使わないと忘れちゃう)。
混同行列(Confusion Matrix)の表中にPrecision, Recallを書いた具体例(分類クラスが3種類以上ある場合にも拡張)

(※もし間違った認識をしている点がありましたら、編集リクエスト・コメントなどご指摘お願い致します。)

その他の[Precision, Recall系の記事のまとめページ一覧はこちら](https://qiita.com/dl_from_scratch/items/1b6e0b7a60aa881b1930)。

## 混同行列 (Confusion Matrix)　定義

>引用: http://popo.ara.black/etc/confusionmatrix.htm
>
>混同行列（Confusion Matrix）とは、クラス分類の結果をまとめた表のことです。陽性のサンプルのうち、何個が正しく陽性と判定され、何個が誤って陰性と判定されたか、といったことを分かりやすくまとめるために用います。
>
>２クラスの場合、混同行列はこのような２×２の行列になります。
>
>|　|予測されたクラス<br>＝Positive|予測されたクラス<br>＝Negative
>|---|---|---
>|実際のクラス＝Positive|True Positive|False Negative
>|実際のクラス＝Negative|False Positive|True Negative

## りんごの例で言えば

例えば、機械学習くんがりんごかどうかを識別する例で言えば、表の上に機械学習くんが予測して、りんごと答えた時と、りんごでないと答えた時の項目を配置して、表の左横には機械学習くんに見せる絵が、りんごの絵の時と、他の物の時の項目を配置、表内の空いている4マスにそれぞれの発生回数を入れていく。りんごの絵を見せてりんごと答えたらTPのマスに+1、りんごの絵を見せてりんごでないと答えたらFNのマスに+1、他の物を見せてりんごと答えたらFPのマスに+1、他の物を見せてりんごでないと答えたらTNのマスに+1。

|　|予測=りんご|予測=りんごでない
|---|---|---
|真値=りんご|TP=90回|FN=15回
|真値=他の物|FP=10回|TN=85回

## 対応する位置にPrecisionとRecallを書き加える

表の対応する位置にPrecision(＝機械学習くんがりんごかどうか予想して答える発言の正しさ＝$\frac{TP}{TP+FP}$)とRecall(＝機械学習くんがりんごを思い出す記憶力の良さ＝$\frac{TP}{TP+FN}$)を合わせて書き加えれば、

|　|予測=りんご|予測=りんごでない|(Recall)
|---|---|---|---
|真値=りんご|TP=90回|FN=15回|0.857..
|真値=他の物|FP=10回|TN=85回| 
|(Precision)|0.9| |りんごのF値=0.878..

## クラスが3種類以上ある場合

例えば、りんご・レモン・ぶどう・メロン・みかんの5種類のクラスを識別する場合は、

|　|予測=りんご|予測=レモン|予測=ぶどう|予測=メロン|予測=みかん
|---|---|---|---|---|---
|真値=りんご|90回|4回|3回|3回|5回
|真値=レモン|2回|85回|1回|4回|3回
|真値=ぶどう|1回|3回|95回|2回|1回
|真値=メロン|4回|2回|4回|87回|3回
|真値=みかん|3回|1回|3回|2回|92回

PrecisionとRecallは、それぞれのクラスに1つずつ用意できて、りんごのPrecision・レモンのPrecision・ぶどうのPrecision・メロンのPrecision・みかんのPrecision、りんごのRecall・レモンのRecall・ぶどうのRecall・メロンのRecall・みかんのRecallが出てくる。りんごのPrecisionは90/(90+2+1+4+3)=0.9など。表の対応する位置に合わせて書き加えれば、

|　|予測=りんご|予測=レモン|予測=ぶどう|予測=メロン|予測=みかん|(Recall)
|---|---|---|---|---|---|---
|真値=りんご|90回|4回|3回|3回|5回|0.857..
|真値=レモン|2回|85回|1回|4回|3回|0.895..
|真値=ぶどう|1回|3回|95回|2回|1回|0.931..
|真値=メロン|4回|2回|4回|87回|3回|0.87
|真値=みかん|3回|1回|3回|2回|92回|0.911..
|(Precision)|0.9|0.895..|0.896..|0.888..|0.885..

この表を、りんごとりんごでないの2種類の表に書き換えてみると、

|　|予測=りんご|予測=りんごでない|(Recall)
|---|---|---|---
|真値=りんご|TP=90回|FN=15回|0.857..
|真値=他の物|FP=10回|TN=388回|0.975..
|(Precision)|0.9|0.963..|りんごのF値=0.878..

りんごのPrecision・りんごのRecall・りんごのF値は、他のクラスの正解・不正解の回数(表中のTNの数)にかかわらず、同じ値のまま。りんごについて評価しているので、りんごのPrecision・りんごのRecall・りんごのF値は、他のクラスの正解状況には影響されないものに。つじつまが合っている。
【SQL基礎】NOT,NULL,AND,OR,ORDER BY,LIMITについて。

前編
[【SQL】SELECT,FROM,WHERE,LIKEについて。 - Qiita](https://qiita.com/Pirori3182/items/ecbf05c4ad3502b03679)

## NOT演算子
「〇〇を含まないデータ」や「〇〇に一致しないデータ」のような条件でデータを取得したい場合は「否定」を意味する「NOT演算子」を用いる。

```sql:sample.sql
-- priceカラムから、1,000以上ではないデータを取得
SELECT *
FROM purchase
WHERE NOT price > 1000;

-- nameカラムが「プリン」を含まないデータを取得
SELECT *
FROM purchases
WHERE NOT name LIKE "%プリン%";
```

## IS NULL
「カラム名 IS NULL」とすることで、「指定したカラムがNULLであるデータ」を取得できる

```sql:sample.sql
-- priceカラムが、NULLのものを取得。
SELECT *
FROM purchase
WHERE price IS NULL;
```

## IS NOT NULL
「カラム名 IS NOT NULL」とすることで、「指定したカラムがNULLではないデータ」を取得できる

```sql:sample.sql
-- priceカラムが、NULLではないのものを取得。
SELECT *
FROM purchase
WHERE price IS NOT NULL;
```

## AND演算子
WHEREに複数の条件を指定することができる。
「WHERE 条件１ AND 条件２」のようにすることで、条件１と条件２を共に満たすデータを検索することができ

```sql:sample.sql
-- categoryカラムが「IT企業」かつfunctionカラムが「独自ドメイン」であるデータを取得

SELECT *
FROM purchases
WHERE category = "IT企業"
AND function = "独自ドメイン"
```

## OR演算子
WHEREに複数の条件を指定することができる。
「WHERE 条件１ OR 条件２」のようにすることで、条件１または条件２のどちらかを満たすデータを検索することができる。

```sql:sample.sql
-- categoryカラムが「IT企業」もしくはfunctionカラムが「独自ドメイン」であるデータを取得

SELECT *
FROM purchases
WHERE category = "IT企業"
OR function = "独自ドメイン"
```

## ORDER BY
データを並び替えるために用いる。
データを並び替えるためには、「（基準となる）並べ替えたいカラム名」と「並べ方」を指定する。

並べ方は、「昇順」は「ASC」、「降順」は「DESC」と指定。
「ORDER BY」は「WHERE」と併用することが可能。

```sql:sample.sql

SELECT *
FROM purchases
WHERE category = "IT企業"
ORDER BY employees DESC;
```

## LIMIT
「最大で何件取得するか」を指定するためには、「制限する」という意味の「LIMIT」を用いる。
IMITはクエリの末尾に記述することで、取得するデータの数を制限する。
「LIMIT」は「WHERE」と併用することが可能。
「ORDER BY」と「LIMIT」を併用することも可能。

```sql:sample.sql

SELECT *
FROM purchases
WHERE category = "IT企業"
LIMIT 100;
```
Pythonで食品のリコール情報をスクレイピングして、pandasデータフレームを作ってみた

pythonの学習記録をつけてみようと思い、Qittaを始めてみました。
仕事は非IT企業なので、、pythonは本当に趣味・・・というか、興味本位で学習しています。

今は、食品衛生に関わる仕事をしているので、pythonを使って何か出来ないかな〜と思い、食品のリコール情報をデータ分析してみよう！と思い立ちました。

その第一段階として、スクレイピングで食品リコール情報のデータフレームを作ってみました。データの元は[リコールプラス](https://www.recall-plus.jp/)というサイト。


```python:food_recall_info.py
from bs4 import BeautifulSoup
import requests
import re
import csv
import time
import pandas as pd

def recalls(url):
    res = requests.get(url)
    soup = BeautifulSoup(res.text, 'html.parser')
    recall_soup = soup.findAll("tr",{"class":{"return","info","apology"}})
    
    campany_list = []
    recall_list = []
    action_list = []
    recall_date = []

    for j in range(len(recall_soup)):
        #会社名を取得
        campany_list.append(recall_soup[j].find("a", href=re.compile("/company/*")).get_text())
        #リコール内容
        recall_list.append(recall_soup[j].find("a", {"style":"float:left"}).get_text())
        #対応方法
        keyword = re.compile(r'回収|回収＆返金|回収＆返金/交換|回収＆交換|返金|交換|点検＆交換|お知らせ|景品表示法違反|お詫び|返金/交換|送付')
        action_list.append(re.search(keyword, str(recall_soup[j])).group())
        #発生日
        recall_date.append(recall_soup[j].find("td", {"class":"day"}).get_text().replace("\n        ","20"))
    return campany_list,recall_list,action_list,recall_date

campany_lists = []
recall_lists = []
action_lists = []
recall_dates = []

for i in range(1,20):
    resl = recalls("https://www.recall-plus.jp/category/1?page={}".format(i))
    campany_lists.extend(resl[0])
    recall_lists.extend(resl[1])
    action_lists.extend(resl[2])
    recall_dates.extend(resl[3])
    
recall_df = pd.DataFrame({'会社名':campany_lists,'リコール内容':recall_lists,'対応':action_lists,'発生日':recall_dates})

```

実行結果

```python

recall_df.head()
会社名	リコール内容	対応	発生日
0	神戸物産	業務スーパー ほしいもスティック一部商品に樹脂片の混入	回収	2020/03/17
1	丸文	丸文 国産大豆使用よせ豆腐 消費期限誤表示	回収	2020/03/17
2	イオン常陸大宮店...	豚肉ロース味付トンテキ用 アレルゲン(乳)表示欠落	お詫び	2020/03/18
3	ツルヤ	軽井沢店 おいしい白身魚ﾌﾗｲ ｱﾚﾙｹﾞﾝ乳成分表示欠落	回収	2020/03/16
4	畑中鯉屋	畑中鯉屋 鯉甘煮 アレルゲン「小麦」の表示欠落	回収	2020/03/13
```

見た目上は、pandasのデータフレームに収納出来た・・・と思います。

はじめは、データフレームにその都度上場を書き込もうかと思ったけれど、やり方がわからずに断念。一先ず、それぞれの列のリストを作ってから、pandasに取り込む格好にしてみました。

ど素人なので、なんかの一つ覚えではじめはappend()で値を追加していました。しかし、それだとリスト形式で追加されてしまい、うまくpandasに取り込めませんでした。

色々調べてみると、リストの中の値だけを追加するには、extend()を使えばよいと分かりました。

一つ勉強になりました。

無事データも作れたので、データ分析をしてみたいと考えています。
今このデータで、分析出来そうな事は、
①リコールが起きた時の回収や返品の割合
②リコールが起きやすい時期はあるのか？

でしょうか。
色々試行錯誤してみたいと思います。
AWSプラクティショナー よく見る単語②

##AWSサービスでよく見る単語
**・EC2**
仮想サーバを提供してるサービス。一番よく見る単語でAWSといったらコレ。
インスタンスタイプから性能を選択することができる。

**・オンデマンドインスタンス**
使用した分だけ課金するインスタンス。

**・リザーブドインスタンス**
1年～3年の期間を決めて課金するインスタンス。
使用したい期間が決まっているときは安くすむので選択するべき。

**・スポットインスタンス**
めっちゃ安いインスタンス。そのかわりに処理途中で落ちることがある。
ちょっとしたテストや開発環境などで使用するといい。

**・ELB**
AWSのロードバランサ（負荷分散してくれるやつ）。
AutoScalingなどといっしょに問題で見ることもある。（詳しくは前記事参照）

**・Lambda**
AWSのプログラム実行サービス。
サーバが必要なく、コードを設置したらすぐ実行してくれるスゴイやつ。

**・ECS**
コンテナ(AWSサービスを利用したシステム全体)の管理をする。

**・Amazon Lightsail**
仮想プライベートサーバ。

**・AWS Batch**
バッチ処理実行環境のサービス。

##ストレージでよく見る単語
**・EBS**
EC2と一緒に使うストレージ。容量は少なめ。
4つくらいタイプがあるので適切なものを選択できる。

**・汎用SSD**
EBSのタイプの一つ。
最大10,000IOPSの性能をもつ。
※IOPSはI/Oの1秒当たりの処理数。要するに処理能力。

**・プロビジョンドIOPS SSD**
EBSのタイプの一つ。
10,000IOPSを越える性能をもつ。最大で64,000IOPS。

**・スループット最適化HDD**
EBSのタイプの一つ。
処理能力がそんなに必要なくて、コストを安くすませたい場合に使う。

**・Cold HDD**
EBSのタイプの一つ。
アクセス頻度が低い場合に使う。
(S3を使えばいいのでは？という意見もある。どっちでもいいんじゃねって感じ。
知らんけど)

**・S3**
めっちゃ容量があるストレージ。耐久性がイレブンナイン(99.999999999%)。
ストレージ料金がクラスによって異なるので使用頻度に合わせて選択できる。

**・標準**
ストレージクラスを選択しないデフォルト。
料金は0.025USD/GB。

**・低頻度アクセスストレージ(標準IA)**
S3クラスの一つ。
アクセス頻度が少ない場合に選択すると安くすむ。
料金は0.019USD/GB。

**・1ゾーン低頻度アクセスストレージ(1ゾーンIA)**
S3クラスの一つ。
アクセス頻度が少なく、耐久性を必要としないものを保存したいときに選択する。
料金は0.0152USD/GB。

**・Amazon Glacier**
S3クラスの一つ。
ほぼアクセスしないが、なくすことはできないものを保存したいときに選択する。
料金は0.005USD/GB。
※保存物の取り出しに物凄く時間がかかるが、課金すると早くできるらしい

**・ライフサイクルポリシー**
上記S3のクラスを経過時間でころころ変更していくこと。
コスト効率がよくなっていく。

**・EFS**
複数のEC2インスタンスで共有利用できるファイルストレージサービス。

**・Storage Gateway**
オンプレとAWSのストレージサービスをつなげられる。

**・Snowball**
ペタバイト級のデータ移動ができるサービス。
オンプレからAWSにデータを送りたい時などに利用される。
【RSpec】paramの書き方

## はじめに
paramとして渡された引数を使うメソッドのテストをするときに、データの作成方法で悩んだので備忘として残します。
`save_hoge`メソッドの中でprivateメソッド、`save_user_hoge!`が呼び出されます。
`hoge`は、メソッド内でparamとして使用されるため、形を整える必要がありました。

### メソッドのコード(省略してます)

```rb:app/models/user.rb
def save_hoge
  save_user_hoge!(hoge)
end

private
def save_user_hoge!(hoge)
    if hoge[:first_hoge_id].present?
      user_hoge.create(
        hoge_id: hoge[:first_hoge_id].to_i
      )
    end
    if hoge[:second_hoge_id].present?
      user_hoge.create(
        hoge_id: hoge[:second_hoge_id].to_i
      )
    end
end
```

## OK

```rb:spec/models/user_spec.rb
let!(:hoge) do
  {
    hoge: {
      first_hoge_id: 1,
      second_hoge_id: 2
    }
  }
end
```

```rb:spec/models/user_spec.rb
let!(:hoge) {
  {
    hoge: {
      first_hoge_id: 1,
      second_hoge_id: 2
    }
  }
}
```

## NG

```rb
let!(:hoge) { hoge: { first_hoge_id: 1, second_hoge_id: 2 } }
```

## まとめ

`do` `end`で囲む場合も、`{}`で囲む場合も同じだと指摘をいただきました。
NG例がだめな原因は、ハッシュをくくる`{}`が足りなかったからみたいです。
AI実装検定の感想と備忘録

記憶が薄くならないうちに、昨日実施されたAI実装検定の感想と備忘録を残そうと思います。
# ●AI実装検定とは
「[AI実装検定](http://kentei.ai/)」とは[Study-AI株式会社](http://study-ai.co.jp/)が運営する資格で、機械学習を実装できる能力を証明する資格です。
ただ第1回ということもあり、今後どれほどの効力を持つものかはまだわかりません。
（受験してみた限り「初歩は修得しました」という証明にはなるかな、といったところです。）

　ページ「[AI実装検定とは | AI実装検定](http://kentei.ai/introduction/feature)」によると、
> **【AI実装検定とは】**
> 　独りよがりの知識ではなく、体系的なディープラーニングの実装知識とスキルを自他ともに認められるための客観的なメジャーがAI実装検定です。
> 　この検定により自分の持っている知識、足りない知識をしっかりと把握することができ、客観的に証明することができます。
> 
> **【AI実装検定のその後】**
> ★AI実装検定の合格者には「ディープラーニング実装士」の称号が付与されます。ロゴや認定証が配布されますのでPRにご活用ください。
> ★AI実装検定（A級）合格者は「E資格」の勉強に取り掛かることができる実力を備えます。

ということです。
　注意すべきは**「「E資格」の勉強に取り掛かることができる実力を備える」**だけであって**「「E資格」の受験資格を得られるわけではない」**という点です。紛らわしい書き方してますよね。

# ●公式教材
### ■バンビチャレンジ
　ページ「[試験対策 | AI実装検定](http://kentei.ai/introduction/howto)」にて、「AI実装検定公式テキストの「バンビ・チャレンジ」」が紹介されています。現状**「テキスト版（講師解説なし）：　お一人様 3,000円（税込）　【期間限定販売中/受験エントリー者のみ購入可】」**だけ購入可能です。
　おそらくしばらくしたら**「ビデオ版（講師解説あり）　：　お一人様 45,000円（税込）【2020年5月1日 販売開始予定】」**だけになるかと思います。
　
### ■公式教材に関する注意事項
　まず第一に、公式テキスト「バンビチャレンジ」は試験範囲全体をフォローしていませんでした。肌感覚としてフォロー範囲は5~6割程度といったところでしょうか。上記試験対策ページには**「A級　～市販の書籍などでも対策可能です～」**とありますが、**むしろ市販の書籍などで対策しないとわからないところが少なくありませんでした。**特に数学の問題は別途学習が必要です。

# ●全体の流れ
　「数学問題20問→プログラミング問題20問→AI問題20問」流れで計60問の問題が出ました。
### ■数学問題
　半分以上公式テキストには含まれていない問題でした。別途高校数学の学習が必要と思います。行列問題と微分問題が3~4割ずつで比率的に高かったです。

### ■プログラミング問題
　半分近く公式テキストには含まれていない範囲の問題があった気がします。ただ[検定問題サンプル | AI実装検定](http://kentei.ai/introduction/subjecttrend)に載っている「Numpy」「Pandas」「Matplotlib」「Seaborn」「Sciket-learn」の基本を押さえておけば大丈夫だと思います。

### ■AI問題
　ほぼすべて公式テキストをしっかりやっておけば解ける問題だったと思います。1, 2問は変則的な問題がありました。

# ●個人的攻略方針と感想
### ■攻略方針
　全体として**「『知らないもの』は後回しにする」**を基本として立ち回りました。
　1時間で60問回答なのでG検定の2時間226問まではいきませんが速度が必要です。私は**「知っている問題＝10秒」「考えれば解ける問題＝45秒」くらい**を目標にしていました。
　それ以外の**「知らない問題（＝考えてもわからない問題）」は調べました。**これはオンライン試験の強みですね、ひたすらGoogleで検索しました。
　
　今回の試験は前ふたつ「数学問題」と「プログラミング問題」にわからない問題が集中しており、最後の「AI問題」に即答できるもの、あるいは少し考えれば解けるものが多くありました。そのため前半で悩みながら問題を解いていくと、最後のほうの比較的簡単な問題を解く余裕がなくなってしまったと思います。
　今回は**「わからないものは飛ばしてとりあえず全問見る」**を徹底して、とりあえず40分で最後まで行きました。そこから最初のわからなかった問題に戻り、調べながら進めて**1分前**にどうにか全問回答できました。

　この方法の何がいいっていうと**「ある程度の余裕をもってできる」**というところです。わからない問題は解けなくても仕方ない、それよりもわかる問題を解くときに余裕がないほうがリスクが高い、という考えはなかなか効果的だと思います。

### ■感想
　試験前から事務局の対応には不安がありました（連絡が来なかったり通知が遅れてきたりなど。）まぁそれは初回なので仕方ないのかもしれませんが、何とも言えない気持ちで試験に臨みました。
　また、今回は試験数日前に試験問題サンプルを確認し、嫌な予感がして公式テキスト以外書籍などで学習したのが功を奏しました。逆を言えば公式テキストだけで勉強した人は正答率がだいぶ低くなってしまったと思います。
　実戦での力をみるという点では間違いではないのかもしれませんが、公式テキストが試験範囲をフォローしていないというのは悩ましいところです。

　さらに言うと、試験の注意事項に**「試験においては、【14:05】以降の「はじめる」ボタン押下、【15:00】以降の「終了」ボタン押下は、実施履歴がシステムに記録されず『未実施・不合格』となりますので、十分にご注意ください。」**という記載がありました。
　試験開始5分後までしか入場を認めないのはわかるのですが、試験終了以降も「はじめる」「終了」ボタンが押せるのは仕様としてどうなのかと思います。
　全問回答後**「達成率が0％」**だったのも気になるところです。合格発表日に全員不合格だった、なんてことにならなければいいのですが。
　
　ちなみに上記の合わせ技で全問回答後達成率が0％で、おかしいと思って「はじめる」ボタンを押してしまった方もいるのではないか、というかいたらどうするのだろうという要らぬ心配もしています。
　
　以上、書き散らした備忘録でした。
DockerでDevice or resource busyと表示された時の対処法

# 問題が生じた状況
Docker Volumeを使ってる際に主に出ると思われる問題です。
自分はfirebaseのfirebase-tools.jsonというファイルをマウントする際に出た問題です。


# 解決策
Docker Volumeで<b>ファイル自体をマウントするのではなくディレクトリをマウント</b>するべきだった模様です。
かなり基礎的なミスな気がしますが、意外と検索してもこれを指摘する記事は出ませんでした。

#### 修正した方法
```diff:docker-compose.yml 
    volumes:
-      - "./secrets/firebase-tools.json:~/.config/configstore/firebase-tools.json"
+      - "./secrets:/root/.config/configstore/"

```     


# 自分の状況では解決しなかった方法
とりあえず片っ端から試したけどダメだったコマンドたち
もし上記の解決策がダメだったら試す価値はあるかもしれません。

## chown 
`chown -R $USER /path`
 だめだった
## lsof 
`lsof +D /path`
これもダメだった
## docker volume prune
`docker volume prune`
これも効果なし
Windows10へインストール操作しないで開発環境を作る（1日目）

# やりたい事
非力な開発環境なので頻繁にパソコンをクリーンインストールして利用中。クリーンインストールする度に環境構築をするのはかなり大変なので、簡単に開発環境を作る方法を模索中。
理想はクラウドIDEだと思うのだが、いまいち実現イメージが沸かない。
Git、Visual Studio Codeにポータブル版があるようなのできっと実現できるはず！と思って試行錯誤中。
# 実現したい事
クリーンインストール後のWindows10にサクッとPython開発環境を構築したい。
## 環境
- Windows10
- PortableGit
- Visual Studio Code（ポータブルモード）
DjangoアプリをローカルからAWSに上げたらCSSが適用されなくなった話

# 経緯
DjangoやAWSの学習のため、以下の記事を元にローカルでDjangoアプリを作成したあと、githubからAWSにclone。
[Django(Python)でシステム開発できるようになる記事_入門編](https://qiita.com/Saku731/items/ed64190a12a4498b9446)
[【20分でデプロイ】AWS EC2にDjango+PostgreSQL+Nginx環境を構築してササッと公開](https://qiita.com/tachibanayu24/items/b8d73cdfd4cbd42c5b1d)

AWS上で`python3 manage.py runserver`した後、ローカルでは管理画面に適用されていたCSSが適用されていないことに気づく。
<img width="1228" alt="スクリーンショット 2020-03-21 10.38.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409123/4a817c25-75dc-74cb-65e0-48e07701e26c.png">
# 解決方法
Nginxのログを確認した結果、CSSのパスが通っていないというエラーが発生しているのを確認。

```
$ tail -F /var/log/nginx/error.log
（中略）
2020/03/21 01:18:04 [error] 23086#23086: *197 open() "/home/ubuntu/repository/mysite/static/admin/css/base.css" failed (2: No such file or directory), client: XXX.XXX.XXX.XXX, server: XXX.XXX.XXX.XXX, request: "GET /static/admin/css/base.css HTTP/1.1", host: "XXX.XXX.XXX.XXX", referrer: "http://XXX.XXX.XXX.XXX/admin/login/?next=/admin/"
```

[Djangoにおける静的ファイル(static file)の取り扱い](https://qiita.com/saira/items/a1c565c4a2eace268a07)によると、パスを通すには`collectstatic`コマンドを使えば良い模様。
`settings.py`の静的コンテンツ取り扱いの設定値を以下の通り設定した後、`python3 manage.py collectstatic`を実行

```Python:settings.py
# 静的ファイルの呼び出し設定を１番下に追加
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_NAME = os.path.basename(BASE_DIR)
#STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] 
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
```

```
$ python3 manage.py collectstatic

You have requested to collect static files at the destination
location as specified in your settings:

    /home/ubuntu/repository/mysite/static

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes

119 static files copied to '/home/ubuntu/repository/mysite/static'.
```

staticディレクトリ配下に管理画面の静的ファイル(`~/.local/lib/python3.5/site-packages/django/contrib/admin/static/`配下にあるもの)がコピーされる。

```
$ ls ~/repository/mysite/static
admin  css  images  js
（css,image,jsはmkdirで作成）

$ ls ~/repository/mysite/static/admin
css  fonts  img  js
```

これによって管理画面のCSSのパスが通った。
<img width="984" alt="スクリーンショット 2020-03-21 11.16.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409123/2012117f-5ccb-8ec9-c6ba-4c5203af1f57.png">
Ruby on Railsで新規アプリケーションを立ち上げる自称最速手順(github連携)

#目的
新規のアプリケーションを作成する際、
毎回「あれ？次どうするんだっけ？」ってなって調べている時間がムダなので、
最低限のものを最速で作る手順を残しておきます。
細かいことにこだわらず、とにかくサッと作成したいときに参考にしてください。
githubにも連携します。

#前提
マークアップはhaml,scssを使用
リセットcssはyui3を使用
ローカルでビューファイルを開くところまでを記載

#1.Railsのバージョン確認

```terminal:ターミナル
% cd ~
% ruby -v
```
バージョンの変更が必要な場合は以下のコマンドを実行
(--version=以降は適宜指定してください。)

```terminal:ターミナル
% gem install rails --version="5.0.7.2"
% rbenv rehash
```

#2.アプリケーションの作成

```terminal:ターミナル
% cd
% cd projects
% rails _5.0.7.2_ new <アプリケーション名> -d mysql
% cd <アプリケーション名>
% rails db:create
% git init
```

#3.GitHubとの連携

GitHub DesktopのCurrent Repositoryタブ
→Add
→Add Existing Repository
→Chooseから ~ projects/<アプリケーション名>を選択
→Add Repository
→コミット名をinitial commitとし、Commit to master
→Publish repository
→Publish repository
→GitHubのリポジトリに反映していればOK

#4.ルーティング/コントローラー/ビュー　の設定

```ruby:routes.rb
Rails.application.routes.draw do
  root to: 'posts#index'
end
```

```terminal:ターミナル
% rails g controller posts
```

```ruby:posts_controller.rb
class PostsController < ApplicationController
  def index    
  end
end
```

```ruby:Gemfile
#最下部に追加
gem "haml-rails"
```

```terminal:ターミナル
% bundle install
```

###app/assets/stylesheetsフォルダ内で以下を実行
application.cssを削除する
application.scssを新規作成する
posts.scssのファイル名を \_posts.scssに変更する
\_reset.scssを新規作成する
ダウンロード/yui3-3.18.1/src/cssreset/css/cssreset.cssのコードを_reset.scssに貼り付ける

```scss:application.scss
@import "reset";
@import "posts";
```
###app/views/postsフォルダ内で以下を実行
index.html.hamlを新規作成

```haml:index.html.haml
hello
```

#確認

```terminal:ターミナル
% rails s
```
ローカルでhelloと表示されれば完了



以上です。
最後まで読んでいただきありがとうございました。