OmniAICreator/Qiita-1.07M huggingface dataset:
JScriptでCSVファイルをSQLで検索してみた

#はじめに
CSVファイル用のODBCドライバが32bit版の環境を想定する。

#環境
- Windows 10 Home (64bit)

#手順

##ODBCドライバの確認
スタートメニューをクリックし、odbcと打ち込むと「**ODBC Data Sources (32-bit)**」が現れるので起動する。

[ドライバー]タブを選択し、一覧の中に
`Microsoft Text Driver (*.txt; *.csv)`
があることを確認する。

##ソースの用意

```ado_sample.js
{
	var cn = WScript.CreateObject("ADODB.Connection");
	cn.Open("Driver={Microsoft Text Driver (*.txt; *.csv)}; ReadOnly=1;");

	var rs = cn.Execute("select name from [test.csv] where id=2");
	for ( ; !rs.Eof; rs.MoveNext()) {
		WScript.Echo(rs.Fields("name").Value);
	}
	rs.Close();

	cn.Close();
}
```

##データの用意

```schema.ini
[test.csv]
ColNameHeader=False
Format=TabDelimited
MaxScanRows=25
CharacterSet=OEM
Col1=id Byte
Col2=name Text
```

```test.csv
1	tako
2	ika
3	manbo
2	geso
```

##実行
32bit版のコマンドプロンプト
`C:\Windows\SysWOW64\cmd.exe`
へのショートカットを用意する。
プロパティの作業フォルダーを空にするといいかも知れない。

```
C:\Projects\etc\adodb>cscript ado_sample.js
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

ika
geso
```

#余談
	cn.Execute("insert into [test.csv] values (4, 'kani')");
テキストファイルなのでupdateはできないがinsertで追加は可能。
ガンダムっぽいカラースキーム@vim

## つくってみた

vimの、ガンダム（っぽい）カラースキーム。

vimのロボット操作感アップ！？

[hnsol/vim-deep-space](https://github.com/hnsol/vim-deep-space)
→ガンダム THE ORIGINっぽいかんじで（darkのみ）
![screenshot_deepspace-gundam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/e98da085-245d-d5a1-a717-98a951b968bd.png)
<img src="http://www.gundam-the-origin.net/images/main6.jpg" width=45%>


[hnsol/vim-one-g](https://github.com/hnsol/vim-one-g)
→キュベレイっぽい感じで（light/dark）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/d07e65a3-91ab-e8f0-6377-03808777b951.png" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/8cbf09e2-b82c-896d-4b81-634a55ad8e99.png" width=45%> 
<img src="http://www.z-gundam.net/z3/ms/img/axis/ms_01.jpg" width=30%> <img src="http://www.gundam-zz.net/ms/images/30.jpg" width=35%>


## インストール

通常のプラグイン管理ツールなどで。

vim-plugの場合

```vim
Plug 'hnsol/vim-deep-space'
set termguicolors
set background=dark
colorscheme deep-space
```

```vim
Plug 'hnsol/vim-one-g'
set termguicolors
set background=dark
colorscheme one
```
syntax error, unexpected end-of-input, expecting end　について

#はじめに
初学者のアウトプットです。
訂正、追記等あればご教示いただけると幸いです。

#エラー文章
エラー文章が発生しては、長くて読む気が無くなりそうですが、
大抵の内容は、エラーが発生しているアドレスを示してくれており、
```SyntaxError: /アドレス/．．．/: エラー内容
```
みたいな感じになっています。
結局、アドレスのエラー内容を修正すればエラーは解決するので、
現段階では、学習の為にもエラー内容部分を翻訳してエラー修正にするのが一番だなと感じています。

#syntax error, unexpected end-of-input, expecting end
表題のようなエラーが出ました。

翻訳　→　構文が誤っています、予期していない終わり方です、endを追加すると良いと思われます。

見直してみると構文に``end``が足りていませんでした。
``end``を追加してエラー解消です。
#まとめ
複雑になればなるほど発生しそうなエラーです。
こんなのは体で覚えてしまってすぐ対処出来るようになりたいです。
JSXとReact要素について整理しました

`JSX`と`React要素`の定義についてざっくりと整理してみました。

## JSXとは

JSXはReactでよく見るHTMLタグのようなもの。

```jsx:
<h1 className="greeting">Hello, world!</h1>
```
## React要素とは

JSXから生成されるJavaScriptのオブジェクト。
Reactはこのオブジェクトを読み取りDOMを構築する。

上のJSXからはこのようなオブジェクトが生成される。

```js:
{
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
}
```

## JSXからReact要素が生成される過程

1. `JSX`はBabelにより`React.createElement()`の呼び出しへとコンパイルされる。

2. `React.createElement()`はオブジェクトを生成する。

このオブジェクトを`React要素`と呼ぶ。
Reactはこのオブジェクトを読み取りDOMをレンダーする。

このように`JSX`はコンパイル後に`React要素`と呼ばれるJavaScriptのオブジェクトになるので、

- 変数に代入したり、
- 関数の返り値にしたり、
- propsとして子コンポーネントに渡したり、

することができる。


## 最後に
とりあえず`JSX`と`React要素`は互いにコンパイル前後で呼び名が変わったもの、程度に理解しておけばよさそう。
【Rails5】check_boxで任意の文字列を渡す方法（ガチ初学者向け）

初投稿です。
初学者のため、参考程度に見ていただければ幸いです。

至らない点、わかりにくい点などあればコメントで教えていただければ幸いです。

#version
Ruby 2.5.7
Rails 5.2.4.4

#How to
まずチェックボックスフォーム機能を実装する際に、デファルトだとか機能ようなコードになると思います。（form_withを使う場合）

```
<%= form_with model: 変数, url:遷移先のパス do |f| %>
   <%= f.check_box :カラム名,{オプション（クラス名など} %>　←チェックボックスを表示
   <%= f.submit %>
<% end %> 
```

このようにするとデフォルトで`"1"か"0"`が送られます。

```
<%= form_with model: 変数, url:遷移先のパス do |f| %>
   <%= f.check_box :カラム名, {オプション（クラス名など}, "true","fales" %>　←チェックボックスを表示
   <%= f.submit %>
<% end %> 
```

このように記述すれば`true,fales`を渡すことができます。

```
<%= form_with model: 変数, url:遷移先のパス do |f| %>
   <%= f.check_box :カラム名, {オプション（クラス名など}, "attende","absence" %>　←チェックボックスを表示
   <%= f.submit %>
<% end %> 
```

同様に`true,fales`の部分を書き換えれば、任意の値を渡すことができます。

**ポイントは、オプションの後ろに記述することです。**
渡したい文字列の後ろにクラス名などのオプションを指定するとエラーが出ます。

簡単なようで意外と車学者がつまずくポイントかなと思い記事にさせていただきました。

誰かの参考になれば・・・
BIOSロックの方法(DELL XPS13)

対象が限定的な話ですが、DELL XPS13のBIOSロック設定をする機会があったので記録します。
写真が斜めっているのは、ご愛敬ください！！

##手順と説明

1．PCを起動または再起動し、DELLのロゴが表示されたら「F2」キーを連打します

2．BIOSセットアップ画面が表示されるので、「Password」をクリックします。

　①**強力なパスワードを有効にする(Enable Strong Password)**
　　こちらの設定を有効化にすると、**最低8文字、1つ以上の大文字、1つ以上の小文字**を含めたパスワードにしないとパスワードの登録、変更ができない設定です。

　②**パスワードの設定(Password Configuration)**
　　Adomin PasswordとSystem Passwordの入力最低数と最大数を決めることができます。

　③**権限者パスワード(Admin Password）**
　　BIOS設定を変更した際に、パスワードを入力しないと変更できなくする設定です。
枠に登録するパスワードを入力　＞　「Enter」を入力　＞　もう一度パスワードを聞かれるので再度パスワードを入力で登録できます。

　④**システムパスワード(System　Password）**
　　PCを起動した際に、パスワードを入力しないとOSを起動させなくする設定です。
枠に登録するパスワードを入力　＞　「Enter」を入力　＞　もう一度パスワードを聞かれるので再度パスワードを入力で登録できます。

　⑤**マスターパスワードのロックアウトを有効化にする(Enable Master Password Lockout)**
　　マスターパスワードのサポートが無効になります。(こちらの設定はいじっていないので、よくわからないです。。。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718459/1c8a744c-b4b8-ecdc-dded-36738f65fa6a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718459/493472f5-3240-0f11-9e2f-0ba07afe4106.png)
　今回は①と③と④を設定しました。


3．パスワードの設定が正しくできると「Password Valid」が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718459/b134fcf9-ea5c-75b2-264b-0a09c79274f9.png)

逆に失敗する(①の強力なパスワードの条件を満たしていない)と「Password Invaid」が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718459/1865060d-f129-f918-3438-66023383f9a8.png)


4．設定が完了したら、「APPLY CHANGES」をクリックして「Save as Custom User Setting」にチェックを入れOKをクリックすれば設定が反映されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718459/92e15bd1-0ea4-599e-70af-b2f12ec7ab39.png)
データサイエンス100本ノックに挑戦

#Python100本ノックに挑戦するまで
データサイエンス100本ノック（構造化データ加工編）というのがあります。
挑戦するまでの手順をメモしたいと思います。
###環境
* windows10 Home
* Core i7
* メモリ8GB

##1. 問題をダウンロード

今回は以下の画面の「Code」からzipファイルをインストールしました。
https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186902/f7464f6d-8b44-fb9f-bc7f-6f49e0ccb0be.png)

