OmniAICreator/Qiita-1.07M huggingface dataset:
VcXsrvの自動起動

# VcXsrvの自動起動

「Windowsを起動するときにVcXsrvも自動で起動したい」
を実現します。

## 最初は自動起動用の設定を手動で用意する

最初は普通にVcXsrvを起動して、自動起動用の設定を選択していきます。
最後に`Save Configuration`ボタンをクリックしてその設定を保存します。
ファイル名は初期値では`config.xlaunch`になります。

## 自動起動の設定

次いで`Winメニュー`の`VcXsrv->Xlaunch->その他->ファイルの場所を開く`をクリックします。

表示されたフォルダ内の`Xlaunch`を右クリックしてコピーします。

今度は`Win＋R`押して、`shell:startup`を入力して`Enter`をクリックします。ここは自動起動用のファイルを格納するフォルダです。
このフォルダ内で右クリックして`貼り付け`を実行すると、先ほどの`Xlaunch`がコピーされます。

この`Xlaunch`を右クリックしてプロパティを表示、`リンク先`の中身を下記のように設定します。2番目のファイルのパスは先の手順で作成した設定ファイルの場所を指定します。

```
"C:\Program Files\VcXsrv\xlaunch.exe" -run "C:\Users\nab\config.xlaunch"
```

## 動作確認

Windowsを再起動するとVcXsrvが指定した設定で自動で起動します。

## 参考

参考：[VcXsrvの自動起動 \- mecobalamin’s diary](https://mecobalamin.hatenablog.com/entry/2018/11/26/220747)
SymPyで条件分岐をやってみる

#はじめに
[SymPyで関数のハードコーディングから解放される](https://qiita.com/kimisyo/items/7df52ac6ae8bfff6bb9d)では、cos, sin, expなど単純な関数式を外出しにして、関数のハードコーディングをせずに済む方法について記載した。

今回条件分岐をやってみる。

#やり方
Piecewise関数を使えばよい。

例えば、値が0より小さければ、0、0以上であれば1にするという処理を考えて見る。SymPyでは、こんな式で定義することができるようだ。

```
Piecewise((0, x < 0), (1, x >= 0))
```

#前回のコマンドを使ってできるか確認

## 入力データ
前回と一緒

```
CMPD_CHEMBLID,exp,smiles
CHEMBL596271,3.54,Cn1c(CN2CCN(CC2)c3ccc(Cl)cc3)nc4ccccc14
CHEMBL1951080,-1.18,COc1cc(OC)c(cc1NC(=O)CSCC(=O)O)S(=O)(=O)N2C(C)CCc3ccccc23
CHEMBL1771,3.69,COC(=O)[C@@H](N1CCc2sccc2C1)c3ccccc3Cl
CHEMBL234951,3.37,OC[C@H](O)CN1C(=O)C(Cc2ccccc12)NC(=O)c3cc4cc(Cl)sc4[nH]3
CHEMBL565079,3.1,Cc1cccc(C[C@H](NC(=O)c2cc(nn2C)C(C)(C)C)C(=O)NCC#N)c1
CHEMBL317462,3.14,OC1(CN2CCC1CC2)C#Cc3ccc(cc3)c4ccccc4
CHEMBL1951182,-.72,COc1cc(OC)c(cc1NC(=O)CCC(=O)O)S(=O)(=O)NCc2ccccc2N3CCCCC3
```

##関数定義ファイル
こんな感じ。記載方法は前回を参照してほしい。

```
exp,"Piecewise((0, x < 0), (1, x >= 0))",CLASS
```

## 出力結果
```
CMPD_CHEMBLID,exp,smiles,CLASS
CHEMBL596271,3.54,Cn1c(CN2CCN(CC2)c3ccc(Cl)cc3)nc4ccccc14,1.0
CHEMBL1951080,-1.18,COc1cc(OC)c(cc1NC(=O)CSCC(=O)O)S(=O)(=O)N2C(C)CCc3ccccc23,0.0
CHEMBL1771,3.69,COC(=O)[C@@H](N1CCc2sccc2C1)c3ccccc3Cl,1.0
CHEMBL234951,3.37,OC[C@H](O)CN1C(=O)C(Cc2ccccc12)NC(=O)c3cc4cc(Cl)sc4[nH]3,1.0
CHEMBL565079,3.1,Cc1cccc(C[C@H](NC(=O)c2cc(nn2C)C(C)(C)C)C(=O)NCC#N)c1,1.0
CHEMBL317462,3.14,OC1(CN2CCC1CC2)C#Cc3ccc(cc3)c4ccccc4,1.0
CHEMBL1951182,-0.72,COc1cc(OC)c(cc1NC(=O)CCC(=O)O)S(=O)(=O)NCc2ccccc2N3CCCCC3,0.0
```

ちゃんと計算できているようだ。

#おわりに
今回は1変数のみからなる条件式だったが、x1の値に応じてx2、x3、x4のいずれかを返すといった複数の変数による複雑な演算も可能だ。可能性は無限大なので試してみよう。
Anaconda+Spyder環境でJanomeを使う

# 概要
Anaconda+Spyder環境でJanomeを使う
現状、Janomeはcondaでインストールすることができないため、
Janome用のpip環境をAnacondaで作る

# 環境
Windows10
Anaconda

# Anacondaでpip環境を作りたい理由
pipとcondaが混ぜるな危険であることはすでに有名な話だと思います
ですが、pipからしか入れられないパッケージも多々存在するのも事実
そうすると、今使っている環境そのままでpipを使いたくなる場合ももちろん出てくる
（今回のJanome（形態素解析エンジン）もpipでしかインストールできない…）

# pip用のAnaconda+Spyder環境を作る
## 「空」の環境を作る
私の場合はSpyderを愛用している（MATLAB好き＆技術計算がメイン）ので、
Spyder用のpip環境を作ります

参考：
http://onoz000.hatenablog.com/entry/2018/02/11/142347

参考URLにもあるように、pip用の仮想環境を作ります
Anaconda Prompt（またはAnaconda Powershell Prompt）で
以下の内容を入力して「空の」環境を作ります

```
conda create --name XXXX(環境名)
```

ここで

```
conda activate XXXX
```
と入力すると仮想環境XXXXが使用する環境になりますが

```
conda list
```
と入力してみると、この環境が「空」であることが分かります
（ディレクトリを作成したのみ）

## pythonとpipをインストールする
次に、

```
conda install python==(バージョン）
```

と入力します
ここで大事なのは「最初はconda」でインストールすることです
そもそも空の仮想環境しか作っていないため、pythonやpipさえインストールされておらず
当然、pip installもできません
これで、pythonやpipなど、最低限のパッケージがcondaでインストールされます

## Spyderをインストールする
さて、ここが問題でした。
Spyderはpipでもインストールできる（ように見える）んですが、
実際は正常にインストールできません
おそらくですが、SpyderはAnacondaとセットのような考え方なんでしょう
（環境が分かれてもSpyderの設定は受け継がれています）
そのため、Spyderまでcondaでインストールします

```
conda install Spyder
```

これでインストールし、正常に動作させることはできます
ただし、本当にこれで問題がないのかの検証はできていません

Spyderをインストールすると多くのパッケージが付属してインストールされます
今のところ問題は起きていませんが、ちょっと不安な面はあります。。

※ちなみに、Jupyter notebookは環境ごとにcondaとpipどちらでも正常に動作します

## Janomeをインストールする
```
pip install Janome
```
でインストール可能です
Janomeに限らず、pipで作った環境は以後pipのみでインストールするようにしています

# Janomeを使ってみる
こちらを参考にしました
https://note.nkmk.me/python-janome-tutorial/
使うのはそれほど難しくないです

```Python
from janome.tokenizer import Tokenizer
t = Tokenizer()
s = '汚物は消毒だ！'
for token in t.tokenize(s):
    print(token)
```
で実行すると

```:実行結果
汚物	名詞,一般,*,*,*,*,汚物,オブツ,オブツ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
消毒	名詞,サ変接続,*,*,*,*,消毒,ショウドク,ショードク
だ	助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
！	記号,一般,*,*,*,*,！,！,！
```
といった形で、しっかりと形態素解析ができています

# まとめ
pipでしかインストールできなくてもAnaconda+Spyder環境で使える
本当に問題ないのかは検証していかなくては…（使うときは自己責任でお願いします）
温湿度気圧センサ BME280 を ESP32につなげる

# BOSHE の 温湿度気圧センサ BME280

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6ad62b0e-09d7-9e9e-e119-a8ebdc0bbdcb.png)
(Final data sheet BME280 Combined humidity and pressure sensor)
https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf


- 電源電圧が 1.71 V to 3.6 V
- 消費電流が毎秒温湿度圧力計測で 3.6 µA 
- スリープ下での消費電流が 0.1 µA

と、ボタン電池などで動かすのに最適なセンサです。
今回は、これを ESP32 で動かしてみます。

# 環境

- Arduino 1.8.10 for Linux
- esp32 by Espressif System Version 1.0.3
- WEMOS LOLIN32
- 秋月電子通商 AE-BME280

# 秋月電子のBME280モジュールキット

「ＢＭＥ２８０使用　温湿度・気圧センサモジュールキット: センサ一般 秋月電子通商-電子部品・ネット通販」
http://akizukidenshi.com/catalog/g/gK-09421/


![IMG_20200524_184247.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/cd4a48b2-ed9a-6222-a3b5-9b89fb918aee.jpeg)

(保管が悪くてラベルが汚くなってしまいました)
 今回はこれを使ってみます。

# GROVE 化

今回 GROVE 接続するために、GROVE コネクタを工夫して取り付けてみました。

![IMG_20200524_230833.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6f7543e1-4f99-9e22-a791-d79ebb893567.jpeg)

# 設定

秋月電子のモジュールはI2C用に4.7kΩのプルアップ抵抗がオンボードで装着されています。今回はそれらを有効にしたうえ、I2Cでアドレス 0x76 の設定にしました。

|設定箇所|設定項目|設定値|設定値の意味|
|:---:|:---:|:---:|:---:| 
|J1|I2C SDAプルアップ|ショート|有効|
|J2|I2C SCLプルアップ|ショート|有効|
|J3|インターフェース|ショート|I2C|
|SDO|I2Cアドレス|GNDに接続|0x76|

# Arduino 用プログラム


便利なライブラリが多く有りますが、今回は他マイコンボードで動かすためのパラメーター取得が目的なのでライブラリ使わずに動かしている以下のプログラムを使用しました。

スイッチサイエンスのおまけページ
「BME280搭載　温湿度・気圧センサモジュールの使い方」
http://trac.switch-science.com/wiki/BME280


# ESP32 で動かす


先のプログラムはArduino Unoの実態配線図と共に掲載されていますが、ESP32でもそのまま使えます。

配線については以下のようにします。

| 信号名 | AE-BME280 | GROVE端子/ケーブル | ESP32 GPIO |
|:---:|:---:|:---:|:---:|
| SCL |SCK|Pin1/黃| 22 |
| SDA |SDI|Pin2/白| 21 |
|(電源/VDD)|VDD|Pin3/赤|(3.3V)|
|(電源/GND)|GND|Pin4/黒|(GND) |

GROVEケーブルの色は、M5Stack用などだと異なるので注意！

![IMG_20200524_224101.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/78d1fe26-800f-5269-3500-005037131948.jpeg)


# 測定パラメータ

元プログラムで記述されている以下の設定をそのまま使用します。

- スタンバイ時間 1000ms
- IIRフィルタ オフ
- 温度測定オーバーサンプリング x 1
- 湿度測定オーバーサンプリング x 1
- 気圧測定オーバーサンプリング x 1
- Normalモード

# 実行結果

```

TEMP : 23.93 DegC  PRESS : 640.62 hPa  HUM : 93.27 %
TEMP : 23.93 DegC  PRESS : 640.62 hPa  HUM : 93.27 %
TEMP : 23.93 DegC  PRESS : 640.62 hPa  HUM : 93.27 %
TEMP : 23.93 DegC  PRESS : 640.62 hPa  HUM : 93.27 %

```

# 未検証

「BME280 を M5stack で使って再びハマったこと、BOSCH 純正ドライバの使用について | mgo-tec電子工作」
https://www.mgo-tec.com/blog-entry-bosch-driver-bme280-m5stack-esp32.html

これによると、ESP32 と BME280,I2C の組み合わせだと安定性に欠けることがあるようです。
この方はその後解決したらしいのですが、今回使用したプログラムは同様の対策を行う必要性があるのかも知れません。

今回は、今回は他マイコンボードで動かすためのパラメーター取得が目的なのでこの件は未検証のままです。
【EC-CUBE4】Error: Maximum execution time of 30 seconds exceeded

EC-CUBE4.0.3

<font color="orange">**突然ロードが長くなってタイトルのようなエラーが出現！！**</font>

- 実行環境はDockerコンテナ（php.iniファイルがない!?）
- そのほかの症状は下記のコマンドでのキャッシュクリアが重い(1~2分)

`php bin/console cache:clear --no-warmup`

#対処方法-試したこと２つ

##一つ目「.htaccessファイル」に一行追加

効果あるのかわからないが、ロード時間を長くする。
（長い分、気分的にロード待ちのストレスが貯まる）

```diff:.htaccess
 DirectoryIndex index.php index.html .ht
+ php_value max_execution_time 120
 <FilesMatch "^composer|^COPYING|^\.env|^\.maintenance|^Procfile|^app\.json|^gulpfile\.js|^package\.json|^package-lock\.json|web\.config|^Dockerfile|\.(ini|lock|dist|git|sh|bak|swp|env|twig|yml|yaml|dockerignore|sample)$">
    order allow,deny
    deny from all
 </FilesMatch>

```

##二つ目、Chromeの「サブフレーム」を削除する

サブフレームとは、iframeなど、ページの一部分の表示などを担っている（サブの）プロセスのこと

###サブフレームの消し方

> Chromeの右上**：**を選択 > その他のツール > タスクマネージャ を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546942/5712e007-7d69-9a02-2247-3accf1f0ab0c.png)


