OmniAICreator/Qiita-1.07M huggingface dataset:
機械学習を一切使わずにレコメンドエンジンを作る方法

## はじめに
レコメンドエンジンというと、機械学習を使わなければいけないとか、難しそうといったイメージをお持ちの方が多いかと思います。この記事では、機械学習を一切用いることなくレコメンドエンジンを実装する方法について紹介します。
## レコメンドエンジンとは？
Amazonを使っていると、「この商品を買った人はこんな商品も買っています。」というものが出てきます。また、YouTubeで動画を見ていると関連動画というものが出てきます。この記事では、このようなアイテムベースのレコメンデーションについて述べます。「あなたへのおすすめ」のような、ユーザーベースのレコメンデーションについては触れないのでご了承下さい。
## 投票によるレコメンデーション
ユーザー登録が可能なサイトについては、ユーザーに投票させることでアイテムベースのレコメンデーションが可能でしょう。GitHubのトピックランキングはスター数によってソートされていますが、そのような感じです。問題は、一人で幾つものアカウントを取得することが可能である場合、スパムユーザーを検出するために機械学習が必要になってしまうことです。
## ハッシュキャッシュ
ここで、スパムメール検知について考えてみましょう。スパムメール検知というと、機械学習が唯一の手段だと思い込んでいませんか？実は、ハッシュキャッシュという技術でスパムメールをはじくことができます。ハッシュキャッシュの本質は「大量に計算したことの証明(Proof of Work)」です。大量に計算するにはお金が掛かるので、無差別にメールを送りつけるのは割に合いません。ハッシュキャッシュでは、ハッシュ値の先頭の0の個数が多くなる（ハッシュ値を符号なし整数とみなしたとき小さくなる）ようなノンスを見つけることで仕事量を証明しています。ハッシュキャッシュはビットコインのマイニングでも使われています。
## 作り方
いま、アイテムが複数あり、各アイテムにはIDが付与されているものとしましょう。アイテムAの関連アイテムとしてアイテムBに投票するには、アイテムAのID、アイテムBのID、そして適当なノンスを提出します。サーバー側ではこの三者を連結したものからハッシュ値を計算し、既存のハッシュ値よりも小さければノンスとハッシュ値をアップデートします。アイテムAの関連アイテム集合は、ハッシュ値の小さい順にソートして表示します。
## 終わりに
レコメンドエンジンの本質は「集合知」です。ハッシュキャッシュは、1ドル1票の原則に基づく投票である点で、集合知と言えるでしょう。また、確率的ではあるものの、非常に透明性が高いため、ユーザーからの信用も得やすいでしょう。
## Salona
Salonaでも同様の手法が用いられています。他の文書のIDをタイトルとした文書はその文書に対するトラックバックとして表示されます。実装の詳細については[Salonaのページ](https://salona.org/salona)をご覧ください。
Raspberry Pi OSのBullseyeへの更新

Raspberry Pi OS の最新公式リリースは[Buster](https://raspida.com/raspbian-buster-update202002) ですが、次のベータテスト版である[Bullseye](https://www.debian.or.jp/using/release.html) にアップグレード（更新）する手順です。OpenCV 4.2など最新のバージョンを使いたいときに便利です。以下の作業は`sudo bash` などしてすべてroot権限（コマンドプロンプトに `#`が含まれる状態）で行って下さい。

1. `/etc/apt/sources.list` に、32ビット版は `deb http://raspbian.raspberrypi.org/raspbian/ bullseye main contrib non-free rpi` 、64ビット版は `deb http://deb.debian.org/debian bullseye main contrib non-free` を追加します。
2. `apt-get update`
3. `apt-get --with-new-pkgs upgrade`
4. `apt-get --autoremove purge libgcc-8-dev gcc-8-base` (これをしないと次の`dist-upgrade`ができない)
5. `apt-get --purge dist-upgrade`
6. `sync`
7. `systemctl reboot`

以上です。
【C/C++】苦手なポインタについて新卒エンジニアが解説してみた

#はじめに
私の苦手なポインタについて、基本的な使い方、値渡し、ポインタ渡しについて解説する。

#対象者
- 未経験新卒エンジニア
- C/C++ 入門者
- ポインタがイマイチ理解できていない方

#ポインタとは
・ポインタとはアドレスを記憶する変数である。
・例えば、型をpaとしたときpa*の型は、paへの"ポインタ"である。
と、言われてもピンと来ない人が大半だと思う。下記のコードを見てほしい。

```C++
int a = 100;
int* pa = &a; // paはaのアドレスを保持:&はアドレス演算子
cout << *pa << endl; // 出力結果：100（変数にアスタリスクをつけることによってアドレスの中身を参照できるようになる）
cout << &a << endl; // 出力結果：0x61ff08 (アドレスが出力される)※実行環境によって出力結果は異なる
```
・一行目：aの箱（変数）に100を代入
・二行目：100が代入されているaの"アドレス"をpaに代入している。
※アドレスを取得するには、アドレス演算子である<b>&</b>を使用する

図で表すと以下の用になる。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609522/92340f79-059f-409b-d4ae-d10cf52f90c7.png)
イメージできただろうか。

つまり、アドレスの受け渡しで値の受け渡しができるということである。
次は通常の値の受け渡し方法とポインタを利用した値の受け渡し方法解説する。

#値渡しとポインタ渡し
###値渡し
値渡しを一言でいうと、値がコピーされて引数に渡される。
実際にコードで確認する。

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

int add(int a, int b) {
	a = a + b;
	return(a);
}

int main(void) {
	int x = 100;
	int y = 200;

	int total = add(x, y); // 引数として100と200をint a、int bにコピーする
	cout << total << endl; // 出力結果：300
}
```
これはaddの引数にxとyを指定して受け取る引数にコピーさせている。
今回の例ではサイズが小さいので問題はないが、サイズの大きい型が引数である場合、プログラム実行結果に大きな差が現れてしまう。
また、int型は４バイトであるので、今回は８バイト、コピー分も含めると16バイトを使用してしまうことになる。
次はこれをポインタで行うとどうなるか確認していく。

###ポインタ渡し
値渡しでの処理をポインタ渡しで記述する。

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

void add(int* a, int* b) {
    *a = *a + *b;
    cout << *a << endl; // 出力結果：300
}

int main(void) {
    int x = 100;
    int y = 200;
    add(&x, &y); // 引数として「x」の"アドレス"と「y」の"アドレス"を設定する
}
```

- main関数のaddの引数としてxとyの"アドレス"を設定する。
- 呼び出されたadd関数は引数でアドレスを受け取り、その中身を参照する。
- 値渡しでは16バイトを使用していたが、今回のポインタ渡しでは8バイトで収まっている。

値渡しではxとyの値を"コピー"していたが、ポインタ渡しでは"アドレス"を参照することによってメモリの節約、処理速度の高速化につながっている。

#確認
最後に確認をしてみよう。
xとyの出力結果を考えてほしい。

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

void add(int* a , int* b) {
	*a = *a + *b;
}

int main(void) {
    int x = 100;
    int y = 200;

    add(&x, &y);
    cout << x << endl; // 出力結果x：
    cout << y << endl; // 出力結果y：

}
```
答え：xは300、yは200

yが200というのは誰でもわかるだろう。
では、なぜ、xが300になるのか。

それはadd関数の引数として"アドレス"で渡しているからである。
100と200を指すアドレスを渡してxのアドレスにxのアドレスの中身(100) + ｙのアドレスの中身(200)を*aに加算し代入している。
add関数内のaはxの"アドレス"を保持しているのでaの値を書き換えるとxの値も書き換わる。

#まとめ
今回はポインタについて簡単に解説してみました。
初めてのQiita投稿でしたが、わかりやすく伝えるというのは本当に難しいですね。
しかし、それと同時に楽しさもありました。自分自身のアウトプットにもなるため、今後も少しずつ記事を投稿していきたいと思います。

#最後に
私自身、まだまだ理解が追いついていない部分のため、誤った記載がありましたら、ご一報いただけると幸いです。

#参考文献/参考サイト
ビャーネ・ストラウストラップ[柴田望洋 訳] プログラミング言語C++ [第４版]
C++ 値渡し、ポインタ渡し、参照渡しを使い分けよう
【 https://qiita.com/agate-pris/items/05948b7d33f3e88b8967 】
手を動かしてさくさく理解する C言語/C++ ポインタ入門 
【 http://vivi.dyndns.org/tech/cpp/pointer.html 】
Markdown 書き方 その1

#はじめに
新卒1年目のエンジニアです。
得た知識を着実に定着させるために、最低でも週1で投稿していきます。

今回と次回の記事は、今後記事を投稿する上で必要となる`Markdown`の書き方をまとめます。

#目次

1. 見出し
2. コードの挿入
3. 引用
4. インライン
5. 太字


#1.見出し
■書き方
**文頭に`#`をつける**
`#`は1~6個つけることで、HTMLのH1~H6まで表現することが可能。
H3から下線が無くなる。

```
#見出しH1
##見出しH2
###見出しH3
####見出しH4
#####見出しH5
######見出しH6
```
■結果
>#見出しH1
>##見出しH2
>###見出しH3
>####見出しH4
>#####見出しH5
>######見出しH6

#2.コードの挿入
■書き方
**バッククオートを使用**して以下のように記述する。
空行を前後に忘れないこと。
>>(空行)
\`\`\`
console.log("Hello, World!");
\`\`\`
>>(空行)

■結果

```
console.log("Hello, World!");
```

ファイル名を表示したい場合は使用言語とファイル名を以下のように記述する。
>>(空行)
\`\`\`javascript:HelloWorld.js
console.log("Hello, World!");
\`\`\`
>>(空行)

■結果

```javascript:HelloWorld.js
console.log("Hello, World!");
```
#3.インライン
■書き方
こちらも**バッククオートを使用**して以下のように記述する。

```
`インライン`
```

■結果
`インライン`

#4.太字
■書き方
**アスタリスク**を使用して以下のように記述する。

```
**太字**
```

■結果
**太字**になりました

#5.引用
■書き方
`>`を使用して以下のように記述する。

```
>引用
>>引用
```

■結果
>引用
>>引用


#終わりに
今回は記事を投稿する上で最低限必要な知識をアウトプットしました。
次回はより発展的な内容をアウトプットしていきます。

#参照
[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
[Qiita マークダウン記法 一覧表・チートシート](https://qiita.com/kamorits/items/6f342da395ad57468ae3)
[Markdown記法 サンプル集](https://qiita.com/tbpgr/items/989c6badefff69377da7)
個人的によく使うGitコマンド

仕事でもプライベートでもGitを使うことが多いので、
個人的に使うGitコマンドをまとめました。
Gitコマンド忘れた場合は是非、こちらのページを参考にしてください。

## clone
- リモートリポジトリをローカルに複製する

```bash
git clone <リポジトリのURL>
```

## remote
- fork元を追加する

```bash
git remote add <名前>　<リポジトリのURL>

# よく使うのは
git remote add upstream <リポジトリのURL> #fork元リポジトリを追加する
```

## fetch
- リモートリポジトリの情報を取得する

```bash
git fetch <リモート名>

# よく使うのは
git fetch origin 
git fetch upstream
```

- フェッチする際にリモートリポジトリ上で削除されたブランチを削除する

```
git fetch -p <リモート名>
```

`-p`は毎回つけたいので`.gitconfig`のエイリアスに追加する

```bash
[alias]
        fetch = fetch -p
```

## switch
- ブランチを作成し、作成したブランチへ移動する

```bash
git switch -c <ブランチ名> <作成元ブランチ>

よく使うのは
git switch -c <ブランチ名> upstream/master #fork元のmasterから作成する
```

- ブランチを移動する

```bash
git switch <ブランチ名>
```

## branch
- ブランチを作成する

```bash
git branch <ブランチ名> <作成元ブランチ>

よく使うのは
git branch <ブランチ名> upstream/master #fork元のmasterから作成する
```

- ブランチを削除する

```bash
git branch -D <ブランチ名> #カレントブランチを削除したい場合は一旦他のブランチに移動してから実行する
```

## add
- 対象のファイルをインデックスに追加する

```bash
git add <ファイル>
```

- 全てのファイルをインデックスに追加する

```bash
git add .
#または
git add --all 
```

## restore
- 対象のファイルをワークツリーに移動する

```bash
git restore --staged <ファイル名>
```

- 対象のファイルをワークツリーから破棄する

```bash
git restore --worktree <ファイル名>
```

- 全てのファイルをワークツリーに移動する

```bash
git restore --staged .
```

- 全てのファイルをワークツリーから破棄する

```bash
git restore --worktree .
```

## commit
- コミットする

```bash
git commit -m "コミットメッセージ"
```

- コメントメッセージを修正する

```bash
git commit --amend
```

## push
- プッシュ先のブランチを追跡ブランチとして登録する

```bash
git push -u <リモート名>　<ブランチ名>:<リモートリポジトリのブランチ名>
```

- 強制的にプッシュする

```bash
git push --force-with-lease <リモート名>　<ブランチ名>:<リモートリポジトリのブランチ名>
```

## pull
- `fetch + merge`ではなく`fetch + rebase`で実行する

```bash
git pull --rebase
```

## merge
- no fast-forwardでマージする

```bash
git merge --no-ff <ブランチ名>
```

## rebase
- コミットを1つにまとめる

```bash
git rebase -i <コミットハッシュ値>
```

※`rebase -i`については以下を参考にしてください。
https://qiita.com/KTakata/items/d33185fc0457c08654a5#git-rebase--i---interactive

- マージコミットを残したままリベースする

```bash
$ git rebase --rebase-merges <ブランチ名>
```


## cherry-pick
- あるコミットの差分をインデックスに追加する

```bash
git cherry-pick -n <コミットハッシュ値> 
```

## stash
- 一時保存(退避)する

```bash
git stash push "メッセージ"
```

- 一時保存(退避)したものを戻す

```bash
git stash apply stash@{数字}

# 数字については
git stash list
# で確認
```

- 一時保存(退避)したものを戻して、削除する

```bash
git stash pop stash@{数字}
```
ハミング符号の訂正

応用情報技術者平成30年春期 午前問3


ハミング符号とは，データに冗長ビットを付加して， 1ビットの誤りを訂正できるようにしたものである。ここでは，X1，X2，X3，X4の4ビットから成るデータに，3ビットの冗長ビットP3，P2，P1を付加したハミング符号 X1X2X3P3X4P2P1を考える。付加ビットP1，P2，P3は，それぞれ
　 X1⊕X3⊕X4⊕P1＝0
　 X1⊕X2⊕X4⊕P2＝0
　 X1⊕X2⊕X3⊕P3＝0
となるように決める。ここで⊕は排他的論理和を表す。
　 ハミング符号 1110011 には1ビットの誤りが存在する。誤りビットを訂正したハミング符号はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/9ef319c8-545c-0e01-d5e0-3efdb616c95d.png)


ロジックとしては、
X1X2X3P3X4P2P1　＝　1110011 とすると、
　X1=1，X2=1，X3=1，X4=0，
　P1=1，P2=1，P3=0
になりますね。

そうすると、付加したハミング符号の結果は、

式１）　X1⊕X3⊕X4⊕P1	＝1⊕1⊕0⊕1	0⊕1	=1
式２）　X1⊕X2⊕X4⊕P2	＝1⊕1⊕0⊕1	0⊕1	=1
式３）　X1⊕X2⊕X3⊕P3	＝1⊕1⊕1⊕1	0⊕1	=1

になります。

つまり、三つはすべて間違っているよね。
その三つは、全てあるのビットは、X1ですので、X1が間違っていることが分かれます。
なので、X1を訂正しなきゃいけないです。訂正の方法は唯一で、反転ですね、
1110011 →　0110011
になります。

考え方が分かった上で、仮に、条件は下記のよう
式１）０
式２）１
式３）１
に変わるとすると、間違っているのはどれかとは、X2ですね。

式達の結果により、どのビットが間違っていることが分かれることは、ハミング符号とのものです。

参照：
https://kanauka.com/kakomon/ko/h25h/001.html
Protocolでパラメータの型をしばる

#Protocolとダックタイピング
動的型付け言語のいいところはダックタイピングが気軽にできること。

##3.7以前
```py
def greet(o):
  print(f'Hi {o.name}!')
```
3.7以前は引数oにnameがあることを保証するにはnameを持つ方Personを定義して、タイプヒント用いてしばる必要があった。

```py
def greet(o: Person):
  print(f'Hi {o.name}!')
```
ただ、この関数を安全に使おうと思うとPersonを継承しなければならず、Dog型のオブジェクトをパラメータとして渡そうと思うとPersonを継承しなければならず、おかしな継承を強いられる。


##3.8以降
Python3.8からProtocolが追加された。
[PEP544](https://www.python.org/dev/peps/pep-0544/)にあるように、ダックタイピングを安全に行うために便利。

```py
from typing import Protocol

class HaveName(Protocol):

  @property
  def name(self) -> str:
    return None
```
Protocalを継承したこのようなクラスを定義して、nameをプロパティに持つクラスを作ると、継承がいらなくなる。

```py
class Person:

  def __init__(self, name):
    self._name = name

  @property
  def name(self) -> str:
    return self._name
```

```py
def greet(o: HaveName):
  print(f'Hi! {o.name}')

greet(Person('name'))
```
VScode+RemoteWSLでWindowsのPython実行環境を作る

この記事ではVScodeとWSLを用いてWindows上で動くPythonの実行環境を作成する方法を解説します。
# メリット
具体的な構築方法に入る前にまず、多くあるPython実行環境の中でこれを選ぶメリットを解説したいと思います。
1. VSCode上でステップ実行等の高度な機能が利用できる
2. インストールするパッケージの管理が容易
3. 必要な機能を選んで使用することができる。

まず1に関してVSCodeを用いることで特別な設定をほぼ行うことなくプログラムのステップ実行(一行ずつ挙動を確認しながら実行すること)やオートフォーマット(スペーシングなどのプログラムの見た目の調節を自動で行う機能)を利用することができます。
次に2に関して。この環境ではPythonにデフォルトで備わっている仮想環境の機能を使用します。そのため、pipによるコマンドベースでのパッケージの管理を行うことができます。また、VSCodeから使用することでactiveな仮想環境の切り替えを容易に行うことが可能です。
最後に3つ目に関してです。今回構築する環境でインストールするのはVSCode関連では拡張機能のRemote-WSLとPython、WSL関連ではPythonのみです。ミニマムな構築からVSCodeの拡張機能を用いた便利機能満載の構築まで自分で選択して行うことができます。
# 構築手順
それでは実際の構築手順を確認していきます。すでに多くの記事が存在しているため、VSCodeのインストールおよびWSLのインストールに関しては省略させていただきます。
##WSL側のセットアップ
Pythonのインストール。お好みでバージョン指定なんかを入れてください。
```sudo apt install -y python
```
プロジェクトのディレクトリを作り、その配下に仮想環境フォルダを作成します。
```mkdir sample_project
cd sample_project
python3 -m venv venv
```

## VS Code側のセットアップ
拡張機能の「Remote-WSL」をインストールしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246777/608c6115-e4fd-1a6e-da60-07874bba04fb.png)
その後、一度Remote-WSLを開き(左下、緑色のアイコン)、Remote-WSL側に拡張機能の「Python」をインストールしておいてください。（Windows側とRemote-WSL側で拡張機能が分けて管理されています。すでにPythonの拡張をインストールしている場合でも追加の設定が必要です）
#コード実行方法

Remote-WSLの機能を用いてVS Code上からWSL上に作成したsample_projectフォルダを開きます(メニューのファイル→フォルダを開くより)。
この状態でVS Codeがフォルダに配置されている仮想環境を認識し、自動で読み込みを行ってくれます。実行したい.pyファイルを開き、F5キーを押すことでフォルダ内の仮想環境がactivateされた状態でコード実行を行うことができます。ブレイクポイントの設定等も可能です。
画像フォルダ横断でのスライドショーを楽しむためのPowerShellスクリプト

# はじめに

画像収集の結果をWebページ単位でフォルダ管理していると、画像を複数指定するのではなく、画像フォルダを複数指定してスライドショーを表示したくなるタイミングがあった。
その際に、先のニーズに合ったOSSやフリーウェアを見つけられなかった為、[IrfanView](https://forest.watch.impress.co.jp/library/software/irfanview/)とPowerShellで複数画像フォルダ指定でのスライドショーを表示するアプローチを採用した。

# 成果物

成果物はGithubで共有しており、同様のお困り事がある方が使えるようにしている。使用方法はReadmeに記載し、また、ライセンスはMitライセンスとしている。

[Github - nezuQ/Nezuq-IV-FolderSlideshow: IrfanViewとPowerShellで複数画像フォルダ指定でのスライドショーを表示する。](https://github.com/nezuQ/Nezuq-IV-FolderSlideshow)

# 解説

IrfanViewは、コマンドラインでの操作を受け付けており、画像ファイルのアドレスを列挙したテキストファイルを指定する事で、スライドショーを表示する事ができる。その為、指定した複数の画像フォルダを元にPowerShellで先のテキストファイルを生成し、読み込ませる事でニーズを解消できた。その際、画像フォルダ内の画像はWindowsエクスプローラー内での表示順を模した順で表示する。（ex.1.gif, 5.gif, 10.gif）
一年プログラマをやれば今の自分とは比べ物にならないぐらい成長していると過信していた自分を殴りたい

**この記事は未経験からSESとしてプログラマーになったやつがこれまで何をしてきたかを振り返るものです**


**これまでの経歴**
・高卒(地元の普通科高校)
・プログラミングスクールに通ったことはない
・プログラミングのプの字も知らない奴が独学してSES会社に入社した
実務経験は10ヶ月程
その半年はほぼテストを担当していた経歴になります。
こんな奴でもプログラマーとして食っていけてます。プログラマーとして名乗るのが恥ずかしいぐらい自分はスキルはないですが。



**内定が決まってから入社まで【2019年2月〜5月】**
2019年の5月に上京してきて、未経験OKで研修3ヶ月でプログラマーになれるというありふれたSES会社に内定が決まった。
これで自分もプログラマーになれるとキラキラした感情だけがあった。この後、SESとして現場に常駐して、精神を病むことになるとは思いもしなかった。
入社前に進めておいてと言われた研修内容のHTML,CSS,JQueryを調べながらなんとか進めていた。


**入社後から研修期間の3ヶ月間【2019年5月〜7月】**
正直、楽しくて仕方なかった。
研修内容は今思うとフロントは特に内容が薄かった。JQueryで動的なUI、Ajaxを導入して実装するぐらいだった。今の研修はどうか知らんが。
サーバーサイドがとにかく楽しかった。
Laravelを使って実装するんだけど、エラーが出ていたりして、全く進まないこともあった。それでも今振り返っても楽しかった。
研修期間のスケジュールは
10：00〜19：00　会社に出社して研修を進める。
19：20　帰宅
20：00〜就寝時刻まで研修
空いてる時間は全て研修にあてていた。
休憩なんて取った記憶がない。お昼食べながらとにかくプログラミングしていた。
同期に「バケモンだな」って言われたことがあったけど、自分では普通だと思っていた。
その同期は「平日研修しているのに休日までプログラミングしたくない」と言っていて、驚いた。
結局彼は研修が終わらないまま、現場に出ることになった。当然かもしれないが、研修が終わらなくて現場で活躍している人を聞いたことがない

研修3ヶ月目になると案件に参画するための面談対策があった。
自分のスキルシートが渡され、みてみると
実務経験2年
スキルシートが完璧に盛られている。でもこれが普通だと思っていた。ほんとおかしな話だが

**1件目の現場【2019年8月〜2020年1月】**
今までの現場の中で一番辛かった現場である。
プロジェクトがぱんぱんで、全く回っていないのに、上司が次々とプロジェクトをとってくる。正直炎上していたと思う。
同時に参画した女性プログラマがその月に辞めていったので、やっぱこの現場は最悪だったなと思う。
書かれているコードが全く読めないのだ。そのコードはZendで書かれていたのだが、全く自分の中でつながらない。
簡単な修正すら何日もかかった。
そして、その現場のメンバーの1人の女性にものすごく冷たくあたられることになる。
同じ空間にいるのに私に聞こえるように
「コードのマージすらできないんですよ！」とインフラ担当の男性に愚痴っていた。
今書いていても辛くなる。
あるとき、帰りのホームでいつのまにか泣いていた。
もう限界だった。何度死のうと思ったことか。
営業に現場を変えて欲しいと相談しても
「契約期間があるから無理」
「契約期限が近づいてきたら考えよう」という返事があった。
もう無理だって言っているのに、「考えよう」なんだ。現場を変えてくれるように動いてくれようとすらしないのかこの会社はと思った。このとき、自分の中の会社に対する不信感が募って、辞めようとおもった瞬間だった。
でも幸いなことに現場のほうから契約を終了するという返事が返ってきた。
やっとこの地獄から抜け出せると思った。

**2件目の現場【2020年2月~5月】**
ここでは一番感謝している現場である。
最終的に現場から4ヶ月で契約を切られることになるがこれは完全に自分が悪く、仕事の進め方において積極的に動かず自分に与えられたタスクしか考えずに仕事をしていたからだ。
でもここで初めて自分でもプログラミングで今発生している問題を解決する力があるんだという機会を与えてくれた現場だったし、学ぶことがものすごく多かった。
問題はこの後の**待機期間**である

**待機期間【2020年6月〜8月】**
コロナの関係で案件が少なくなって面談を組めないという営業の言い訳を聞きながら、自己学習を進めていた。
最初は早く現場に入りたい気持ちでいた。すぐに現場も決まるとたかを括っていた。
だんだんそうではないと気づいたのが待機して2ヶ月目の7月。その間に面談したのがたったの2件。
そんな中、待機期間が長くなってくると自分の中で**「このまま現場に出て仕事したくない」**という気持ちに変わっていった。
プログラマーとして仕事することに完全に自信がなくなった。
そして待機期間3ヶ月目の8月に入る。
このまま現場が決まらずにいても自分にとって良くないけど、自分じゃどうにもできないしどうしようと思っていたところに面談が入った。面談の手応えは全くなかったので、営業から連絡がきたらこのまま辞めようと思っていた。
そんなときに営業から電話で
**「面談の結果OKだったよ」**
...マジか、辞められなくなった。そして今その現場で仕事して1週間が経つ

**終わりに**
こんなプログラマーもいるんだよと知って欲しくてこの記事を書きました。
周りより自分のスキルが劣っていると感じてもあまり落ち込まないでください。その分学ぶことが多いので自分のスキルアップにつながります。
そうは言っても落ち込むものは落ち込むのが人間ですからね。
そんなときは美味しいものを食べて、お風呂に入って、すぐ寝ましょう。すっきりしますよ。
この記事を読んでこいつよりはマシだな、明日も頑張ろうなんて思ってくれたら嬉しいです。
AIにおけるディープラーニング

応用情報技術者平成30年春期 午前問1

AIにおけるディープラーニングに最も関連が深いものはどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/3bc8790c-a36d-c53a-f50f-0f4577b12279.png)


１、ディープラーニング(Deep Learning)は、
人間や動物の脳神経をモデル化したアルゴリズム(ニューラルネットワーク)を多層化したものを用意し、それに「十分な量のデータを与えることで、人間の力なしに自動的に特徴点やパターンを学習させる」ことをいいます。

２、木構造やグラフ構造に対する「深さ優先探索」に関する記述
試行錯誤しながら条件を満たす解に到達する方法であり，場合分けを行い深さ優先で探索し，解が見つからなければ一つ前の場合分けの状態に後戻りする。

３、コンピュータの制御に偶発的な要素を取り入れる「遺伝的アルゴリズム」に関する記述
生物の進化を模倣した方法であり，与えられた問題の解の候補を記号列で表現して，それを遺伝子に見立てて突然変異，交配，とう汰を繰り返して逐次的により良い解に近づける。

４、焼きなまし法に関する記述
物質の結晶ができる物理現象を模倣した方法であり，温度に見立てたパラメタを制御して，大ざっぱな解の候補から厳密な解の候補に変化させる。

・焼なまし（やきなまし、英語: annealing）、焼鈍し、焼き鈍し、焼鈍（しょうどん）、アニーリングとは、加工硬化による内部のひずみを取り除き、組織を軟化させ、展延性を向上させる熱処理である。 目的に応じて多くの種類・方法が存在する。


参照

焼なまし
https://ja.wikipedia.org/wiki/%E7%84%BC%E3%81%AA%E3%81%BE%E3%81%97#:~:text=%E7%84%BC%E3%81%AA%E3%81%BE%E3%81%97%EF%BC%88%E3%82%84%E3%81%8D%E3%81%AA,%E7%A8%AE%E9%A1%9E%E3%83%BB%E6%96%B9%E6%B3%95%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E3%80%82


https://www.ap-siken.com/kakomon/30_haru/q1.html
CSSでヘッダーメニューを上部に固定する方法（多階層メニュー）

# 概要
前回、[CSSでヘッダーメニューを上部に固定する方法](https://qiita.com/Tamamotch/items/c19e0415d4ff6ec75285)を投稿しましたが、メニュー構造を多階層にしたい時もあるでしょう。
ということで、前回のコードを応用して多階層メニューの上部固定を行います。
この記事だけを見ても分かるように、前回と重複する説明ももう一度記載しておきます。

**キーワード**
*position: sticky; display: flex;*


# サンプル
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="tamamotch" data-slug-hash="GRZEQEG" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ヘッダーメニューを上部に固定（多階層メニュー）">
  <span>See the Pen <a href="https://codepen.io/tamamotch/pen/GRZEQEG">
  ヘッダーメニューを上部に固定（多階層メニュー）</a> by Tamamotch (<a href="https://codepen.io/tamamotch">@tamamotch</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


# 解説
## 前処理

```css
* {
  margin: 0;
  padding: 0;
}
```

デフォルトCSSの関係であちこちに隙間ができてしまうので上書きする。
指定した覚えのない謎の隙間がある場合はデフォルトCSSを疑うべし。


## header

```css
header {
  position: sticky;
  top: 0;
  z-index: 100;
}
```

`position: sticky;`
**header**要素をスティッキーアイテムにする。
自動的に親要素である**body**要素がスティッキーコンテナになる。
これにより、**header**要素が貼り付く。
なお、スティッキーコンテナ内に兄弟要素がないときちんと貼り付かない仕様とのことなので、兄弟要素**main**も用意する。
試しに**main**要素を丸っと削除すると、スクロールと共に**header**要素が流れていってしまうのが分かる。

`top: 0;`
貼り付く場所を最上部に固定する。

`z-index: 100;`
スクロールした時に全要素の上に重なるよう、適当な大きさを指定しておく。


## 親メニュー、子メニュー共通

```css
.ul-menu,
.ul-submenu {
  list-style-type: none;
  text-align: center;
}
```

`list-style-type: none;`
リストのマーカーを削除する。

`text-align: center;`
テキストを左右中央寄せにする。


## 親メニュー

```css
.ul-menu {
  display: flex;
}
```

`display: flex;`
**ul**要素をflexコンテナにし、子要素**li**をflexアイテムにする。
これにより、子要素**li**が横並びになる。

```css
.li-menu {
  flex: 1;
  position: relative;
}
```

`flex: 1;`
flexアイテムである**li**要素の横幅を均等にする。
試しにこれを削除すると、**li**要素の横幅がそれぞれのテキスト幅になるのが分かる。

`position: relative;`
子メニューの位置決定のために設定しておく。


## 子メニュー

```css
.ul-submenu {
  position: absolute;
  width: 100%;
  visibility: hidden;
}
```

`position: absolute;`
親ボックスを基準に位置を決める。
そのためには、親ボックス(**.li-menu**クラス)に`position: relative;`を設定しておく必要がある。
これにより、親メニューの真下に子メニューが配置される。

`width: 100%;`
親ボックスと同じ横幅にする。

`visibility: hidden;`
非表示にする。


## 親メニュー > 子メニュー

```css
.li-menu:hover > .ul-submenu {
  visibility: visible;
}
```

`visibility: visible;`
**li-menu**クラス（**li**要素）にカーソルを合わせると、直下の**ul-submenu**クラス（**ul**要素）を表示する。


## クリック範囲

```css
a {
  display: block;
  text-decoration: none;
  padding: 10px 0 10px 0;
}

```

`display: block;`
表示形式をblockにする。
これにより、**a**要素のクリック範囲が親要素**li**のサイズと同じになる。

`text-decoration: none;`
見栄えのために、テキストの装飾（リンクの下線）を行わない。

`padding: 10px 0 10px 0;`
見栄えのために、上下に10px太らせる。

```css
.a-1 { background-color: pink; }
.a-2 { background-color: moccasin; }
.a-3 { background-color: lightblue; }
.a-2_1 { background-color: orange; }
.a-2_2 { background-color: gold; }
.a-2_3 { background-color: yellow; }
```

`background-color: xxx;`
デモ時に分かりやすいように各範囲に色を付けておく。


## main

```css
main {
  height: 500px;
}
```

`height: 500px;`
ある程度スクロールできるよう、高さを持たせておく。
Gitlab起動時に「runsv not running」エラーが出た場合の対処法

↓を実行して

```bash
sudo gitlab-ctl start
```

↓のエラーが出た場合は

```bash
fail: alertmanager: runsv not running
fail: gitaly: runsv not running
fail: gitlab-exporter: runsv not running
fail: gitlab-workhorse: runsv not running
fail: grafana: runsv not running
fail: logrotate: runsv not running
fail: nginx: runsv not running
fail: node-exporter: runsv not running
fail: postgres-exporter: runsv not running
fail: postgresql: runsv not running
fail: prometheus: runsv not running
fail: puma: runsv not running
fail: redis: runsv not running
fail: redis-exporter: runsv not running
fail: sidekiq: runsv not running
```

↓で直るかもしれません。

```bash
sudo /opt/gitlab/embedded/bin/runsvdir-start
```

**環境：**

|||
|:--|:--|
|Ubuntu|18.04.5 LTS (Bionic Beaver)|
|gitlab-cli|1:1.3.0-2|
|GitLab Community Edition|13.0.5|
「NrealLight Developer Kit」でWifi接続、OSアップデート等を行う方法

##はじめに
NrealLight Developer Kitで個人アプリを開発する際、
例えば
>・Wifi接続
・OSアップデート
・インストールしたアプリの残骸の削除等

したいことはいっぱいあります。

**ですが**、「NrealLight Developer Kit」は「NrealLight」と違い、
Nreal独自の**Computing Unit**があります。
※「NrealLight」は推奨スペックを満たすスマートフォンを使用します。

####つまり、スマートフォンの画面が無いので、困ったと言う話です。

（また、個人的に、OSアップデートで無くなるエラーもありましたので、
この機会にそれらを行う方法を書きたいと思います。

##「scrcpy」コマンドを使用する
```
scrcpy
```

##「scrcpy」とは

>このアプリケーションは、USB（またはTCP / IP経由）で接続されたAndroidデバイスの表示と制御を提供します。

**つまり、接続したAndroidデバイスの画面を出力できるものらしいです。**

必要条件や、インストール方法などは、
下記の参考にさせていただいたページをご覧ください。
参考 : https://github.com/Genymobile/scrcpy

##実際にやってみた
私はMacOS環境で行なっております。

「Computing Unit」をType-CーUSBで接続し、
デバイスの認識が確認できたところで、下記コマンドを入力
（※デバイス認識の有無は「[adb devices](https://developer.android.com/studio/command-line/adb?hl=ja#Enabling)」コマンド等で確認してください。

```
scrcpy
```
AndroidOSのホーム画面が立ち上がりました。
![HomeDisplay.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/d5baf911-1935-913f-f2e2-b664c60d0273.png)

Androidスマートフォン同様、
SettingでWifi設定やOSアップデートなどを行うことができます。
![SettingDisplay.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/c4014ccc-fa25-1187-ddad-b39895286844.png)

##「scrcpy」を使用する時は？
個人の意見ですが、「scrcpy」を使用するのは
>・デバイスの設定
・インストールしたアプリの確認

ぐらいかなと思っています。(現状

NrealLightのグラス上のホーム画面では、個人開発アプリを1つしか表示できません。
adbコマンドでアンインストールせずにインストールすると、エラーを吐いたりも、、（上書きなら問題ない）

また、グラス上の設定画面で設定できることは**非常に少ない**ため
そんな時に「scrcpy」を使っていく感じだと思います。

##おわりに
がっつりNreal Lightの開発はしてないので、なんともですが、
知っていて損はないと思います。
（Snapdragonを用いた開発等でも「scrcpy」を使ったりするのだろうか...)

今回、ただ「scrcpy」を紹介しただけになりましたが、
今後もNreal Lightに関する記事を書いていきたいと思います。

##参考
https://github.com/Genymobile/scrcpy
https://developer.android.com/studio/command-line/adb?hl=ja
UITableViewのinsertRows()でEXC_BAD_ACCESSが発生した件

筆者が開発しているiOSのアプリで、App Store Connect経由でクラッシュログが繰り返し送られてくるものの、再現方法も解決方法もずっと謎であった不具合が解決したのでメモとして残しておきます。

## 問題の内容

送られてくるクラッシュログは以下のようなものでした。

```
Thread 0 name:
Thread 0 Crashed:
0   UIKitCore                     	0x000000018fde4bd0 __46-[UITableView _updateWithItems:updateSupport:]_block_invoke + 60 (UITableView.m:3826)
1   UIKitCore                     	0x000000018fde4bd0 __46-[UITableView _updateWithItems:updateSupport:]_block_invoke + 60 (UITableView.m:3826)
2   UIKitCore                     	0x000000018fde4cdc __46-[UITableView _updateWithItems:updateSupport:]_block_invoke.1109 + 212 (UITableView.m:3911)
3   UIKitCore                     	0x000000018fde4040 -[UITableView _updateWithItems:updateSupport:] + 2036 (UITableView.m:3919)
4   UIKitCore                     	0x000000018fddcfe4 -[UITableView _endCellAnimationsWithContext:] + 11128 (UITableView.m:2387)
5   UIKitCore                     	0x000000018fdf5ad8 -[UITableView _updateRowsAtIndexPaths:withUpdateAction:rowAnimation:usingPresentationValues:] + 628 (UITableView.m:7767)
6   UIKitCore                     	0x000000018fdf5bec -[UITableView insertRowsAtIndexPaths:withRowAnimation:] + 172 (UITableView.m:7776)
7   KifuBox                       	0x000000010087fc8c GameListViewController.addGame(game:) + 1140 (GameListViewController.swift:460)
8   KifuBox                       	0x00000001008826bc addGame + 16 (GameListViewController.swift:436)
9   KifuBox                       	0x00000001008826bc GameListViewController.newPushed() + 1804 (GameListViewController.swift:628)
10  KifuBox                       	0x000000010088329c @objc GameListViewController.newPushed() + 28 (<compiler-generated>:0)
(以下略)
```

`UITableView`で作成した一覧で新規に行を追加した場合に、`insertRows(at:with:)`でEXC_BAD_ACCESSが発生するというものです。
送られてくるクラッシュログの発生環境から見ると、iPadでのみ発生し、iPhoneでは発生していませんでした。OSのバージョンはあまり関係ないようで、11系〜13系まで幅広く発生していました。

発生し始めた時期に行った修正内容でinsertRows近辺のものがないか調べましたが、あまり関係のありそうなものがありませんでした。

ネットでもいろいろ検索してみたところ、テーブルの更新部分を`beginUpdates()`〜`endUpdates()`で囲うと良いという情報があったのでやってみましたが、効果はなく、それ以外に有効な情報は見つかりませんでした。

## 再現条件と解決方法

それから紆余曲折を経て、やっと再現方法がわかりました。このアプリは`UISplitViewController`を使用して、プライマリー部分にリストを、セカンダリー部分にそのコンテンツを表示するようなものになっています。
iPadではリストとコンテンツが同時に表示されるので、わかりやすいように表示されているコンテンツに対応するリストの行を選択表示していました。

`UITableView`で編集モードに入ると、選択状態が解除されてしまうため、編集モードから出た際に行を`selectRow(at:animated:scrollPosition:)`で再選択するロジックを、問題が起こり始めた時期に追加していたのですが、このロジックに誤りがあり、既になくなっている行を`selectRow`してしまうケースがありました。

確実に再現できた例でいくと、リストに1行しかない状態で編集モードに入り、行を削除して編集モードから抜けると、既に行は1つもないにもかかわらず、row=0, section=0の行を`selectRow()`してしまっていました。この状態から新規に行を追加して`insertRows(at:with:)`を行うとクラッシュする、という現象でした。

このような理由だったので、`selectRow()`が正しくなるように修正した結果、クラッシュしないようになりました。

## まとめ

`UITableView`で存在しない行が`selectRow()`されている状態で`insertRows(at:with:)`を行うとクラッシュする場合があります。
あまり発生しにくいケースだとは思いますが、ネット上にもほとんど情報が見つからなかったので、一応記事にしておきました。
最近(2020/08)のDocker for Macのファイルアクセス遅い問題事情メモ

調べたことまとめる。

* いにしえよりDocker for Macでhost-container間のファイルアクセス遅い問題は議論されている
    * https://github.com/docker/for-mac/issues/77
    * https://forums.docker.com/t/file-access-in-mounted-volumes-extremely-slow-cpu-bound/8076
* macOSでなんで遅いかが↓ここら辺に書いてあるっぽい（が読んでない
    * https://web.archive.org/web/20201007205306/https://docs.docker.com/docker-for-mac/osxfs/#performance-issues-solutions-and-roadmap
* その問題の対応として、2017年にvolumesオプションに `cached`, `delegated` フラグが追加された。consistencyを少し犠牲にしてファイルアクセスを高速化している。 `consistent` (デフォルト) > `cached` > `delegated` の順にconsistencyが高い。
    * https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/
    * https://web.archive.org/web/20200611082225/https://docs.docker.com/docker-for-mac/osxfs-caching/
    * https://github.com/docker/for-mac/issues/1592
* 以下のベンチマークだと、consistent(デフォルト)と比べて `cached`, `delegated` は2-3倍くらい速い。
    * https://www.amazee.io/blog/post/docker-on-mac-performance-docker-machine-vs-docker-for-mac
* が、これでもまだLinuxなどに比べると遅く、公式じゃない手段でいくつかそれより高速化する方法がある。
    * https://www.jeffgeerling.com/blog/2020/revisiting-docker-macs-performance-nfs-volumes
        * ここでいろいろ手動で設定してNFSマウントする方法、 [docker-sync](http://docker-sync.io/) と言うgem、 [bg-sync](https://github.com/cweagans/docker-bg-sync)と言うcontainerがベンチマークとともに紹介されている。いずれも `delegated` flagより2倍かそれ以上速い。
* 一方Docker公式では[Mutagen](https://mutagen.io/)と言うツール(?)がEdgeリリース v2.3.1.0(2020-05-20)で導入された。ネイティブに近いパフォーマンスが出るらしい。
    * https://docs.docker.com/docker-for-mac/edge-release-notes/#docker-desktop-community-2310
    * https://docs.docker.com/docker-for-mac/mutagen/
    * ベンチマーク https://github.com/docker/for-mac/issues/1592#issuecomment-634960996
* しかし、これがパフォーマンス改善に効果がある一方、いくつか問題がありEdge v2.3.5.0で削除された
    * https://docs.docker.com/docker-for-mac/edge-release-notes/#docker-desktop-community-2350
    * ↓で理由が説明されている。キャッシュが追いつかない場合があったり、サブディレクトリがキャッシュされない問題があったりするらしい（詳しく知らないので読み間違えてるかも）
        * https://github.com/docker/for-mac/issues/1592#issuecomment-678397258
* 代わりにgRPC-FUSEと言うファイルシステムが同じEdge v2.3.5.0で導入された。
    * https://docs.docker.com/docker-for-mac/edge-release-notes/#docker-desktop-community-2350
* 公式曰く "This has much faster file sharing and uses much less CPU than osxfs" らしい(osxfsが古い(現状の)ファイルシステム)が、上記issueにポストされたベンチマークでは全然速くなってなかった。
    * https://github.com/docker/for-mac/issues/1592#issuecomment-678411517
* 上記issueにMutagenの開発者が、「Docker for Mac導入されなくてもMutagen自体は使えるから試してみてね」的なこと言ってる。
    * https://github.com/docker/for-mac/issues/1592#issuecomment-678489727
    * 使い方 https://mutagen.io/documentation/orchestration/compose
* mutagenが削除されることを不満に思っている人が多いようで「mutagen入ってるEdge release build使い続けるわ」とか同issueにコメントついてる。
* mutagenはEdgeの時点で削除され、stableに入る予定は今のところない（が、いろいろ考え直してデザインし直して入り直す可能性はある）。gRPC-FUSEは9月にstableに入る予定。デフォルトでgRPC-FUSEになるが、設定で古いやつ（osxfs）に切り替えることができる。
    * 2020/09/30 に gRPC-FUSE入りのDocker for Mac 2.4.0.0がリリースされた
    * https://docs.docker.com/docker-for-mac/release-notes/#docker-desktop-community-2400
Rails label_tag 英語が小文字表示になってしまう(humanize)


# はじめに

`label_tag`を用いてフォームを作成していた時に`*** ID`をnameに指定しても表示が`*** id`となってしまうことが起きたので、`Rails`のソースコードを読んで小文字変換されてしまう理由を調べてみました。

前提として

```ruby

<%= label_tag '*** ID' %>

> *** id
```


# ソースコード
```ruby
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 215
def label_tag(name = nil, content_or_options = nil, options = nil, &block)
  if block_given? && content_or_options.is_a?(Hash)
    options = content_or_options = content_or_options.stringify_keys
  else
    options ||= {}
    options = options.stringify_keys
  end
  options["for"] = sanitize_to_id(name) unless name.blank? || options.has_key?("for")
  content_tag :label, content_or_options || name.to_s.humanize, options, &block
end
```
引用先
https://api.rubyonrails.org/

これを見ると、option類は何も渡していないので、`content_or_options`, `options`, `block`は引数として渡していないことが分かります。
コードを読んでいくと、最後の`name.to_s.humanize`が怪しそうだったので`humanize`について調べてみましょう。


#humanize
属性名(英語)を調整してくれるメソッド
具体的には

- 先頭にアンダースコアがある場合は削除

- 末尾に"_id"がある場合は削除
  - オプションのパラメータ keep_id_suffix を true (デフォルトは false) に設定することで、末尾の '_id' を保持して大文字化

- アンダースコアがあれば、スペースに置き換え

- 頭文字を除くすべての単語を小文字に

- 最初の単語を大文字に
  - 最初の単語の大文字化は、 :capitalize オプションを false に設定することでオフにすることができる（デフォルトは true）。

例

```ruby
humanize('news_number')                  # => "News number"
humanize('news_id')                        # => "News"
humanize('news_id', capitalize: false)     # => "news"
humanize('_id')                              # => "Id"
humanize('news_id', keep_id_suffix: true)  # => "News Id"
```

今回の場合だと

```ruby

humanize('ニュース ID')  # => "ニュース id"
```

`頭文字を除くすべての単語を小文字に`こちらが適応されていて`id`が小文字になってしまっていたということでした。

# 最後に
ロジックを知るためにRailsのソースコードを読むということが良いとわかっていても、二次情報に頼りがちだったので、ちゃんと読んでいかないとダメですね。railsへの理解度も上がりますし、根源的なところを知っておくことは自分の実力に大きく関わってくると思うので。(底レイヤーなところまでは、カバーできていませんが、、)そのことを念頭におきつつ、二次情報なども活用することで、より理解度を高めていければなと思います。
環境構築

#初めに
pythonの環境を構築しました。経緯をまとめます。

#「環境構築」とは
プログラミングをするためのツール（推奨は VSCode ）をインストールすること
このページ「[Visual Studio Code インストール手順](https://qiita.com/ryo-sato/items/7d465e22c6d7a1e79803)」にてセットアップできます。

#単語の説明
「コーディング」と「エディター」
「コーディング」は筆を動かす （コードを入力していく）こと
「エディター」とは、編集する物という意味をさすので画用紙、プログラムを作成するときに使うアプリケーションのことをさします。
・windowsのメモ帳
・開発環境を提供するアプリ
「コーディングツール」は「エディター」とニアリーイコール

#VSCODEのインストール
[Visual Studio Code インストール手順](https://qiita.com/ryo-sato/items/7d465e22c6d7a1e79803)

##VSCODEのダウンロード
https://code.visualstudio.com/
を開いたらダウンロードのボタンを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693119/c9f1660c-e48e-da01-5689-6178972d15b0.png)
ダウンロードが完了したら指示に従いインストールする。
指示に従い「次へ」
ＯＳを再起動する。

#pythonのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693119/590dd896-3c1e-07d3-c870-58f4b85a8bdc.png)

任意の場所に「mypythonproject」というフォルダを作成する。
ターミナル（右下のエリア）に記載のある
「PS C:\Users\simps\OneDrive\ドキュメント\MyPythonProject>」←の後に「python」と入力
入力後、「ＥＮＴＥＲ」を押す。

WINDOWSがインストール画面（python3.8）を開く。
インストールする。
Python3のリスト・辞書型の書き方

型について

```
# List型
  sampleA = [[name,"Sato"],[age,1]], [[name,"Mori"],[age,20]]

# Dictionary型
  sampleB = {"apple":1, "orange":2}

# 型を調べる
  type(sampleA)
  type(sampleB)

#List型からKey/Valueを取り出す
  for index, value in enumerate(sampleA)

#辞書型からKey/Valueを取り出す
  for index, value in items(sampleA)
```
超簡単にhotelとmkcertでローカルでSSLで開発できるようにする


* hotelを使ってローカルドメインで開発は便利(案件を複数抱えてる時など）
* hotel付属の証明書でSSL通信はできるが、ブラウザのセキュリティ警告が邪魔。特にAPI通信などは其のために1回画面の無いAPIエンドポイントをブラウザで開くなどしていた、、。


ということを踏まえて、いい加減ちゃんとローカルでもSSLで開発できるようにしなきゃなぁと思って簡単にできるツール無いかなと探したらmkcertというものがあることを発見。以下その時のメモ。

※ hotelはnodejsで動くproxyです。詳細は、https://github.com/typicode/hotel


##  mkcertインストールと証明書の作成

https://github.com/FiloSottile/mkcert

このgithubにある手順を参考にインストール。私はUbuntuなのでソースからビルドしましたがMacならbrewでいけるようです。LinuxBrewなんてものがあるのを初めて知りましたがあまり必要になることもなさそうなので今回はやめておきました。

インストール後に、

```
$ mkcert -install
```

で、ローカル認証局を作成。

次に必要な分だけドメインを指定して証明書を作成。私はhotelの設定ファイルでtldをdevelopにしているので、こんな感じになります。

```
cd ~/.hotel

$ mkcert \
  -cert-file=cert.pem \
  -key-file=key.pem \
  pop-os \
  *.project1.develop \
  *.project2.develop \
  *.project3.develop
```

hotel用の証明書を作るので、~/.hotel に移動してから、hotelが使用する名前で証明書ファイルを作成します。

これでhotelを再起動。

```
$ hotel stop && hotel start
```

これでローカルでも開発段階から独自ドメイン＆SSLで開発できます。hotelはほんとに便利で重宝していたのですが、mkcertも楽でいいですね。証明書作るコマンドとかいちいち憶えてないし、、、。

![Screenshot from 2020-08-30 19-03-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184118/933eefcd-f0a1-fa18-401b-2caf601810dd.png)
テスト自動化ツール Katalon Studio 紹介（非プログラマ向け）

この記事ではKatalon Studioの特徴などを紹介しています。
手っ取り早く使ってみたい方は[こちら](https://qiita.com/Mimmy/items/a0bb7deeb9ff9614ac02 "Katalon Studio で webサイトのテスト自動化 (非プログラマ向け)
")をどうぞ

##概要
Katalon Studio は開発者ではなくプログラムの知識が浅い人でも、有識者の場合でも
テスト自動化をストレスなくできることを目指して開発されているツールです。
同じKatalonチームが開発している[Katalon Recorder](https://chrome.google.com/webstore/detail/katalon-recorder-selenium/ljdobmomdgdljniojadhoplhkpialdid "Katalon Recorder")というものもあって、こちらはChromeなどブラウザの拡張機能として手軽に導入できますが、Katalon Studioはブラウザの拡張機能ではなくデスクトップアプリです。ダウンロードして豊富な機能を利用可能です。

公式ダウンロードサイト
https://www.katalon.com/homepage/


##魅力

- ユーザーの操作をレコードしてテストケースを作れる

- 対応範囲がかなり広い
 - OS - Windows , mac , Linux
 - ブラウザ - chrome , firefox , IE11 , Edge(chromium) , safari
 - テスト対象 - Webサイト , API , Windowsデスクトップアプリ , モバイルアプリ(iOS,Android)

- テストケース内にgroovyを使ったプログラムコードも書けて痒いところに手が届く

- 実行結果がメール送信できたり、専用ページ「[Katalon TestOps](https://www.katalon.com/testops/ "Katalon TestOps")」にレポートを送れたりで複数人と共有できる

- [Katalon Store](https://store.katalon.com/ "Katalon Store")に公開されている豊富な無料プラグインで拡張できる。プラグインの自作・公開もできます
- データ駆動テスト（エクセルなどからデータを読み込んでパターン別のテストをする）が簡単に作れる
- 公式リファレンス（ https://docs.katalon.com/katalon-studio/docs/overview.html ） が英語ですがしっかりしてるので、大抵の謎はこちらで解決できます

##価格
####具体的な価格
▽公式の価格紹介ページより確認ください
https://www.katalon.com/pricing/

monthly(月額)とannual(年額)での支払いプランを選択できます。
通常機能を利用するのに購入が必要なのは「Katalon Studio Enterprise」だけでOKです。
jenkinsなどのCI自動化ツールでコマンドからの実行を利用したい場合は「Katalon Runtime Engine」も必要になります。

####利用例
私の場合だとKatalon Studio Enterprise(月額\$69)とKatalon Runtime Engine(月額\$49)を利用しているので月に12500円近く使っています。高く感じる人もいるかもしれないですが、ちゃんとツールを稼働させていれば人が人件費でやるテストよりずっと安価かと思います。

####無料の範囲
元々無償のツールですが、バージョン7以降から有償化しています。
始めてダウンロードして使ってみたい場合、1ヶ月間は無料で全機能を利用可能でその後は無料範囲に機能が制限されるようになります。つまり、ずっと無料で使える機能もあります。
勝手に有償プランにされるとかはないので、気軽に使ってみて気に入ったらライセンス購入するといいでしょう。

また、アプリケーションは同じものですがライセンスの違いで
無料範囲は公式サイトでKatalon Studio(KS),
有料はKatalon Studio Enterprise(KSE)
という名称で紹介されており、[こちらのPDF](https://d1h3p5fzmizjvp.cloudfront.net/wp-content/uploads/2020/04/03171512/KSE-brochure-03042020.pdf "Katalon Brochure")で違いを紹介されています

![スクリーンショット 2020-08-30 10.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699916/569e7913-cadd-2329-3571-8b4fa27bf0cc.png)
上記はKSとKSEの違い比較表を[PDF](https://d1h3p5fzmizjvp.cloudfront.net/wp-content/uploads/2020/04/03171512/KSE-brochure-03042020.pdf "ライセンス別機能比較")から撮ったものですが、左側にある機能の名称を見てもこれから始める人には何のこっちゃわからないと思います。
まずは使ってみて、やりたいことに必要な機能を理解した上で購入を考えるといいでしょう。
（個人的にはデバッグができなくなる時点でKSE購入必須なんですが、「デバッグって何？必要なの？」って方も初心者の中にはいるので、一概には言えなくなりました。。）
Colaboratoryで競馬データスクレイピング

#Colaboratoryで競馬データのスクレイピング
競馬データのスクレイピングをしたい、かつ機械学習となったら、Colaboratory便利なので、
Colaboratoryで競馬のスクレイピングをしたコードをメモします。

（htmlの変更でスクレイピングできなくなるかもしれませんので注意してください。2020.8/30動作確認済み）

# 以下コード
```python:sample.ipynb
#Chromiumとseleniumをインストール
#「!」印ごとColaboratoryのコードセルに貼り付けます。
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
```

```python

#BeautifulSoupのライブラリをインポート
from bs4 import BeautifulSoup
import requests
import re
import pandas as pd
```
```python
race_date ="2020"
race_course_num="06"
race_info ="03"
race_count ="05"
race_no="01"
url = "https://race.netkeiba.com/race/result.html?race_id="+race_date+race_course_num+race_info+race_count+race_no+"&rf=race_list"

# 該当URLのデータをHTML形式で取得
race_html=requests.get(url)
race_html.encoding = race_html.apparent_encoding  
race_soup=BeautifulSoup(race_html.text,'html.parser')
```
```python
#　無駄な文字列を取り除いてリストへ格納
def make_data(data):
    data = re.sub(r"\n","",str(data))
    data = re.sub(r" ","",str(data))
    data = re.sub(r"</td>","'",str(data))
    data = re.sub(r"<[^>]*?>","",str(data))
    data = re.sub(r"\[","",str(data))
    return data
```
```python
# レース表だけを取得して保存
HorseList = race_soup.find_all("tr",class_="HorseList")

# レース表の整形
# 表の横列の数=15("着順,枠,馬番,馬名,性齢,斤量,騎手,タイム,着差,人気,単勝オッズ,後3F,コーナー通過順,厩舎,馬体重(増減))
col = ["着順","枠","馬番","馬名","性齢","斤量","騎手","タイム","着差","人気","単勝オッズ","後3F","コーナー通過順","厩舎","馬体重(増減)","出馬数"]

# 出馬数をカウント
uma_num = len(HorseList)

df_temp = pd.DataFrame(map(make_data,HorseList),columns=["temp"])
```
```python
df = df_temp["temp"].str.split("'", expand=True)
df.columns= col
df["出馬数"] = uma_num 
df
```
![スクリーンショット 2020-08-30 19.24.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514658/c0db9cb0-becc-4d92-11b0-8003f393586f.png)

# 最後に
あとは日付などを変えていけばたくさんスクレイピングできます。
環境構築もいらないColaboratoryはやっぱり便利ですね。

#参考
https://qiita.com/Mokutan/items/89c871eac16b8142b5b2
https://qiita.com/ftoyoda/items/fe3e2fe9e962e01ac421
[Powershell][基礎]System.Object[]の中身の確認方法 

`select-object`の`-expand`オプションを使う

#### 例

```
$data = Get-XXXX
$data | Select-object -Expand <System.Object[]の列名>
```
#### 記
・列名が重複しているとエラーになる
・@{}表記の場合もこの方法で展開可能
Ubuntu20.04のデフォルトで利用されるpythonコマンドのバージョンを3系に変更する

# 内容
- デフォルトだとpythonコマンドは2系に割当らていて、3系を利用するためにはpython3を利用する必要があってちょっとあべこべな感じなので治す

# 構成
- Ubuntu20.04

# 手順

## バージョン確認
```
yuta:~ $ python --version
Python 2.7.18rc1

yuta:~ $ python3 --version
Python 3.8.2
```

## alternativesへの登録
```
yuta:~ $ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
update-alternatives: /usr/bin/python (python) を提供するために自動モードで /usr/bin/python2.7 を使
います

yuta:~ $ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2
update-alternatives: /usr/bin/python (python) を提供するために自動モードで /usr/bin/python3.8 を使
います
```

## デフォルトにするpythonのバージョンを選択

```
yuta:~ $ sudo update-alternatives --config python
alternative python (/usr/bin/python を提供) には 2 個の選択肢があります。

  選択肢    パス              優先度  状態
------------------------------------------------------------
* 0            /usr/bin/python3.8   2         自動モード
  1            /usr/bin/python2.7   1         手動モード
  2            /usr/bin/python3.8   2         手動モード

現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 0
```

## 動作確認
```
yuta:~ $ python --version
Python 3.8.2
```

# 参考
https://codechacha.com/ja/change-python-version/
rails AWSのデプロイが反映されない場合

## AWS　デプロイが反映されない場合に行うこと
環境
rails 5.2.4
unicorn
nginx
capistranoで自動デプロイした場合にすぐにAWSに反映されないことがある方向け

## 解決法
デプロイする前にローカルで
```cap production unicorn:stop
```
この後に、
```bundle exec cap production deploy
```
をターミナルでうちましょう。unicornがストップします。自動デプロイでも同じようにunicornはストップさせているはずですが、すぐに反映されないことも多いです。私の環境ではこれですぐにデプロイが反映されています。EC２のインスタンス再起動をしていたこともありましたが、こちらの方が良いような気がします。

また```git add .```
    ```git commit```　したあとに、`git push`　することもたまに忘れてしまうことがあります。
codepenでVuetifyを試す

# はじめに
Vue.jsやReactの使い方を試したいときに、Node.jsをインストールしたりVue.jsをインストールしたりと手間がかかります。[CodePen](https://codepen.io/)というサイトを使用すると環境作成なしでWebブラウザ上で試せたり、他の人にそのコードを共有するなどが簡単にできます。
デフォルトではVue.jsとVuetifyを使用する設定になっていないため、その設定方法をまとめます。

# 手順
1. CodePenにログインしてPenを作成する
2. Pen上でのVue.jsとVuetifyを有効にする
  1. Penの設定を開く
  2. Vue.jsとVuetifyをJavaScriptから呼び出す
  3. VuetifyをCSSから呼び出す
3. Vuetifyを試す

# 1. CodePenにログインする

[CodePen](https://codepen.io/)にログインして、右上のユーザアイコンをクリックします。
表示されたウィンドウのNewPenをクリックして、Vue.jsを試す画面を表示します。
![1.NewPen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481713/ea1bc58a-83d4-4957-0150-12bee4fe6736.png)

# 2. Vue.jsとVuetifyのJavaScriptを有効にする

この状態でもhtml、CSS、JavaScriptを試すことはできますが![2.OpenSettings.png]
Vue.jsとVuetifyを使用するためには、この2つのライブラリを呼び出すように設定する必要があります。

## 2. 1. Penの設定を開く

Penの設定を開くには右上のSettingsをクリックしてPen Settingsウィンドウを開きます。
![2.OpenSettings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481713/09a16390-9a64-c16e-2123-af76670733a5.png)

## 2. 2. Vue.jsとVuetifyをJavaScriptから呼び出す

Pen SettingsウィンドウのJSをクリックして、JavaScript用の設定を開きます。
Add External Scripts/Pensの項目にvueを入力すると候補がでてくるので必要なVueとVuetifyをクリックします。
この時に候補になければ手でURLを入れることもできます。
![3.SettingsJS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481713/b686e35d-b78e-6460-f830-25f18eb311b7.png)


## 2. 3. VuetifyをCSSから呼び出す

この状態では、VuetifyのCSSがあたっていないためCSS用の設定をしていきます。
検索でVuetifyが出てこなかったのでAdd External Stylesheets/Pensの項目に手で以下のURLを入れて、Saveボタンを押します。

```

https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css
```

![4.SettingsCSS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481713/58b88617-6eed-83d0-83ee-2eaafe386e14.png)


# Vuetifyを試す

これで環境作成が完了したのでVuetifyを試してみます。
公式のVuetifyのメニューボタンとほとんど同じですが、公式だとCSSやJSのメソッドなどを使わないのでCSSとメソッドを使いためにクリック後のリストを縞々にしました。

<p class="codepen" data-height="376" data-theme-id="dark" data-default-tab="html,result" data-user="mink0212" data-slug-hash="RwagePL" data-preview="true" style="height: 376px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="menu">
  <span>See the Pen <a href="https://codepen.io/mink0212/pen/RwagePL">
  menu</a> by mink0212 (<a href="https://codepen.io/mink0212">@mink0212</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 終わりに
CodePenを使用してVuetifyを使用する方法をまとめました。JSの設定等は色々なサイトでやっているのですが、CSSは省略していることが多く注意が必要です。
これで面倒な環境作成から解放されてちょっとしたことを試すのが簡単になり、ソースとソースの結果を容易に他の人に共有できるため、共有相手に環境を作ってもらう必要もなく便利だなと感じました。
ソースの長さによっては読みやすさが変わってしまうため、大きいソースの共有には向いていませんが、簡単な勉強会やQiitaのようなところに乗せるには十分に思えます。
[過去POST][初心者向け]ページネーションの原理がわからない。railsにて

## 過去POST
過去自分がTECH::CAMPのメンターをしていた時期にメモしていた内容を公開します。
rails でよしなにやってくれるので知らなくてもいいのですが、たまに聞かれることがあったので書きました。
初心者向けのざっくりとした解説です。


## Q.ページネーションの原理がわからない。


```ruby

class TweetsController < ApplicationController

  def index
    @tweets = Tweet.order("created_at DESC").page(params[:page]).per(5)
  end

  def new
  end

  def create
    Tweet.create(tweet_params)
  end

  private
  def tweet_params
    params.permit(:name, :image, :text)
  end

end
```

ここで

`.page(params[:page]).per(5)`

とありますが、これが納得できないという人がいました。

これもSQL文の発行に関わるものです。

```ruby

# page(params[:page]).per(5)
params[:page]= 1
```

の場合SQLは(順番は一旦無視します。)

```sql

SELECT `tweets`.* FROM `tweets` LIMIT 5 OFFSET 0
```

ページが代わり

```ruby

# page(params[:page]).per(5)
params[:page]= 2
```

の場合

```sql

SELECT `tweets`.* FROM `tweets` LIMIT 5 OFFSET 5
```

となります。
ここで重要なのが

```
LIMIT 5
OFFSET 5
```

です。

まず
`LIMIT 5`
は、データをmax５件まで取得するという意味です。

`OFFSET 5`
は、データを前から５件をスキップするという意味です。

つまり

```sql

SELECT `tweets`.* FROM `tweets` LIMIT 5 OFFSET 5
```

というのは、ツイートテーブルから、ツイートレコードを前から５件飛ばし、
その後最大5件のレコードを取得してくるというものです。
[過去POST][初心者向け]N+1問題が理解できない。.includesを使うとどうなるのか(Railsにて)

## 過去POST
過去自分がTECH::CAMPのメンターをしていた時期にメモしていた内容を公開します。

## N+1問題が理解できない。includes(:user)とする意味がわからない。

```ruby

class TweetsController < ApplicationController

# 中略

  def show
    @tweet = Tweet.find(params[:id])
    @comments = @tweet.comments.includes(:user)
  end

# 中略

end
```
で使用している。

これはなにも考えなければ
`@comments = @tweet.comments.includes(:user)`
の部分は
`@comments = @tweet.comments`
でもできる。

しかしこれではN+1問題が発生してしまう。
（要は、SQLの発行回数が多くなってしまう。）

### 【問題の概要】
この文の意味は

>詳細を表示したツイートについているコメントのレコードを取得
>コメントのレコードに紐つくユーザーレコードの取得

をしている

単純に
`@tweet.comments`
のように書くと、コメントレコードごとにユーザーレコードを取ってくるという動作をしてしまう。
つまりSQL文でかくと、
(tweetは一旦省略、コメント数は４件、ユーザーは２人とする。)

```sql

SELECT 'comments'.* FROM 'comments’
```
を実行すると

```sql

SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 1 LIMIT 1
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 2 LIMIT 1
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 2 LIMIT 1
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 2 LIMIT 1
```

のようにcommentsレコードの数だけ、userレコードを取得するクエリが発行される。
これがN+1問題。

では`.includes(:user)`

をつかうとどうなるのか

```sql
SELECT 'comments'.* FROM 'comments'
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' IN (1, 2)
```
のように一文で終わる。
これが`includes`の意味です。
`(:user)`は`user_id`ですね。
Azure Synapse Analytics SQLプールのPolyBaseについて

Azure Synapse Analytics SQLプールのPolyBaseについて調べましたのでメモ程度に

#PolyBaseを使ったデータロード
Azure Synapse Analytics SQLプールでは様々なデータロードの方法がSQL Server同様にサポートされています。その中でもPolyBaseはデータベースへ非常に高速にデータをロード事が可能なロード方法です。Azure Synapse Analytics SQLプールが大量のデータを取り扱う特性上、大量のデータを高速にロードする方法は重要です。

PolyBaseを使ったロード方法は以下の通りです。

* データをAzure Blob Storage、Hadoop、Azure Data Lake Storage Gen2のいずれかにデータを格納
* Synapse SQLプールにてAzure Blob Storageのデータ格納場所とデータ形式を定義し外部表を作成
* Synapse SQLプールのテーブルへ外部表からInsert SELECTを実施

#PolyBaseが高速な理由
##3層アーキテクチャでの処理の実行
PolyBaseが高速にロードできるのには理由があります。Synapse SQLプールは1つのコントロールノード、複数のコンピュートノード、60のディストリビューションにより構成されています。Synapse SQLプールにてSELECT分等のSQLを実行する場合、複数あるコンピュートノードに処理を分割して実行し、最後コントロールノードで集計を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697647/8330656b-c52f-622d-32b9-4dcd165ca4b4.png)

このアーキテクチャについては以下の記事に簡単にまとめております。
[Azure Synapse Analytics SQLプール（旧：SQL Data Warehouse）とは](https://qiita.com/masahiro-yamaguchi/items/e74c2cf8f17cf098691f)

##ロード時にボトルネックになることのあるコントロールノード
一方、Synapse SQLプールにデータを投入することを考えると、コントロールノードが１つしかない為、ここがボトルネックに陥りがちです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697647/24f28e34-0cfd-c606-684f-80020ea1c6a0.png)

##PolyBaseはコンピュートノードが直接データをロード
PolyBaseを使ったロードの場合はコントロールノードを利用せず、直接コンピュートノードを使ってパラレルロードを行う仕様になっているようです。これにより高速にロードすることが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697647/da17c3df-0ebe-2b25-6eda-6e1782ec9d56.png)

なので、PolyBaseを使ったロードの場合、コンピュートノードの数やスペックによりロード性能が異なります。

##終わりに
具体的なPolyBaseの手順と性能はまたどこかで検証し記載したいと思います。
[過去POST]TECH::CAMPのメンターをしていた時の回答メモを一部公開します

# 過去POST
過去自分がTECH::CAMPのメンターをしていた時期にメモしていた内容を公開します。
小分けにしようとしましたが小粒なものはまとめておきます。
記憶が曖昧なので間違っている箇所もあるかもしれないです…


## Q.ハッシュの中身が取り出せない

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}
から取りたい文字列を取るコードを書きましょう。
のような問題だったと思います。

### 該当コード

```ruby

def movie_info(movie, data)
  puts movie[data]
end

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"

info = gets.chomp

movie_info(movie, info)
```

### 解説

ここで
`puts movie[:data]`
としてしまうとうまくいかないです。
その原因は型が違うからです。

`info = gets.chomp`
ここでキーを「文字列」として受け取っているので
ハッシュの定義も文字列"title"を使っているのでここでは問題はおこりません。

`puts movie[:data]`
一方で、こう記述すると、シンボル型で出力してしまい、
型が違うためなにも出力されません。

ちなみに型を調べるのは.classを使うと調べられます。
`ex) info.class`

もしシンボル型を使いたいなら
`movie = {title: => "ハリーポッター”}`
のようにハッシュの定義を変えて
`info = gets.chomp.to_sym`
のように書き換えるとうまくいきます。

`puts movie[data.to_sym]`
でも大丈夫です。（シンボル型に変換）

## Q.devise, no method error
devise関連でno method errorが出た時。current_sign_in_atがないなど。

### 対処方法
deviseによって作成した、該当のマイグレーションファイルを確認
該当箇所周辺のコメントアウト外して
データベースを作成し直す
`$ rake db:migrate:reset`
このコマンドで一気にできます。

このコマンドは、データベースを一度ドロップして、
今あるマイグレートファイルを元にデータベースを作り直すというコマンドです。
もちろんデータベースに入っていたデータは消えます。
色々データが入っていて残しておきたい場合、CSVでデータを出力してどっかに保存してからやるべきかと思います。

直前にマイグレートしたものならrollbackで戻っても良いかもしれません。

`$ rake db:migrate:status`

で現在どのファイルがmigrateされているのか確認できます。

*ちなみに `db:reset`やっても意味ないです。スキーマファイルから作り直すだけなので。

### 原因
deviceをインストールした際、デフォルトでコメントアウトされている項目をそのままにしてしまい
使用したいメソットが生成されなかったため。
もう一度マイグレーションをやり直すことで解決するはず。


## Q.heroku上で、idが１０刻みで付与される
開発環境では問題ないが、本番環境でのみ、変わってしまう。
あまり気になる人はいない気がしますが、これはclearDBのデフォルトの設定です。
herokuでは、dbサーバーとしてcleardbを使っているようです。

【参照】
http://w2.cleardb.net/faqs/#general_16
When I use auto_increment keys (or sequences) in my database, they increment by 10 with varying offsets. Why?
ClearDB uses circular replication to provide master-master MySQL support. As such, certain things such as auto_increment keys (or sequences) must be configured in order for one master not to use the same key as the other, in all cases. We do this by configuring MySQL to skip certain keys, and by enforcing MySQL to use a specific offset for each key used. The reason why we use a value of 10 instead of 2 is for future development.
WSL2を使ったDokcerで、`Aws::S3::Errors::RequestTimeTooSkewed` のエラー対処法

----
[追記]
環境構築手順のまとめを [Windows 10 Home WSL2でDockerを使う](https://qiita.com/wakki_haya/items/da1a4e15b1d347ef3c1e) に更新しました

----

## 環境
- WSL2 (Windows 10 Home)
- Docker for Windows

## エラー
Docker上で、AWSと連携しようとしたときに、

```
Aws::S3::Errors::RequestTimeTooSkewed: The difference between the request time and the current time is too large.
```
のエラーが出た

## 原因
WSL2で動くDockerコンテナの時刻が大幅にずれているのが原因

Windows ホスト側

```
$ data 
Sun Aug 30 18:16:29 JST 2020
```

コンテナのシェル内

```
$ data
Sun Aug 28 11:16:29 JST 2020
```


## 解決法
### はじめに
`Aws::S3::Errors::RequestTimeTooSkewed`のエラーはTimezoneが違う場合でも発生するので、
docker-compose.yml 内でtimezone をJSTに設定しとく。

```docker-compose.yml
services:
  web: 
   environment:
     TZ: Asia/Tokyo
```

### つぎに
WSL2の時刻を `data --set` コマンドで同期させる。
まず、コンテナのシェル内でdataコマンドを使うときに、 `operation not permitted` にならないように、権限設定をしとく必要がある。

```docker-compose.yml
services:
  web:
   privileged: true
```


### つぎに
コンテナのシェル内で、`data`コマンドを使って日付を変更する

```
$ data --set "2020-08-30 18:16:29"
```

で完了。

## 他に試したこと
1. `hwclock -s` を用いて無理やり時間を変えれるらしい。

-> 下記のエラーが出て、少し解決しようとしてみたが、謎すぎて諦めた

```
$ hwclock -s
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method
```

## 参考リンク
https://qiita.com/sadakan5/items/4c0a394fd1d6be34efb2