##2.Dockerのインストール
~~以下のDownload from Docker Hubをクリックして、exeファイルを実行。~~←windows Proはこれでok
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186902/b35e9edd-f5b9-d28e-2637-d28e447aa814.png)
windows10 Homeの場合はDocker Toolboxをインストールする必要がある。exeファイルはデフォルトでインストール。
https://github.com/docker/toolbox/releases
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186902/4557f753-fdf5-26b6-9566-f54de1e67551.png)


コマンドプロンプトでインストールされたか確認。

```
$docker --version
Docker version 19.03.13, build 4484c46d9d
```

##3. Docker上で動かす
以下のコマンドを実行。

```
natsumin@DESKTOP-7LNP3VI MINGW64 /c/Python/100knocks-preprocess-master/100knocks-preprocess-master (master)
$ docker-compose up -d --build                                                                                          
```

上記のコマンド実行が終了したら以下にアクセス

```
http://localhost:8888/
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186902/061f01c0-096f-ddff-4db5-88c59793436c.png)

###参考にさせていただいたページ
https://qiita.com/karaage0703/items/1b18b1f4ab65d35afb5f
https://qiita.com/syuki-read/items/714fe66bf5c16b8a7407#comment-394d2f7656bd5b977e11
https://qiita.com/zeffy1014/items/dda78f4ab0449989dfe1
OpenCVの基本操作のメモ

#画像の読み込みと表示
このコードを使う前提としてはmatplotlibとopencv-pythonのインストールがされたことです。
opencvは画像をbgr(blue,green,red)として読み込むため、一旦rgbに変換してから画像表示をします。

```showpic.py
import cv2
from matplotlib import pyplot as plt

#read image file
img = cv2.imread('cat.jpg')
#convert BGR to RGB. opencv read image file color as bgr by default.
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#plot image
plt.imshow(img)
#show image
plt.show()
```

#画像のサイズの取得
画像を読み込んで、画像のheight(高さ)、width(幅)、チャンネル数を出力します。

```showshape.py
import cv2

#read image file
img = cv2.imread('mortyandrick.jpg')
#get image resolution
imgshape = img.shape
#print image resolution
print(imgshape)
```
千葉県Go To EAT向けに店舗検索BOT（AI LINE BOT）を作った話(1)

こんにちは。初めて記事を作成しております。
「不適切な記事」のボーダーラインが分かっていないので至らない所あればご指摘ください。


現在、私は千葉県のGo To EATキャンペーンを使っています。
プレミアム付き食事クーポンを10000円で買うと12500円分の食事券として使えるのでとてもお得です。

【千葉県Go To EAT事業公式サイト】
　<a href ="https://www.chiba-gte.jp/">https://www.chiba-gte.jp/</a>

ただ一つ、微妙だなぁと思ったのがクーポンが使えるお店が検索しづらいこと。
提供されているUIは、駅名等の地域情報から近くにあるお店が分かるのですが、
「今日はこれが食べたい！」といった目的が決まっている場合には検索しづらいと感じました（個人的意見）。
地域情報の他に料理のジャンルや店名でも検索出来たらいいのに。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896062/0957727e-d353-8fbd-ac95-457ecfbcb303.png" width=80%>

そこでLINEのAPIを利用して、利用者が入れたキーワードを元にお店をサジェストしてくれるAI LINE BOTを作ろうと思い立ちました。
やってみたら意外とサクサク手が進み、作りたいものが出来たのでやったことを共有します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896062/907cf019-c223-7a4f-6058-cc6bba45344e.png" width=30% >　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896062/fed5bdde-048e-ea77-e83d-f0bb1af037f4.png" width=30%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896062/fe6ec8d9-fe64-3453-7ab3-8c18676fd4bb.png" width=30%>


<a href="https://github.com/Haradasn/linebot">作成に使用したプログラムソース</a>

この記事では、以下の方々を対象にやったことをご紹介していきたいと思います。

　・LINE BOT（messagingAPI）を作ってみたい。
　・簡単な機械学習モデルを作ってみたい。
　・システム構築にお金をかけたくない（AWS無償トライアルやOSSを利用して費用ゼロで構築）。

　（自分のスキルを世の中に発信することで最終的に転職活動に有利になればと思っています　笑）
MySQLからPostgresの移行時にやったこと(AWS Aurora)

# はじめに
今携わっているWebアプリケーションではMySQL(AWS Aurora)を使用していますが、昨今のユーザー数増加により少しずつ問題が起き始めています。
元々Indexの作りがよくないこともあるのですが、PostgreSQL(AWS Aurora)に移行したらどうだろう？という検証を行った結果、数倍どころの問題じゃないぐらいの性能差が出たため、移行作業を行うこととしました。
今回はその際にやったことをまとめてみました。

# 環境

## 移行前
AWS Aurora MySQL 5.7

## 移行後
AWS Aurora PostgreSQL 11.8

# DBの移行方法
AWS DMSという移行を簡単にできるサービスがあるため、それを使用して移行しました。
一度きりの移行も継続的なレプリケーションも対応しているため、移行がものすごく楽になりました。

# 移行時にテストしてクエリを修正した際のポイント
MySQLとPostgreSQLではクエリが少し変わります。ここではその違いによって変更した点を記載していきます。（これがメインコンテンツ）

## シングルクォーテーションとダブルクォーテーション
文字列を囲む際ですが、MySQLは特にシングルとダブルどちらでも問題ありません。
しかし、PostgreSQLはシングルクォーテーションしか受け付けません。
なので、その違いがあれば吸収してあげる必要があります。
こういう時のためにシングルクォーテーションに統一しておくというのはアリかと思います。検索でどうこう出来る修正ではないため、結構修正は面倒くさかったです。

``` MYSQL
# MYSQL
name = "hogehoge"
```

``` PostgreSQL
# PostgreSQL
name = 'hogehoge'
```

## 関数の違い
例えばMySQLの`ifnull`はPostgreSQLでは`COALESCE`といった違いがそこそこあります。
これも1つ1つ調べるのも手間なので、動かしてエラーになった箇所を書き換えるというやり方で修正しました。
また、同じ関数があった場合でも引数の型の問題でエラーになることもあります。
例えば`lpad`関数は、MySQLでは数字でも問題なく動作してくれますが、PostGreSQLでは文字を渡して上げなければいけないといった違いが存在します。
分かりづらいですが、このような違いによるエラーはかなり発生しやすいのと普段から両方に対応した書き方はしづらい箇所なので、移行時の手間として許容するしかなさそうです。こういう処理を全てアプリケーション側でやれば移行時の手間は無くなりますが、それはそれで手間です・・・

```
# MySQL
lpad(id, 4, "0")
```

```
# PostGreSQL
lpad(cast(id as character varying), 4, '0')
```

## 日付の扱い方について
一番大きく修正したのは日付（正確には時刻）周りです。
ここら辺はMySQLの方が便利になっていて、例えば日付の差分を取得する方法は以下となります。

```
# MySQL
DATEDIFF(NOW(), created_at)
```

```
# PostGreSQL
extract(epoch from (now() - created_at)) / (60 * 60 * 24)
```

また、時刻に秒とか分を足すというロジックにも違いがあります。
例えば秒を足すというロジックには以下の違いがあります。

```
# MySQL
DATE_ADD(time, INTERVAL value SECOND)
```

```
# PostGreSQL
time + make_interval(secs => value)
```

こうした違いはどうしても存在するため、これも手間として許容する必要があります。

## group byの違い
MySQLは結果に一意性があれば良いのですが、PostGreSQLはクエリの段階で一意性を求めてくるようです。
なので、`sum`だったりで集計する箇所かつ`join`絡むような少し複雑なクエリを書いている箇所で`group by`するカラム不足であるエラーが多発しました。
単純なクエリであれば特に問題ありませんが、`join`が絡むとこの問題が多発します。

例として`hogehoge`と`members`というテーブルを`join`してデータを取得したいとします。
その際のクエリを書きましたが、このクエリはMySQLだと動作しますが、PostGreSQLではエラーになってしまいます。
PostGreSQLでは、このエラーとなった`members.name`カラムも`group by`に含める必要があるのです。

```
# MySQL
select
  hogehoge.member_id,
  members.name,
  hogehoge.date,
  sum(hogehoge.value)
