OmniAICreator/Qiita-1.07M huggingface dataset:
ベストプラクティス

# アプリ構成ベストプラクティス
プロジェクト構成を分かりやすく。
ディレクトリ、ファイル構成の最適化。

デフォルトのまま構築すると、少々問題がある

- ベースと設定のディレクトリ名が被る問題
- staticファイルがアプリごとに配置されてしまう問題
- テンプレートフォルダがアプリごとに配置されてしまう問題

## ベースと設定のディレクトリ名が被る問題
設定ファイルディレクトリ名を指定した上で、コマンド実行。

```
mkdir django
cd django
```

startproject

```
django-admin.py startproject config .
```
```
django
├── config
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
```

## staticファイルがアプリごとに配置されてしまう問題

### ディレクトリ構成
ベースディレクトリ直下に、静的ファイル用ディレクトリを設置する。

```
django
├── config
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── static
│   ├── app
│   ├── images
│   └── js
└── templates
```

### 静的ファイルディレクトリ設定
***STATIC_URL***
静的ファイル配信用ディレクトリ。
python manage.py startapp [app]にて生成されたディレクトリ内のstaticフォルダの場所を指す。
ベストプラクティス上、使用しない。

***STATICFILES_DIRS***
任意の、staticフォルダの定義が可能。

***STATIC_ROOT***
本番環境で使用するstatisフォルダ設定に使用。
DEBUG=False(本番環境)の場合に適用される。


```py:example
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_NAME = os.path.basename(BASE_DIR)

STATICFILES_DIRS = os.path.join(BASE_DIR, 'static')
```


## テンプレートフォルダがアプリごとに配置されてしまう問題

### ディレクトリ構成
ベースディレクトリ直下に、template用ディレクトリを設置する。

```
django
├── config
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── static
└── templates
```

### templateディレクトリ設定
***TEMPLATES***にて設定を行う。

```py:setting.py
TEMPLATES = [
    {
        ...
        'DIRS': [<適切なPath>],
    },
]

```
[Oracle Database Express Edition 11g Release 2]インストール

# 参考サイト
◆Oracle Database Express Edition 11g Release 2 をインストールしてテーブルを作成してみる
　https://www.doraxdora.com/blog/2017/08/31/post-2304/

◆Oracle Database 11g Express Edition -ただでOracleのデータベース使いましょう。
　https://qiita.com/GohanOmori/items/0b58a656174c767e239e

◆Oracle11g XEをインストールするときの注意点
　https://qiita.com/alpha_pz/items/8123375f6b9660b3ef32

◆超初心者の Oracle データベース開発環境導入
　https://qiita.com/heignamerican/items/5e69f7590378f2f00549

# インストール後のお試しコマンド

```sql:oraora.sql
-- DB接続
> sqlplus sys/[パスワード]@XE as sysdba


```

よし、ベース環境は整えたから次は。。。Coming Soon...
Elixirで円周率求めてみた

#なぜ円周率を求めるのか
特に理由はなく、ゼミでとりあえず何かつくってみよう的なノリでした。ちなみにElixir歴一週間にも満たないひよっこが書いております。
ちなみにモンテカルロ法使うらしいです、僕もいまいちよくわからないので、気になる人は自分でググるなりしてください。
ちなみに僕は解けなかったのでHaskellのめっちゃできる先輩に解説してもらった後、自分で何も見ずにやってみました。ほぼコードは同じですが、、、

#とりあえず書いてみる

```elixir:pi.exs
defmodult Pi do
  def pi n do
    Stream.repeatedly(fn -> [:rand.uniform(), :rand.uniform()] end)
    |> Enum.take(n)
    |> Enum.map(fn x -> dist(x) end)
    |> Enum.map(fn x -> x < 1 end)
    |> mond
  end


  def dist [x, y] do
      x * x + y * y
  end

  def mond x do
    t = x
        |> Enum.filter(fn a -> a == true end)
        |> Enum.count()
    l = Enum.count(x)
    (t / l) * 4
  end
end
```
#どうやっているか

```elixir:pi.exs
defmodult Pi do
  def pi n do
    Stream.repeatedly(fn -> [:rand.uniform(), :rand.uniform()] end)
    |> Enum.take(n)
    |> Enum.map(fn x -> dist(x) end)
    |> Enum.map(fn x -> x < 1 end)
    |> mond
  end
```
まず、`Stream.repeatedly(fn -> [:rand.uniform(), :rand.uniform()] end)`で１以下の乱数の無限リストを作ります(座標です)。次に`|> Enum.take(n)`で最初のからｎ個とって、`|> Enum.map(fn x -> dist(x) end)`dist関数を呼び出し、`|> Enum.map(fn x -> x < 1 end)|> mond`返ってきた値をmond関数に渡す。
###dive関数とmond関数

```elixir:pi.exs

  def dist [x, y] do
      x * x + y * y
  end

  def mond x do
    t = x
        |> Enum.filter(fn a -> a == true end)
        |> Enum.count()
    l = Enum.count(x)
    (t / l) * 4
  end
```

dive関数は距離を、mond関数は、$π=4t/l$でπが求まるそうなので計算していきます。ここら辺はモンテカルロ法　円周率計算　などでググってください。すみません。

#結果

```
$ iex pi.exs
Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.9.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Pi.pi(10)
3.2
iex(2)> Pi.pi(100)
3.24
iex(3)> Pi.pi(1000)
3.092
iex(4)> Pi.pi(10000)
3.1536
iex(5)> Pi.pi(100000)
3.14328
iex(6)> Pi.pi(1000000)
3.144968
iex(7)> Pi.pi(10000000)
3.142738

```
できた！ただ、`100000000`までいくと`segmentation fault (core dumped)`が起こった。

#最後に
このコードをもっと良くするために間違っているところや、もっとこうした方がいいなどElixirの強い人アドバイスください。よろしくお願いします。
僕は関数型プログラミング言語は初めてでしたが、オブジェクト指向より自分に合っているのではと思うぐらい楽しいです、ここまで見てくだっさてありがとうございました。
HypriotOSのラズパイDockerサーバのGPG鍵期限切れ

# はじめに
家でRaspberry Pi 3 B+にHypriotOSをインストールしてDocker基盤を構築して運用しています．
久しぶりにパッケージを更新しようと思いapt updateを叩いたところGPG keyの期限切れでエラーが発生しました．
その時の記録です．

備忘録的なものなので，正しくないところがあるかもしれませんので，参考にされる場合はご注意ください．

# 発生した事象
久しぶりに（そもそもちゃんと定期的に実行すべきですが）ラズパイサーバのパッケージを更新しよと思い，apt updateを実施したところ，以下のようなエラーが発生しました．

```shell
HypriotOS/armv7: hoge@buri in ~
$ sudo apt update
Get:1 http://archive.raspberrypi.org/debian stretch InRelease [25.4 kB]
Get:2 http://raspbian.raspberrypi.org/raspbian stretch InRelease [15.0 kB]
Get:3 https://download.docker.com/linux/raspbian stretch InRelease [31.1 kB]
Get:5 http://archive.raspberrypi.org/debian stretch/main armhf Packages [221 kB]
Get:6 http://raspbian.raspberrypi.org/raspbian stretch/main armhf Packages [11.7 MB]
Get:4 https://packagecloud.io/Hypriot/rpi/debian stretch InRelease [23.2 kB]
Err:4 https://packagecloud.io/Hypriot/rpi/debian stretch InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 64AEF170D1528977
Fetched 12.0 MB in 28s (416 kB/s)
Reading package lists... Done
Building dependency tree       
Reading state information... Done
56 packages can be upgraded. Run 'apt list --upgradable' to see them.
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://packagecloud.io/Hypriot/rpi/debian stretch InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 64AEF170D1528977
W: Failed to fetch https://packagecloud.io/Hypriot/rpi/debian/dists/stretch/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 64AEF170D1528977
W: Some index files failed to download. They have been ignored, or old ones used instead.
```

鍵の有効期限切れのようです．