サブフレームを選択し、プロセスを終了させる。

どうやら、複数のタブを開いていると複数のサブフレームも起動してしまい、プロセスが渋滞になるようだ。

#まとめ

すぐに効果が出た方法はサブフレームの削除だ。

安定的に起動させたい場合は、ウィンドウは１つにして、タブはすぐに削除すること。

- - - 

#調べてる途中でPCを軽くするために便利だと思ったもの

[Catalinaにアップデート後にMacアクティビティモニタにカラム情報が表示されません。](https://discussionsjapan.apple.com/thread/250802196)
ターミナルで`defaults delete com.apple.ActivityMonitor`を叩いて解決！！

- - -
【iOS】XCUIElementTypeQueryProviderの定義済みクエリとUI要素の対応

XCUITestでUITestを作成する場合、UI要素の検索でXCUIElementTypeQueryProviderの定義済みクエリを
使うこともあると思います。
定義済みクエリを使用する時、クエリと実際のUI要素との対応が一部曖昧な部分があったので、
よく使いそうなUI要素との対応を備忘録的に記録しておこうと思います。

## UILabel
```
    func test_UILabelを取得() {
        let label = app.staticTexts["UILabel"] // accessibility identifierを指定
        XCTAssertTrue(label.exists) // 指定したaccessibility identifierのUI要素が存在するか確認
    }
```
## UIImageView
```
    func test_UIImageViewを取得() {
        let imageView = app.images["UIImageView"]
        XCTAssertTrue(imageView.exists)
    }
```

## UITextField(secureTextEntryではない)
```
    func test_UITextFieldを取得() {
        let textField = app.textFields["UITextField"]
        XCTAssertTrue(textField.exists)
    }
```

## UITextField(secureTextEntryである)
```
    func test_secureTextEntryのUITextFieldを取得() {
        let secureTextField = app.secureTextFields["UITextField_Secure"]
        XCTAssertTrue(secureTextField.exists)
    }
```

## UIButton
```
    func test_UIButtonを取得() {
        let button = app.buttons["UIButton"]
        XCTAssertTrue(button.exists)
    }
```

## UITextView
```
    func test_UITextViewを取得() {
        let textView = app.textViews["UITextView"]
        XCTAssertTrue(textView.exists)
    }
```

## UISegmentedControl
```
    func test_UISegmentedControlを取得() {
        let segmentedControl = app.segmentedControls["SegmentedControl"]
        XCTAssertTrue(segmentedControl.exists)
    }
```

## UISlider
```
    func test_UISliderを取得() {
        let slider = app.sliders["UISlider"]
        XCTAssertTrue(slider.exists)
    }
```

## UISwitch
```
    func test_UISwitchを取得() {
        let uiSwitch = app.switches["UISwitch"]
        XCTAssertTrue(uiSwitch.exists)
    }
```

## UIView
```
    func test_UIViewを取得() {
        let view = app.otherElements["UIView"]
        XCTAssertTrue(view.exists)
    }
```

## 終わりに
上記のUI以外のクエリは以下のリンクをご参照ください。
定義済みクエリを全て確認できます。
クエリはiOS, macOSの区別なく定義されているので一部iOSでは使えないものもあります。(touchBarなど)
https://developer.apple.com/documentation/xctest/xcuielementtypequeryprovider
Nuxtアプリ(SSR)をGAEでデプロイした際に「cannot get /」が発生するバグ

# 問題

ssr対応したNuxtアプリをGAEでデプロイした際に、 `cannot get /` が表示される。
再更新するとアプリ画面を開くことができる。

# 解決策

server.jsの記述を一部変更して解決。

```js

const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()
const host = process.env.HOST || '0.0.0.0'
const port = process.env.PORT || 3000

app.set('port', port)

// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')

async function start() {
  // Init Nuxt.js
  const nuxt = new Nuxt(config)

  // Build only in dev mode
  if (config.dev) {
    const builder = new Builder(nuxt)
    await builder.build()
  }

  // Give nuxt middleware to express
  app.use(nuxt.render)

  // Listen the server
  app.listen(port, host)
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true
  })
}
start()

```

```js
 app.use(nuxt.render)
```

の部分を以下に変更した。

```js

  app.use(async (req, res, next) => {
    await nuxt.ready()
    nuxt.render(req, res, next)
  })
```
ゼロから始めるLeetCode Day35「160. Intersection of Two Linked Lists」

#概要
海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day34「118. Pascal's Triangle」](https://qiita.com/KueharX/items/75e711c6b051685d490c)

基本的にeasyのacceptanceが高い順から解いていこうかと思います。

[Twitter](https://twitter.com/kueharx)やってます。

# 問題
[160. Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/)

Top 100 Liked QuestionsのEasy問題の最後から二つ目の問題です。

問題としては、2つの単方向連結リストの共通部分が始まるノードを見つけてくださいというものです。

例が図で解説されており、諸事情でこちらに直接載せることはできないので各々が確認して頂けると幸いです。


# 解法

最初こう書いたら、

```Python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if headA == None or headB == None:
            return None
        
        LNA = headA
        LNB = headB
        while LNA != LNB:
            if LNA == None:
                LNA = headB
            else:
                LNA.next
            
            if LNB == None:
                LNB == headA
            else:
                LNB.next
        return LNA
# Time Limit Exceeded
```

時間切れになったので、以下のようにwhile以降を内包表記で書き直してみたら行けました。

```Python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if headA == None or headB == None:
            return None
        
        LNA = headA
        LNB = headB
        while LNA != LNB:
            LNA = headB if LNA == None else LNA.next
            LNB = headA if LNB == None else LNB.next
        return LNA
# Runtime: 168 ms, faster than 75.08% of Python3 online submissions for Intersection of Two Linked Lists.
# Memory Usage: 29.1 MB, less than 100.00% of Python3 online submissions for Intersection of Two Linked Lists.
```

なお、この問題の公式の解説の解き方ではBruteForce,HashMap,Two Pointerのいずれかを使うと良いよ！ってなってます。
気になるかたはそちらをチェックすることもお勧めします。

こっちの書き方の方が良いよ！とかこの言語で書いてみたよ！とかがあれば是非コメントしてみてください。
JOI 2010 本選 B 古本屋

##問題
https://atcoder.jp/contests/joi2011ho/tasks/joi2011ho2
##見た感じ
まず、セールがあるとはいえ、価格の高いやつから売っていくのが最適やろということで、各カテゴリーの中で降順にソートして、そこからナップザックすればよさそう。
計算するのは、以下の漸化式

```math
dp[i][j]=i番目までのカテゴリーからj個うった時の儲けの最大値\\
g[i]::カテゴリーiに含まれる本の集合、ソート済み\\
dp[i+1][j]=\max_{l<=min(j,|g[i+1]|)}dp[i][j-l]+\sum_{m=0}^{l-1}g[i][m] + l*(l-1)
```
##解法
ソートして、ナップザックしていく。
roopの中で想定していない計算(例えば、全部で7個選ぶときで先に3個決まってるけど$|g[i]|<4$で空白ができる)とかも慎重に実装しないと出てくるけど今回はmaxをとるから大丈夫
##ソースコード

```c++
const int N_MAX=2001;
int n,k,c[N_MAX],dp[11][N_MAX];
vint g[10];

int solve(){
    rep(i,10){
        sort(g[i].begin(),g[i].end(),[](int i,int j)->bool{return c[i]>c[j];});
    }
    int count=0,m;
    rep1(i,10){
        m=g[i-1].size();
        count+=m;
        rep(j,min(k,count)+1){
            if(j==0){
                dp[i][0]=0;
                continue;
            }
            int res=dp[i-1][j],gsum=0;
            for(int l = 1;l<=min(j,m);l++){
                gsum+=c[g[i-1][l-1]];
                res=max(res,dp[i-1][j-l]+gsum+l*(l-1));
            }
            dp[i][j]=res;
        }
    }
    return dp[10][k];
}

int main(){
    int i,x;
    //入力
    cin>>n>>k;
    rep(i,n){
        cin>>c[i]>>x;
        g[x-1].push_back(i);
    }
    //処理
    int ans=solve();
    //出力
    cout << ans <<endl;
}
```　　

##気づいたこと
セール代のとこが別にほかの個数の関数でも同じ解法でいけるね
ActiveModel::Serializerのテストでつまづいたこと

### はじめに
[ActiveModel::SerializerのRspec](https://qiita.com/mightysosuke/items/68ba860624973db3c8ca)でテストの書き方の例を挙げました。
ですが、他のSerializerのテストを書く時につまづいたことがあるので、投稿します。

### ソースコード

今回の例は、ArticleとCategoryが多対多の関係にあり、`article_category.rb`という中間モデルを持っているとします。

```rb:article.rb
class Article < ApplicationRecord
  has_many :article_categories
  has_many :categories, through: :article_categories
end
```

```rb:article_serializer.rb
class ArticleSerializer < ActiveModel::Serializer
  attributes :id, :title
  has_many :categories
end
```

このSerializerのテストを書くとこんな感じ

```rb:article_serializer_spec.rb
require 'rails_helper'

RSpec.describe ArticleSerializer, type: :serializer do
  context "新たに記事が作成された時" do
    let(:article) { create(:article) }
    let(:category) { create(:category) }
    let(:article_category) do
      create(:article_category, category: category, article: article)
    end

    it "シリアライズされたJSONが作成されること" do
      serializer = ArticleSerializer.new(article)
      expect(serializer.to_json).to eq(article.to_json(:only => [:id, :title], :include => { :category })
    end
  end
end

```

### テスト結果
テストしてみると、返却されたJSONにhas_many関係の`category`が含まれておらず、空のままでした。なぜ、、、

### 解決方法
このテストの書き方が悪かったようで、このように書いたら通りました。

```rb:article_serializer_spec.rb
require 'rails_helper'

RSpec.describe ArticleSerializer, type: :serializer do
  context "新たに記事が作成された時" do
    let!(:article) { create(:article) }
    let!(:category) { create(:category) }
    let!(:article_category) do
      create(:article_category, category: category, article: article)
    end

    it "シリアライズされたJSONが作成されること" do
      serializer = ArticleSerializer.new(article)
      expect(serializer.to_json).to eq(article.to_json(:only => [:id, :title], :include => { :category })
    end
  end
end

```

変更点は、`let`を`let!`としたところです。
`let`のままだとexampleの中で作られるオブジェクトは、`article`だけです。
なぜかというと、`let`ではそのオブジェクトがexampleの中に出てくるときにのみオブジェクトが作成されるからです。

というわけで、このような例では`let!`を使うといいですね！
bashでテキストファイルを行毎に読み込む

# 目的
bashでテキストファイルを行毎に読み込む処理を、IFSを利用して実装した際の備忘録です。

IFSとは
> [【シェルスクリプト】IFSで区切り文字（デリミタ）を変更する方法](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwi6lJql2czpAhUa_GEKHXkOD4gQFjABegQIChAE&url=https%3A%2F%2Fwww.server-memo.net%2Fshellscript%2Fifs.html&usg=AOvVaw2Ij18Vkhkln_BjGegZSiQi)
> 環境変数「IFS」（Internal Filed Separator）には、bashの場合「スペース」「タブ」「改行」（$' \t\n'）といった値が初期設定されていて、これらが文字の区切りとして認識されています。

# お試し

まず以下のtest.txtを用意します。

```test.txt
banana 100 abc
apple  200 xyz
```

以下のように読み込もうとすると、

```sh:test1.sh
for i in `cat test.txt`;
do
    echo $i;
done
```

スペース区切りで出力されます。

```
$ ./test1.sh
banana
100
abc
apple
200
xyz
```

改行区切りで出力したい場合は、以下のようにIFSに改行を指定します。

```
IFS='                                                                                                                                                  
'
for i in `cat test.txt`;
do
    printf '%s\n' "$i";
done
```

```
$ ./test2.sh
banana 100 abc
apple  200 xyz
```

以下のようにreadを利用しても可能。

```
while read -r line ;
do
    echo "$line";
done < test.txt
```

```
$ ./test3.sh
banana 100 abc
apple  200 xyz
```

# 備考
他にもっと良い方法があれば教えていただければ幸いです。

# 参考
[IFSに改行のみを指定したい](https://ja.stackoverflow.com/questions/17999/ifsに改行のみを指定したい)
[readするときはIFS=を付けておくとstrictな感じで気持ちが良い](https://qiita.com/kawaz/items/00a4b1693bf4cf67e8ca)
[【シェルスクリプト】IFSで区切り文字（デリミタ）を変更する方法](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwi6lJql2czpAhUa_GEKHXkOD4gQFjABegQIChAE&url=https%3A%2F%2Fwww.server-memo.net%2Fshellscript%2Fifs.html&usg=AOvVaw2Ij18Vkhkln_BjGegZSiQi)
現在のブランチでpushする方法


現在ポートフォリオを作成する中で、

```
git add -A
git commit -m "test"
git checkout master
git merge XXXXXXX
git push 
```

の手順で、いつもリモートリポジトリにpushしていたのですが、

```
git push origin HEAD
```

でカレントブランチをリモートにpushできるみたいです。
gitは、チーム開発で必須なので、スムーズに使えるようにせねばですね。
コマンドも決まったものしか覚えていないので、少しずつ覚えていきたい所。

それでは。
【Rails】モデルの使い方がイマイチわからない…

# 経緯
現在、とあるプログラミングスクールに通っているのですが、検索機能（検索窓）を実装する際に、処理をモデルとコントローラーを使い分けるように言われました。
えー…　全部コントローラーでいいじゃん…（もちろん、今では積極的に分けて使用していますよ！）

**・コントローラー…DBからデータを取得したり、保存したり単純な処理のみ記載**
**・モデル…DBから取得した値に複雑な処理を行うものを記載**
というイメージで使い分けています。

ただ、何故**モデルで設定した『処理のカタマリ』**をコントローラーで使えるのか理解できなかったので使いたくなかった、、いや使えなかったんですよね。
（この記事は検索機能の解説をするための記事ではありません。あくまでモデルの使い方について私の頭の整理です。）

# 検索機能の実装


```ruby:models/tweet.rb（モデル）
class Tweet < ApplicationRecord
  validates :text, presence: true
  belongs_to :user
  has_many :comments

  def self.search(search)
    return Tweet.all unless search
    Tweet.where('text LIKE(?)', "%#{search}%")
  end

end

```
※２〜４行目は必要のない記載ですが、あえて「モデルに書いてるよ」ってわかるように残してます。
また、見やすいように謎の改行が入っておりますがご容赦ください。

```ruby:controllers/tweets_controller.rb（コントローラー）
class TweetsController < ApplicationController

  def search
    @tweets = Tweet.search(params[:keyword])
  end

end


```


# 理解不明ポイント
### ①コントローラーの「search」メソッドって何？<br>（リファレンスに載ってないぞ？？）
リファレンスになんぞ載っていいる訳ないのです。
なぜなら**「モデルで自作したメソッド」**だから！！

### ②モデルの「self」ってなに？<br>（ググると、当たり前のように「クラスメソッド」って言われますが…）
- ここで詳しい説明はしませんが、こいつには**クラス名が代入**されます。
   (代入という表現はわかりやすくするために使用しています)
- tweet.rb（tweetモデル）の一行目を見てください。クラス名、なんだかわかりましたよね？
- つまり、「self.search(search)」は**「「Tweet.search(search)」**なんです。（どっかで見たような、）

### ③何故モデルで設定した『処理のカタマリ』をコントローラーで使えるの？<br>（いよいよ本題です）
なんとなく分かってきましたかね？？

- コントローラーで使用している「Tweet.search(params[:keyword])」はモデルで**自作したメソッド「self.search(search)」**と同じなんです。

# メソッドの正体
我々がよく使っている「findメソッド」や「includeメソッド」等の様々なメソッドって実は、
今回「searchメソッド」を自作したように**RailsのActiveRecordが作ってくれている**んです！！

**各モデルがActiveRecordを継承**しているから、コントローラーでメソッドを使えているんですね！
（厳密には　class Tweet < ApplicationRecord < ActiveRecord::Base）
tweet.rb(tweetモデル)の一行目を見れば記載がありますね。


# アイツ
さて、長くなってきましたが一つ解決してないヤツがいますよね。
そう、結局「self = クラスメソッド」って何だったのか。

クラスメソッドは読んで字の如く、「クラス」に対して使用できるメソッドです。
「クラス」って何だったか思い出せますか？？
わからない方はtweet.rb(tweetモデル)の一行目を見てみてください。

**私もこれ以上はまだ理解できてません！！笑**

# 謝辞
ちょっとわかりにくい説明だったかもしれませんが、プログラミング歴２ヶ月なので許してください。
（自分の頭は割と整理できました。）
ここまで長々と書かせていただきましが、最後まで読んでいただきありがとうございます。

もし、解釈が間違っている場合は、教えていただけるととても嬉しいです。

どんどはれ。
RSpecについて

#前提
本日学んだことを書いていきます。

#本題

#モデルスペック（Model spec）
　モデルが正しく機能しているかテストする。
  バリデーションのテストで使われることが多い。

#リクエストスペック（Request spec）
　GET/POST/DELETEなどのリクエストを送ったとき、正しいレスポンスが返ってくるかをテストする。
　例えばGETリクエストなら正しくページが表示されるか、POSTリクエストなら正しくデータが登録されるか、などのテストを行う。

#システムスペック（System spec）
　ユーザーの立場に立って、想定通りの画面操作が行えるかどうかをテストする。
　例えばリンクやボタンをクリックする、フォームに値を入力するなどの操作を1つ1つ行いながらテストする。


```Gemfile.
group :development, :test do
  #省略
  gem 'rails-controller-testing'  # 追記
  #省略
end

group :test do
  #省略
  gem 'webdrivers'  # 追記
end

gem 'devise'  # 追記

#省略
```

#リクエストスペック用
rails-controller-testing：便利なマッチャーを提供してくれる

#システムスペック用
webdrivers：Chromeとやりとりするのに必要なChromeDriver を含む
devise：ログインなどの認証処理に便利なヘルパーを提供してくれる

#get xxx_path
　xxxパスにGetリクエストを送る
#expect(response).to xxx
　リクエストを送った結果のレスポンスが xxx であることを確認する
#be_success
　成功レスポンス（＝エラー無しのレスポンス）である
#have_http_status "200"
　レスポンスが200ステータス（ページが正常に表示された意味）を持つ

#before do ... end
　上記で囲んだ処理は、同じcontext（なければdescribe）内の it テストの前に毎回実行される

#visit xxx_path
　xxx_pathへ飛ぶ

#expect(page).to have_content xxx / have_title yyy
　開いたページにxxxが存在する / yyyというタイトルであることを確認

#factory_bot_rails
→ファクトリを使えるようにするrails用gem

#faker
→人の名前や料理名などをランダムで自動生成してくれるgem。
 例えばテストユーザーを100人作りたい場合などに、「ありそうな名前」を100人分自動生成してくれる便利なgem

#let(:user) { create(:user) }
　user = create(:user)とほぼ同義。違いとしては、letを使うと遅延評価になる。
　つまり、userという変数が必要とされるまで式が実行されない。
　create(:user)によってユーザーファクトリからサンプルユーザーを作成し、userという変数に代入している。

#fill_in A, with: B
　Aの欄にBと入力する

#click_button A
　Aボタンをクリックする

#have_css 'input#user_email'
　特定のCSS要素が存在することをテストする。

#expect(A).to be_truty
「A式の戻り値がtrueであることを確認する」という意味。

#expect(A).not_to ...
　toの逆で、「...でないことを確認する」という意味。
　to_notでも同じ意味になる。
[質問]GCEのWindowsServer へリモートアクセスVPNでつなぎたい

初投稿＆質問です。

GCP内にWindowsServer2016を立ち上げました。
このサーバーに Windows標準のリモートアクセスVPNでつなぎたいのですが、
どうやってもつながりません。

手順は、下記を参考にそのとおりにやってみました。
[GCEのWindowsファイル共有サーバにリモートアクセスVPN経由でアクセスしてみた](https://www.apps-gcp.com/gcewindows-server-via-remote-access-vpn/)

しかし、アクセスしようとすると、エラー812「RAS/VPNサーバーに構成されたポリシーにより、接続できませんでした。」と表示され、失敗します。
（上記サイトなどを参考に、暗号化プロトコルCHAPにチェックをしたり、レジストリを追加してみたりもしましたが、解決せず。）
（WindowsServer 2012でも試してみましたが同様です。）

サーバー側の「ルーティングとリモートアクセス」-「（サーバーの）プロパティ」のセキュリティタブ内（認証方法）にて、
「リモートシステムは認証なしで接続できる」にチェックを入れたところ、クライアント側では「接続済み」になりました。しかし、
サーバー側「ルーティングとリモートアクセス」の「リモートアクセスクライアント」を見ると、確かにクライアントが表示されるのですが、
    - ユーザー名：＜Unauthenticated User＞
    - 状態：NAPに対応していません
と表示され、やはりファイルにアクセスすることはできませんでした。

上記サイトとどこが異なるのかわかりません。
どなたか、ご教示いただけないでしょうか。
よろしくお願いいたします。　<(_ _)>
Eigen::SparseMatrix初期化の注意点

Eigen::SparseMatrixに入れた覚えのない値が入っていて意味不明すぎて絶叫してしまった。

実は`setFromTriplets() `の入力の`triplet`に重複があると足し合わせられてしまうとのこと。

以下ドキュメントからの引用。
>A triplet is a tuple (i,j,value) defining a non-zero element. The input list of triplets does not have to be sorted, and can contains duplicated elements. In any case, the result is a sorted and compressed sparse matrix where the duplicates have been summed up. 

https://eigen.tuxfamily.org/dox/classEigen_1_1SparseMatrix.html#acc35051d698e3973f1de5b9b78dbe345
https://eigen.tuxfamily.org/dox/group__TutorialSparse.html

つまり`(i,j,value1)`と`(i,j,value2)`を入れると`(i,j)`には`value1+value2`が入る。

警告を出すか、最後の`value2`で上書きするかしてくれや。
勝手に足して嬉しい界隈があるのか？
Git

#プログラミング勉強日記
　2020年5月24日
##Git 
 
#####Gitとは
　プログラムソースなどの変更履歴を管理する分散型の管理システムのことであり、共同開発する際に用いることができる。Gitを使う準備として`git init`で実行する。

#####共同開発の流れ
　コードを変更する→共有する準備をする→共有する
この共有する準備をするところがGitが活躍するところである。

- 共有するファイルの選択：`git add ファイル名`

- 選択したファイルをメッセージ付きで記録する：`git commit -m "メッセージ"`
　このメッセージのことを<font color=orange>コミットメッセージ</font>という。コミットメッセージは、そのコミット（変更内容）がどのような内容かわかるようにしなければいけない。

#####共有の仕組み
　Gitでは<font color=orange>リモート</font>と呼ばれる共有ファイルの置き場を使う。
<img width="505" alt="Git.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/2d3a192e-9be5-dff0-b8ed-29e2fe0f6803.png">
このようにリモートにファイルをアップロードしたり、リモートからダウンロードをしたりすることで開発者同士がファイルを共有することができる。
リモートの登録にはそのリモートのURLが必要であり、`git remote add リモート名 URL`でリモートを登録することができる。（一般的にはリモート名は<font color=skyblue>origin</font>とすることが多い）

-  リモートのファイルのダウンロード：`git pull origin master` 
　このアップロードを<font color=orange>プル</font>という。
-  リモートのファイルのアップロード：`git push origin master`
　このアップロードを<font color=orange>プッシュ</font>という。
<img width="505" alt="Git2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/b3c47b48-7d55-5061-34fe-6876a74f4dc1.png">

※共同開発において自分が変更した箇所を把握して、その変更の中で相手に共有するべき箇所を選択することが大切である。（完成しているコードは共有するべきだが、未完成のコードは共有しないほうがいい）



#####自分が変更したファイルのファイル名を表示する：`git status`
　<font color=red>変更があったファイルは赤色で表示される。</font>
　addしたファイルの確認も行うことができる。
　→<font color=green>addされたファイルは緑色</font>、<font color=red>addされていないファイルは赤色</font>で表示される。

#####変更内容を表示する：`git diff`
　<font color=green>追加されたコードが緑色で表示される。</font>
　<font color=red>変更前のコードは赤色</font>、<font color=green>変更後のコードは緑色</font>で表示される。
この確認を行ってからaddを使うと良い。

#####コミットメッセージをみる：`git log`　変更内容をみる：`git log -p`
　変更内容が多い場合には特殊なモードになる。上下キーで表示範囲を変えられて、<font color=blue>Qキー</font>を押すと終了する。

#####Githubについて
　このGitの仕組みを利用して、世界中の人々がプログラムのコードやデザインデータなどの自分の作品を保存、公開することができるようにしたウェブサービスである。
　実際にGitの環境構築を行った。これからHTML&CSSとJQueryの勉強を行ったあとに実際にWebサイトを作っていきたいと思う。
[rails]よく使うバリデーションまとめ


バリデーションの日本語にするには下記参照#

deviseを日本語表記にする。
https://qiita.com/ryuuuuuuuuuu/items/48dec280cf8925968c65

deviseを日本語化する
https://qiita.com/you8/items/921e0dd1210eb0d158df

Railsのバリデーションエラーのメッセージの日本語化
https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b


#空でないこと  

```:model  
validates :title, presence: true
```

ちなみに、マイグレーションファイルに記載する下記の
 
```  
null: false
```
も同じく空でないこと、という意味ですが
それぞれDB側への制限と、アプリケーション側への制限になるので
両方ともかけましょう！

#重複禁止

```:model 
validates :email, uniqueness: true
```

#長さ

```:model
validates :title,    length: { minimum: 1 }       # 「1文字以上」
validates :title,    length: { maximum: 75 }      # 「75文字以下」
validates :title,    length: { in: 1..75 }        # 「1文字以上75文字以下」
validates :password, length: { is: 8 }            # 「8文字のみ」
```

#正規表現についての参考リンク
半角、全角縛りや@とドメインを含むなどの細かい条件のために必要です。

正規表現を使い際に注意すること
https://qiita.com/kokorinosoba/items/78811d7e2b6bc424b1b1


正規表現10選！！とにかくよく使うパターンをまとめました
https://complesso.jp/9916/

追加したい
[Rails]「jQueryValidationプラグイン」を使用してフォームのバリデーションを実装
https://qiita.com/NT90957869/items/84ca64d145f8ef9c4fdd
GoogleAppsScriptで関数から複数の値を返す

## はじめに
GoogleAppsScriptで処理の共通化をしたい。
関数から複数の戻り値を返す方法。


## コード
```javascript
// シートの全範囲のデータ取得
function getSpreadsheetDataRange(getSheetByName) {
  //  途中の処理は省略

  // 以下の結果を返却
  return {sheet, startRow, lastRow, numRows, numColumns, values};
}

function main() {
  // 結果を受け取り
  const {sheet, startRow, lastRow, numRows, numColumns, values} =   getSpreadsheetDataRange('送信先リスト');
}
```

## 参考
* [一つの関数で複数の変数、値を戻して別の関数に使いたいです](https://teratail.com/questions/238197)
* [[JavaScript] 関数から複数値を返す](https://javascript.programmer-reference.com/js-multiple-return-value/)
Raspberry Pi Zero WにNode.jsをインストールしたメモ

『Raspberry Pi Zero W』にNode.jsをインストールしたメモです。


![IMG_4539.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/8890587b-58e0-e189-21fc-075707d1ce1e.jpeg)


初期設定の記事は[こちらhttps://qiita.com/Qiita/items/c686397e4a0f4f11683d](https://qiita.com/takashi53/items/7cf6f3487dfd1c0057f9)

インストール前のディスク使用量を確認しておく。

```shell-session
pi@raspberrypi:~ $ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root        7.0G  3.5G  3.2G   53% /
devtmpfs         212M     0  212M    0% /dev
tmpfs            217M     0  217M    0% /dev/shm
tmpfs            217M  5.9M  211M    3% /run
tmpfs            5.0M  4.0K  5.0M    1% /run/lock
tmpfs            217M     0  217M    0% /sys/fs/cgroup
/dev/mmcblk0p1   253M   53M  200M   21% /boot
tmpfs             44M     0   44M    0% /run/user/1000
```


# nodebrewをインストール

Node.jsをインストールするために、Node.jsのバージョン管理するシステムを入れる。

```shell-session
pi@raspberrypi:~ $ curl -L git.io/nodebrew | perl - setup
```

パスを通す。

```shell-session
pi@raspberrypi:~ $ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc
```

パスの確認。

```shell-session
pi@raspberrypi:~ $ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
```

再起動

```shell-session
pi@raspberrypi:~ $ source .bashrc
```

パスの確認。「/home/pi/.nodebrew/current/bin」が増えていればOK。

```shell-session
pi@raspberrypi:~ $ echo $PATH
/home/pi/.nodebrew/current/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
```

バージョン確認。

```shell-session
pi@raspberrypi:~ $ nodebrew ls-all
```

もしくは

```shell-session
pi@raspberrypi:~ $ nodebrew ls-remote
```

ローカルのバージョンを確認。

```shell-session
pi@raspberrypi:~ $ nodebrew ls
not installed

current: none
```


# Node.jsインストール


今回はv9.11.2をインストールした。
最新はv14.3.0だけど、インストールエラーになってしまった。
Raspberry piで使える最新Node.jsのバージョンを確認する方法が分からなかったので、ひたすらに、指定するバージョンを下げていって、しらみつぶしにインストールした。

```shell-session
pi@raspberrypi:~ $ nodebrew install-binary v9.11.2
Fetching: https://nodejs.org/dist/v9.11.2/node-v9.11.2-linux-armv6l.tar.gz
######################################################################### 100.0%
Installed successfully
```


このままではバージョン確認できません。

```shell-session
pi@raspberrypi:~ $ node -v
-bash: node: コマンドが見つかりません
```


バージョン指定が必要だ。

```shell-session
pi@raspberrypi:~ $ nodebrew use v9.11.2
use v9.11.2
pi@raspberrypi:~ $ node -v
v9.11.2
```

もう一度、nodebrewのローカルバージョン確認してみよう。

```shell-session
pi@raspberrypi:~ $ nodebrew ls
v9.11.2

current: v9.11.2
```
今度は、インストールされたバージョンが表示された。



これでNode.jsのインストール終わり。

```shell-session
pi@raspberrypi:~ $ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root        7.0G  3.6G  3.1G   55% /
devtmpfs         212M     0  212M    0% /dev
tmpfs            217M     0  217M    0% /dev/shm
tmpfs            217M  5.9M  211M    3% /run
tmpfs            5.0M  4.0K  5.0M    1% /run/lock
tmpfs            217M     0  217M    0% /sys/fs/cgroup
/dev/mmcblk0p1   253M   53M  200M   21% /boot
tmpfs             44M     0   44M    0% /run/user/1000
```

Node.jsをインストールしたことで0.1G利用した。

今日はここまで。
Lambda@EdgeのテストをJestで書く

# 概要

Lambda@Edge の単体テストを [Jest](https://jestjs.io/ja/) で書いたときのメモ。今回書いたのは Lambda@Edge だけど、Lambda でも基本的には同じはず。Jest はシンプルで良いですね。

# 導入方法

導入したいディレクトリを作成して、そこで以下のコマンドを入力していく。Jest の導入はすごく簡単。

* `npm init`
    * npm を初期化する
    * インタラクティブに設定項目を聞かれるので、お好みで設定
    * `test command` だけ `jest` と入力する
* `npm install -D jest`
    * jest をインストールする

# テスト対象ファイル

今回テストするファイルはこちら。Lambda@Edge のリクエストオリジンで動作させるような処理。

```javascript:main.js
"use strict";

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;

  // /hoge にアクセスしたら /index.html へ向き先を変える
  if (request.uri.indexOf("/hoge") === 0) {
    request.uri = "/index.html";
    callback(null, request);
    return;
  }

  callback(null, request);
};
```

# テストファイル作成

テストファイルは `XXX.spec.js` または `XXX.test.js` で作成する。この Lambda では callback が最終的にどのように実行されたかをチェックしたいので、 jest.fn() でモック化して呼び出す。

```javascript:main.spec.js
const { handler } = require("./main");

// Mockオブジェクトを作成
const getMockEvent = (request) => {
  return {
    Records: [
      {
        cf: { request },
      },
    ],
  };
};

describe("handlerのテスト", () => {
  it("/hoge は /index.html に変更される", () => {
    const event = getMockEvent({ uri: "/hoge" });
    const callback = jest.fn();
    handler(event, null, callback);
    expect(callback).toHaveBeenCalledWith(null, { uri: "/index.html" });
    expect(callback).toHaveBeenCalledTimes(1);
  });

  it("/foo は何もされない", () => {
    const event = getMockEvent({ uri: "/foo" });
    const callback = jest.fn();
    handler(event, null, callback);
    expect(callback).toHaveBeenCalledWith(null, { uri: "/foo" });
    expect(callback).toHaveBeenCalledTimes(1);
  });
});
```

# 実行結果

```
$ npm test                                                                                                                                                                                         

> jest

 PASS  ./main.spec.js
  handlerのテスト
    ✓ /hoge は /index.html に変更される (3 ms)
    ✓ /foo は何もされない (1 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.459 s
Ran all test suites.
```

# aws-lambda-mock-context

ちなみに Lambda の context をモック化したい場合は、下記のライブラリを使うのがシンプルで良い。今回の例では context が必要なかったので null にしているが、これを使えば `const ctx = context()` だけでモックが作成できる。

* [SamVerschueren/aws-lambda-mock-context - GitHub](https://github.com/SamVerschueren/aws-lambda-mock-context)
R.swiftでビルドエラー(Pods/R.swift/rswift: No such file or directory)が発生

## 事象
これです。よく見るやつですね。

```
Pods/R.swift/rswift: No such file or directory
Command PhaseScriptExecution failed with a nonzero exit code
```

Google先生に聞けばCleanすれば直るとか諸々削除してpod installすれば直るとかBuildConfigの設定が間違っているとか、色々な解消法が出てくるかと思います。

今回、数分前までBuildできていたものが、いきなりBuildできなくなり
一般的な解消方法を全部やってもダメで、数時間潰しました。

■一般的な方法 (引用元 https://qiita.com/masa-321/items/19f66557dcff65553f18)

```
・Clean（Command + Shift + K）
・DerivedDataファイル以下全ての中間ファイル（キャッシュ？）を削除
参考：[Xcode][小ネタ] DerivedDataの削除についての備忘録
・Podfileを編集して、Podの再インストール。
・最近アップデートしたライブラリがあれば、ダウングレードして試してみる。
・Cocoa Podsのアップデート
・Carthageのアップデート
・キーチェーンのログインをロック＆解除を１度繰り返す
・古いMacbookの証明書をコピー
参考：iOSアプリ開発で実機による開発を複数台（メイン機ではない2台目以降）のMacで行いたい場合
・Build Phases＞Run Script＞Shellにて、タイピングミスがないか（余計なスペースが入っているケースがある）・・・①
・Xcodeの再起動
・Macbook本体の再起動
```

## 原因
アンチウイルスソフトが生成された```Pods/R.swift/rswift```を生成される度に消してました。
F**k
git push時のエラー

# 状況
いつもどおりにgithubにリポジトリを作成したあとに、

```
$ git init
$ git add .
$ git commit -m "Initial commit"
$ git remote add origin https://github.com/XXXX/XXXXXX.git
$ git push -u origin master
```

をするとエラーが発生。

# エラー内容

```
...
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
...
```

どうやらデータが大きすぎるようです。

# 解決法
ファイル直下に.gitignireファイルを生成し、中に必要ないファイル(/dataset,*/.dbなど)を書き込と、無事pushが成功しました。

# 参考
https://qiita.com/inabe49/items/16ee3d9d1ce68daa9fff
rex0220 計算式プラグインでテーブル内項目の値別に番号付与

計算式プラグインでテーブル内項目の値別に番号付与が出来ないかと相談を受けたので、やってみました。
テーブル内の計算で実行速度に問題があったので、計算式プラグインを変更して対応しました。

# テーブル行の追加・削除操作例

文字列T1 にドロップダウンT1 の値別に、番号を付加します。

![2020-05-24_22h04_34.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/fde26aa5-7674-1f35-71b9-608d5e83a3a1.gif)


# 環境

- [kintone](https://kintone.cybozu.co.jp/) 
- [計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73) 標準機能に無い、いろいろな計算式を指定可能なプラグイン Ver.29 以降


# アプリ設定

- テーブル内に、数値項目で行番号、文字列、ドロップダウンを配置します。
- 値別番号付与のための作業用項目として、文字列項目「連結」を追加。

<img width="587" alt="2020-05-24_22h08_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/06a3fcc9-d71e-3902-4545-267d4e79cae8.png">


# 計算式プラグインの設定

- 「循環参照を許可」をチェックします。

<img width="970" alt="2020-05-24_22h09_56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/65758204-6925-a7ba-c1c1-808d78ac44bc.png">

# 計算式

- 「行番号」：ROWNO(行番号)+1<br>※ROWNO関数は、指定されたテーブル項目の０から始まる行位置を返します。


- 「連結」： TARRAY(ドロップダウンT1)<br>※文字列項目に TARRAY関数を指定すると、処理結果の配列をカンマ「,」区切りの文字列に変換します。
テーブルの行毎に行全体の文字列連結を行うと、行数が増えると処理時間が増大するので、一旦全体の文字列を作成しておきます。
※ランク：１<br>テーブル内の計算より先に処理させるため、１を指定します。


- 「文字列T1」： IF(ドロップダウンT1,
ドロップダウンT1&(
ARRAY_COUNT(SPLIT(JOIN(SLICE(SPLIT(連結,","),0,ROWNO(Table)+1),
",")&",",ドロップダウンT1&","))-1))

    - SPLIT(連結,",")：連結をドロップダウンT1 の配列に変換
    - SLICE(SPLIT(連結,","),0,ROWNO(Table)+1)：先頭行から処理中のテーブル行までの値を取得
    

# 計算式プラグイン Ver.29 変更点の影響

今回の試作では、SLICE 関数とテーブル内項目の計算処理のパフォーマンス改善が必要でした。
Ver.28 以前で実装した場合、５０行程度の行数があるとテーブルの追加・変更等で計算処理に１０秒程度かかっていました。※計算処理内容は、異なります。
Ver.29 では、同条件で約１秒程度の計算処理に改善されました。

・MATCH 関数追加
・SLICE 引数に計算式を指定可能に変更
・ROWNO にテーブル指定時の不具合対応
　テーブル行追加・削除でROWNO計算式が実行されない
・テーブル内項目の計算処理のパフォーマンス改善
　循環参照かつ編集不可のテーブル内項目の値変更イベント処理抑止

# あとがき

まだまだ、計算式プラグインで実装が困難な課題があります。
今回のような改善で、少しずつでも実現できる範囲を広げていきたいと思います。
SymPyで関数のハードコーディングから解放される

#はじめに
数式処理ライブラリであるSymPyを使って、Pandasデータフレームの列に対し、外部ファイルに定義した関数により演算を行い、その結果を出力してみた。

#コマンド仕様
こんな感じ。trainが入力ファイル、outputが出力ファイル、functionが関数定義ファイル。

```
$ python command/calculate_function.py -h
usage: calculate_function.py [-h] -train TRAIN -function FUNCTION -output
                             OUTPUT

optional arguments:
  -h, --help          show this help message and exit
  -train TRAIN        input function file.
  -function FUNCTION  input function file.
  -output OUTPUT      output csv file.
```

#関数の指定方法
関数定義ファイルはこんな感じとした。

```
exp,cos(x),NewExp
exp,exp(x),ExpExp
exp,sin(x),SinExp
```
1列目が演算対象の列名、2列名が関数式。ちなみにxは演算対象の列の値を意味する。3列目が計算結果を格納する列名。


#やってみよう

ソースはこんな感じ。
関数式をpythonソースとして認識させるために、execコマンドを利用している。

```calculate_function.py
import argparse
import csv
import pandas as pd
import numpy as np
from sympy import *
import csv


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("-train", type=str, required=True, help="input function file.")
    parser.add_argument("-function", type=str, required=True, help="input function file.")
    parser.add_argument("-output", type=str, required=True, help="output csv file.")

    args = parser.parse_args()

    df = pd.read_csv(args.train, index_col=0)

    # データの読み込み
    file = open(args.function, 'r')
    data = csv.reader(file)
    for row in data:
        exec('x=Symbol("x")')
        exec('f='+str(row[1]))
        exec('func = lambdify((x), f, "numpy")')
        exec('df["{0}"] = func(df["{1}"])'.format(row[2], row[0]))
    file.close()

    df.to_csv(args.output)


if __name__ == "__main__":
    main()

```

#実行

入力ファイル

```
CMPD_CHEMBLID,exp,smiles
CHEMBL596271,3.54,Cn1c(CN2CCN(CC2)c3ccc(Cl)cc3)nc4ccccc14
CHEMBL1951080,-1.18,COc1cc(OC)c(cc1NC(=O)CSCC(=O)O)S(=O)(=O)N2C(C)CCc3ccccc23
CHEMBL1771,3.69,COC(=O)[C@@H](N1CCc2sccc2C1)c3ccccc3Cl
CHEMBL234951,3.37,OC[C@H](O)CN1C(=O)C(Cc2ccccc12)NC(=O)c3cc4cc(Cl)sc4[nH]3
CHEMBL565079,3.1,Cc1cccc(C[C@H](NC(=O)c2cc(nn2C)C(C)(C)C)C(=O)NCC#N)c1
CHEMBL317462,3.14,OC1(CN2CCC1CC2)C#Cc3ccc(cc3)c4ccccc4
```

関数ファイルは関数指定ファイルの例で示したファイル。

出力結果

```
CMPD_CHEMBLID,exp,smiles,NewExp,ExpExp,SinExp
CHEMBL596271,3.54,Cn1c(CN2CCN(CC2)c3ccc(Cl)cc3)nc4ccccc14,-0.9216800341052034,34.46691919085739,-0.3879509179417303
CHEMBL1951080,-1.18,COc1cc(OC)c(cc1NC(=O)CSCC(=O)O)S(=O)(=O)N2C(C)CCc3ccccc23,0.38092482436688185,0.30727873860113125,-0.9246060124080203
CHEMBL1771,3.69,COC(=O)[C@@H](N1CCc2sccc2C1)c3ccccc3Cl,-0.8533559001656995,40.044846957286715,-0.5213287903544065
CHEMBL234951,3.37,OC[C@H](O)CN1C(=O)C(Cc2ccccc12)NC(=O)c3cc4cc(Cl)sc4[nH]3,-0.9740282491988521,29.07852705779708,-0.22642652177388314
CHEMBL565079,3.1,Cc1cccc(C[C@H](NC(=O)c2cc(nn2C)C(C)(C)C)C(=O)NCC#N)c1,-0.9991351502732795,22.197951281441636,0.04158066243329049
CHEMBL317462,3.14,OC1(CN2CCC1CC2)C#Cc3ccc(cc3)c4ccccc4,-0.9999987317275395,23.103866858722185,0.0015926529164868282
```

それなりの結果がでてるようだ。

#おわりに
Sympyでは条件分岐などもっと複雑な計算式も与えることができそうなので、それについては改めて記事にしたい。
GitHub で任意のユーザが出したプルリクエストへのリンクを追加するユーザスクリプト書いた

[プルリクエスト/イシューの検索ページ](https://github.com/pulls)(GitHubにログインしてないと見れないページ)で `author:任意のユーザ名` で検索すると任意のユーザが出したプルリク/issueを表示できる。

どんな感じのOSS活動してるのか見れてなかなか面白いのでユーザスクリプトにしてみた。こんな感じにユーザページに Pull Request ってリンクが追加される。 [greasyfork](https://greasyfork.org/ja/scripts/404032-add-pull-requests-link-to-github-user-page) か [gist](https://gist.github.com/oieioi/524fe895c9b9d968cc64e314e510e80d) からインストールできます。プログラマの採用担当やってる人におすすめ。

![スクリーンショット 2020-05-24 22.44.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26239/dd5319dc-7e7f-cd05-abf6-b740817f6b2b.png)
iOSのBageを標準とは違う位置に無理やりつける方法

ごくまれに、TabBarのバッチの位置をカスタムしたいとお願いされることがあります。
無理やりバッチをつけるのはちょっとめんどくさいですが、上手くできたので、メモっておきます。


```swift

class CustomTabViewController: UITabBarController {

    private var badges: [UIView] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()

        addBage(position: 3, text: "11", frame: CGRect(x: 30, y: 5, width: 18, height: 18))
    }

extension MainTabViewController {
    
    // バッチをつける
    private func addBage(position: Int, text:String, frame:CGRect) {
        guard tabBar.subviews.count > position else {
            return
        }
        let tabBarButton = tabBar.subviews[position]
        for subView in tabBarButton.subviews {
            guard let icon = subView as? UIImageView else { continue }
            let badge = createBage(text: text, frame: frame)
            icon.addSubview(badge)
            badges.append(badge)
        }
    }
    
    // バッチを全て剥がす
    private func removeAllBage() {
        badges.forEach { bage in
            bage.removeFromSuperview()
        }
    }
    
    // バッジを生成
    private func createBage(text: String, frame: CGRect) -> UIView {
        let bageView = UILabel(frame: frame)
        bageView.text = text
        bageView.textAlignment = .center
        bageView.font = .systemFont(ofSize: 13)
        bageView.adjustsFontSizeToFitWidth = true
        bageView.minimumScaleFactor = 0.5
        bageView.textColor = .white
        bageView.layer.cornerRadius = 9
        bageView.layer.masksToBounds = true
        bageView.backgroundColor = .red
        return bageView
    }
}
}

```
AWS日記⑥ (SNS)

# はじめに
今回は Amazon SNS (Amazon Simple Notification Service) を利用して簡易な問い合わせページを作成します。

# 準備
SNSのトピックを作成し、サブスクライブに問い合わせの受け取り先(メールアドレスなど)を設定します。
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)

[参考資料]
[Amazon SNS とは](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/welcome.html)
[チュートリアル: Amazon SNS トピックを作成する](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-tutorial-create-topic.html)
[「AWS SNS」の紹介](https://qiita.com/callibrie/items/4bcab29c17368f99f443)

# WEBページ・API作成
GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、SNS を使用するため aws-sdk-go を利用します。
参考資料ではアクセスキーを指定する方法をとっていますが、今回はLambdaにポリシーを追加する方法をとります。

[参考資料]
[AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/sns/)
[AWS Lambda アクセス許可](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-permissions.html)
[Go+ AWS SNSを使ってSMSを送信する](https://qiita.com/EaE/items/ad32174480f7e4ae0f3a)
[AWS SDK for Go SNS コードサンプル](https://qiita.com/nightswinger/items/40ade14c8b508147f4f0)

##### メッセージを送る際には Publish を使う。

```golang:main.go
func sendmessage(name string, message string, mail string) error {
        svc := sns.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        input := &sns.PublishInput{
                Message:  aws.String("[Name]\n" + name + "\n\n[Mail]\n" + mail + "\n\n[Message]\n" + message),
                TopicArn: aws.String(topicArn),
        }
        _, err := svc.Publish(input)
        if err != nil {
                return err
        }
        return nil
}
```


今回は、ページ表示とAPIの API Gatewayを別々に作成し、APIのメソッドはPOSTに設定しました。
[作成したLambda 関数、テンプレート](https://github.com/tanaka-takurou/serverless-contact-page-go)


# 終わりに
今回は問い合わせ機能のみなので難しい部分はありませんでした。
送信の上限値があるようなので、実際に運用する際は気をつけようと思います。
[Amazon SNSを利用したSMSの一斉送信](https://qiita.com/tanaka512/items/159a3327fd4ac2eb658f)
Dockerとはなんなのか？難しい言葉なしで説明！

Dockerという技術が注目されていますが、
どの記事を読んでも難しい言葉だらけで理解しにくかったので、
簡単な言葉だけでまとめてみました！


### 結論を（ざっくり）言うと、、
Dockerとは、
「仮装環境を動かせるもの」です！


ここでいう仮装環境とはOSのこと。
OSには
・Mac OS
・Windows OS
・Cent OS　などなど複数の種類があります。


例えば、
Mac bookを買えば Mac OS が入っている
Surface を買えば Windows OSが入っている
ように
パソコンを購入するとOSが１つ入っています。

OS（環境）があって初めて、いろんなアプリが動きます。
逆に、OSがないとパソコンは何もできません。

つまり
このdockerを使えば、
１つのパソコンでいろんな OS（仮装環境）を動かすことができるのです。


アプリ開発では、
開発環境上で
・プログラミングソース
・データベース
が必要になりますが、
Dockerを使用することで、
それら全てを丸ごと管理することができるので
チームで開発するときに便利です。


さらにメリットとしては
コマンドだけで設定ができたり
イメージと言われるファイルでデータベースなどを準備できたり
イメージからコンテナを生成してアプリを動かしたり
など開発を便利にできる機能があります。
（この辺はまだまだ知識が浅いので説明できません、、、）


参考にして頂けたら嬉しいです！


参考したもの
https://www.youtube.com/watch?v=VIzLh4BgKck&t=90s
systemctl で Tomcat を制御できない…

これまで仕事関係で CentOS を使う機会が多かったのですが、今後は、自宅で Respberry Pi を扱う時間を増やそうと考えています。
Debian系のディストリビューションは、Debian の古いバージョンを十年以上前に触って以降、ほとんど使っていませんでした。
（時々、Ubuntu は触りましたが、GUI での利用が大半…）

サーバー環境を構築している中、Debian系でも systemctl が使えるんだ…（ディストリビューション間の違いがなくなりつつあるのかな？）なんて思ったりもしていますが、[歴史的な経緯](https://ja.wikipedia.org/wiki/Systemd) を眺めると、一筋縄でも行かないようで…。

ディストリビューションの間の違いが埋められたら良いな（楽！）…という思いもあり、
systemctl を積極的に使っていこうと思いました。

---

さて本題ですが、

```
$ sudo systemctl stop tomcat
Failed to stop tomcat.service: Unit tomcat.service not loaded.

$ sudo systemctl enable tomcat.service
Failed to enable unit: Unit file tomcat.service does not exist.
```

Failed 連発です。
適当にやるとだめですね…。
tomcat.service は自分で作る？（aptでインストールされたのだから、用意されていると思うが…）などと思いながら、
インストール先を調べてみたら、ありました。
「tomcat.service」ではなく「tomcat9.service」でした。

```
$ dpkg -L tomcat9
/.
/etc
/etc/cron.daily
/etc/cron.daily/tomcat9
/etc/logrotate.d
/etc/rsyslog.d
/etc/rsyslog.d/tomcat9.conf
/etc/tomcat9
/etc/tomcat9/Catalina
/etc/tomcat9/policy.d
/etc/tomcat9/policy.d/01system.policy
/etc/tomcat9/policy.d/02debian.policy
/etc/tomcat9/policy.d/03catalina.policy
/etc/tomcat9/policy.d/04webapps.policy
/etc/tomcat9/policy.d/50local.policy
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/tomcat9.service
/usr
/usr/lib
/usr/lib/sysusers.d
/usr/lib/sysusers.d/tomcat9.conf
/usr/lib/tmpfiles.d
/usr/lib/tmpfiles.d/tomcat9.conf
/usr/libexec
/usr/libexec/tomcat9
/usr/libexec/tomcat9/tomcat-start.sh
/usr/libexec/tomcat9/tomcat-update-policy.sh
/usr/share
/usr/share/doc
/usr/share/doc/tomcat9
/usr/share/doc/tomcat9/changelog.Debian.gz
/usr/share/doc/tomcat9/copyright
/usr/share/tomcat9
/usr/share/tomcat9/default.template
/usr/share/tomcat9/etc
/usr/share/tomcat9/etc/catalina.properties
/usr/share/tomcat9/etc/context.xml
/usr/share/tomcat9/etc/jaspic-providers.xml
/usr/share/tomcat9/etc/logging.properties
/usr/share/tomcat9/etc/server.xml
/usr/share/tomcat9/etc/tomcat-users.xml
/usr/share/tomcat9/etc/web.xml
/usr/share/tomcat9/logrotate.template
/usr/share/tomcat9-root
/usr/share/tomcat9-root/default_root
/usr/share/tomcat9-root/default_root/META-INF
/usr/share/tomcat9-root/default_root/META-INF/context.xml
/usr/share/tomcat9-root/default_root/index.html
/var
/var/cache
/var/cache/tomcat9
/var/lib
/var/lib/tomcat9
/var/lib/tomcat9/lib
/var/lib/tomcat9/webapps
/var/log
/var/log/tomcat9
/usr/share/doc/tomcat9/README.Debian
/var/lib/tomcat9/conf
/var/lib/tomcat9/logs
/var/lib/tomcat9/work

```