from
  hogehoge
  INNER JOIN members on members.id = hogehoge.member_id
group by hogehoge.member_id, hogehoge.date

```

```
# エラー内容
ERROR:  column "members.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3:   members.name,
          ^
SQL state: 42803
Character: 47
```

```
# PostGreSQL
select
  hogehoge.member_id,
  members.name,
  hogehoge.date,
  sum(hogehoge.value)
from
  hogehoge
  INNER JOIN members on members.id = hogehoge.member_id
group by hogehoge.member_id, hogehoge.date
```

### Railsの補足
Railsで`first`でデータを取得するとクエリに`order by {primary key}`が付与されます。
これを今回のようなケースで書いているとこの`{primary key}`も`group by`に含める必要が出てくるため、自分で書いたクエリ部分は追加したけどエラーになるというような状況が出てきてしまいます。
ご注意ください。

## selectの返却順
PostgreSQLはMySQLと違って計算過程で見つけた順番で`select`した結果を返却してくるため、思ってない順番で返却されることがあります。
まとめて取得するというような場合はきちんと`sort`してあげるようにしないと、思った通りの取得順番にはならないため注意が必要です。

# 終わりに
MySQL5.7のスタートってもう7年前なんですね・・・
BigQueryのパーティション分割テーブルのパーティション毎のデータ量を求める

BigQueryはパーティション分割テーブルを使うことで、パフォーマンスやコストを最適化することができます。

https://cloud.google.com/bigquery/docs/partitioned-tables

しかし、公式のドキュメントには分割された各パーティション毎のデータサイズを求める方法が書かれていません。

`__PARTITIONS_SUMMARY__` メタテーブルを使うことで、パーティションの一覧やそれらの作成・更新時刻を確認することはできますが、このテーブルにサイズの情報はありません。
では、どうやってパーティション毎のサイズを確認できるのでしょうか？

# 解決策
各パーティションに対して、パーティション内をフルスキャンするクエリをdry runし、推定スキャン量のデータを使う。

```ruby
partitions = [
  '2020-01-01',
  '2020-01-02',
  '2020-01-03',
]

partitions.each do |partition|
  sql = "SELECT * FROM <テーブル名> WHERE DATE(<パーティションカラム>) = '#{partition}'"
  command = "bq query --nouse_legacy_sql --dry_run \"#{sql}\""

  res = `#{command}`
  m = res.match(/(\d+) bytes/)

  if m
    bytes = m[1].to_i
    puts "#{partition}, #{bytes}"
  end
end
```

dry runであればクエリ料金がかからないことを利用して、パーティションのサイズを調査しています。
あとは、この情報をCSVとしてGoogle SheetやBQに入れることでさらなる調査ができます。
rubyクラスを利用したアプリ


シンボルクラスとストリングクラスは同義と考える
hash = {"key" => "value"}
hash = {key: => "value"}

###教訓
1.`attr_accessor :id, :name, :content` クラス外から参照、編集するために必要な処理
2. `@@xxx`はクラス変数。クラスを使うたびに定義される
3. `@xxx`はインスタンス変数。インスタンス毎に定義される
4. `@tasks << task(TASKクラスを利用したインスタンス)`ではインスタンス変数に、`task(TASKクラスを利用したインスタンス)`を配列の要素として代入している。※ハッシュを代入していると思っており、ハッシュのメソッドを探していた。
5. initializeはインスタンス作成時に動作する（主に変数の初期値設定）
6. クラス毎に用途を分けた方が良い。今回なら、TASKクラスはタスクを保存するため用途。TODOクラスはtaskインスタンスを扱う用途。


```
class Task
  # コードを追加
  attr_accessor :id, :name, :content
  @@count = 0
  
  def initialize(**params)
    @name = params[:name]
    @content = params[:content]
    @id = @@count += 1
  end

  def info
    "タスクNo.#{@id} : #{@name} #{@content}"
  end
end

class Todo
  # コードを追加
  # initializeはインスタンス作成時に動くから、作成時にインスタンス変数等に引数を代入したい時に引数を定義する
  # 今回の場合は空配列を初期化するために実装しただけなので、引数を定義していない
  def initialize
    @tasks = []
  end
  
  # 作成後のインスタンスごとに引数を渡しながらメソッドを動作させるときはあらかじめ引数を用意しておく
  def add(task)
    @tasks << task
  end

  def info
    @tasks.each do |todoList|
      puts todoList.info 
    end
  end
-----------ここをid:にどうやってtodoList.delete(id:1)の値を入れ込むかわからなくて苦労した。----
  def delete(id:)
    delete_task = @tasks.find { |task| task.id == id }
    @tasks.delete(delete_task)
  end
end
---------------------------------------------------------------------------------
task1 = Task.new(name: "洗濯", content: "8時までに干し終える")
task2 = Task.new(name: "仕事", content: "9時〜18時")
task3 = Task.new(name: "買物", content: "卵,ネギ")

todoList = Todo.new
todoList.add(task1)
todoList.add(task2)
todoList.add(task3)
todoList.info
puts "----"
todoList.delete(id:1)
todoList.info

```
[Rails]selfについての理解を深めたい[初心者]

#はじめに
プログラミングの超初心者です。
``self``への理解が全然できていないと感じたので、アウトプットも兼ねて、学んだことをまとめます！
それではいきましょう！！

#selfって何のこと？
``オブジェクトそのものを指す特殊な変数``です。

と、説明だけでは非常に分かりにくいですよね。
一緒に、どのように使用されているのか、確認していきましょう。

#使用例

```ruby:book.rb
class Book < ActiveRecord::Base
  def hoge                 #インスタントメソッド
  end

  def self.hoge            #クラスメソッド
  end

  def author               #インスタントメソッド
    self.hoge              #インスタンスメソッドのhogeが呼ばれる
    hoge                   #インスタンスメソッドのhogeが呼ばれる
    self.class.hoge
  end

  def self.author          #クラスメソッド
    self.hoge              #クラスメソッドのhogeが呼ばれる
    hoge                   #クラスメソッドのhogeが呼ばれる
  end
end
```

#クラスメソッド(特異メソッド)とは？
さて、``クラスメソッド``とは一体、何を指しているのでしょうか？
ざっくりの認識では、``クラス全体の中から何かを取り出す``際に使用するものです。
一つ一つのインスタンスには紐づいておらず、クラスに対して働きかけるメソッド、とも言い換えられるでしょう。
後述する``特異クラス``と分ける形で、``特異メソッド``と呼ばれます。

メソッドの呼び出しには、必ずレシーバが必要になります。
クラスメソッドには、あらかじめレシーバとしてself(自分自身のオブジェクト)が指定されているので、クラスから直接呼び出せる仕掛けになっています。

#インスタントメソッドとは？
では、``インスタントメソッド``とは何ぞや、となるでしょう。
簡単に説明すると、``特定のインスタンスから、何かを取り出す``際に使用されるもの、という認識でOKです。
逆に言うと、メソッド名に``self``を付けないと、指定したオブジェクト(レシーバ)に対してしか、そのメソッドを使用することが出来ないということです。

#特異クラスとは？
クラスメソッドの中で、別名``特異メソッド``と紹介していたのを覚えていますか。
実際は、クラスメソッドで毎回``self``と記載すれば大丈夫なのですが、クラスメソッドが複数に渡る場合は、いちいち``self``と打っていくのが面倒ですよね。
そこで使えるのが、``特異クラス``です。
使い方は、以下の通りです。

```ruby:book.rb
class Book < ActiveRecord::Base
  class << Book
    def say_thanx
      puts "#{self}, thanx"
    end
  end