# 解決法
新しい鍵をダウンロードしてきて登録します．
[packagecloudのhypriotのページ](https://packagecloud.io/app/Hypriot/rpi/gpg#gpg-apt)を参考にしました．

```shell
curl -L https://packagecloud.io/Hypriot/rpi/gpgkey | sudo apt-key add -
```

以上でエラーを解決できました．

# おわりに
普段Debian系を使う機会が少なく，詳しくないのでちゃんとした方法があるのかもしれません・・・
ひとまずこれで修正できたのでメモとして残しておきます．
SpringでMySQLエラー Unknown column ' 値1 ' in 'field list'  

Spring Java の Entityで

Unknown column ' 値1 ' in 'field list'  

が出てハマりました。

結論から言うと大文字が混ざっていたのが問題でした。

ターミナルからMySQLに直接SQLを流し込むと大文字でも正常に動作しますが、
Spring + Java のプログラムから呼び出そうとするとカラムがないというエラーになります。

field がない　と特定の列名を指定してくる場合はカラムに日本語や大文字などが混ざっていないか注意しましょう。
COMオブジェクトを含んだネイティブ関数のP/Invokeメソッド変種

COMオブジェクトを生成する、ファクトリー関数をP/Invokeメソッドとして宣言する場合、(COMオブジェクトを含まなくてもそうだけど)いろいろな宣言が可能なので、そのメモ。

### ネイティブ関数
[SHCreateDefaultContextMenu](https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shcreatedefaultcontextmenu) を例にする。

```cpp
SHSTDAPI SHCreateDefaultContextMenu(_In_ const DEFCONTEXTMENU *pdcm, _In_ REFIID riid, _Outptr_ void **ppv);
```

## メソッドいろいろ
### 素直なP/Invokeメソッド
C# 7.2から使用できるin引数を使用している。

```csharp
[DllImport("shell32.dll", PreserveSig = false)]
void SHCreateDefaultContextMenu(in DEFCONTEXTMENU pdcm, in Guid riid, out IContextMenu ppv);
```
### C# 7.2より前
`Guid`構造体には、`UnmanagedType.LPStruct`が使えるらしいので、`ref` を付けずにポインタを渡せる。

```csharp
[DllImport("shell32.dll", PreserveSig = false)]
void SHCreateDefaultContextMenu(ref DEFCONTEXTMENU pdcm, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IContextMenu ppv);
```

### COMオブジェクトをinterfaceではなく、objectで受け取る

```csharp
[DllImport("shell32.dll", PreserveSig = false)]
void SHCreateDefaultContextMenu(ref DEFCONTEXTMENU pdcm, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)]out object ppv);
```

### 戻り値をHRESULTのまま受け取る
`DllImport` 属性の`PreserveSig`を`true`(デフォルト)にしておけば、ネイティブ関数の`HRESULT`の値をそのまま受け取れる。
その代わり、エラーチェックは自分でやる必要がある。

```csharp
[DllImport("shell32.dll", PreserveSig = true)]
int SHCreateDefaultContextMenu(in DEFCONTEXTMENU pdcm, in Guid riid, out IContextMenu ppv);
```

### 最後の引数を戻り値として受け取る
COMのIDLには `retval`属性があり、メソッドの戻り値があるかどうかは最後の引数の属性で決まる。
単なる属性なので、P/Invokeでもシグニチャ次第となる。
`PreserveSig = false`が付与されている前提で、

- 戻り値を`void`にすれば戻り値なしになる
- 最後の引数を戻り値に移動させればそれが戻り値になる

```csharp
[DllImport("shell32.dll", PreserveSig = false)]
IContextMenu SHCreateDefaultContextMenu(in DEFCONTEXTMENU pdcm, in Guid riid);
```

### 付録:上記で使用している型の宣言

```csharp
struct DEFCONTEXTMENU
{
    public IntPtr hwnd;
    public IContextMenuCB pcmcb;
    public PCIDLIST_ABSOLUTE pidlFolder;
    public IShellFolder psf;
    public uint cidl;
    public PCUITEMID_CHILD_ARRAY apidl;
    [MarshalAs(UnmanagedType.IUnknown)]
    public object punkAssociationInfo;
    public uint cKeys;
    // const HKEY            *aKeys;
    public IntPtr[] aKeys;
}

[ComImport]
[SuppressUnmanagedCodeSecurity]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214e4-0000-0000-c000-000000000046")]
internal interface IContextMenu
{
    void QueryContextMenu(
        /* [annotation][in] */
        IntPtr hmenu,
        /* [annotation][in] */
        uint indexMenu,
        /* [annotation][in] */
        uint idCmdFirst,
        /* [annotation][in] */
        uint idCmdLast,
        /* [annotation][in] */
        uint uFlags);
    
    void InvokeCommand(
        /* [annotation][in] */
        in CMINVOKECOMMANDINFO pici);
    
    void GetCommandString(
        /* [annotation][in] */
        UIntPtr idCmd,
        /* [annotation][in] */
        uint uType,
        /* [annotation][in] */
        UIntPtr pReserved,
        /* [annotation][out] */ 
        StringBuilder pszName,
        /* [annotation][in] */
        uint cchMax);
}
```
ほめ達の学び

## はじめに
最近、会社の研修でほめる達人、通称「ほめ達」の研修と3級のほめ達検定たるものを受けてきました。

この研修は必修でそして半日拘束。

**「このクソ忙しいときに、なんでほめることを勉強しないといけないんだよ！」**


と思っていましたが、想像以上に勉強になったのでその内容を書いておきます。

正直、会社が主催する肩苦しい研修と比較すると、講師の話も面白く、何倍も実践的で、何倍も学びがありました。


## 研修の内容

- **講師** : 一般社団法人　日本ほめる達人協会理事長　西村様
ほめ達
https://www.hometatsu.jp/

- **講義形式** : 基本座学、時々ワークショップ



## 気付きと学び
#### 1.ありがとうの反対は当たり前
これが一番心に残った。
最近、メンバを誉めよう、認めようと思っていても、なかなかそのポイントが見つからないことに悩んでいた。
いつも周りの人の言動・行動を見ていて、「いいな！」と思ったらノートに書くようにしているが、最近そのメモの量がガクッと減っている。

「なんでなのかな？」と思っていたけど、なかなか自分の中で答えが見つからなかった。

でも、今日分かった。
それは、<font color="Red">**自分の当たり前の基準がいつの間にか上がっていて、その物差しで周囲を見ていたんだな**</font>って。
そして、当たり前だと思ったら感謝は生まれない。
人と比較してはダメ=自分比較してもダメなんだということが言語化出来たことで、**人のいいとこメモが増えない悩み**がいきなり解決した。

試しに、人のいいとこメモを開いて書いてみたらめちゃめちゃ書けた。
なんで、こんな単純なとこに躓いてたんやろ。

#### 2.「ほめる」を他人のコントロールに使わない
なるほどなーって。
この考え方はなかった。ほめていい気持ちにさせて、気持ちよく仕事してもらおうと思ってたけど、
それもダメなんだ。結局、**「人をコントロールしよう」**という腹黒さが残ってるもん。
さらに

- **「ほめる」ことで自分の心が整う**
- **「ほめる」ことで相手との関係性が変わる**

とのこと。

自分はこれを聞いて、
<font color="Red">**人のためにほめるんじゃない、自分のためにほめるんだ。
自分が変われば、周囲も変わる。
それは、周囲が自分をどう見ているかではなく、周囲を自分がどう見ているかが変わるからなんだ。**</font>
ということだと、理解した。

#### 3.ほめ達とは、他人と自分が絶望的に違うことを知っている人のこと

これも上述の気付きと一緒。
結局、人はコントロールできない、人は理解できない、人は自分とは違う、ということをちゃんと理解しないと。
最近、仕事ができる人に囲まれているから、多くを指示しなくても自主的に動いてくれる。
しかも、自分が動いてほしい方向に。
だから、「ああ、みんな自分と同じ考えなんだなぁ。」なんて、思ってたけど、大きな間違いだった。

仕事は、ゴールを極力定量化して表現する。
スケジュールもそう、売り上げもそう。

そして、その数値を上げていく方法は、そんなに多くない。

だから、要領がいい人の仕事は、全部同じように数字が上がってくる。
しかし、その数字を作っている人の考えや些細な行動が絶望的に違うということに気が付いていなかった。

いや、昔は気が付けていた。
いつからか気が付かなくなったんだ。

<font color="Red">**成果をうまく生み出せなかったころは、周囲のできる人の些細な行動をずーっと見ていたから、人との違いが分かってたんだ。**</font>
その行動をいつの間にか止めていた、つまり、学ぶことを止めていたんだ。

仕事のレベルが上がったことに驕り、人間のレベルを下げていたんだ。

#### 4.ダメ出しは本能、ほめるは覚悟

人間は本能的に欠けたものを見つける生き物である。
だから、欠点は本能的に見つけることができる。
つまり、脳が動いていなくても欠点は"見える"。

しかし、ほめるポイントは見えない。
覚悟を持って誉めようと思ったときに脳が回り、ほめるポイントを探し始める。

そして、ほめようとすると、人は全体を俯瞰する。
その人の性格、人となり、言動、行動、どこにほめるポイントがあるのか。認めるポイントがあるのか。

気が付くと、自分の心の視野が狭くなっている。
そして、それはなかなか気が付くことができない。

### 5.ほかにもたくさん

他にもいろいろな学びがあったが、全部を一度に自分の力にするのは無理。
だから、箇条書きで書いておく。
これが、いつか自分の心に引っ掛かり、成長の糸口になるかもしれない。

- 二言あいさつ
- ダメ出しされると、心のコップは下を向く
- 失敗しているとき優しい言葉でほめる
- 部下のピンチは上司のチャンス
- ほめるとは、人・モノ・起きる出来事の価値を発見して伝えること
- ほめるポイントを探す方法は自分に置き換えてみること
- 言葉の3Dを言わない→でも・だって・どうせ＋できません→この言葉を言うだけで、脳は眠る
- 女性は共感脳・男性は解決脳
- 女性の話を聞く秘訣は、配送屋と運送屋
- 3つのお願い→全力拍手・全力うなづき・笑顔
- 先手必笑
- ねぎらいはいつでも手軽にできるが、流通はしていないので相手の手元で金貨に化ける
- 人に質問してほめるときのイメージはヒーローインタビュー
- 自分の持っている数字に悪影響を与えうるとき、ほめる能力は著しく低下する
- 出来たからほめるのではない。ほめるからできるようになるのだ。
- 起きる出来事と感情を切り離す
- 全然だめなアウトプットが出てきたら「そうくるか」「惜しい」
- 心の距離を縮めるには、小さな頼み事をして「ありがとう」
- 出来るようになるためには、量稽古と3年先の稽古
- 伝えるには、メリットを伝え、分解して、意味を伝え、深く理解させ、気持ちよくさせ、理解させる。
- 成長を誉める。合格点でほめない。60点から63点に上がったら、その3点を誉める

## 最後に
まとめ終わって、本当にいい研修だったなって思う。

この記事を書くときに、ほめ達のHPに行ったら講師のブログが上がってた。
研修終わって1時間くらいしか経っていないのに、すごいスピード感。

そのブログを見て、西村さんは常に人のほめるポイントを探してるんだなってことが分かった。
<font color="Red">ほんと、完璧やわ！</font>
C#で作ったCOMをExcel VBAから呼ぶ

##事象
dllをregasmで登録。その後VBAエディタで参照設定すると、インテリセンスは効くがオブジェクト生成できない
→実行時エラー「ActiveXコンポーネントはオブジェクトを作成できません。」

##原因
32bitのregasmで登録していたから。
もしExcelが32bitなら、64bit版のregasm使わなくてもいけたのかもしれない。

```
[NG]
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\regasm CCC.dll /codebase /tlb

[OK]
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm CCC.dll /codebase /tlb

[おまけ、登録解除]
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm /tlb /u CCC.dll
```

##発生環境
windows10 1803 64bit
VS2019 16.0.3
Excel 16.0.11727 64bit
SQLite3でCSV出力しPythonで読み込む方法

#はじめに

下記よりsqlite3.exeを手に入れる。

- https://www.sqlite.org/

ダウンロード方法は下記を参考にした。

- [SQLiteコマンドラインツールのダウンロードとインストール](https://www.dbonline.jp/sqlite/install/index1.html)

#データベースに接続しcsv出力する方法
作成したデータベースに接続するには、sqlite3.exeを起動し下記のよう実行する。

```
.open データベース名
```
データベース名は拡張子がなんでも良い。（ただし拡張子がなかったら何のファイルかわからなくなる。）
下記のように実行すると作成したテーブルが確認できる。

```
.tables
```
全行をcsvに出力するには下記のように実行する。

```
.mode csv
.output 出力ファイル名.csv
SELECT * FROM　テーブル名;
```
ヘッダーを入れたい場合は最初に「.headers on」と実行すれば良い。

#csvファイルをPythonで読み込む
NumPyでCSVファイルを読み込むにはnp.loadtxt関数を使えば楽。

```python:
import numpy as np

csv_np = np.loadtxt(
    "CSVファイルのパス",
    dtype="float",       # 要素の型を指定
    delimiter=",",       # ファイルの区切り文字
    comments="#",        # header/footerの先頭に書かれる文字
    skiprows=0,          # 先頭の何行を無視するか（指定した行数までは読み込まない）
    usecols=None         # 読み込みたい列番号（指定する場合はタプルで）
)
```
下記のようなやり方もできる。
文字列を1文字ずつの配列にしてそれをNumPy配列にそれぞれ入れいている。

```python:
import numpy as np
num = #行数
col = #分けたい配列の長さ
csv_np = np.zeros((num,col), dtype='float32')
with open('CSVファイルのパス', 'r') as fr:
    for i,row in enumerate(fr.readlines(),start=0):
        csv_np[i] += np.array(list(map(np.float,row[:col])))
```

#参考
[Pythonでsqlite3を使ってデータベースにリストを入れる](https://qiita.com/Tanakadesu/private/58519ef46cca2704479c)
[SQLite3でクエリの結果をCSVファイルへ出力する方法](https://www.xmisao.com/2013/09/05/how-to-export-the-results-of-query-to-csv-sqlite.html)
[SQLiteからCSVファイルへ書き出す方法](https://qiita.com/qqhann/items/69ef194e3378bb68608a)

#その他
行数をカウントする方法。

```
select count(カラム名1), count(カラム名2) from テーブル名;
```

テーブル情報を取得する方法

```
select * from sqlite_master;
```
outgoing webhooksから画像情報が取れないことを知る。

## outgoing webhooksから画像情報が取れない

本体がlambdaに乗っかるslackbotを作ってるときにoutgoing webhooksから画像情報が取れないことに気づきました。
試行錯誤の末、何とか小細工して解決できたので共有します。

## outgoing webhooksのpostdata

```
token=XXXXXXXXXXXXXXXXXX
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
thread_ts=1504640714.003543
timestamp=1504640775.000005
user_id=U2147483697
user_name=Steve
text=googlebot: What is the air-speed velocity of an unladen swallow?
trigger_word=googlebot:
```

textがあるならimageも欲しかったなぁ



## files.listを呼ぶという二度手間で解決しました。

てな訳で画像を投稿→slackのfile.list呼ぶ→レスポンス.filesをtimestampの降順にソート→一番先頭の要素を取得という方法で画像情報の取得に成功しました。。。
**（画像を投稿してから30秒ほど待たないとfile.listには反映されないのでご注意を）**


```
def sort_data(file_data):
    """
    timestampが一番新しいファイルを返す。


    Parameters
    ----------
    file_data : str
        ファイルデータ
    """
    try:
        print("sort_data start")
        files = file_data["files"]
        
        timestamp = ""
        # timestampが一番新しいファイル
        latest_file = ""
        
        for i,file in enumerate(files):
            if i == 0:
                timestamp = files[i]["timestamp"]
                latest_file = files[i]
            else:
                if int(files[i]["timestamp"]) > int(timestamp):
                    latest_file = files[i]
                    timestamp = files[i]["timestamp"]
        print("sort_data end")
        return latest_file
    except Exception:
        raise

```


もっとスマートなやり方をご存知の方いらっしゃいましたら教えてください。。。


参考URL
・slack api
https://api.slack.com/methods/files.list
・slcak outgoingwebhooks
https://api.slack.com/custom-integrations/outgoing-webhooks
Vue.js はまったポイントメモ(APIでデータ取得)

Vue.jsを始めて1ヶ月
色んな記事やブログのソースを参考にして、
基本をおろそかにしたらツケが回ってきたので、自戒を込めてメモにします。

##親子コンポーネントでのデータ受け渡し → pagesでの表示
#### 作りたい形
```
　　　(親コンポーネント)　　　　　　　　　　　（子コンポーネント）
API叩いてデータ取得(json)　→　親からデータを受け取り、templateで整形
　　　　　 ↑　　　　　　　　　　　　　　　　　　|
(pages A) request 'A'　    　 返却　　　← 
(pages B) request 'B'　　　　　返却　　　←
(pages C) request 'C'　　　　　返却　　　←
```
- ページ(A~C)にアクセスしたら、親コンポーネントにリクエストを通知
- 親コンポーネントはAxiosでサーバー側APIを叩いてデータを取得
- 取得したデータを子コンポーネントに渡して、templateを適用してviewに返却

下記で紹介されているファクトリパターンAPIを参考にして、小規模アプリを作っています。
[【Vue.js】Web API通信のデザインパターン (個人的ベストプラクティス)](https://qiita.com/07JP27/items/0923cbe3b6435c19d761)

#### ハマったポイント 「親comp → 子comp → pagesの流れでpropsすると思った」

```vue:index.vue
<template>
  <div id="app">
      <p>index.vueの内容です</p>
      <child-component/>
  </div>
</template>

<script>
  import Child from '../components/Child.vue';

  export default {
    components: {
      'child-component': Child,
    }
  }
</script>
```
pages配下のindex.vueではChildをimportしてきて・・・

```vue:Child.vue
<template>
  <p>子コンポーネントの内容です</p>
  <p>{{ info }}</p>
</template>

<script>
  export default  {
    name: 'child',
    props: ['info']
  }
</script>
```
ChildはParentからpropsで受け取って・・・

```vue:apiComponent.vue
<!--親コンポーネント-->
<template>
    <child :info="info" />
</template>

<script>
  import SpotList from './SpotList.vue'
  import Child from './Child.vue';

  import {RepositoryFactory} from '../api/RepositoryFactory'
  const SpotsRepository = RepositoryFactory.get('spots');

  export default {
    name: "api-component",
    components: {
      'spotlist': SpotList,
      'child': Child,
    },
    data() {
      return {
        isLoading: false,
        info: [], //取得したデータはinfoに格納する
      };
    },
    created() {
      this.fetch()
    },
    methods: {
      async fetch() {
        this.isLoading = true;
        const {data} = await SpotsRepository.get(); // データ取得
        this.isLoading = false;
        this.info = data;
      }
    }
  }
</script>
```
親はAPIから取得したデータを配列に入れて、`v-bind`すれば・・・
![スクリーンショット 2019-07-10 23.51.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239110/6fa2465d-e400-878c-e752-3553861563b4.png)
なにも表示されない(悲)

結論としてはpages側のImportを親コンポーネントに変えると表示されました。

``` vue:index.vue
<template>
  <div id="app">
    <api-component />
  </div>
</template>

<script>
  import ApiComponent from '../components/apiComponent.vue';

  export default {
    components: {
      'api-component': ApiComponent,
    }
  }
</script>
```
![スクリーンショット 2019-07-10 23.56.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239110/fcd216aa-66f8-7bc3-9c70-47859397ecd7.png)

キャメルケース、ケバブケースなど記載の仕方が違う?
データ反映を`mounted`にする?など、色々試したのですが上手く行かず、時間を費やしました。

`v-bind`などが絡む場所は、コンポーネント間の関係に気をつけないといけませんね。。。
Excelファイルのセルの値をVBA以外の言語で読み込む

##何この記事
業務上何故か素敵に装飾されたExcelファイル
（長い関数、セルの書式や入力規則設定、シートの保護等も含む）を
大量に読み込んで入力データを処理する必要があるが、
VBAだと遅いので別言語でいろいろやってみた。
（さわってみただけなので何か他に良い方法があるかもしれない）

##やってみた言語
####JavaScript
JavaScriptでExcel（XLSX）を読み込む
https://qiita.com/tomgoodsun/items/bc5f2db3c28e1a6525d2

inputのfileタグでディレクトリを指定可能にする+Sheet.jsを使う方法。
弱点はシート保護された状態のファイルを旧いエクセルなんかで保存されると
「シート保護解除しろ」と言われ、開けない。
シート保護解除or新しめのバージョンのExcelファイルで保存で回避可能。
セルの表示形式が違うと値の型が違って泣くはめになる。

読み込めない場合がある点を除けばお手軽にやるなら一番いいと思われる。

####Java
POIを使う。
弱点はいろいろ落としてくるのが面倒臭い。

####Python
Pandasを使う。
セルの表示形式が違うと日付が入っているはずなのに値の型が違って(float/str/datetimeなど)泣くはめになる。
そしてやはりJavaScriptと同様に
シート保護された状態のファイルを旧いエクセルなんかで保存されると
「シート保護解除しろ」と言われる。
Excelが入っている場合はxlwingsを利用することで回避は出来る。

##結論
**何かを入力させるのにExcelを使うな**
[お国からしてExcelファイルを配って入力して印刷させている](https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/koyou_roudou/koyou/kyufukin/index.html)ぐらいだからなんともならないのか。
GitHubで誤って違うブランチにマージしてしまった時にWeb上だけで戻す方法

# 状況
1. masterとブランチAは同じコミット上にいる
2. ブランチAを親ブランチとしてブランチBを作った
3. ブランチBでソースをゴニョゴニョいじってコミット&プッシュした
4. GitHubのWebでブランチBをブランチAにマージしようとして、:boom:**誤ってmasterにプルリク出してマージしてしまった**:boom:
5. 間違いに気が付かずにWeb(リモート)でブランチBを削除した
6. 間違いに気が付かずにローカルでブランチBを削除した
7. クライアントツールの樹形図を見ていて間違いに気がついた:biohazard:

# Web上だけで戻す(revert)方法
## 1. リモートで削除してしまったマージ元のブランチを復活させる
1. [Pull Request]タブを開いて[Filters]に入力されている「is:open」を削除してEnter
2. ![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/1e6e69da-e70c-aace-e515-7e47f472b036.gif)
3. マージ済みのプルリクが表示されるので、間違ったマージを選択して開く
4. 削除してしまったマージ元のブランチの横にある[Restore branch]ボタンでブランチを復活させる
5. ![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/d1993cd8-c123-7c16-1013-5beb03d92d8a.gif)


## 2. マージを戻す
1. マージしたところの横にある[Revert]ボタンで「マージを戻す用のプルリク」を作る
2. ![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/d6faf9f9-d688-5a67-5d4f-b4e0f12b869f.gif)

2. ここで `revert-{誤ったプルリクの番号}-{マージ元のブランチ名}` というフォーマットの「マージを戻す用のブランチ」が自動で作成される
3. 「マージを戻す用のプルリク」をマージする
4. 「マージを戻す用のブランチ」を削除する(とっておきたかったら削除しなくてもOK)


## 3. 今度は間違えないようにマージをやり直す
1. [Code]タブの[branches]タブで復活させたマージ元のブランチの横にある[New pull request]ボタンでプルリク画面を表示する
2. **マージ先ブランチが間違っていないことをすごくよく確認**してプルリクを出してマージする

## ローカルで削除したブランチはWeb上では戻せない
戻せたらスゴスギと思う。
プッシュしないでうっかりローカルブランチを削除してしまったから復活させたい！というときは `git reflog` と `HEAD` で復活させられそう(やっていないけど)
`git add` とかしてなくてまだGit管理下にいないファイルはもう無理かも
[【Git】削除したブランチは復活できる！Git初心者から中級者になりたい方へ | ジーニアスブログ](https://www.genius-web.co.jp/blog/cat-123/git-branch-reflog-rescue.html)
Rubyのclassの作り方

#はじめに
まだ理解が浅いのですが、メモ用に書いてみました。

#classの作成(インスタンス変数の数分、引数をとる)
rubyでちょとしたメモアプリなどを作成する時とかにclassを使っていたのですが、いつも以下のように書いてました。

```rb

class User
  attr_accessor :name, :age, :gender, :admin

  def initialize(name, age, gender, admin)
    @name = name
    @age = age
    @gender = gender
    @admin = admin
  end
end

user = User.new("sakakinn" ,29 ,"男性" ,true)
p user

```
出力結果↓

```

#<User:0x00007ff6db152550 @name="sakakinn", @age=29, @gender="男性", @admin=true>
```


この書き方だとuserを作成した時にキーがなくわかりずらいのかな。
また、以下のように引数の数が足りないとエラーになってしまいます。

```rb

class User
  attr_accessor :name, :age, :gender, :admin

  def initialize(name, age, gender, admin)
    @name = name
    @age = age
    @gender = gender
    @admin = admin
  end
end

user = User.new("sakakinn") # nameだけ入力した場合
p user

```

出力結果↓

```
Traceback (most recent call last):
        2: from ruby1.rb:12:in `<main>'
        1: from ruby1.rb:12:in `new'
ruby1.rb:4:in `initialize': wrong number of arguments (given 1, expected 4) (ArgumentError)
```

#引数を１つにまとめた場合

paramsにまとめてみました。
上の場合と同じように出力されます。

```rb

class User

  def initialize(params)
    @name = params[:name]
    @age = params[:age]
    @gender = params[:gender]
    @admin = params[:admin]
  end
end

user = User.new(name: "サカキ", age: 29 , gender: "男性" , admin: true)
p user
```
出力結果↓

```
#<User:0x00007fd49887aa18 @name="サカキ", @age=29, @gender="男性", @admin=true>
```
@nameにだけ値を渡してみます。

```rb

class User

  def initialize(**params)
    @name = params[:name]
    @age = params[:age]
    @gender = params[:gender]
    @admin = params[:admin]
  end
end

user = User.new(name: "サカキ")
p user
```
出力結果↓

```
#<User:0x00007fcf6515ea50 @name="サカキ", @age=nil, @gender=nil, @admin=nil>
```
エラーにならずちゃんと値がかえってきました。
[備忘録]Qiitaのapiを使用する by vue.js

# Qiitaの記事数を取得したい
api
https://qiita.com/api/v2/docs
今回は記事を取得するだけなのでapi取得しなくてもOK
操作したいならapi必要

# ソースコード

```vue.js
<template>
  <div class="git">
    <h>post num :{{userDatas}}</h>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "GitData",
  props: {
    userName: String
  },
  data() {
    return { userDatas: Number };
  },
  mounted() {
    const request = axios.create({
      baseURL: "https://qiita.com/api/v2/"
    });
    request.get(`users/${this.userName}/items`).then(res => {
      this.userDatas = res.data.length;
    });
  }
};
</script>

<style lang="scss">
</style>

```

# memo
やったこと
- qiitaのapiで記事数を取得
- ajaxで帰ってくるresponseの型について理解できてない...
socat でコンテナ内のコマンドを TCP ソケット経由で実行する

標準入出力を利用するコマンドを外部からネットワーク経由で実行したいことありませんか？
コンテナを使っているとまれにありますよね。例えばデータサイエンティストが実装したシンプルな Python スクリプトとか。
`socat` を使って TCP ソケット経由で外部からコマンドを実行できるようにしてみました。

## 課題
例えば 1マイクロ秒の誤差もないすごい `date` コマンドを持っているコンテナがあるとします。このコンテナは `docker run date:latest` を実行すると日時を標準出力に表示します。
この `date` コマンドをホスト側から実行するのは容易ですが、別のコンテナから実行したくても直接コマンドを実行する方法が見つかりませんでした。

![socat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126845/af58f7ca-53f2-b6a5-c663-33ab59cfbcf3.png)

これを実現するために ssh や Docker on Docker で `date` コンテナを実行する方法もありますが、呼出元のコンテナに Docker をインストールしたり `docker.sock` を共有したり事前準備がやや面倒です。

この記事では上記のような「別コンテナのコマンドを実行して標準出力を取得したい」ケースを `socat` を使って解決します。

## 具体的な例

[前の記事](https://qiita.com/grohiro/items/4fb633b348bb1d08ca51)でヘッドレス Chrome を使用して HTML を標準出力にダンプするコンテナを作成しました。このコンテナを実行すると対象のウェブサイトの HTML が出力されます。

```bash
$ docker pull grohiro/headless-chrome
$ docker run grohiro/headless-chrome http://www.google.com/
#=> (HTMLが出力される)
```

コンテナの内部では `gooogle-chrome` コマンドを実行して HTML をダンプしています。このコンテナを `socat` を使って TCP ポート 9000 経由で外部から実行できるようにします。

## コンテナイメージの作成

まずは上記の Chrome コンテナに `socat` を追加したイメージを作成します。そしてヘッドレス Chrome を起動するラッパースクリプトも追加します。

*Dockerfile*

```Dockerfile
FROM grohiro/headless-chrome
USER root
RUN apt-get install -y -qq socat
COPY ./chrome.sh /
ENTRYPOINT ["socat", "tcp4-listen:9000,fork,reuseaddr", "system:/chrome.sh"]
```

*chrome.sh*

```bash
#!/bin/sh
read URL
google-chrome --headless --no-sandbox --dump-dom --start-maximized --disable-gpu "$URL"
```

ファイルを作成したら Docker イメージをビルドします。名称は `headless-chrome-socat` です。


```bash
$ docker build -t headless-chrome-socat .
```

作成したコンテナを実行すると TCP ポート 9000 が `socat` にバインドされて LISTEN 状態になります。このポートに送信したデータは `chrome.sh` の標準入力に渡されます。

`chrome.sh` は標準入力の文字列を Chrome の引数として実行します。Chrome は指定された URL を読み込み HTML を標準出力にダンプします。

`socat` はこの標準出力をリクエスト元のコンテナにレスポンスとして返します。

実行元のコンテナはソケットの入力を読み込むことで Chrome がダンプした HTML を取得することができます。

![socat2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126845/b82feacd-61bb-5748-be19-4fbaae48c562.png)


## 動作確認

まずはホスト側から手動で URL を入力して HTML が出力されるか確認します。

以下のコマンドで作成したコンテナのポート 9000 を `127.0.0.1:9000` にマッピングして起動します。

```bash
$ docker run -p 9000:9000 headless-chrome-socat
```

ポート 9000 に接続して URL を送信してみましょう。

```bash
$ nc 127.0.0.1 9000
http://www.google.com
#=> (HTMLが出力される)
```

入力した http://www.google.com が `chrome.sh` 経由でヘッドレス Chrome に渡されて HTML が出力されました。

## docker-compose

ここまでできたら `docker-compose.yml` を定義します。

*docker-compose.yml*

```yaml
services:
  crawler:
    # コマンド実行元のコンテナ
    image: php:7.5-slim
  chrome:
    # ヘッドレス Chrome コンテナ
    image: headless-chrome-socat
```

この `docker-compose.yml` で `crawler` コンテナの中から `tcp://chrome:9000` に URL を送信すると Chrome が実行されて HTML が取得できるようになりました。

例えば `crawler` コンテナ内の PHP からは `fsockopen()` を使ってデータを読み書きできます。

```php
$response = "";
$fp = fsockopen('chrome', '9000');
if ($fp) {
    fwrite($fp, "https://www.google.com\n");
    while (!@feof($fp)) {
        $response .= fgets($fp, 4096);
    }
}
```
開発者向けオプションが有効なユーザに対してダイレクトリクルーティングする

タイトルは若干釣りです。元ネタは[こちら](https://github.com/AndroidDagashi/AndroidDagashi/issues/901)

設定の取得方法を調べたのでメモしておきます
開発者にだけ採用ページへのリンクを表示するようにすれば、サービス愛を持ったエンジニアに応募してもらえてみんなハッピーになるはず・・・・・・!?

```kotlin
val status: Int = Settings.Secure.getInt(this.contentResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0)
```

有効にしている端末では1が返却されました。
無効な端末では0が返却されてました(手元になかったのでシミュレータで確認)
HTML の ブロック要素 余白 について ～margin と paddingを簡易図を用いて解説～

# 目的
- HTMLのブロック要素における余白の概念と設定方法をまとめる。
- marginとpaddingについてまとめる。

# 押さえるポイント
- HTMLのブロック要素は余白のサイズを設定することができる。
- ブロック要素の内側と外側の余白を設定することができるのでとても理解しにくい部分である。
- 余白はピクセル数を用いて設定する。
※marginとpaddingはHTMLを実施していて最初にぶち当たる壁である。完全に理解しようとせず、余白の概念を頭に入れながら[Progate](https://prog-8.com/dashboard)などで勉強コーディングを進めることをお勧めする。

# marginとpaddingの表している部分
下記のような記載のされたHTMLファイルが存在したとする
- 下記にHTMLファイルの内容を記載する。

``` html
<h1>おはようございます。</h1>
```
- marginプロパティで設定できる部分は下記画像の橙色の矢印部分である。
  - h1要素の外側の余白のサイズを設定する 
- paddingプロパティで設定できる部分は下記画像の青色の矢印部分である。
  - h1要素の内側の文字からの余白のサイズを設定する。

![margin_and_padding.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3bc856f3-4c37-8017-5c73-0d0084a7b632.png)

# marginの設定方法の例
- 下記にHTMLファイルの内容を記載する。

``` html
<h1>おはようございます。</h1>
```

- marginプロパティでh1要素の外側の余白を設定する。
- 下記にCSSファイルの内容を記載する。

``` css
h1 {
    margin: 上側橙矢印部分の余白のピクセル数 右側橙矢印部分の余白のピクセル数 下側橙矢印部分の余白のピクセル数 左側橙矢印部分の余白のピクセル数;
}
```

- 四方の外側余白をそれぞれ指定する方法が最もスタンダードな記載方法であるが、下記のように省略することも可能である。
- 下記にCSSファイルの内容を記載する。

``` css
/* 四方に同じサイズの余白を設定したいとき */
h1 {
    margin: 四方の外側余白のピクセル数;
}

/* 縦の余白サイズと横の余白サイズの省略指定 */
h1 {
    margin: 上下の外側余白のピクセル数 左右の外側余白のピクセル数;
}

/* 上のみの外側余白指定 */
h1 {
    margin-top: 上側橙矢印部分の余白のピクセル数;
}

/* 右のみの外側余白指定 */
h1 {
    margin-right: 右側橙矢印部分の余白のピクセル数;
}

/* 下のみの外側余白指定 */
h1 {
    margin-bottom: 下側橙矢印部分の余白のピクセル数;
}

/* 左のみの外側余白指定 */
h1 {
    margin-left: 左側橙矢印部分の余白のピクセル数;
}

```

# paddingの設定方法の例
- 下記にHTMLファイルの内容を記載する。

``` html
<h1>おはようございます。</h1>
```

- paddingプロパティでh1要素の内側の余白を設定する。
- 下記にCSSファイルの内容を記載する。

``` css
h1 {
    padding: 上側青矢印部分の余白のピクセル数 右側青矢印部分の余白のピクセル数 下側青矢印部分の余白のピクセル数 左側青矢印部分の余白のピクセル数;
}
```

- 四方の内側余白をそれぞれ指定する方法が最もスタンダードな記載方法であるが、下記のように省略することも可能である。
- 下記にCSSファイルの内容を記載する。

``` css
/* 四方に同じサイズの余白を設定したいとき */
h1 {
    padding: 四方の内側余白のピクセル数;
}

/* 縦の余白サイズと横の余白サイズの省略指定 */
h1 {
    padding: 上下の内側余白のピクセル数 左右の内側余白のピクセル数;
}

/* 上のみの内側余白指定 */
h1 {
    padding-top: 上側青矢印部分の余白のピクセル数;
}

/* 右のみの内側余白指定 */
h1 {
    padding-right: 右側青矢印部分の余白のピクセル数;
}

/* 下のみの内側余白指定 */
h1 {
    padding-bottom: 下側青矢印部分の余白のピクセル数;
}

/* 左のみの内側余白指定 */
h1 {
    padding-left: 左側青矢印部分の余白のピクセル数;
}

```

# まとめ
- HTMLファイルにおける余白について大雑把にまとめた。
- 筆者に余裕ができたら本記事の内容を濃くしていく予定。
- marginとpaddingは実際にコーディングしてみるとわかる部分も多いので、余白を完全理解していなくても実際に書いてみることをお勧めする。
- HTMLファイルのひな型を[こちら](https://qiita.com/miriwo/items/7277779308e845482fc3)に記載しているので、余白を学ぶついでに適当なピクセル数で遊んでみることもありかもしれない。

# 付録
筆者が書いたHTMLやCSS系の記事のリンクを張る。
1. [Visual Studio Code 導入方法 VSCode ダウンロードから日本語化対応まで～画像付き導入解説～](https://qiita.com/miriwo/items/306769d90d910944e471)
↑便利なエディタの導入方法
2. [HTML の ひな型 の 記載方法](https://qiita.com/miriwo/items/7277779308e845482fc3)
↑HTMLをコーディングするひな型の紹介
3. [HTML の 要素 に 背景色 を設定する](https://qiita.com/miriwo/items/0348104262c6bb4a5d3d)
↑HTMLの要素の背景の色を設定する方法
今日の学習

##やったこと
・クラスメソッドについて
・オブジェクトについて
・継承について
##学んだこと
ruby クラス使い方
→メソッドなどの処理などを入れる箱のようなもの.
この入れ物のなかに処理を書くのが基本。

```ruby:qiita.rb
# Stringという型（クラス）の値をnewで作成し変数whoへ代入
who = String.new("jobs")
 
#whoにはString型の値が入っている
p who
```
上記はStringクラスからnewしてString型の値を作成し、変数whoへ代入している。
そしてp whoでwhoの中身の値を表示している。

実行結果
```
"jobs"
```


次のクラスはUserクラスの型からnewしてUserクラスの値を作成し、変数userに値を代入している。
↓

```ruby:qiita.rb
Userという型（クラス）の値をnewで作成し変数userへ代入
user = User.new
 
userにはUser型の値が入っている
p user  （A）
 
user.name = "user"
p user.name　（B)
```
実行結果
```<User:0x00007fbde51ca2f0>
”user"
```

実行結果（A)の出力結果が得られている。この場合Rubyのクラスの表示方法として決められている定型フォーマットに沿った何かしらのクラスであるという意味の<User:0x00007fbde51ca2f0>という表示になっている。

（B)は、Userクラスのメソッドの出力である。

・クラスとインスタンス
クラスには処理を書いていくが、実際に処理を行うときはクラスからインスタンスというものを生成して、処理を行わせる。インスタンスの生成には「new」メソッドを使用する。


```
class User
  def name
    @name
  end

  def name=(name)
    @name=name
  end

end

user = User.new
user.name="yutaka"
p user.name
```
実行結果
```
"yutaka"
```
このようにクラスを使うときは基本的にnewメソッドを使用してインスタンスを生成して処理を行うことを特に意識しておく。

☆よく言われる例としてはクラスがたい焼きの型、インスタンスがたい焼きなどと言われる。
つまりクラスからインスタンスが生成されといったイメージが大切。
またインスタンスはそれぞれ独立して値を持つことができる。

```
class User
  def name
    @name
  end

  def name=(name)
    @name = name
  end

end

user1 = User.new
user2 = User.new
user1.name = "yutaka"
user2.name = "hanako"
p user1.name
p user2.name
```
実行結果
```
”yutaka”
   "hanako"
```

・クラスの継承
あるクラスの定義を他のクラスの処理に引用すること。



##補足教材
・クラスのinitializeについてhttps://www.sejuku.net/blog/21170
・ruby クラス使い方まとめ　https://www.sejuku.net/blog/15328
・https://www.youtube.com/watch?v=cLD2I5QvrCU
Jenkins Decrarative Pipelineで stage を配列定義

複数環境を管理している場合などに、「全ての環境に対して処理を行いたい」という場合があります。

環境ごとに一つずつ処理を実行するのは面倒。
Pipelineでstageごとの処理を繰り返し書くのは面倒。
ループ処理で実施してしまいたいですよね。

## やりたいこと

こんな処理です。
例として複数リージョンで処理をするケースをあげています。

```Groovy
pipeline {
    agent any
    stages{
        stage('ap-northeast-1') {
            steps{
                script{
                    echo "ap-northeast-1 の処理"
                }
            }
        }
        stage('us-east-1') {
            steps{
                script{
                    echo "us-east-1 の処理"
                }
            }
        }
    }
}
```
script の中身に、リージョン名だけ変えて何度も同じことを書くのは面倒だったりします。


## 配列のLoop

以下のように書くことで、変更する部分を変数化できます。

```Groovy
pipeline {
    agent any
    stages{
        stage('Prepare'){
            steps{
                script{
                    env_list = ["ap-northeast-1","us-east-1"]
                    
                    env_list.each { region -> 
                        stage(region) {
                            echo "${region} の処理"
                        }
                    }
                }
            }
        }
    }
}
```
実行画面は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/e531e4ea-1422-ae75-b18d-8723c3ad5261.png)

`Prepare` Stageで、他のstageをラップしています。
これにより、配列を展開するGroovy処理を記述できるようになっています。

## アレンジ版

### map利用

map を利用することもできます。
stageごとに変動させたい値が2つある時便利です。

```Groovy
script{
    env_map = [
        "ap-northeast-1": "tokyo",
        "us-east-1": "virsinia"
    ]

    env_map.each { region -> 
        stage(region.key) {
            echo "${region.value} の処理"
        }
    }
}
```

実行画面は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/6859b048-3af5-21ef-8e9b-598d6beca789.png)

### Parameters でパラメータ切り替え

stageに入る前に script を挟んでいることで、
if分岐などでStage内の内容を調整することも可能です。

```Groovy
pipeline {
  agent any
  parameters {
      choice(name: 'Cloud', choices: 'aws\ngcp', description: '説明')
  }
  stages{
    stage('Prepare'){
      steps{
        script{
          if (params.Cloud == 'aws'){
            env_map = [
              "tokyo": "ap-northeast-1",
              "virsinia": "us-east-1"
            ]                    
          } else if (params.Cloud == 'gcp'){
            env_map = [
              "tokyo": "asia-northeast1",
              "virsinia": "us-east4"
            ]
          }
          
          env_map.each { region -> 
            stage(region.key) {
              echo "${region.value} の処理"
            }
          }
        }
      }
    }
  }
}
```

## 最後に

Jenkins Decrarative Pipeline で stae を配列で定義する方法を紹介しました。
複数環境からの情報収集、複数環境へのデプロイなどで活用していけると思います。

確認には、Jenkins は 2.183, プラグインは初回起動時の推奨のもののみを使いました。
個人的によく使うWordPressテンプレートタグチートシート

基本的なやつ

```php
<?php the_category(); ?> // カテゴリー
<?php echo get_the_date(); ?> // 日付
<?php echo get_the_title(); ?> // タイトル
<?php the_post_thumbnail('thumbnail'); ?> // サムネイル
<?php the_permalink(); ?> // パーマリンク
<?php echo get_template_directory_uri(); ?> // 画像ファイルの前
```

切り出したテンプレートを出力 [wpdocs](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_template_part)

```php
<?php get_template_part( $slug ); ?>
```

WP_Query　[wpdocs](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/WP_Query)　[チートシート](http://notnil-creative.com/blog/archives/1288)

```php
<?php
$args = array(
    'post_type' => 'post', 
    'posts_per_page' => -1,
    'no_found_rows' => true,  //ページャーを使う時はfalseに。
 );

$the_query = new WP_Query($args);
if ($the_query->have_posts()) :
  while ($the_query->have_posts()) : $the_query->the_post();


  endwhile;endif;
  wp_reset_postdata();
?>
```

ダッシュボードで設定できるメニューの出力 [wpdocs](https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_nav_menu)

```php
<?php
$args = array(
  'menu_class'      => 'menu',
  'container'       => false,
wp_nav_menu( $args );
?>
```

bodyになんか適当にクラスを振ってくれるやつ [wpdocs](https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/body_class)

```php
<body <?php body_class( $class ); ?>> // 基本的に$classは空白でよい
```

カスタム投稿タイプ [wpdocs](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/register_post_type)

```php
<?php register_post_type( $post_type, $args ); ?>
```
AtomでGitHub Markdownの行末にスペース二つと改行を入れるキーバインドを作った

# 目的 : I want to insert two spaces and one new line to line endings in Atom Editor.
技術書典の本を書くために、AtomでGitHub Markdownを書いているのですが、行末にスペースを２個入れるのが地味にめんどくさいです。
なので、スペース2個と改行を挿入してくれるキーバインドを作りました。

# 方法 : I wrote two config file.
まず、Atomの設定ファイルが入っているフォルダ `.atom` を開きます。設定を開いて、左下に `open config folder` とあるので、それをクリックすると楽です。

次に、 `keymap.cson` と `init.coffee` に次のコードを追加します。

```cson:keymap.cson
'atom-text-editor':
  'ctrl-enter': 'user:hardbreak-markdown'
```

```coffee:init.coffee
atom.commands.add 'atom-text-editor',
  'user:hardbreak-markdown': (event) ->
    editor = @getModel()
    editor.insertText("  \n")
```

あとはAtomを再起動するだけです。
これで、ctrl-enterでスペース2個と改行を挿入するキーバインドが作れました。

# 感想 : I thought.
`keymap.cson` のコメントに書かれているURL、 https://flight-manual.atom.io/behind-atom/sections/keymaps-in-depth/ に載っているサンプルスクリプトは罠でした。
昔は設定ファイルがJavaScriptだったのでしょうが、今はcoffeeスクリプトなため、このままでは動きません。
正解はこちら https://atom.io/docs/api/v1.38.2/CommandRegistry でした。
まぁそんな罠にはまりつつも無事に目的のキーバインドが作れたので良しとします。
技術書典の本バリバリ書くぞー！！
Leetcode #763: Partition Labels

```swift
func partitionLabels(_ S: String) -> [Int] {
    var dict = [Character: (Int, Int)]()
    for (index, char) in S.enumerated() {
        if let value = dict[char] {
            dict[char] = (value.0, index)
        } else {
            dict[char] = (index, index)
        }
    }

    var answer = [Int]()
    var str = Array(S)
    var start = 0
    while start < str.count {
        var index = start
        var end = dict[str[start]]!.1
        while index < end {
            if let value = dict[str[index]] {
                end = max(end, value.1)
            }
            index += 1
        }
        answer.append(end-start+1)
        start = end + 1
    }
    return answer
}
```
ヤマハルーターnvr510でv6プラスを＋α

# ヤマハルーターnvr510でv6プラスを＋α

ヤマハNVR510を使って、簡単にv6プラス接続ができたので、手順をメモしたいと思います。

## 環境

ルーター：NVR510
FWバージョン：Rev.15.01.14
回線：IPv6プラス(MAP-E)

## 接続まで

以下の通り、設定を行った。

1. IPoEの自動接続とフィルタの設定
2. ユーザーとPW設定
4. DHCP予約設定
5. SSH設定

## IPoEの自動接続

まずは、FW(ファームウェイ)バージョンの確認を行ったところ、IPoE非対応の古いFWだったので更新しました。更新は、[こちら](http://www.rtpro.yamaha.co.jp/RT/firmware/index.php)からWindows用RT-RevUpperをダウンロードして実行しました。ルーターとPCを有線で接続して実行するだけで更新が可能でした。v6プラスはtransix方式とMAP-E方式がありますが、私の環境はMAP-E方式でした。

[こちら](https://network.yamaha.com/setting/router_firewall/flets/flets_other_service/internet-gui)に従って、WebUIで設定したところ、無事にIPoE接続ができました。

次に、[こちら](https://network.yamaha.com/setting/router_firewall/flets/flets_other_service/ipv6_ipoe-rtx1200)に従って、コマンドを実行。transixとMAP-E、光でんわの有無でコマンドが異なるようなので、ご注意ください。

## PW設定

「管理」→「アクセス管理」→「ユーザーの設定」から、管理者パスワードとユーザーの設定を行いました。
ユーザーは後にSSHで接続することを考えて、「管理ユーザーへの昇格」を__許可する__に設定しました。

## DHCP予約設定

スマートホームデバイスの一部にDHCPの割り当てIPアドレスが変更されると困るものがあったので、[YAMAHAのドキュメント](http://www.rtpro.yamaha.co.jp/RT/manual/nvr500/dhcp/dhcp_scope_bind.html)を参考に以下のコマンドで端末に固定のIPアドレスを払い出す設定に変更しました。

`dhcp scope bind scope 1 192.168.100.XXX MACAddress`

IPアドレスは各自の環境に合わせて変更してください。

割り当てを解除する場合、以下の通りコマンドを実行して下さい。

`no dhcp scope bind 1 192.168.100.xxx`

__端末によっては__`dhcp scope unbind 1 192.168.100.xxx`__とするようですが、私の環境では当該コマンドは使えませんでした。__

## SSHの設定



下の画像の通り、LANからのみSSHの接続を受け付けるように設定しました。SFTPは使う予定はないので、__すべて許可しない__としました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/2d01424e-1d5a-c286-eb47-a3f26830bc32.png)

次に、`ssh user@192.168.100.1`でルータにSSH接続しました。

まずは、DHCPのIPアドレス払い出し状況を確認するために`show status dhcp`を実行。実行結果は以下の通りでした。MACアドレスと端末名は伏字にしています。

```
DHCPXR[vԍ: 1
   lbg[NAhX: 192.168.100.0
               蓖ĒAhX: 192.168.100.5
          (^Cv) NCAgID: (01) AA AA AA AA AA AA
                         zXg: XXXXXXXXXXXX
                     [Xc: 59 55b
               蓖ĒAhX: 192.168.100.10
          (^Cv) NCAgID: (01) AA AA AA AA AA AA
                         zXg: XXXXXXXXXXXX
                     [Xc: 39 44b
               蓖ĒAhX: 192.168.100.11
          (^Cv) NCAgID: (01) AA AA AA AA AA AA
                         zXg: XXXXXXXXXXXX
                     [Xc: 33 1b
               蓖ĒAhX: 192.168.100.12
 NCAgC[TlbgAhX: AA AA AA AA AA AA
                         zXg: XXXXXXXXXXXX

```

文字化けしとるやんけ。。。。。というわけで、文字コードを`console character ascii`でASCIIに変更したところ、文字化けはなくなりました。ただ、このままだと次回ログイン時にも文字化けがするので、管理者に昇格し、設定を保存する必要があります。

```
> administrator
Password: <--(管理者のPWを入力)
# console character ascii
# save
Saving ... CONFIG0 Done .
```

これで、次回以降も文字化けなしで接続できます。

## 雑感

- コマンドでのフィルタ設定は不要かも
- スマートホームやSSHが不要の人は、IPoE接続設定だけでも十分かも
- ただし、Web GUIからのコマンド実行はストレスがたまるので、SSHかTelnetを使うほうが楽

## 参考

- [ファームウェア配布ページ](http://www.rtpro.yamaha.co.jp/RT/firmware/index.php)
- [インターネット接続 : Web GUI設定](https://network.yamaha.com/setting/router_firewall/flets/flets_other_service/internet-gui)
- [フレッツ光ネクスト インターネット(IPv6 IPoE)接続 : コマンド設定](https://network.yamaha.com/setting/router_firewall/flets/flets_other_service/ipv6_ipoe-rtx1200)
- [10.1.5 DHCP 予約アドレスの設定](http://www.rtpro.yamaha.co.jp/RT/manual/nvr500/dhcp/dhcp_scope_bind.html)
HTMをPython3環境で動かす

#背景
NuPICを他のモジュールと組み合わせて使いたくなったが、そちらがPython3でしかインストールができないことが判明。
仕方なくNuPICの方をPython3に対応させることにした。
今回はHTM Communityの有志の方が作成しているhtm.coreをソースからビルドして利用する。

#実行環境
・Ubuntu18.04
・gitはインストール済み

#インストール方法
①Cmakeをインストール

```
$ sudo apt install cmake -y
```
②Virtualenvをインストール

```
$ sudo apt install virtualenv
```
③htm.coreリポジトリをgit cloneする

```
$ git clone https://github.com/htm-community/htm.core
$ cd ./htm.core
```
④venv環境を作成

```
$ virtualenv --system-site-packages -p python3 ./venv
$ source ./venv/bin/activate
```
⑤必要なpythonツールをそろえる

```
$ python -m pip install --user --upgrade pip setuptools setuptools-scm wheel
$ python -m pip install --no-cache-dir --user -r bindings/py/packaging/requirements.txt
```

⑥Pythonパッケージとしてビルド

```
$ python setup.py install --user --force
```
割と時間がかかります。

⑦動作確認

```
$ python
>>> import htm           # Python Library
>>> import htm.bindings  # C++ Extensions
```
エラー等でなければ完了です。
Leetcode #680: Valid Palindrome II

```swift
func validPalindrome(_ s: String) -> Bool {
    let s = Array(s)
    var start = 0
    var end = s.count - 1
    while start < end {
        if s[start] != s[end] {
            return isValid(s, start, end-1) || isValid(s, start+1, end)
        } else {
            start += 1
            end -= 1
        }
    }
    return true
}

private func isValid(_ s: [Character], _ start: Int, _ end: Int) -> Bool {
    var start = start
    var end = end
    while start < end {
        if s[start] != s[end] {
            return false
        } else {
            start += 1
            end -= 1
        }
    }
    return true
}
```
Leetcode #383: Ransom Note

```swift
func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
    var dict = [Character: Int]()
    for char in magazine {
        if let value = dict[char] {
            dict[char] = value + 1
        } else {
            dict[char] = 1
        }
    }
    for char in ransomNote {
        if let value = dict[char] {
            if value == 0 {
                return false
            }
            dict[char] = value - 1
        } else {
            return false
        }
    }
    return true
}
```
RSpecの導入

#ユーザー認証の単体テスト

ユーザーモデルクラスが単体で正常に動作するかテストを行う


##RSpecを導入する
Gemfileに　gem 'rspec-rails'　を追記する

```ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri

  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
  gem 'rspec-rails'

end
```
追記したらbundle intallを行う

##RSpec用の設定ファイルを作成する

```
$ rails g rspec:install
```
ターミナルで実行すると、以下のようにファイルが作成される

```
   create  .rspec
   create  spec
   create  spec/spec_helper.rb
   create  spec/rails_helper.rb
```

.rspecに追記する

```ruby:.rspec
--format documentation
```
これで設定ファイルの準備は完了♩

##RSpecが正常に利用できるかの確認

```
$ bundle exec rspec
```
ターミナルで上記を実行して、次の通り表示されれば利用できます。

```
No examples found.


Finished in 0.00058 seconds (files took 0.20912 seconds to load)
0 examples, 0 failures
```
今日学んだ事


#7/10(水)
###●groupメソッド
・テーブルのレコードを指定したカラムでまとめた状態で取得する。

コード

```
モデル.group(カラム名)
```
・idが一番小さいコードの１件が表示されるが、裏側ではまとめられた状態で取得されている。
・具体的に何個まとまっているか個数は分からない。

###●countメソッド
・配列などの要素数を返すメソッド。
・groupメソッドに続けて使うと、まとめられたそれぞれのレコードの数が取得できる。
コード

```
モデル.group(カラム名).count
```
・返り値はハッシュとなる

###●keysメソッド
・ハッシュはkeysメソッドを持っている
・ハッシュのキーだけを取り出し、配列として返すメソッド

###●mapメソッド
・配列の中身を１つずつ取り出してブロックという構文を繰り返し実行する。
・ブロックの返り値を集めた新しい配列を作成する。
コード

```
配列オブジェクト.map{|ele| ブロックの処理}
```

###●order('count_カラム名').count(カラム名)
・指定したカラムをグルーピングし、それぞれのレコード数でソートできる
TeraTermマクロ SSH自動ログイン

2017/06/03に作成した資料をアップします。

TeraTermのインストールフォルダにあるログインマクロの雛型「ssh2login.ttl」をコピーまたは編集し、そのファイルを実行することにより。自動ログインを行うことができる。

### 1. パスワード入力版（ダイアログでパスワードを入力する。）

```ttl:ssh2login.ttl
username = 'user01'          ; ログインするサーバーのユーザー名
hostname = '192.168.0.8'     ; ログインするサーバーのホスト名またはIPアドレス
portnum = '22'

msg = 'Enter password for user '
strconcat msg username
passwordbox msg 'Get password'

msg = hostname
strconcat msg ':portnum /ssh /auth=password /user='
strconcat msg username
strconcat msg ' /passwd='
strconcat msg inputstr

connect msg
```

### 2. パスワード保存版（平文）
マクロファイルにパスワードを保存し、SSH接続を自動化する。

```ttl:ssh2login.ttl
username = 'user01'          ; ログインするサーバーのユーザー名
hostname = '192.168.0.8'     ; ログインするサーバーのホスト名またはIPアドレス
userpasswd = 'xxxxxxxx'      ; ログインするサーバーのパスワード
portnum = '22'

msg = hostname
strconcat msg ':portnum /ssh /auth=password /user='
strconcat msg username
strconcat msg ' /passwd='
strconcat msg userpasswd     ; パスワード変数（userpasswd）を利用
strconcat msg inputstr

connect msg
```
### 3. パスワード保存版（暗号化）
パスワード暗号化ファイル（passwd.dat）でパスワードを保存し、SSH接続を自動化する。
（初回のみパスワードを入力、2回目以降はパスワード入力無し。）

```ttl:ssh2login.ttl
username = 'user01'          ; ログインするサーバーのユーザー名
hostname = '192.168.0.8'     ; ログインするサーバーのホスト名またはIPアドレス
passwdfile = 'passwd.dat'    ; パスワード暗号化ファイル
portnum = '22'

getpassword passwdfile username userpasswd  ; パスワード暗号化ファイルからパスワード取得

msg = hostname
strconcat msg ':portnum /ssh /auth=password /user='
strconcat msg username
strconcat msg ' /passwd='
strconcat msg userpasswd
strconcat msg inputstr

connect msg
```
### 4. 公開鍵認証版
秘密鍵でSSH接続を自動化する。
（初回のみ秘密鍵のパスフレーズを入力、2回目以降はパスフレーズ入力無し。）

```ttl:ssh2login.ttl
username = 'otsuka'          ; ログインするサーバーのユーザー名
hostname = '192.168.0.8'     ; ログインするサーバーのホスト名またはIPアドレス
key_file = 'id_rsa'          ; 秘密鍵ファイルを指定
passwdfile = 'passwd.dat'    ; パスワード暗号化ファイル
portnum = '22'

getpassword passwdfile username userpasswd ; パスワード暗号化ファイルからパスフレーズ取得

msg = hostname
strconcat msg ':portnum /ssh /auth=publickey /user='     ; 公開鍵認証を指定
strconcat msg username
strconcat msg ' /passwd='
strconcat msg userpasswd
strconcat msg ' /keyfile=' 
strconcat msg key_file
strconcat msg inputstr
connect msg
```

### 【秘密鍵、公開鍵の作成及び配置】
+ ホームディレクトリに移動

```
$ cd
```

+ 秘密鍵、公開鍵のセットを作成

```
$ ssh-keygen -t rsa -b 2048 -P パスフレーズ -f id_rsa
```

id_rsa（秘密鍵）、id_rsa.pub（公開鍵）が作成される。
id_rsa（秘密鍵）をローカル端末（TaraTerm側に配置）する。
id_rsa.pub（公開鍵）を以下の通り、サーバー側のユーザーのホームディレクトリに配置する。

+ ホームディレクトリに.sshディレクトリが存在しいない場合は作成

```
$ mkdir .ssh
```

+ .sshの権限を変更

```
$ chmod 700 .ssh
``` 

+ .sshディレクトリにauthorized_keysファイルが存在しない場合は作成

```
$ touch ./.ssh/authorized_keys
```

+ authorized_keysファイルに公開鍵を追加

```
$ cat id_rsa.pub >> ./.ssh/authorized_keys
```

+ authorized_keysファイルの権限を変更

```
$ chmod 600 ./.ssh/authorized_keys
```

以上