end
```

↑に、``book = 'book'``という条件を与えた上で、``book.say_thanx``を打ち込むと、``book, thanx``と出力されます。
全体の流れは、クラスメソッドと似通っていますが、``<< Book``により、bookオブジェクトの特異クラスを呼び出しているため、あくまでもオブジェクトに対しての特異メソッド、という定義です。

#おわりに
自分でこの記事を書いていて、``なんて初心者にはとっつきにくい概念なんだろう``と思っています。
記事の中では、あくまで概念にしか触れていませんので、実際にアプリ制作で使用する際は、もっと実地に即した形での運用になると思います。
「なぜこの記載をしているのか」を大切にして、ただの丸暗記に終始することの無いよう、自戒を込めて執筆しました。
【PHP】単数系の英語を複数形に直す

作ったコードをQiitaに書く様にしていきたいと思います。

単数系の英語を複数形に直すというコードを下記の条件で作成しました。
・末尾がs, sh, ch, o, x である場合英単語の末尾にesを付ける
・末尾がf, fe のいずれかである英単語の末尾の f, fe を除き、末尾に ves を付ける
・末尾の1文字がyで、末尾から2文字目がa, i, u, e, oのいずれでもない英単語の末尾の y を除き、末尾に ies を付ける
・上4つに当てはまらないものにはsを付ける


英語に多くある不規則変換は、それ用に辞書を作成し対応しています。
なので実際に使用する際はもっと多くの不規則変換を登録する必要があると思われます。

```PHP
<?php
function SingularToPlural($in)
{
    //不規則変換用の辞書
    $dictionary = [
        'child'      => 'children',
        'crux'       => 'cruces',
        'foot'       => 'feet',
        'knife'      => 'knives',
        'leaf'       => 'leaves',
        'louse'      => 'lice',
        'man'        => 'men',
        'medium'     => 'media',
        'mouse'      => 'mice',
        'oasis'      => 'oases',
        'person'     => 'people',
        'phenomenon' => 'phenomena',
        'seaman'     => 'seamen',
        'snowman'    => 'snowmen',
        'tooth'      => 'teeth',
        'woman'      => 'women',
    ];

    //先に不規則変換をチェックしてから変換を行う
    if (array_key_exists($in, $dictionary)) {
        return $dictionary[$in];
    } else {
        $Singular = $in;
        $Singular = preg_replace("/(s|sh|ch|o|x)$/", "$1es", $Singular);
        $Singular = preg_replace("/(f|fe)$/", "ves", $Singular);
        $Singular = preg_replace("/(a|i|u|e|o)y$/", "$1ys", $Singular);
        $Singular = preg_replace("/y$/", "ies", $Singular);

        if (!preg_match("/s$/", $Singular)) {
            $Singular = $Singular . "s";
        }
        return $Singular;
    }
}

//単語毎に改行してある入力を想定、それをループ処理で取得する
while ($line = fgets(STDIN)) {
    $array[] = trim($line);
}
foreach ($array as $row) {
}
foreach ($array as $value) {
    echo SingulartoPlural($value) . "\n";
}
?>
```
Android studio：Kotlin：画面遷移

参照：
https://freelance-magazine.net/2020/02/25/androidkotlin%E5%85%A5%E9%96%80%EF%BC%9A%E3%82%A4%E3%83%B3%E3%83%86%E3%83%B3%E3%83%88intent%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E7%94%BB%E9%9D%A2%E9%81%B7%E7%A7%BB%E3%81%AB%E3%81%A4%E3%81%84/

ファイル→新規→アクティビティ→からのアクティビティを作る。

Activity NameをSecondActivityなど適当につけ、中身を作る。

MainActivity.ktにまず以下をインポート

```kotlin:MainActivity.kt
import android.content.Intent
import android.view.View
```

なにかボタンを押したときに遷移する場合は以下のように記載。
場所はclass MainActivity : AppCompatActivity() {　の中で　override fun onCreate(savedInstanceState: Bundle?)  の外。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?){
    ///いろいろー
}
    // 実行ボタンタップ時
    fun Button_Tap(view: View?){
        val intent = Intent(this, SecondActivity::class.java)
        startActivity(intent)
    }

}
```

ボタンのOnClickに「Button_Tap」を紐付けする。
【油断大敵】G検定に合格したので勉強法をまとめた

2020年11月7日（土）に行われたG検定にめでたく一発合格を果たしました。
受験料は12,000円なので絶対落とせない試験だったのでホッとしてます。

本記事では、「G検定って簡単で余裕」だとほざいている過去の私のようなあなたのために試験に挑むにあたり注意すべき点と勉強方法についてご紹介していきます。

まず大事なことを最初に言います。G検定の問題は **「難しい」** です。

## 筆者のスペック

- IT企業勤務(6年目)
- ビジネスデベロッパー

## G検定の概要
以下HPを参考しました。

> ディープラーニングの基礎知識を有し、適切な活用方針を決定して、事業活用する能力や知識を有しているかを検定する。

## 実施概要
	
- 試験時間：120分
- 知識問題（多肢選択式・220問程度）
- オンライン実施（自宅受験）

## 注意点

- 試験中にWebブラウザで検索することは許可されています。
- 120分で約220問を解く必要があるため、検索できる時間は限られます。正直一問ごとに検索していたら最後まで解き終わりません
- 問題は「難しい」です、公式テストの内容は２割出るかどうかです。私の場合、直近の法律関係の問題が５割以上出た感覚です。（合格率は50~60%ですが、問題の正答率は高くないと思います。おそらくボーダー調整を行っていると予想します。）

## 勉強法

上記注意点を踏まえて勉強を書いていきます。

私は仕事で普段機械学習エンジニアリングをやっていますが、それでもG検定で出てくる問題は非常に難しく感じました。

正直機械学習を多少やっていても、基礎から勉強をすることをお勧めします。（問題の中でディープラーニングの歴史みたいな問題も出るので）

## 勉強手順
 1. 書籍でディープラーニングの基礎知識(歴史・手法・事例)を網羅的に抑える
 2. 動画で具体的な実装イメージを固める
 3. 問題集をやってみる
 4. チートシートを**自分で作成する**

### 1.書籍でディープラーニングの基礎知識(歴史・手法・事例)を網羅的に抑える

まずは公式テキストブックを読むことをお勧めします。現状G検定の試験範囲を細かに抑えているテキストは存在しません。ただ１〜２割程度以下の定番テキストから出る問題があったので、ディープラーニングの歴史・手法・事例を網羅的に抑えましょう。

参考書：G検定公式テキスト
https://www.amazon.co.jp/dp/4798157554/

### 2. 動画で具体的な実装イメージを固める

上記テキストの中でもディープラーニングの手法・実装についてはなかなかイメージがつかない方もいるかと思います。

その場合は以下の動画が大変おすすめです。一回見るぐらいでOKです。

参考動画：Deep Learning入門 シリーズ
https://www.youtube.com/watch?v=-Dl8s4iufxI&list=PLg1wtJlhfh23pjdFv4p8kOBYyTRvzseZ3

全てを理解することは難しいと思いますので、ざっくりイメージできれば問題ありません。

### 3. 問題集をやってみる
通称「黒本」呼ばれる問題集をやってみてください。正直この問題集を１００％正答できるぐらいにやり込むことをお勧めします。基礎知識が本当についているか確認しましょう。

参考書：徹底攻略 ディープラーニングG検定 ジェネラリスト 問題集 徹底攻略シリーズ
https://www.amazon.co.jp/dp/B07NDVCN99?tag=g-kentei-22&linkCode=ogi&th=1&psc=1

ただここで安心しては言えなくてこの時点でようやく３割程度点数が稼げるぐらいだと思います。

### 4. チートシートを自分で作成する
では、残りの7割をどのようにして点を取っていくかというと「チートシートを**自分で**作成」してください。
「自分で作ること」がポイントです。

「G検定　チートシート」と調べると、試験対策用のチートシートがたくさん出てくるのですが、他人の作ったものを試験前日に用意すると失敗します。

これは僕のやらかしたことですが、自分が作っていないチートシートを利用すると今検索したい内容が自身のチートシートにあるかどうかの判断で時間を要してしまいます。

予めチートシート内容をある程度把握していれば、すぐにGoogle検索窓から探すべきか、自身のチートシートでCtrl+Fするべきなのか判断できますよね。

僕はチートシートに書かれている内容を把握していなかったので、かなりの時間をロスしてしまい、試験終盤は残りの１０問をヤマカンで提出することになりました。。。

## まとめ

G検定は合格率が高くても、問題は難しいので油断すると落ちます！！

（G検定はノー勉で行けますと勧める方はだいぶ罪深いと個人的には思ってる。。）
【NFS】Linuxホスト間のファイル共有

##目標
NFSサーバを構築し、Liunxホスト間でのファイル共有を実現する（AWS環境利用）。

##NFSの基礎知識
ネットワークを通じてファイルシステムを共有する際に使われる通信プロトコル。
主にUnix系OS同士のファイルシステム共有にはNFSが古くから使われており、
NFSサーバが公開したディレクトリをNFSクライアントがマウントすることで、
リモートファイルシステムをローカルファイルシステムと同様に扱うことが可能となる。

（[Linux教科書 LPICレベル2 Version4.5対応](https://www.shoeisha.co.jp/book/detail/9784798151250)より）

##前提
・AWS EC2インスタンス2台（本記事ではAmazon Linux 2 AMI (HVM), SSD Volume Type利用）(※１)が構築済みであること。

※１
NFSサーバとして利用するインスタンスに関しては、**2049番ポート（NFS）を開けておく**こと。

##作業の流れ
| 項番 | タイトル |
|:----:|:-------------|
| 1 | [NFSサーバの構築](#1nfsサーバの構築) |
| 2 | [NFSクライアントの構築](#2nfsクライアントの構築)|

##手順
###1.NFSサーバの構築
**①必要パッケージのインストール確認**
事前作成したEC2のNFSサーバ用インスタンスにOSログインし、ルートスイッチ後、NFS用パッケージのインストール確認

Amazon Linuxではデフォルトでインストールされていました（※）

```
[root@ip-172-31-43-189 ~]# rpm -qa | grep nfs
libnfsidmap-0.25-19.amzn2.x86_64
nfs-utils-1.3.0-0.54.amzn2.0.2.x86_64
```

※未インストールの場合、以下コマンドを実行してインストール

```
yum install nfs-utils
```

**②NFS公開ディレクトリのセットアップ**
NFSを利用して公開するディレクトリ、及び共有確認用のテストファイルをその配下に作成します。

```
mkdir -p /export/nfs
touch /export/nfs/share.txt
```

NFSの公開ディレクトリは`/etc/exports`内に記述します。

```
vi /etc/exports
```

`/etc/exports`には、公開するディレクトリ名、公開するクライアント（ホスト名orIPアドレス）、オプションを、
エクスポートするディレクトリ1つにつき1行で記述します。

本記事では、先ほど作成した/export/nfsを、全ホスト（*）に公開、オプションとして読み書き可能（rw）かつrootアクセス可能（no_root_squash）（※）という公開設定とします。

```:/etc/exports
/export/nfs  *(rw,no_root_squash)
```

※no_root_squashオプションについて
通常NFSクライアントからNFSサーバへrootアクセスを試みた場合（rootユーザでNFSマウントを行った場合）、セキュリティ確保のため匿名アカウントへマッピングされます。
しかしno_root_squashオプションを指定することでNFSクライアントからroot権限でのNFSサーバアクセスが可能となります（セキュリティ的には好ましくないため、本来は適用するクライアントの範囲を絞るべきのようです）

`exportfsコマンド`を利用して、/etc/exportsの記述内容を反映します。

```bash
exportfs -ar
```
エクスポート状況を表示し、以下のように公開ディレクトリ/export/nfsが出力されればOKです。

```
# exportfs -v
/export/nfs     <world>(rw,sync,wdelay,hide,no_subtree_check,sec=sys,secure,no_root_squash,no_all_squash)
```

**③NFSサーバ起動**
NFSサーバ起動→自動起動→状態確認

```
systemctl start nfs-server
systemctl enable nfs-server
systemctl status nfs-server
```

NFSサーバでエクスポートされているディレクトリを調べるには`showmountコマンド`を利用します。
以下のような出力となれば、適切に公開ディレクトリ/export/nfsがNFSサーバに反映されています。

```
# showmount -e
Export list for ip-172-31-43-189.ap-northeast-1.compute.internal:
/export/nfs *
```

###2.NFSクライアントの構築
**①NFS公開ディレクトリのマウント**
NFSクライアントとして利用するEC2インスタンスにOSログイン後、ルートスイッチ。
その後、以下のファイルシステムタイプをnfsとしたマウントを実行し、先ほど作成したNFSサーバの公開ディレクトリ/export/nfsを/mntへマウントします。
NFSサーバのプライベートIPアドレス部分は詰め替えを行ってください。

```
mount -t nfs NFSサーバのプライベートIPアドレス:/export/nfs/ /mnt
```

dfコマンドで/mntに公開ディレクトリ/export/nfs が正常にマウントされたか確認を行います。

```
# df -h /mnt
Filesystem                  Size  Used Avail Use% Mounted on
13.114.211.230:/export/nfs  8.0G  1.4G  6.7G  17% /mnt
```

また、/mnt配下に事前作成した共有確認用テストファイルshare.txtが存在することも一応確認します。

```
# ls -l /mnt
total 0
-rw-r--r-- 1 root root 0 Nov 20 05:52 share.txt
```

**②NFS公開ディレクトリの起動時自動マウント**
ついでに/etc/fstabを利用して起動時の自動マウントを有効化します。

```
echo 'NFSサーバのプライベートIPアドレス:/export/nfs /mnt nfs rw 0 0' >> /etc/fstab
```

再起動実行

```
reboot
```

再起動後、自動でNFSの公開ディレクトリがマウントされていればOKです。

##参考にさせて頂いた書籍及びサイト
・参考書籍
[Linux教科書 LPICレベル2 Version4.5対応](https://www.shoeisha.co.jp/book/detail/9784798151250)
・参考サイト
[【CentOS 7】NFSサーバ構築の備忘録](https://qiita.com/zaki-lknr/items/5c17b53b51eae7b21e2e)
matplotlibインストール時のpolyfitエラー

# matplotlibインストール時にエラーが出た
OSはMacOS BigSur。
python versionは3.6.10。
何も考えずに「numpy, pandas, matplotlib」をインストールしようとしたら、下記エラーが出た。

```shell
pip install matplotlib

RuntimeError: Polyfit sanity test emitted a warning, most likely due to using a buggy Accelerate backend. If you compiled yourself, see site.cfg.example for information. Otherwise report this to the vendor that provided NumPy.
RankWarning: Polyfit may be poorly conditioned
    
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```

# 対処法
インストールされたnumpyのバージョンが新しすぎる。らしい。
1.18を入れると動く。

```shell
pip install numpy==1.18
pip install matplotlib
```
pythonでbar chart race

# pythonでbar chart race
![out.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/9098dd4e-3d65-9294-d10a-d6c40d04a501.gif)
Youtubeなどでよく見かける棒グラフレースは[flourish](https://flourish.studio/)で作成されることが多いようですが、pythonで作成するライブラリがあるので紹介します。インストールや使用方法やDependencyなどは以下を参照のこと。
https://www.dexplo.org/bar_chart_race/
使い方は超簡単で、各データ名をコラムに持つ、日付ごとレコードをpandasのDataFrameに格納し、関数を呼び出すだけです。具体的にはこんなデータを用意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/3f74f813-2bd0-6d46-d155-b3d731a60939.png)
これを関数に与えるだけなのですが、GoogleがCovid-19の向こう28日間予測を公表しているのでそれをサンプルデータとして使用してみます。以下サンプルコードです。

```python
import pandas as pd
import bar_chart_race as bcr
df = pd.read_csv('https://storage.googleapis.com/covid-external/forecast_JAPAN_PREFECTURE_28.csv')
df = df.pivot_table(index='target_prediction_date', 
    columns='prefecture_name',
    values='cumulative_confirmed')
bcr.bar_chart_race(df=df, n_bars=10)
```

Jupyter上で実行し、しばらくするとアニメーションが表示されるはずです。
4行目でピボットしているのは、GoogleのレコードがPrefectureごとにレコードになっているので、ここでは累積陽性者数(cumulative_confirmed)に着目して、県ごとの数字をコラムに配置しています。変換後のDataFrameが上記の画像というわけです。Googleは他にもいろんな予測値を発表しているので、valuesの引数を色々変えて試してみるとよいです。
https://storage.googleapis.com/covid-external/COVID-19ForecastUserGuideJapan_Japanese.pdf

## オプションなど
``n_bars=10``はTop 10を表示するオプションで、省略すると全部棒グラフになります。``filename``オプションで、mpeg動画やgifアニメを作成することができますが、別途ffmpegやImageMagickのインストールが必要です。その他グラフを縦にしたりタイトルを入れるオプションなど、上記の作者さんのサイトにものすごく詳しく書いてあるので見たほうが早いです。
## 参考にした記事
[FFmpegで動画をGIFに変換](https://qiita.com/wMETAw/items/fdb754022aec1da88e6e)(トップの圧縮GIF画像を作成するのに)
[Pythonで二次元ランダムウォーク+matplotlib.animationのgif保存](https://ai-gaminglife.hatenablog.com/entry/2018/06/29/172551)(ImageMagickのインストール)
[Create a Bar Chart Race Animation in Python with Matplotlib](https://www.dunderdata.com/blog/create-a-bar-chart-race-animation-in-python-with-matplotlib)
enumを使用して投稿の公開設定をする（二択式）

# はじめに
## やりたいこと
- 投稿機能に公開ステータスを持たせる
- デフォルトは非公開にする
- 公開設定をセレクトボタンで選択させる

##　やってみて
enum自体は非常に奥が深いモジュールだと感じましたが、私がやりたいことは簡単に実装できました。
ですので、この投稿は初心者でもすぐに実践できる内容になっていると思います。

## 参考
[Rails公式リファレンス](https://api.rubyonrails.org/v5.2.3/classes/ActiveRecord/Enum.html)
[Pikawaka <【Rails】enumチュートリアル](https://pikawaka.com/rails/enum)

# 手順

## DB設計

```ruby:db/migrate/create_item.rb
class CreateItems < ActiveRecord::Migration[6.0]
  def change
    create_table :items do |t|
      t.string :title,        null: false
      t.string :tagbody
      t.string :url
      t.text :body,           null: false
      # statusカラム、integeｒ型、deroult: 0 を指定
      t.integer :status,      null: false, default: 0
      t.integer :category_id, null: false
      t.references :user,     foreign_key: true

      t.timestamps
    end
  end
end
```

boolean型で作成することもできますが、2個以上の定数と紐付けたい場合はinteger型を選択。

## Model

```ruby:models/item.rb
enum status: { closed: 0, open: 1 }
```
デフォルトを非公開にするので「closed」という定数を「0」に設定しました。

## Controller
通常通りストロングパラメーターとcreateアクションを定義します。

```ruby:controllers/items_controller.rb
class ItemsController < ApplicationController
  
  def create
    @item = Item.new(item_params)
    if @item.save
      redirect_to root_path
    else
      render :new
    end
  end

  private

  def item_params
    params.require(:item).permit(:title, :tagbody, :body, :url, :status, :category_id).merge(user_id: current_user.id)
  end

end
```
## View

formの書き方

```erb:views/items/new.html.erb
<%= form_with model:@item, url: '/items', local: true do |f| %>

  <%= f.select :status, Item.statuses.keys.to_a, {}, { class:'item-open' } %>

<% end %>
```
### 解説

f.selectの使い方

```:
<%= f.select 属性, 選択肢の集合, {オプション}, {HTMLオプション} %>
```

Item.statuses.keys.to_a について

`enumで指定した定数はハッシュの形で配列になっています。
したがってstatuses（複数形）.keys.to_a（配列を返すメソッド）の形で呼び出します。`

### 実装例

投稿画面

![画面収録 2020-11-20 16.42.42.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771826/b35373c0-eeb6-d68b-5f6b-e9aa08be8f63.gif)

DB

![スクリーンショット 2020-11-20 16.44.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771826/b212fe12-a5ae-beab-8430-f8c5e00df256.png)

数字で保存される

# 呼び出し方

公開記事だけをインスタンス変数に含める

```ruby:controllers/item_controller.rb
class ItemsController < ApplicationController

  def index
    @items = Item.open.order('created_at DESC')
  end

end

```

# おわりに

今回はenumを使用して二択のセレクトボックスからDBに保存する形を実践しました。
今後はより多くの選択肢を与えたり、enumを使用して検索・確認・更新などの機能を実装してみたいなと思います。

✔︎
Goのdeferの仕組みをきちんと理解する

deferって関数の最後で実行させたい処理に使うんでしょ、程度に考えていたが、きちんと理解をしようとdeferについて深堀りしてみた。

# deferについてざっくり説明
- deferで処理を記述しておくとfuncの最後で実行してくれる。
- 以下の例だと、"今日は"が実行され、funcの終わりになるので、その後"金曜日です。"が実行される。

```go
func hogehoge() {
    defer fmt.Println("金曜日です。")
    fmt.Println("今日は....")
}
```
```
今日は....
金曜日です。
```


# ちょっと深堀り
 [Tour of Go](https://tour.golang.org/flowcontrol/12)の説明によると

1. 囲まれているfunctionがreturnされるまで実行が見送られる。
2. defer呼び出しの引数は即時に評価されるが、実行がreturnされるまで見送られる。

との説明がある。
1はなんとなく理解できるが、２の**"即時に評価される"**という記述が気になったのであとで詳しく解説したい。

また、[プログラミング言語Go](https://www.maruzen-publishing.co.jp/item/?book_no=295039)の説明によると

1. deferを使うことでリソースの開放などがきれいに記述できる。
2. deferの正しい位置は資源の獲得に成功した直後

という旨の説明がある。
以下が例である。

```go
resp, err := http.Get(url)
defer resp.Body.Close() //本当はdeferの前にエラー判定いれるべき
```
Javaとかだと関数の最後にclose()を記述したりすることが多く、たまーにclose()を書き忘れたりすることもあるが、
goであればdefer使ってリソースを取得した直後に開放処理入れておくのが推奨されている。

# 即時に評価される、とは？
実際にコードを見たほうが早いと思うので、以下のサンプルを見て欲しい。

```go
func main() {
    defer today()()
    fmt.Println("今日は....")
}

func today() func() {
    fmt.Println("金曜日ですか？")
    return func() {fmt.Println("それとも土曜日ですか？")}
}
```

これを実行するとどうなるだろうか？
deferはmainが終わる時に呼び出されるから、```今日は...```がまず呼び出され、次にtoday()内の```金曜日ですか？```、最後に```それとも土曜日ですか？```という流れるになるかと思うかもしれない。

しかし、実行してみると

```
金曜日ですか？
今日は....
それとも土曜日ですか？
```

となるのである。さてなぜだろう？
ポイントはtoday()の返り値が関数型である点だ。

前項の**defer呼び出しの引数は即時に評価されるが、**という部分に注目して欲しい。

```defer today()()```の記述の部分で評価が実施されるのである。(なんで括弧が２つあるのか？と一瞬思う方もいるかもしれないが、話がそれるので最後に解説したい)

なので、

```go
fmt.Println("金曜日ですか？")
```
が実行される。その後、main内の処理に進み、

```go
fmt.Println("今日は....")
```
が実行される。

その後、遅延実行で

```go
fmt.Println("それとも土曜日ですか？")
```

という流れである。

# defer today()()の括弧が２つあるのはなぜ？？
括弧２ついらないんじゃない？？と思うひともいるかもしれないが、これは必要である。ためしに括弧を１つで実施するとどうなるだろうか？

```go
func main() {
    defer today()
    fmt.Println("今日は....")
}

func today() func() {
    fmt.Println("金曜日ですか？")
    return func() {fmt.Println("それとも土曜日ですか？")}
}
``````

```出力結果
今日は....
金曜日ですか？
```

順番が変わった上に、土曜日が消えている。。。。

```go
defer today() //1
defer today()() //2
```

この２つの記述は根本的に違うのである。

1はあくまで、deferの処理でtoday関数を実行する。つまり、main関数の最後にtoday()が実行されるのである。この処理では無名関数がreturnされているが、無名関数は実行されないということなのである。

それに対し、2はtoday()でリターンされた関数をmain関数の最後に実施するのである。わかりやすく記述すると2はdeferの処理で無名関数```func() {fmt.Println("それとも土曜日ですか？")}```を実行しているのである。
C#のTaskの動きを理解するために

# 背景
C#での非同期処理について理解できず、いろいろとためした結果、個人的に一番理解しやすいと思ったコードの備忘録です。

# 概要
## C#の非同期関数
- `async`キーワードがついた関数が非同期関数。
- `JavaScript`で`async`で宣言された関数が`Promise`を返すのと似たように、C#では`Task<T>`を返す
- 内部では`await`が必ず使用される。使用されていない場合、`async`キーワードがついていても通常の関数として実行される。
- `await`キーワードを付与して実行された非同期処理は`Task<T>`が完了するまで待つ。

## 参考
[Task.Run メソッド](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.tasks.task.run?view=net-5.0)
 
## Taskを利用したコード
```csharp
List<string> list = new List<string>() { "ABCDEFG", "HI", "JKL" };
List<Task> tasks = new List<Task>();

list.ForEach(str => {
    tasks.Add(
        Task.Run(async () => {
            await Task.Delay(str.Length * 1000);
            Console.WriteLine(str);
        })
    );
});

Task allTask = Task.WhenAll(tasks);
allTask.Wait();
```
## 1.複数の非同期タスクを定義
非同期であることがわかりやすいように、`List<string> list`内の**それぞれの文字列の長さ*1秒後に文字列を出力する**タスクを`Task.Run`で作成し、`List<Task> tasks`に追加していく。

## 2.非同期タスクがすべて完了するのを待つ
`Task.WhenAll()`の戻り値`Task allTask`で`Wait()`を実行することですべての非同期タスクが完了するのを待つ

## 結果
```bash:Result
HI
JKL
ABCDEFG
```
実際に実行した結果、一番時間がかかる"ABCDEFG"の出力までの約７秒ですべてのタスクが完了していることがわかった。

![スクリーンショット 2020-11-20 161853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197227/7f52326c-f397-c0df-3261-14284b857bcc.png)
ffmpegで動画を連結する備忘録

PHPから実行した際の備忘録。
連結する全動画の画角、コーデックが同じであること。

```text:file_list.txt
file '/var/***/1.mp4'
file '/var/***/2.mp4'
file '/var/***/3.mp4'
file '/var/***/4.mp4'
file '/var/***/5.mp4'
```

```php
# 動作確認済み
$cmd = "ffmpeg -f concat -safe 0 -i {$file_list_path} -c copy {$output_local_path}.mp4";
system($cmd);

# こっちは未テスト
$cmd = "ffmpeg -f concat -safe 0 -i {$file_list_path} -c:v copy c:a copy {$output_local_path}.mp4";
system($cmd);
```

* -f concat
    * 連結指示
* -safe 0
    * file_list.txt 内でファイルパスを絶対パスで指定する際に必要とのこと
* {file_list_path}
    * 連結するファイルのパスを書いたテキストファイルパス
* -c copy
    * オリジナルのコーデックを再エンコードしない（無劣化）
* -c:v copy
    * ビデオコーデックを再エンコードしない（無劣化）
* -c:a copy
    * オーディオコーデックを再エンコードしない（無劣化）
Xamarin.FormsにてiOSのビルドエラー。画像がFile not foundとされる問題

以下の問題が発生していましたが解決したので記録しておきます。
同じような問題を抱える開発者もいると思うので参考になれば幸いです。

# 問題
以下のビルドエラーがでる

> File not found: ~/Library/Caches/Xamarin/mtbs/builds/~/AppIcon.appiconset/[画像ファイル名].png

# 前提
* Microsoft Visual Studio 2019　を使用
* iOS ビルド時にエラー
* Macbookの容量がないなどの理由でLibrary/Caches/内の削除など行った
* AppIcons.appiconsetで設定している

# 原因
iOSのプロジェクトファイルにすでに使用されていないAssetの参照先が残っていた。
Macbook内のLibrary/Cachesフォルダ内に対象のファイルが存在しないためエラーを起こしていた。

# 解決策
iOSのプロジェクトファイルにすでに使用されていないAssetの参照先を削除する。

```xml:ProjectName.iOS.csproj
  <ItemGroup>
    <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\appstore.png">　<!-- AppIconsではなくAppIconなど、以前設定していたパスが残っている（この部分を削除） -->
      <Visible>false</Visible>
    </ImageAsset>
    <!-- （略） -->
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\appstore.png">  <!-- 以下は現在使用している正しいパス -->
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\Contents.json">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon120.png">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon152.png">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon167.png">
      <Visible>false</Visible>
    </ImageAsset>
    <!-- （略） -->
  </ItemGroup>
```

#結論
iOSのプロジェクトファイル内は普通は編集することはないはずでバグの一種で設定が残っていたと思われる。（改善されている可能性もある）
MacbookのLibrary/Caches/内の削除前は問題なくビルドが通っていたので削除を行ったことでエラーが表面化したと思われます。
以上、同様の問題で参考になれば幸いです。
デフォルト引数が素敵【2020/11/20】

### javascriptでは、デフォルト引数が設定できる

ある条件がtrueの時だけ、モデルを呼び出して処理をしたい

- メソッド側

```javascript
model.method(data, true) 
model.method(data)
```

- モデル側(model.js)

```javascript
method(data, isHTML = false) {
    if(isHTML) {
      console.log(data)
    }
  }
```

とすれば、メソッド側でtrue/falseの分岐を一々書かなくても、必要なものにtrueを追加で引数に入れるだけで良い。
コードがシンプルになる。


参照: [MDN-Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Default_parameters)
DarknetのMakefileを変更して再ビルドする

#はじめに
以前、Darknetを使用して物体検出にチャレンジしてみました。
[【参考】Jetson Nanoを使って物体検出(YOLO) ](https://qiita.com/Kim_Burton/items/455d21c8eb9da687aecc)
Darknetでは、設定ファイルである`Makefile`の内容を更新後、ターミナル上で`make`と打ち込んでビルドすることになります。
この時、`Makefile`の内容を書き間違えたため、`Makefile`の内容を変更して保存し、再び`make`を実行したところ、エラーが出てしまいました。

#Makefileの内容を変更して再ビルドする
Darknetを再ビルドするには既存のコンパイル環境を削除する必要があります。
手順は簡単で下記を実行するだけです。

```bash
#darknetディレクトリに移動
cd darknet

#既存の環境を削除
make clean

#再ビルド実行
make
```
dbcaが見たことないエラー出力した

10g環境を作る必要があり、見たことないエラーに遭遇した。。

```
$ dbca -silent -createDatabase -responseFile ./dbcal.rsp
UnsatisfiedLinkError exception loading native library: njni10
Exception in thread "main" java.lang.UnsatisfiedLinkError: get
        at oracle.net.common.NetGetEnv.get(Native Method)
        at oracle.net.config.Config.getNetDir(Unknown Source)
        at oracle.net.config.Config.initConfig(Unknown Source)
        at oracle.net.config.Config.<init>(Unknown Source)
        at oracle.sysman.assistants.util.NetworkUtils.<init>(NetworkUtils.java:222)
        at oracle.sysman.assistants.util.step.StepContext.<init>(StepContext.java:255)
        at oracle.sysman.assistants.dbca.backend.Host.<init>(Host.java:682)
        at oracle.sysman.assistants.dbca.backend.SilentHost.<init>(SilentHost.java:125)
        at oracle.sysman.assistants.dbca.Dbca.getHost(Dbca.java:150)
        at oracle.sysman.assistants.dbca.Dbca.execute(Dbca.java:94)
        at oracle.sysman.assistants.dbca.Dbca.main(Dbca.java:180)
```

JNI関連っぽいので環境変数を疑う。。。
環境変数設定して、relink allを実行したら解消した。

```
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
export SHLIB_PATH=$ORACLE_HOME/lib32:$SHLIB_PATH
cd $ORACLE_HOME/bin
./relink all
```

お疲れさまでした。
Android studio：Kotlin：text viewに囲み線

app/srv/main/res/drawableに以下を追加

```xml:bg_border_black.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="1dp"
        android:color="@color/black" />
    <corners android:radius="5dp" />
</shape>
```

app/srv/main/res/layout/activity_mail.xmlなどの囲み線をつけたいtextviewに以下を追加して背景に設定。

```xml:activity_main.xml
    <TextView
        android:background="@drawable/bg_border_black"/>
</shape>
```
参考：
https://www.koheiando.com/tech/android/200
マイグレーションでよく使うコマンドメモ

# はじめに
マイグレーションを行う時によく使うコマンドの備忘録
パッケージマネージャーコンソールに入力する

## マイグレーションファイルを作成
テーブルの作成や更新した後に使う

```
PM> Add-Migration [ファイル名]
 ```

## データベースの更新
マイグレーションファイルを元に、データベースを更新する時に使う

```
PM> Update-Database
 ```

## マイグレーションの一覧を取得
どのマイグレーションファイルを読み込んでいるのか確認できる

```
PM> Get-Migrations
 ```


## データベースの状態を戻す
データベースの更新が間違っていた時に取り消すために使う

```
PM> Update-Database -TargetMigration [ファイル名]
 ```
raise ValueError, "unsupported hash type"となった時の対応方法



# 事象 : hmacをインストールしようとして失敗した
- 環境 : Cloud9


```bash
$ pip install hmac
Defaulting to user installation because normal site-packages is not writeable
Collecting hmac
  Downloading hmac-20101005.tar.gz (4.5 kB)
Requirement already satisfied: setuptools in /usr/lib/python3.6/dist-packages (from hmac) (36.2.7)
Collecting hashlib
  Downloading hashlib-20081119.zip (42 kB)
     |████████████████████████████████| 42 kB 1.1 MB/s 
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python3.6 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-5jes0rhx/hashlib/setup.py'"'"'; __file__='"'"'/tmp/pip-install-5jes0rhx/hashlib/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-uvx1s968
         cwd: /tmp/pip-install-5jes0rhx/hashlib/
    Complete output (22 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3.6/dist-packages/setuptools/__init__.py", line 10, in <module>
        from setuptools.extern.six.moves import filter, map
      File "/usr/lib/python3.6/dist-packages/setuptools/extern/__init__.py", line 1, in <module>
        from pkg_resources.extern import VendorImporter
      File "/usr/lib/python3.6/dist-packages/pkg_resources/__init__.py", line 36, in <module>
        import email.parser
      File "/usr/lib64/python3.6/email/parser.py", line 12, in <module>
        from email.feedparser import FeedParser, BytesFeedParser
      File "/usr/lib64/python3.6/email/feedparser.py", line 27, in <module>
        from email._policybase import compat32
      File "/usr/lib64/python3.6/email/_policybase.py", line 9, in <module>
        from email.utils import _has_surrogates
      File "/usr/lib64/python3.6/email/utils.py", line 28, in <module>
        import random
      File "/usr/lib64/python3.6/random.py", line 46, in <module>
        from hashlib import sha512 as _sha512
      File "/tmp/pip-install-5jes0rhx/hashlib/hashlib.py", line 80
        raise ValueError, "unsupported hash type"
                        ^
    SyntaxError: invalid syntax
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```

## 原因 : そもそもインストールする必要がないから
インストールしなくてもhmac, hashlibはあるようだ・・・おちついてメッセージを見ると
`Requirement already satisfied: setuptools in /usr/lib/python3.6/dist-packages (from hmac) (36.2.7)`
と書いてある。
結果がわかると何故とりあえずインストールしようとしたのかがわからない。

参考 : [python - Unsupported hash type error while installing hashlib using pip3 - Stack Overflow](https://stackoverflow.com/questions/46129813/unsupported-hash-type-error-while-installing-hashlib-using-pip3)

[はじめてのHMACとCloud9で混乱を極めてPythonのバージョンアップなどもしてしまった・・・](https://qiita.com/ponsuke0531/items/fc5852bbd2297575e69b)

### 対応 : インストールしないでただ使う
`import hmac, hashlib`を書いて使えばOK
制限時間付き標準入力

プログラムを書いていて一度は制限時間のある、標準入力を作りたいと思ったことはあると思います。因みに僕はありません。
以外と簡単に Go で実現できたのでメモがてら書きます。いつかの自分のためですね。

## 方法

方法はいたって簡単で、標準入力を受け取るサブルーチンを作って、入力テキストをチャンネルで受け取るだけです。

```go
in := make(chan string, 1)
go func() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Scan()
	in <- sc.Text()
}()
````

上記のチァンネルと `time.NewTimer` や `time.NewTicker` を組み合わせることで簡単に実現できます。

```go
timer := time.NewTimer(time.Second * 10)
select {
  case text := <-in:
    // 入力を使った処理
  case <-timer.C:
    // タイムアウト時の処理
}
```

## 適当に作ったサンプル
上記の方法で適当に作ったサンプルです。ローカルで実行してみると雰囲気を掴めると思います。

```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"time"
)

func main() {
	in := make(chan string, 1)
	go func() {
		sc := bufio.NewScanner(os.Stdin)
		sc.Scan()
		in <- sc.Text()
	}()

	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()
	fmt.Println("制限時間は5秒。坊っちゃんの作者を入力して")
	for i := 0; i < 5; i++ {
		select {
		case text := <-in:
			if text == "夏目漱石" {
				fmt.Printf("入力できてすごい\n")
			} else {
				fmt.Printf("間違えているよ\n%s\n", text)
			}
			i = 5
		case <-ticker.C:
			switch i {
			case 0:
				fmt.Println("制限時間あるので早めに")
			case 1:
				fmt.Println("はやくはやく")
			case 2:
				fmt.Println("邪魔だと思う？")
			case 3:
				fmt.Println("僕もそう思う")
			case 4:
				fmt.Println("ゲームオーバー(笑)")
			}
		}
	}
}
```

## 締め

簡単でしたが、いつ使うんでしょうね。
Jetson Nanoを使って物体検出(YOLO) -②Jetson Nano上で物体検出YOLOの実行-

#はじめに
会社の同僚とJetson Nanoを使用して、YOLOによる物体検出にチャレンジしてみました。

[①【基本】Jetson Nanoの設定](https://qiita.com/Kim_Burton/items/74ae879ab7162321ca1c)
②【基本】Jetson Nano上で物体検出YOLOの実行
③【発展】オリジナルモデルを作成して実行

今回は②Jetson Nano上で物体検出YOLOの実行編となります。

#2. YOLOとは
どこに&何があるかを推定する(Object Detection)ためのディープラーニングの手法です。

Object Detectionの初期の手法としては、R-CNNが知られています。
R-CNNはGPUを使っても結果の出力に約30秒くらいかかるという弱点があり、リアルタイム推論には不向きでした。
それをさらに改良して高速にした手法がFast R-CNN、Fast R-CNNをちょっと高速にした手法がFaster R-CNNになります。
推論速度はGPUスペックにもよりますが、結果的にFaster R-CNNでもリアルタイムで使用するには速度が遅いという弱点がありました。

そんな中で1人の大学院生がFaster R-CNNをさらに高速にし、リアルタイムでも実現可能にした手法を開発しました。それがYOLOです。

どれくらい速いかというと、[公式ページ](https://pjreddie.com/darknet/yolo/)にあるグラフを見ていただくとわかりやすいです。
横軸が推論速度、縦軸が精度で、紫とオレンジのラインが他の手法、ピンクのラインがYOLOなんですが、、、速すぎてグラフを突き抜けています（笑）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697702/cab4004b-5891-f008-a5ce-0a0861a47a36.png)

ちなみに、YOLOはYou Only Look Onceの略で、You Only Live Once（人生は一度きり）のパロディとなります。
あと、噂によるとYOLOを開発した大学院生はComputer Visionの世界から引退してしまったそうです。（こんなに能力が高いのに、、、すごすぎます。）


#3. ダウンロード&設定
ダウンロードするのは[公式バージョン](https://pjreddie.com/darknet/yolo/)ではなく、その派生版である[AlexeyABさんバージョン](https://github.com/AlexeyAB)を使用します。
下記は[前章](https://qiita.com/Kim_Burton/items/74ae879ab7162321ca1c)で構築したJetson Nano上で実行しています。

学習済モデルについては、通常版とtiny版があり、精度は高いが速度が遅いのが通常版、精度は低いが速度は速くなるのがtiny版となります。
今回はtiny版を使用します。
通常版も試してみましたが、Jetson Nano上ではかなり推論速度が遅くリアルタイムには不向きかなと感じました。
（tiny版になると精度は下がってしまいますが…）

```bash
##Darknetのダウンロード
git clone https://github.com/AlexeyAB/darknet darknet
cd darknet

##学習済モデルのダウンロード
wget https://pjreddie.com/media/files/yolov3-tiny.weights
```

ダウンロードしたら、`darknet`ディレクトリの中に`Makefile`というファイルがあるはずです。
このファイルの中身の`GPU`、`CUDNN`、`OPENCV`部分を下記に変更してください。
また、Jetson NanoのGPUを有効にするために、`ARCH`部分の下記のコメントアウトを外してください。

```text:Makefile
GPU=1
CUDNN=1
OPENCV=1

...

# For Jetson TX1, Tegra X1, DRIVE CX, DRIVE PX - uncomment:
ARCH= -gencode arch=compute_53,code=[sm_53,compute_53]
```

あとは、cudaのパスを設定する必要があります。
ターミナルで下記を実行してください。

```bash
export PATH=/usr/local/cuda/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH}
```

あとはコンパイルするだけです。

```bash
##ビルド
make

##ビルドできたか確認する
./darknet
```
`usage: ./darknet <function>`と返ってくればビルド成功です。

※もし、'Makefile'の中身を間違えた等で、再ビルドが必要になった方は[こちら](https://qiita.com/Kim_Burton/items/5348409c2a95ecf386a5)をご参考ください。
#4. USBカメラで物体検出の実行
さて、USBカメラで物体検出を実行してみましょう。
Jetson NanoにUSBカメラをつないで、下記を実行するだけです！

```bash
./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights
```

#5. まとめ＆最後に
前回はJetson Nanoの環境設定、今回はJetson Nano上でYOLOを使用してリアルタイム推論を実行してみました。

Darknetが提供するモデルが使えると、人とか犬とか馬とかパソコンとかマグカップとかを検出できるようになります。
・・・でも、これって実務の中では使えないですよね。

犬とか馬とかそんなことはどうでも良くて、もっと違うことを検出したい！
次回はオリジナルモデルの作成の方法と、それをJetson Nano上で実行する方法について記載します！
OpenSSLでSSL証明書を検証して有効期限を確認する。

## はじめに
先日レガシーなL4ロードバランサ配下のSSL証明書を更新しました。
OpenSSLを使えば更新後にlocalhostに対してSSL証明書を簡単に検証できます。
Let's Encrypt の更新確認などにも活用できるかもしれません。

## やってみよう

#### 必用なもの
opensslだけ

#### 外部から hoge.com のSSL証明書を検証する場合

検証だけでは何ですので、検証結果から有効期限を表示してみます。

```sh:
openssl s_client -connect hoge.com:443 -tls1_2 < /dev/null 2> /dev/null | openssl x509 -text | grep 'Not'
```

```text:実行結果
Not Before: Nov 18 03:34:53 2020 GMT
Not After : Feb 16 03:34:53 2021 GMT
```

#### localhost から hoge.com のSSL証明書を検証する場合

前述のやりかたで外部からSSL証明書できますが、L4ロードバランサ配下の場合は外部からアクセスできません。
その場合はこうやりましょう！

```sh:
openssl s_client -connect localhost:443 -tls1_2 -servername hoge.com < /dev/null 2> /dev/null | openssl x509 -text | grep 'Not'
```

```text:実行結果
Not Before: Nov 18 03:34:53 2020 GMT
Not After : Feb 16 03:34:53 2021 GMT
```