OmniAICreator/Qiita-1.07M huggingface dataset:
Windowsからショートカットのクリックだけで対象サーバにSSHログイン

Puttyで公開鍵証明書を使ったログインを設定した後、ユーザー名の入力を求められることなくログインする方法です。

## 手順

- [Putty最新版](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html)のダウンロード
- Puttyのインストール
- Putty設定画面から、公開鍵ログインする設定を保存
- Puttyに「公開鍵ログインする設定」と「ユーザー」を指定して実行するバッチファイルを作成

### 公開鍵ログインする設定
以下画面の通りPuttyの設定を作成して保存。

![putty0000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486347/bbae2e2d-99d6-7a17-6872-e8bedd45ed44.jpeg)

![putty0001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486347/98a53dee-cf00-d670-8bfc-c16cf5804f0d.jpeg)

### Puttyに「公開鍵ログインする設定」と「ユーザー」を指定して実行するバッチファイルを作成
以下ファイルを「fileserver.bat」等のファイル名で保存。
※usernameは、適宜変更してください。例えば「test」ユーザーなどです。

```
cd "C:\Program Files\PuTTY\"
start /B putty.exe -load fileserver -l username
```

上記batファイルのポイントは、start /Bでputtyを呼び出すことで、
putty起動後にdos窓が残らないようにしている点です。


## おまけ（Linuxサーバでの公開鍵ログイン設定方法）

Linux側で公開鍵ログインする為の設定方法です。
自動ログインさせたいユーザーで実施してください。
※ rootユーザー以外の一般ユーザーで実施してください。

ここでは、サンプルとして、testユーザーで実施しています。

```
# .sshディレクトリに移動（なければ作成）
cd ~/.ssh

# 公開鍵、秘密鍵のペアを作成
ssh-keygen -t rsa -b 2048 -f `hostname`

# 作成されたファイルを確認
ls -la `hostname`*
# -rw------- 1 test test 1823 Feb 16 13:11 fileserver
# -rw-r--r-- 1 test test  397 Feb 16 13:11 fileserver.pub

# .pubをsuthorized_keysに追記
cat `hostname`.pub >> authorized_keys
chmod 0600 authorized_keys

# 秘密鍵を表示＞Puttyインストールフォルダにあるputtygen.exeで読み込ませ、ppkファイルで保存
cat `hostname`

# 秘密鍵と、authorized_keysに転記済み公開鍵を削除
rm `hostname`
rm `hostname`.pub

# ファイルの削除確認
ls -la `hostname`*
ls: cannot access 'fileserver*': No such file or directory
test@fileserver:~/.ssh$
```

## 最後に
以前はPuttyを起動後に、保存しておいた設定をダブルクリックしてログイン時にユーザー名を入力してログインしていました。しかし、上記のバッチファイルを作成し、タスクバーにピン止めしておくことで、よく使うサーバにはすぐにログイン出来るようになりました。
CarrierWaveでデフォルト画像の設定

CarrierWaveでユーザーアイコンの実装をしていたのですが、デフォルト画像の表示で少し躓いてしまったのでメモしておきます。

#前提
- CarrierWaveは導入済み
- 登録した画像表示はできる

#image_uploader.rbの設定
CarrierWaveを入れたときに

```
$ rails g uploader image
```
をしたらimage_uploader.rbというファイルが生成されます。

このファイルを以下のようにいじってください。

```image_uploader.rb
#アップロードした画像の表示
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

#デフォルト画像の設定
  # Provide a default URL as a default if there hasn't been a file uploaded:
  def default_url(*args)
  #   For Rails 3.1+ asset pipeline compatibility:
    ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  end
```

これで登録時にファイル選択をしなかった場合、デフォルト画像をimageとして渡す準備ができました。

#assets/images配下に画像を設置
assets/images配下にデフォルト画像を設置してください。
画像名はこの場合「default.png」にしときましょう。

#Viewの設定
Viewに、if文でユーザーのimageがある場合とない場合で表示が変わるように設定してあげましょう。

以下は例です。

```erb:_show.html.erb
<% if post.user.image? %>
  <img src='<%= post.user.image %>' class="icon" alt="ユーザーアイコン">
<% else %>
  <image src="/assets/default.png" class="icon" alt="ユーザーアイコン" %>
<% end %>
```

#まとめ
CarrierWaveさんは非常に便利なのですが、デフォルト画像設置に関しては画像パスとして渡っているので、dbを調べてもnullとしか表示されず焦ってしまうというパターンがよくあるようです。

よく使う機能だとは思いますので、誰かの助けになれば幸いです。

ではでは。
【リリース】Qiitaの新着記事をニュース感覚で聞き流せるwebアプリ【聞い太?】

# Qiitaの新着記事をニュース感覚で聞き流せるwebアプリ【聞い太?】

Qiitaの新着記事をニュース感覚で聞き流せるwebアプリを作りました。

【聞い太?】
https://technews-app.herokuapp.com/

記事選択して▶️ボタンを押すと、選択した記事を読み上げます。(safariは一部制限あり)

また、記事タイトルやタグに関連する技術書を表示しています。

満員電車の中やながら作業も、インプット時間として有効活用出来ます★

新着順なので本家にはあまり出てこない記事も発見できるかも?

日々のスキルUPに是非🖥

# 使った技術
Ruby on Rails(6.0.2.1)
Ruby(2.6.4)
JavaScript / jquery
Heroku
S3
QiitaAPI
Web Speech API
Amazon Polly
Selenium Webdriverなど。
KerasでAutoencoderを試して簡単な問題で試してみた

#　目的
異常検知問題をやってみたくてKerasで簡単な問題を作ってみました

#　内容
y=x-0.5＋ε
という式でx,yのペアを作りそれを入力、と出力にして学習してみました

#　コード
```python:autoencoder.ipynb
import numpy as np
import random
from keras.models import Model,Sequential
from keras.layers import Dense,Activation,Dropout,Input
from keras.layers.normalization import BatchNormalization
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
# 関数
def func(x,w):
    return(x+(random.random()*2-1)*w)
# データ作成
x1=[random.random() for i in range(500)]
X=np.array([[z,func(z-0.5,0.05)] for z in x1])
Y=np.array([[z,func(z,0.0)] for z in x1])
X_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.2)
# 学習モデル作成
encoding_dim = 1
activation="relu"
hidden=10
output_dim = X_train.shape[1]
model=Sequential()
model.add(Dense(hidden,input_shape=(X_train.shape[1],),activation=activation))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Dense(encoding_dim,activation=activation))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Dense(hidden,activation=activation))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Dense(output_dim,activation=activation))
print(model.summary())

#学習実施
model.compile(optimizer='sgd', loss='mae')
model.fit(X_train, X_train, epochs=50,batch_size=50, validation_data=(X_test, X_test),verbose=0)

#学習結果表示
pred=model.predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],s=0.1)
plt.scatter(pred[:,0],pred[:,1],s=0.1)
plt.show()
plt.scatter(X_train[:,0]-pred[:,0],X_train[:,1]-pred[:,1])
```

#結果
青い点が学習データ（x,y)をペアで入力と出力
オレンジの点が同じデータを入力したときの出力

なぜかうまく学習できません
今のところ原因はわかっていません。
activationをreluやsgdなどに変えたりlossを変えたり隠れ層の数を変えましたが
大きく改善していません


![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517750/dfa55cc8-769d-cef5-7fc5-245bde5d16de.png)


#解決
いろいろいじって自己解決しました
結果的には、活性化関数をreluとかtanhとかにしていましたが、思い切ってKerasのデフォルトのNoneにしたところ,下のグラフのようにまっすぐのりました。
単純な線形問題だからこれでうまく行くのか、それとも回帰問題はこれで正解なのかはもう少し試してみて考えます

![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517750/c52730a8-3a16-73d6-903d-800848f082a6.png)
ツイッターデベロッパーでのapp作成手順

[前回の記事](https://qiita.com/n-ike/items/88d4bc5334c14368e195)で、TwitterAPIの利用申請が完了しました。

実際にRubyでbotを作成するには、デベロッパー上でappを作成する必要がありますので、本記事ではその手順を記載します。

#手順１　Appの名称と説明を入力する

作成するAppの名称をApp name欄に入力してください。
(すでに登録されている名称は使用できません。)

Application description欄には、アプリの説明を記載してください。簡単にで問題ありません。
[![Image from Gyazo](https://i.gyazo.com/5c036689373b18041732171d77a90f6e.png)](https://gyazo.com/5c036689373b18041732171d77a90f6e)

#手順2 必須のURLを入力する

Website URL、Callback URLを入力してください。
本来は本番環境でのURLを入力する欄ですが、とりあえず登録段階ではキータの自分のページや、ツイッターのトップページ等でも問題ありません。
開発段階では、
http://localhost:3000/
と記載したいところですが、2020年2月時点では認められませんでした。
※この部分については、キータでも記事によって記入方法が異なると思います。
 しかし、登録の段階では何でも良いので入るものを入れてしまいましょう。
[![Image from Gyazo](https://i.gyazo.com/fd5e6995253d58eaef956c09c0c0302a.png)](https://gyazo.com/fd5e6995253d58eaef956c09c0c0302a)

#手順3 Appの使用方法について説明する

開発予定のアプリケーションがどのように使用されるのか記載しましょう。
簡単にで問題ありません。

記入が完了したら、Createボタンを押してください。
その後出てくるポップアップ画面でも、Createボタンを押してください。
[![Image from Gyazo](https://i.gyazo.com/5c66520020d26c6af8f664effaf4db5b.png)](https://gyazo.com/5c66520020d26c6af8f664effaf4db5b)

[![Image from Gyazo](https://i.gyazo.com/08e290a45205dd47ff2ef1815dde2921.png)](https://gyazo.com/08e290a45205dd47ff2ef1815dde2921)

#手順4 登録内容を確認する
以下のような画面が表示されたら登録完了です。
内容を変更したい場合は、右上のEditボタンから編集してください。
[![Image from Gyazo](https://i.gyazo.com/efb1f9980c4ef301b1364a2f55bf9a43.png)](https://gyazo.com/efb1f9980c4ef301b1364a2f55bf9a43)

以上で登録作業は完了です。
次の記事では、登録したAppを使用して、実際にRubyファイルからツイートする方法を解説します。

最後まで読んでいただきありがとうございました。
Nuxt.jsでグローバル（共通の）CSSを設定する方法

##Nuxt.jsでグローバル（共通の）CSSを設定する方法
Nuxt.jsのディレクトリ構成は下記のようになっています。
![nuxt.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/ea63b66c-4c9c-0a84-5142-f2dc1fa583ad.jpeg)

assetsディレクトリにcssファイルを作成します。

```
├── assets
│   ├── main.scss
```
次にnuxt.config.jsで読み込みます。

```js:nuxt.config.js
export default {
  css: [
    '~/assets/main.scss'
  ],
}
```

これでグローバルCSSの設定は完了です。

グローバルでは無く個別のページでCSSを読み込む場合は各ページでインポートします。

```vue
<style lang="scss">
 @import "assets/main.scss";
</style>
```
Vuetify使おうと思ってwebpack3からwebpack4への移行した時のメモ

#概要
タイトル的なことをやったらハマったけど最終的に出来たっぽいのでまとめてみた。

#経緯
[Vuetifyのクイックスタートガイド](https://vuetifyjs.com/ja/getting-started/quick-start#webpack-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)に以下のような記述があり、自分のvue init webpackで作成したプロジェクトを確認したらwebpack3系で作られていた。
> ツリーシェーキングに vuetify-loader を使用する場合は、Webpackのバージョン >=4であることを確認してください。

#バージョン色々
- vue: 2.5.22 -> 2.6.11
- vue-cli: 3.3.0
- webpack: 3.12.0 -> 4.41.6

#移行手順
- 依存関係の更新
    - [こちら](https://uuka.hatenablog.com/entry/2018/09/30/015713)を参考にさせて頂いた。
- ソースコードの編集
    - 上記のリンクにも記載がありましたが、より詳細がわかりやすかったので[こちら](https://qiita.com/skillet/items/29c425cca3b7d6094abe)を参考にさせて頂いた。
- 個別にやったこと
    - 上記を実施した際に、なぜかwebpack-dev-serverのバージョンだけ上がってなかったので、とりあえず`npm isntall --save-dev webpack@latest`した。

#ハマったとこ
上記の移行手順をやり切って、`npm run build`は無事成功。
お次は`npm run dev`でローカル動作確認を、と思ったらdevサーバは立つもブラウザに以下のエラーが出て画面は描画されず。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584842/2b017714-236c-029d-ea8a-894576717b74.png)
とりあえずググると[このような記事](https://chaika.hatenablog.com/entry/2019/02/04/083000)が。なるほど、そんなんもうわからん…

#解決
ひたすらググり続けて[同事象のissue](https://github.com/webpack/webpack-dev-server/issues/2010)に以下のコメントを発見。
> use `webpack-dev-server@3.5.1` instead of 3.9.0 solved the problem

ほう？そういえばさっきwebpack-dev-serverを適当に最新化したぞ…

```package.json
    "webpack-dev-server": "^3.10.3"
```

やっぱり。
`npm isntall --save-dev webpack-dev-server@3.5.1`してみよう。

```package.json
    "webpack-dev-server": "^3.５.１"
```

`npm run dev`実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584842/7b2bc61a-0ef2-c34d-7935-1524cc815603.png)
おー、できた！（画面も描画された）

そんなわけでひとまずwebpack3 -> webpack4の移行は完了。Vuetifyの導入に戻ります。

#参考文献
- [vue init webpackで作成したプロジェクトをwebpack4に移行する](https://uuka.hatenablog.com/entry/2018/09/30/015713)
- [Vue CLI 2系でwebpack3からwebpack4への移行手順](https://qiita.com/skillet/items/29c425cca3b7d6094abe)
- [Vue.js アプリの webpack のバージョンを 4 系に上げた](https://ravelll.hatenadiary.jp/entry/2018/05/22/000449)
- [Webpack 4 で Cannot assign to read only property 'exports' of object エラー](https://chaika.hatenablog.com/entry/2019/02/04/083000)
- [Cannot assign to read only property 'exports' of object '#<Object>' #2010](https://github.com/webpack/webpack-dev-server/issues/2010)
pythonでヒープを実装してみた

pythonとアルゴリズムの勉強かねがね、ヒープを実装してみました。
今回ヒープを実装してみて、木構造に対してすこし理解ができたのかなと思います。

ちょっとずつアウトプットしていきたいので、ヒープソートは次にします。

```heap.py
import random
import copy

# 準備する値の数を入力
numbers = 10

# ソート済の値を格納するリストの作成
sorted_list = []

# 乱数の作成
num_list = list(range(numbers))
random.shuffle(num_list)

def heap(num_list):

    while True:
        # whileループ開始時の配列を保持
        check_list = copy.deepcopy(num_list)
        # 頂点から順にチェックしていく
        for i in range(len(num_list)):
            # ノードの下に値が1つしか残っていない場合(終端パターンその1)
            if len(num_list) == (i+1)*2:
                node = num_list[i]
                left = num_list[(i+1)*2-1]
                # ノードより子供が大きい場合は値を入れ替える
                if node > left:
                    num_list[i] = left
                    num_list[(i+1)*2-1] = node
                    # 値の入れ替えが発生したので上から再確認
                    break
                # 終端なのでbreak
                break
            
            elif len(num_list) > (i+1)*2:
            # ノードの下に値が2つ以上残っていない場合(終端ではないパターン)
                node = num_list[i]
                left = num_list[(i+1)*2-1]
                right = num_list[(i+1)*2]
                # ノードより子供のいずれかが大きい場合、より値の小さい子供と値を入れ替える
                if node > left or node > right:
                    if left < right:
                        num_list[i] = left
                        num_list[(i+1)*2-1] = node
                    else:
                        num_list[i] = right
                        num_list[(i+1)*2] = node
                    # 値の入れ替えが発生したので上から再確認
                    break
            else:
            # ノードの下に値が残っていない場合(終端パターンその2)
                break
        # whileループの冒頭と比較して、配列が同一だった場合whileループをbreak
        if check_list == num_list:
            break
    return num_list



def main(num_list):
    # メイン処理
    print("START : ",num_list)

    num_list = heap(num_list)

    print("GOAL  : ",num_list)

if __name__ == '__main__':
    main(num_list)
```
Lottie でマイクロインタラクション事始め

ふと思い立ってマイクロインタラクションの実装方法について調べてみましたのでコードのメモと成果物を置いておきます。

使ったのは Airbnb が提供しているアニメーションライブラリの [Lottie](https://airbnb.design/lottie/)。After Effects で作ったアニメーションをブラウザやアプリ上で動かせるようになります。

今回はサンプルで配布されている[ハートのアニメーション](https://www.lottiefiles.com/2415-twitter-heart)をクリックしたら動くものを作ってみました。

## コードと成果物

雑ですが取り急ぎ作ったものをそのまま。
vue でやれるようになりたい気持ちです。

```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js" type="text/javascript"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.6.4/lottie.min.js"></script>

  <style>
    g{
      cursor: pointer;
    }
  </style>

</head>
<body>
  <div id="lottie"></div>

  <script>
  var params = {
      container: document.getElementById('lottie'),
      renderer: 'svg',
      loop: false,
      autoplay: false,
      path: "2415-twitter-heart.json"
  };
  var animation = lottie.loadAnimation(params);
  $(function(){
      $('#lottie').on('click',function(){
        animation.play();
      });
  });
  </script>

</body>
</html>
```

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">なるほど <a href="https://t.co/kWcyVwAJZM">pic.twitter.com/kWcyVwAJZM</a></p>&mdash; sasaki (@shirokuro331) <a href="https://twitter.com/shirokuro331/status/1228887297501777921?ref_src=twsrc%5Etfw">February 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

アニメーション作るのはまた別スキルの話ですが、こんな感じでマイクロインタラクション実現させてユーザー体験向上させる仕掛け作れるのは良いですね。

参考 : 
[より良いUIのためのマイクロインタラクション入門](https://goodpatch.com/blog/ui-micro-interaction/)
数値の文字化を高速にしてみた

#sprintf()からの限界へ挑戦
数値データを文字列にする機会が、JSONフォーマットをレスポンスするAPIで増えた気がします。数値の書式フォーマット付き文字列化といえば、sprintf()を使うでしょう。通常ならば、それで全く問題ありません。

しかし、sprintf() は、フォーマット文字列を複雑に定義できる反面、そのパースに処理も必要なので、単純なパターンであれば、ちょっとオーバースペックすぎるところです。そこで、`sprintf(s,"%.1f",fv)` に限って処理する関数で置き換えてみることにしました。

# 実装方針
* 書式指定文字列は使用しない。いさぎよく "%.1f" 相当だけ。
* 小数点以下第二位は切り捨てとする（sprintf()の実装では四捨五入される）

というかんじで、書いてみたのが以下のコードです。

```fv2s.c

void fv2s(char *s, double fv)
{
    int iv,i,zf;

    if ((fv >= 1000000) || (fv <= -1000000)){ // overflow error, fallback                                                                                            
        sprintf(s,"%.1f",fv);
        return;
    }

    iv = fv * 10;
    if (iv < 0){
        *s++ = '-';
        iv = -iv;
    }

    zf = 0;
    i = ((iv % 10000000) / 1000000);  if (zf || (i != 0)){*s++ = i + '0'; zf = 1;}
    i = ((iv %  1000000) /  100000);  if (zf || (i != 0)){*s++ = i + '0'; zf = 1;}
    i = ((iv %   100000) /   10000);  if (zf || (i != 0)){*s++ = i + '0'; zf = 1;}
    i = ((iv %    10000) /    1000);  if (zf || (i != 0)){*s++ = i + '0'; zf = 1;}
    i = ((iv %     1000) /     100);  if (zf || (i != 0)){*s++ = i + '0'; zf = 1;}
    i = ((iv %      100) /      10);  *s++ = i + '0';
    *s++ = '.';
    i = ((iv %      10)         );    *s++ = i + '0';
    *s = '\0';
}
```

# コード解説
* 100万以上、-100万以下の場合は、無理せず素直に本家 sprintf() に処理を依頼しています。（今回のターゲットしている値の扱う範囲でざっくり適当に決めています）
* 今回は、小数点以下第一位までを使用しますので、10倍して整数化してしまいます。
* 負の数の場合は、符号を記述します。
* 高位の桁から順に１桁ずつみていき、文字化して追記していきます。
* C言語の場合は、文字化するには '0' (0x30) を加算するのが手っ取り早いです。
* 先頭の桁で0の場合はスキップしますが、一旦0以外の数値が出たあとは0でも出力します。
* 前項によらず、一の位は0でも必ず出力します。
* 小数以下第一位も、同様に必ず出力します。

#実行結果

```
% gcc -O2 a.c
% time ./a.out 1
fv2s optimized version
0.117u 0.003s 0:00.12 91.6%	0+0k 0+0io 0pf+0w

% time ./a.out 2
sprintf native version
3.063u 0.000s 0:03.06 100.0%	0+0k 0+0io 0pf+0w
```

25倍速くなりました。　めでたしめでたし。
参考までに、上記のテストに使ったコードはこちら

```a.c
int random_check()
{
    char s1[1023];
    char s2[1023];
    int i;
    float fv;

    srand(time(NULL));
    for (i = 0; i < 10000000; i++) {
        fv = (((double)rand() / RAND_MAX) - 0.5) * 100000000;
        fv = (((int)(fv * 10)) / 10);
        sprintf(s1,"%.1f",fv);
        fv2s(s2,fv);
        if (strcmp(s1,s2) != 0){
            printf("error %.1f, %s, %s\n", fv, s1, s2);
        }
    }
}

int speed_test_1()
{
    char s[1023];
    int i;
    printf("fv2s optimized version\n");
    for (i = 0; i < 10000000; i++) {
        fv2s(s, 23.4);
    }
}

int speed_test_2()
{
    char s[1023];
    int i;
    printf("sprintf native version\n");
    for (i = 0; i < 10000000; i++) {
        sprintf(s,"%.1f", 23.4);
    }
}

int main(int argc, char **argv)
{
    int opt = 0;
    if (argc >= 2){
        opt = atoi(argv[1]);
    }
    switch (opt){
    case 0: random_check(); break;
    case 1: speed_test_1(); break;
    case 2: speed_test_2(); break;
    }
    return 0;
}
```

かなり、用途が限定されるので、どれほどお役に立つかわかりませんが、まあ、こういうチャレンジは、やってて楽しいですよね。
eccube4のコマンドが覚えられない人はMAKEFILEを使おう

eccube4では以下種類のコマンドを多様するが、正直全部覚えてられなくないですか？

- docker
- symfony
- eccube

僕は毎回コマンドを思い出すのが面倒なのでMAKEFILEに書く事で対応しました。

よく使うコマンドはMAKEFILEでまとめてしまいましょう。

```
#-----------------------------------------------------------
# Symfony controls
#-----------------------------------------------------------

#Symfonyキャッシュの削除
clear-cache-symfony:
	php bin/console cache:clear --no-warmup

#全てのキャッシュを削除・再生成する
clear-all-cache:
	rm -rf app/proxy/entity/src
	composer dumpautoload
	php bin/console eccube:generate:proxies
	php bin/console cache:clear --no-warmup

#proxyの再生成
generate-proxy:
	php bin/console eccube:generate:proxies

#proxyの削除
remove-proxy:
	rm -rf app/proxy/entity/src

#マイグレーションファイルを参照してDBに変更を加える
migration:
	php bin/console doctrine:migrations:migrate

#マイグレーションファイルの生成
generate-migration:
	php bin/console doctrine:migrations:generate

#既存Entityとデータベースの差分からマイグレーションを作成
migration-diff:
	php bin/console doctrine:migrations:diff

#マイグレーション実行前のクエリを確認するコマンド
migration-update:
	php bin/console doctrine:schema:update --dump-sql

#マイグレーションファイルのクエリを反映
migration-update-force:
	php bin/console doctrine:schema:update --dump-sql --force

#現在のマイグレーションの反映状況を確認
migration-status:
	php bin/console doctrine:migrations:status

#-----------------------------------------------------------
# Composer controls
#-----------------------------------------------------------

#Composer クラスマップの再生成
dump-autoload:
	composer dumpautoload

#-----------------------------------------------------------
# Docker controls
#-----------------------------------------------------------
up:
	docker-compose up --build

stop:
	docker-compose up --build

#-----------------------------------------------------------
# Ec-cube controls
#-----------------------------------------------------------

#プラグインインストール
#make plugin-install ARG=Recommend4
plugin-install:
	php bin/console eccube:plugin:install --code=${ARG}

#プラグインアンインストール
#make plugin-uninstall ARG=Recommend4
plugin-uninstall:
	php bin/console eccube:plugin:uninstall --code=${ARG}

#プラグイン有効化
#make plugin-enable ARG=Recommend4
plugin-enable:
	php bin/console eccube:plugin:enable --code=${ARG}

#プラグイン無効化
#make plugin-disable ARG=CrosssellProduct4
plugin-disable:
	php bin/console eccube:plugin:disable --code=${ARG}

#-----------------------------------------------------------
# php-cs-fixer controls
#-----------------------------------------------------------
fixer-cutomize:
	php-cs-fixer fix  ./app/Customize/

fixer-plugin:
	php-cs-fixer fix  ./app/Plugin/

fixer-src:
	php-cs-fixer fix  ./src/

```
Spacemacsのhelm-yasで候補が出ない場合の解決方法

[Learn Emacs Org Mode: Spacemacs Intro Tutorial - YouTube](https://www.youtube.com/watch?v=PVsSOmUB7ic)を見てOrg Modeを学習していたところ、Yasnippetの候補が出てこなくて困った。

# 環境
- GNU Emacs 26.3
- Spacemacs [master branch]
- .spacemacsに以下のレイヤーがインストールされていること
    - auto-completion
    - org

## 解決方法
Youtubeのコメント欄で同様の症状の方がいて、
返信で下記の方法が書いてありました。

```
Press SPC SPC 
=> Select package install
=> Select yasnippet-snippets
=> Press Return key
```

動作を確認します。

```
Press SPC i s
```

![Screenshot from 2020-02-16 12-29-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62023/a3a9509b-cee0-8fda-8dd9-25f3ed7a86aa.png)

出た！
Salome-Meca 2018を用いた節点共有によるAssyの応力解析（SSLV）

複合材とは、材質の異なる形状のものが合わさって構成されるモデルであり、その材質が異なる境界面では、モデルの節点が共有されており、全体としてのモデルは、Solidが１つになるという考え方です。

この資料は[オープンCAE勉強会＠岐阜](http://opencae.gifu-nct.ac.jp/pukiwiki/index.php?OpenCAE%20Users%20Wiki)で公開されているFS氏ご提供の「[SALOME-Mecaの使用法解説](http://opencae.gifu-nct.ac.jp/pukiwiki/index.php?SALOME-Meca%A4%CE%BB%C8%CD%D1%CB%A1%B2%F2%C0%E2)：3.0 複合材料の設定」をSalome-Meca 2018（Code_Aster 13.6）のAsterStudyモジュールを用いて実行しました。

# ジオメトリ

直方体が２個

# 材料

２種類の材料を定義します。柔らかい材料（Aluminum）と硬い材料（Steel）を定義します。

|材料名|ヤング率|ポアソン比|
|:--|:--|:--|
|Aluminum|70,600MPa|0.345|
|Steel|212,000MPa|0.293|

# 拘束条件と荷重条件

|境界条件|トポロジ|境界条件の種類|条件|
|:--|:--|:--|:--|
|fix|面|変位|DX=DY=DZ=0|
|load|面|圧力荷重|0.1MPa|

![0300BC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201403/8a969069-3dad-2086-c52c-19969c1048a8.png)


# 解析結果

相当応力図を示します。

![0300multi-P.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201403/91c38aa7-39a8-3dcd-e936-2e60745401c3.png)


# コマンドファイル

```python
DEBUT(LANG='EN')


mesh = LIRE_MAILLAGE(identifier=u'0:1',
                     FORMAT='MED',
                     UNITE=20)

mesh = MODI_MAILLAGE(identifier=u'1:1',
                     reuse=mesh,
                     MAILLAGE=mesh,
                     ORIE_PEAU_3D=_F(GROUP_MA=('load', 'fix')))

model = AFFE_MODELE(identifier=u'2:1',
                    AFFE=_F(MODELISATION=('3D', ),
                            PHENOMENE='MECANIQUE',
                            TOUT='OUI'),
                    MAILLAGE=mesh)

Steel = DEFI_MATERIAU(identifier=u'3:1',
                      ELAS=_F(E=210000.0,
                              NU=0.293))

Aluminum = DEFI_MATERIAU(identifier=u'4:1',
                         ELAS=_F(E=70600.0,
                                 NU=0.345))

fieldmat = AFFE_MATERIAU(identifier=u'5:1',
                         AFFE=(_F(GROUP_MA=('Base', ),
                                  MATER=(Aluminum, )),
                               _F(GROUP_MA=('Top', ),
                                  MATER=(Steel, ))),
                         MAILLAGE=mesh)

load = AFFE_CHAR_MECA(identifier=u'6:1',
                      DDL_IMPO=_F(DX=0.0,
                                  DY=0.0,
                                  DZ=0.0,
                                  GROUP_MA=('fix', )),
                      MODELE=model,
                      PRES_REP=_F(GROUP_MA=('load', ),
                                  PRES=0.1))

reslin = MECA_STATIQUE(identifier=u'7:1',
                       CHAM_MATER=fieldmat,
                       EXCIT=_F(CHARGE=load),
                       MODELE=model)

reslin = CALC_CHAMP(identifier=u'8:1',
                    reuse=reslin,
                    CONTRAINTE=('SIGM_ELNO', 'SIGM_NOEU'),
                    CRITERES=('SIEQ_ELNO', 'SIEQ_NOEU'),
                    RESULTAT=reslin)

IMPR_RESU(identifier=u'9:1',
          FORMAT='MED',
          RESU=_F(NOM_CHAM=('SIGM_NOEU', 'SIEQ_NOEU', 'DEPL'),
                  RESULTAT=reslin),
          UNITE=2)

FIN()
```
Raspberry Pi 3BやPi Zero WHでAlexa Gagdet Toolkitを動かす

# Raspberry Pi 3BやPi Zero WHでAlexa Gagdet Toolkitを動かす

## やりたいこと

Alexa Gadget ToolkitをRaspberry Pi 3BやPi Zero WHで動かす。(3B+は持っていないので。)
個人的にはタイマーの残り時間を表示したい。

## 理由

* 現時点の[公式のサンプル(v2.0.0)](https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples#prerequisites)だと、3B+対応となっており、実際Pi Zero WHでは動作しなかった。
* [v1.0.0時点のcommit](https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples/tree/e0d86669109339c20434f4fbae2721db8749a360)の[READMEの前提環境](https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples/tree/e0d86669109339c20434f4fbae2721db8749a360#prerequisites)を見ると、Pi Zero WHが記載されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78540/b12a0900-05a6-70e7-0d04-20905c9729ee.png)

## 事前準備

* `sudo apt-get update` などで最新化しておく

## 対策

* git cloneしたあと、v1.0.0時点のcommitを使用 

> git checkout e0d86669109339c20434f4fbae2721db8749a360

* その時点の[README](https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples/tree/e0d86669109339c20434f4fbae2721db8749a360)の手順を実行

> sudo bash ./setup.sh

* あとはお好きなサンプルをどうぞ。

# その他

## Alexa Gagdet Toolkitとは

Alexa Gagdet Toolkitでできること

* https://developer.amazon.com/ja-JP/docs/alexa/alexa-gadgets-toolkit/understand-alexa-gadgets-toolkit.html
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78540/aa28325a-02b9-26fa-b364-9f1d9b9708ec.png)

* 公式サンプル 
* https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples
【JavaScript】誕生年の配列を作るサンプルコード(ギネス世界記録を反映)

## はじめに
**ギネス世界記録の最高齢**を反映した、誕生年の整数配列を作るサンプルコードを残します。
セレクトボックスで使えるのではと思います。

## 環境
```yaml
OS: macOS Catalina 10.15.3
```
## 結論

```javascript:sample.js
  const year = new Date().getFullYear()

  // ギネス世界記録の最高齢
  const maxAge = 117 

  const start = year - maxAge
  const end = year

  // 必要な範囲の整数配列を作成
  const years = [...Array(end - start + 1).keys()].map( i => start + i)

  // 降順に並び替えて選びやすくする
  // ※最終的にはこれを使う
  const descYears = years.sort((a,b) => {
    return (a < b ? 1 : -1)
  })
```


## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:
Salome-Meca 2018を用いた軸対称問題（SSLA）

スタンプ台にスタンプを押し付けたときのスタンプ台の応力分布

この資料は日本機械学会マルチフィジックス研究会 CAE設計演習問題作成WGによる「[CAE設計演習問題集](http://www.fml.t.u-tokyo.ac.jp/multiphysics/prob/index.htm)」の「1-6 接触による応力分布」を軸対称の等分布荷重問題に置き換えたものです。

# ジオメトリ

- スタンプ台：直径200mm×高さ100ｍｍ
- スタンプ（荷重範囲）：直径60mm

# 材料

- ヤング率：E=200,000MPa
- ポアソン比：$\nu$=0.3

# 拘束条件と荷重条件

|境界条件|トポロジ|境界条件の種類|条件|
|:--|:--|:--|:--|
|fix|線|変位|DX=DY=0|
|load|線|圧力荷重|100MPa|

![stampBC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201403/3799b36a-090b-1acf-96ec-a22911aeaa16.png)

# 解析結果

相当応力図を示します。

![stamp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201403/59a11c24-49c4-e1d8-35fa-c9c5a9e698d5.png)


# コマンドファイル

Salome-Meca 2018（Code_Aster 13.6）のAsterStudyモジュールを用いました。

```python
DEBUT(LANG='EN')


mesh = LIRE_MAILLAGE(identifier=u'0:1',
                     FORMAT='MED',
                     UNITE=20)

mesh = MODI_MAILLAGE(identifier=u'1:1',
                     reuse=mesh,
                     MAILLAGE=mesh,
                     ORIE_PEAU_2D=_F(GROUP_MA=('load', )))

model = AFFE_MODELE(identifier=u'2:1',
                    AFFE=_F(MODELISATION=('AXIS', ),
                            PHENOMENE='MECANIQUE',
                            TOUT='OUI'),
                    MAILLAGE=mesh)

mater = DEFI_MATERIAU(identifier=u'3:1',
                      ELAS=_F(E=200000.0,
                              NU=0.3))

fieldmat = AFFE_MATERIAU(identifier=u'4:1',
                         AFFE=_F(MATER=(mater, ),
                                 TOUT='OUI'),
                         MAILLAGE=mesh)

load = AFFE_CHAR_MECA(identifier=u'5:1',
                      DDL_IMPO=_F(DX=0.0,
                                  DY=0.0,
                                  GROUP_MA=('fix', )),
                      MODELE=model,
                      PRES_REP=_F(GROUP_MA=('load', ),
                                  PRES=100.0))

reslin = MECA_STATIQUE(identifier=u'6:1',
                       CHAM_MATER=fieldmat,
                       EXCIT=_F(CHARGE=load),
                       MODELE=model)

reslin = CALC_CHAMP(identifier=u'7:1',
                    reuse=reslin,
                    CONTRAINTE=('SIGM_ELNO', 'SIGM_NOEU'),
                    CRITERES=('SIEQ_ELNO', 'SIEQ_NOEU'),
                    RESULTAT=reslin)

IMPR_RESU(identifier=u'8:1',
          FORMAT='MED',
          RESU=_F(NOM_CHAM=('SIGM_NOEU', 'SIEQ_NOEU', 'DEPL'),
                  RESULTAT=reslin),
          UNITE=80)

FIN()
```
関数を並列処理で実行する

一つの関数に引数をとって、引数の値によって並列処理させる方法は良い記事がたくさんでてきます。

[Pythonの並列処理・並行処理をしっかり調べてみた](https://qiita.com/simonritchie/items/1ce3914eb5444d2157ac)

ただ、開発する中で既に定義されている、引数を取らない複数の関数を並列処理する方法があまりでてこなかったので(ユースケースが少ないのかもひしれませんが)、まとめてみます


コードは[Github](https://github.com/mynkit/FunctionParallelProcessing)にもあがっています

今回並列処理にjoblibを用いているので、install済でない方はinstallしておきましょう

```sh
pip install joblib
```

まずは複数の関数をただ順番に実行していく関数の定義です。

```Python
def run_func(*funcs):
    [f() for f in funcs]
```

次に、この関数を並列処理させます。

```Python
from joblib import Parallel, delayed

def parallel_process_func(*target_funcs):
    Parallel(n_jobs=-1)([delayed(run_func)(func) for func in target_funcs])
```

n_jobsは同時処理数で、-1のときはできるだけマシンのコアを使って並列処理させます。たとえば3にすれば3並列処理となります。

以上で完了です。実際に動かしてみましょう。


```Python
def x():
    print('-- x() START --')
    [i for i in range(10000000)]
    print('-- x() END --')


def y():
    print('-- y() START --')
    [i for i in range(10000000)]
    print('-- y() END --')

parallel_process_func(x, y)
```

実行すると以下のような出力となるはずです。

```
-- x() START --
-- y() START --
-- x() END --
-- y() END --
```

並列処理されてますね。

定義したparallel_process_func関数に、関数名をただ渡していけばいいだけなので使い勝手も悪くなさそうです
初めて触るGraphQL

## この記事のターゲット

- GraphQLって聞いたことしかない
- ちょっと触ってみたい

## 環境
- macOS Mojave 10.14.5
- express ^4.17.1
- express-graphql ^0.9.0
- graphql ^14.6.0

## 下準備
1.node.jsを使うので手元にない場合はinstallしてください。

```
$ brew install node
```

2.プロジェクトのディレクトリを用意してください。npmからgraphqlなどをinstallするのでnpm initまで。

```
$ mkdir gql-sample
$ cd gql-sample
$ npm init
```

3.必要なパッケージをinstallします。
具体的には以下の3つ。

- graphql
- express
- express-graphql

```
$ npm install graphql express express-graphql -save
```

## 実践
下準備ができましたので早速GraphQLサーバーを立ててみましょう。
まずはサーバー側のJavaScriptを作ります。

```server.js
const express = require('express');
const express_graphql = require('express-graphql');
const { buildSchema } = require('graphql');
// GraphQL schema
const schema = buildSchema(`
 type Query {
    hello: String
 }
`);
// Root resolver
const root = {
    hello: () => 'world!'
};
// Create an express server and a GraphQL endpoint
const app = express();
app.use('/graphql', express_graphql({
 schema: schema,
 rootValue: root,
 graphiql: true
}));
app.listen(4000, () => console.log('GraphQL server running on localhost:4000/graphql'));
```

consoleからnodeを実行。

```
$ node server.js
```

うまくいっていればブラウザで以下を開くことで画面が出ているはずです。

```
localhost:4000/graphql
```

<img width="1679" alt="スクリーンショット 2020-02-13 9.01.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177043/9fb301be-ab1c-ec7d-ed3a-f4ac717bb299.png">

早速クエリを投げてみましょう。
画面の左側がクエリを書く場所で、右側が結果が表示される場所です。

左側に以下を入力して画面左上にある再生ボタンをクリック。

```
{
  hello
}
```

右側に結果が表示されれば成功です。

<img width="1680" alt="スクリーンショット 2020-02-13 12.47.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177043/738c6dae-4a31-3118-785e-3098c65947d3.png">


簡単にソースコードをみていきましょう。

ここでGraphQLサーバーが受け付けるクエリの形を宣言しています。
今回はStringで'hello'のみ受け付けるようになってます。
画面でhelloではなくworldなどをクエリに入れるとエラーが出るはずです。

```
// GraphQL schema
const schema = buildSchema(`
 type Query {
    hello: String
 }
`);
```

クエリを受け取って何を返すかが以下で宣言されてます。
今回はhelloというクエリがきたら文字列の'world!'を返すという単純なものです。

```
// Root resolver
const root = {
    hello: () => 'world!'
};
```

ちょっとだけ書き換えてみましょう。

```
function foo() {
    return 'hoge'
}
// Root resolver
const root = {
    hello: () => foo()
};
```

helloを受けたらfoo関数を実行するようにしてみました。
レスポンスは相変わらず文字列ですが、関数を呼び出せるならできることの幅が大きく広がりますね。

実行してhogeが取得できれば成功です。
RubyでルールのあるSortプログラムを作る

#はじめに
rubyでオリジナルのソートを作るためのメモ
JSONが入っているのは自分のローカルサーバで作りやすかったから

#コード
``` ruby:ruby.rb
require 'json'

$jsonfile = <<EOF
[{"id":643,"name":"7_to_7_3","tag":"ミットナイトレストラン7to703,胡桃ちの,漫画","created_at":"2018-12-02T11:30:34.013Z","updated_at":"2018-12-02T11:30:34.013Z"},
{"id":644,"name":"7_to_7_4","tag":"ミットナイトレストラン7to704,胡桃ちの,漫画","created_at":"2018-12-02T11:31:05.979Z","updated_at":"2018-12-02T11:31:05.979Z"},
{"id":641,"name":"7_to_7_10","tag":"ミットナイトレストラン7to710,胡桃ちの,漫画","created_at":"2018-11-29T12:01:43.992Z","updated_at":"2018-11-29T12:01:43.992Z"},
{"id":645,"name":"7_to_7_11","tag":"ミットナイトレストラン7to711,胡桃ちの,漫画","created_at":"2018-12-02T11:31:47.163Z","updated_at":"2018-12-02T11:31:47.163Z"}]
EOF

def num_kaiseki(str)
    output = []
    tmp = str
    num = str.rindex(/[0-9]/)
    out =""
    count = 0
    if (num !=nil)
        while(tmp[num-count])
            if (tmp[num-count]=="_")
            elsif (tmp[num-count].index(/[0-9]/)==nil)
                if(out[0]==".")
                    out = out[1..tmp.size]
                end
                break
            end
            if (tmp[num-count]=="_")
                out = "."+out
            else
                out = tmp[num-count]+out
            end
            count+=1
        end
    else
        num = tmp.size
    end
    output = [tmp[0..tmp.size-out.size-1] ,out.to_f]
end
def sort_jouken(a,b)
    t_a = num_kaiseki(a)
    t_b = num_kaiseki(b)
    if (t_a[0] == t_b[0])
        output = t_a[1]<=>t_b[1]
    else
        output = t_a[0]<=>t_b[0]
    end
    output
end

list = JSON.parse($jsonfile)
list.each do |word|
    p num_kaiseki(word["name"])
end
bb = list.sort { |a,b| sort_jouken(a["name"],b["name"]) }
bb.each do|word|
    print word["id"],":",word["name"],","
end
```

#不満点
小数点のルール条件めちゃくちゃだから、どうにかしないと
pythonでGeocoding

久しぶりにPythonのライブラリを試したので、備忘録として。
使ったのは`geopy`　と `geocoder`。
Google Colabを使ったのでpythonのversionは3です。
https://colab.research.google.com/drive/1LlQ2131p4JV3IY9xOyZcGp_Wg3fRk2p3

## インストール パッケージ

```console
$ pip install geopy geocoder
```

https://github.com/geopy/geopy
https://github.com/DenisCarriere/geocoder

## code geocoder
```python
import geocoder

my_location = geocoder.ip('me')
my_location.geojson
```
Colabで実行したので、orgがGoogleになっています。
西の方のアドレスが出てくるのかと思ったんですが、ちゃんと自動で物理的に近いサーバに繋がるようになっているっぽいです。
ちなみに、コードを実行した場所はNYのダウンタウンです。

```bash
{'features': [{'geometry': {'coordinates': [-74.006, 40.7143],
    'type': 'Point'},
   'properties': {'address': 'New York City, New York, US',
    'city': 'New York City',
    'country': 'US',
    'hostname': '169.205.229.35.bc.googleusercontent.com',
    'ip': '35.229.205.169',
    'lat': 40.7143,
    'lng': -74.006,
    'ok': True,
    'org': 'AS15169 Google LLC',
    'postal': '10004',
    'raw': {'city': 'New York City',
     'country': 'US',
     'hostname': '169.205.229.35.bc.googleusercontent.com',
     'ip': '35.229.205.169',
     'loc': '40.7143,-74.0060',
     'org': 'AS15169 Google LLC',
     'postal': '10004',
     'readme': 'https://ipinfo.io/missingauth',
     'region': 'New York',
     'timezone': 'America/New_York'},
    'state': 'New York',
    'status': 'OK'},
   'type': 'Feature'}],
 'type': 'FeatureCollection'}
```

```python
# 緯度経度
my_location.latlng

# 住所
my_location.address
```
住所は番地までは出てこないので、対応するデータの粒度が都市サイズとかだと、
ゴニョゴニョ簡単に出来そうです。

```bash
[40.7143, -74.006]
'New York City, New York, US'
```

## code geopy
```python
from geopy.geocoders import Nominatim
# locator作成
geolocator = Nominatim(user_agent="user", timeout=10)
location = geolocator.geocode('New York City, New York, US')
location.latitude, location.longitude
location = geolocator.reverse("40.7127281 -74.0060152")
location.address
```
比較のためにgeocoderが表示した住所を使ってみました。
geopyの方が細かく出るみたいです、Googleマップで見る限り、アドレスの精度は結構良さげです。
https://www.google.com/maps/place/40%C2%B042'45.8%22N+74%C2%B000'21.7%22W/@40.7127281,-74.0066803,18z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d40.7127281!4d-74.0060152

```bash
(40.7127281, -74.0060152)
'New York City Hall, 260, Broadway, Civic Center, Manhattan Community Board 1, Manhattan, New York County, New York, 10000, United States of America'
```

最後に東京タワーとタイムズスクウェアの距離を確認してみました。

```python
from geopy import distance

loc_tokyo = geolocator.geocode("Tokyo tower, Tokyo, Japan")
loc_times_square = geolocator.geocode("Times Square, Manhattan, NY")
src = (loc_tokyo.latitude, loc_tokyo.longitude)
dist = (loc_times_square.latitude, loc_times_square.longitude)
distance.distance(src, dist).km
distance.distance(src, dist).miles
```

簡単に出せました。ただ、loc_tokyoの住所を見たら、
'東京タワー, 東京タワー通り, 麻布, 南青山6, 港区, 東京都, 105-0011, 日本 (Japan)'という知らない住所になりました。
多分、lat & lon でちゃんと東京とNYの場所を設定するば、精度は上がるのだと思います。

```bash
10870.216621346974 # km
6754.439461884453 # mile
```
validates メソッドでユニーク制約を行うと ActiveRecord::RecordNotUnique ではなく、 ActiveRecord::RecordInvalid が raise される

# 概要
DBのユニーク制約だけを行なっていた状態から、ユニーク制約の validates メソッドを書いたときにエラーハンドリングで少しはまったので共有です。

# 解説

## DBのユニーク制約のみがかかっているとき

```ruby:user.rb
# == Schema Information
#
# Table name: users
#
#  id         :bigint(8)        not null, primary key
#  name      :string(255)      not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  index_users_on_name    (name) UNIQUE
#

class User < ApplicationRecord
end

```

`ActiveRecord::RecordNotUnique` が raise されます

```ruby:sample.rb
User.create!(name: 'Duplication')
User.create!(name: 'Duplication')

=> ActiveRecord::RecordNotUnique

```

## ユニーク制約の validates メソッドがあるとき

```ruby:user.rb
# == Schema Information
#
# Table name: users
#
#  id         :bigint(8)        not null, primary key
#  name      :string(255)      not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  index_users_on_name    (name) UNIQUE
#

class User < ApplicationRecord
  validates :name, uniqueness: true # 追加
end
```

`ActiveRecord::RecordInvalid` が raise されます

```ruby:sample.rb
User.create!(name: 'Duplication')
User.create!(name: 'Duplication')

=> ActiveRecord::RecordInvalid
```

## 注意点

例えば下記のようにユニーク制約に引っかかったときの例外処理を書いているコードがあるときは validates メソッドでユニーク制約をかけると `ActiveRecord::RecordNotUnique` ではキャッチできなくなるので注意です。

```ruby:sample.rb
begin
  User.create!(name: 'Duplication')
rescue ActiveRecord::RecordNotUnique
  head :conflict
end
```
Swift　基礎知識　1

#はじめに
現在、私はRubyを中心に学んでおります。
学習を進める中、他言語にも興味が沸いた為、Swiftに関して用語等を整理していたいと思いました。
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご教授願います。

#Swiftとは

- ネイティブアプリを開発するためのプログラミング言語
    - ネイティブアプリ　：　あるプラットフォームで直接動作するアプリのこと（スマホとかですね）


- 対象OS
    - MacOSとiOS
    - 上述の通り、iPhoneやiPadなどの端末で使えるアプリ、もしくはMacパソコン向けのアプリを開発することができる。


#今までのネイティブアプリ開発は？
- これまではObjective-Cが使われていた。（現在も使える様です）
- RubyやPHPなど最新の設計思想を盛り込んでいて、スクリプト言語のように簡単にアプリを開発することができる。



#特徴
- SwiftはXcodeを使って開発をする。
    - XcodeはApple IDがあれば無料でダウンロードすることができる。


勝手なイメージですが、敷居が高くなく、すぐに入り込めそうな感じがします。

#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
応用情報技術者試験　合格への道：ネットワーク:データ通信と制御

こちらを参考にしています。41問出題されています（2020/1/27現在）
https://www.ap-siken.com/index_te.html#10_2
※たぶん過去問が増えるごとに変更される

通信機器に関する問題が多く、具体的にどのような機械でどのような通信が行われているかを把握すると解ける問題が多い。


#■CSMA/CDに関する問題　8問

・複数の通信が同時に行われた場合は衝突を検出し、送信を中止してランダム時間待ってから再び送信をする
・その結果衝突の頻度が増すとスループットが下がる

ということを理解していればどの問題も解けます。

CSMA/CD（Carrier Sense Multiple Access with Collision Detection)　通常の有線LANです。
CSMA/CA（Carrier Sense Multiple Access/Collision Avoidance)　無線LAN

無線通信は信頼できる衝突検出の手段がないので、CSMA/CAは送信の前に待ち時間を毎回挿入することになる。

Detection：検出、Avoidance:回避

応用情報の問題は英語がわかっていると解ける子問題が結構あるので、積極的に英語も覚える

これが理解できていると「LANの制御方式に関する記述：H18秋期 問57」も解ける


#■レイヤ2スイッチ、スイッチングハブに関する問題　8問

・スイッチングハブとブリッジは同等の機能を持つ、MACアドレスで中継先を判断する

ということを理解していると解ける問題だけです。

「レイヤ2」とは「データリンク層」に属しMACアドレスで中継先を判断する形式。なのでLAN内でしか判別できないものと理解しておくとよい。


##・ポートVLAN
　→VLAN(Virtual LAN)。スイッチングハブ(レイヤ2スイッチ)に接続された端末をグループ化する機能、またはその機能で形成されたネットワーク。
　　複数のポートを論理的なグループにまとめ，グループ内だけの通信を可能にする。

「レイヤ3」は「ネットワーク層」に属す。ルータも「ネットワーク層」なのだがルータはソフトウェア的に処理をおこなうので、ASICと呼ばれる専用のハードウェアチップを用いる「レイヤ3」の方が速い。


#■OSI基本参照モデルに関する問題　4問

とりあえず「セション層」に関する問題が3問。

##・データの送受信管理をするところ

「ネットワーク層」に関する問題が1問。

##・エンドシステム間のデータ伝送を実現するために，ルーティングや中継などを行う。

を覚えておく。

OSI基本参照モデルに関しては全部覚えておいた方が良いと思うが、ここでは割愛します。


#■MACフレームとIPパケットに関する問題　3問

個人的に何度やっても間違えてしまう問題。

基本的に覚えておかなくてはいけないのは

・ルータの内側であればMACアドレスがわかれば、その機器に到達する。

・ルータの外側のMACアドレスがわからなくてもIPアドレスがわかっていればARPでMACアドレスを取得することができる

ルータに届けるためにはルータのMACアドレスを指定しないと届かない（ルータの内側の話なので）、接続先の機器に届けるためにIPを指定しないといけない、ルータの外側のMACアドレスに関してはARPに任せればよいという理解で回答する。


#■ルータの機能に関する問題　3問

・ルータは「ネットワーク層」で「ネットワーク同士を接続」し、通過するパケットのIPアドレスを見てパケットを最適な経路に転送する通信装置


#■LAN間接続装置に関する問題　2問

出題されている2問ともリピータを理解すれば解ける。

リピータは「物理層で相互に接続する」、「同種のセグメント間で信号を増幅する」ということを覚えておく。


#■プロキシ、フォワードプロキシに関する問題　2問

ネットワーク:ネットワーク方式 でも出題されています。
　→フォワードプロキシは自分のネットワーク内で動く、リバースプロキシは自分のネットワーク外で動く


#■1問ずつ出題されている問題

1問ずつ出題されている問題をすべて網羅するのは、費用対効果が低いかと思います。

とりあえず過去に出題されている問題について、理解しておくべき文言について記載しておきます。

##・ルーティングテーブル
　→個々のネットワークの宛先への経路の一覧を保持しているテーブル状のデータ構造。
　　IPアドレスをもとにネットワークをまとめて、アクセスを行いやすくしているものだと理解する。
　　テーブル内で複数合致するものがあるときはプレフィックス長が最も長い（IPが左側から一番同一である）ものを採用する

##・リンクアグリゲーション
　→複数の物理回線を論理的に1本に束ねる技術

##・IEEE802.3
　→「イーサネット」をベースにIEEEが標準化した規格
　　イーサネットでは、物理層およびデータリンク層を規定している。

##・バス型配線
　→バス形配線　同軸ケーブルなどの1本のケーブルに，全ノードが接続されている。
　　その他、スター型、リング型、ツリー型などがある。形状の説明と名前が一致していいるのでそれで覚える


##・パケット交換とフレームリレー方式
　→フレームリレー方式は、パケット交換方式の一種。フロー制御や再送制御などを簡略化することで伝送効率を向上させている。
　　簡略化しているから速いけど比較的に安定していない


##・コネクションレス型通信
　→データを一方的に送り付ける方式。
　　送信するすべてのパケットに，あて先を示す情報を付加する


##・データ伝送
　→無手順
　　　特定の制御手順をもたない伝送制御手順で信頼性・伝送効率ともに低い。
　　ベーシック手順
　　　文字列情報を伝送するための制御手順。
　　　テキストデータの文字列に変換することで、テキストデータ伝送用の手順を使用してバイナリデータを送ることが可能。
　　HDLC手順
　　　同期方式としてフラグ同期を採用することで任意のビットパターンを伝送できる高効率・高信頼性の伝送制御手順。
　　　CRCによる誤り検出機能を有している。

##・トークンリング方式のLAN
　→「トークン」と呼ばれる特殊なフレームを常時1つ巡回させ、これを受け取ったノードだけが送信を行うことで、フレームの衝突を回避する
　　データを送信するノードは，まず送信権を獲得しなければならない。


##・V.24
　→「データ端末装置」と、モデムなどの「データ回線終端装置」のインタフェースに関する規定

#■最後に

とりあえず過去問は調べましたが、全部を理解するのは難しいと思われます。

ここだけににこだわるよりも、全般的に勉強する方が点数は取りやすいでしょう。
GASでPardotのAPIを扱う方法

手順としては
① APIキーの取得をしてプロパティストアに保存
② ①で取得したAPIキーを使ってAPIをたたく

という手順になります。

APIキーは取得後60分間のみ有効なので注意が必要です。

下記のURLを参考にGASでコードを書くと下記の様になります。
https://developer.salesforce.com/docs/atlas.ja-jp.salesforce1api.meta/salesforce1api/pardot_authentication.htm


```JavaScript
  var email = ''; //Pardotで登録しているメールアドレス
  var password = ''; //Pardotで登録しているPW
  var user_key = ''; //設定からAPIユーザーキーを取得　※1
  
  // API取得用のURL
  var url = 'https://pi.pardot.com/api/login/version/4';
  
  var parameters = {
    method : 'post',
    payload : 'email='+email+'&password='+password+'&user_key='+user_key+'&format=json',
  };
  
  var response = UrlFetchApp.fetch(url,parameters);  
  var json = JSON.parse(response.getContentText());
  var api_key = json.api_key;
  
  var prop = PropertiesService.getScriptProperties();
  prop.setProperty('api_key', api_key);
}
```

　※1箇所のユーザーキーは
下記画像の「設定」の中の「私のプロファイル」から取得可能

![2020-02-16_10h37_58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/e7ecef96-2e31-51c1-84d7-2441f6d0b17e.jpeg)


```JavaScript

function getData() {
  
  //上記で取得したAPIキーをプロパティストアから取得
  var prop = PropertiesService.getScriptProperties();
  var api_key = prop.getProperty('api_key');
  var user_key = '';

  
  //URLを変更することによって取得したい情報を変更
  //http://developer.pardot.com/kb/api-version-4/campaigns/
  //例えばキャンペーン情報がほしい場合は{}をcampaignを入れる
  var url = "https://pi.pardot.com/api/{}/version/4/do/query";  
  
  var options = {
    method : 'post',
    payload : 'api_key=' + api_key + '&user_key=' + user_key + '&format=json'
  };
  
  var result = JSON.parse(UrlFetchApp.fetch(url, options).getContentText()).result;
  var total_results = result.total_results;　//返ってきたデータ数
  var resultArray = result.{};　//{}は上記で設定したURLと同じcampaignならcampaignを入れる
  
  var array = [];
  
  for(var i=0; i<resultArray.length; i++){
    array.push([]);
    array[i].push(resultArray[i].name);
  }
  
  Logger.log(array);

  var shtName = 'シート名';
  var sht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(shtName);
  sht.getRange(10,1,array.length,array[0].length).setValues(array);
}

```
Dockerで起動したJupyter Notebookでvimキーバインドを使う

# 概要
最近はデータサイエンスの勉強で統計学の本を読んでいるのですが、本を読んでいるだけだとなかなかイメージしにくいこともあるので、Jupyter Notebookを使って手元でコードを書きながらやりたいなと思いました。
Jupyter Notebookでコード書くならvimのキーバインドが使えないとテンションが上がらないのでvimが使えるようにしたいと思いましたが、多少ハマった部分などあったのでやり方をまとめました。

# 環境
||バージョン|
|:--|:--|
|Mac|10.15.3|
|Docker|19.03.4|
|docker-compose|1.24.1|

# 環境構築手順
Dockerfileとdocker-composeを使ってvimのキーバインドが使えるJupyter Notebookを起動します。
※以下ファイルはGitHubにもまとめているのでご参考ください。
https://github.com/hikarut/Jupyter-Notebook

##### 1. notebook保存用のディレクトリ作成
```
$ mkdir notebooks
```

##### 2. Dockerfileの作成

```dockerfile:Dockerfile
FROM jupyter/minimal-notebook:latest

USER root

RUN pip install jupyter_contrib_nbextensions && \
    jupyter contrib nbextension install --user && \
    git clone https://github.com/lambdalisue/jupyter-vim-binding /home/jovyan/.local/share/jupyter/nbextensions/vim_binding && \
    jupyter nbextension enable vim_binding/vim_binding

EXPOSE 10000
CMD ["bash"]
```
※`jupyter-vim-binding`レポジトリのクローン先はコマンドjupyterのpathと合わせる必要があります。(`jupyter --path`コマンドで確認出来ます)

##### 3. docker-compose.ymlの作成

```yml:docker-compose.yml
version: '3'
services:
  data-science:
    restart: always
    build: .
    container_name: 'data-science'
    ports:
      - "10000:10000"
    working_dir: '/root/'
    tty: true
    volumes:
      - ./notebooks:/root/notebooks/
```

##### 4. コンテナのビルド
```bash
$ docker-compose up -d --build
```

##### 5. コンテナにログイン
```bash
$ docker-compose exec data-science bash
```

##### 6. Jupyter Notebookの起動
```bash
/root# jupyter notebook --port 10000 --allow-root
```
表示される`http://127.0.0.1:10000/?token=xxxxxxxxxxxxxxxx`にアクセスします。

##### 7. VIM bindingのエクステンションを有効にする
デフォルトだとエクステンションの設定に`disable`にチェックが入っているのでチェックを外して有効にします。
<img width="1204" alt="スクリーンショット 2020-02-16 9.41.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110485/78a474d2-796b-cc24-795c-8088e57d2888.png">

これでnotebook上でvimが使えるようになります
<img width="1173" alt="スクリーンショット 2020-02-16 9.47.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110485/fda13e04-b8eb-cefe-997c-ecd9c0895a7d.png">

# 最後に
Jupyter Notebookでvimのキーバインドを使えるようにするやり方は結構まとまっていたのですが、色々試していたら以外とハマった部分もあったので自分なりにまとめてみました。
これで快適なNotebookが書けそうです！
(ただ今回はユーザーを全てrootにしちゃったのでその辺は変えた方が良いかもです。。)


##### 参考
* [Jupyter Notebook on Docker でvim_bindingを使う](https://www.social-impacts.net/2019/02/jupyter-notebook-on-docker-%E3%81%A7vim_binding%E3%82%92%E4%BD%BF%E3%81%86/)
* [Jupyter Notebook on DockerでVim keybindsを利用する](https://qiita.com/izumin5210/items/90adb4fd1f59d1aeaaa7)
* [JupyterNotebookにVimの力を加えると、光と闇が両方そなわり最強に見える](https://qiita.com/_snow_narcissus/items/80f81926707807ee9bf1)
コンフィグファイルをyamlじゃなくてpythonファイルで食わせる、という案

![n3215e416cf319a3a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491308/fe54ef1a-698e-a28f-c36f-51f4fdda2b7f.jpeg)


# ymlファイルでのコンフィグの入力

機械学習モデルの学習・推論時のコンフィグ情報の入力にはyamlファイルを使うのではないかと思います。

ただし個人的には、yamlでは変数が使えないのが歯がゆい点ですね。一応アンカーとエイリアスという変数っぽいものはあるのですが、それは行ごとの値の保持なので、例えば親ディレクトリが共通な時とかに部分的な共通点を保持できないです。

例えば、

```yaml
image: "/path/to/dataset_name/data_version/Images"
label: "/path/to/dataset_name/data_version/Csv"
```

を

```yaml
shared_dir = "/path/to/dataset_name/data_version/"

image: shared_dir + "Images"
label: shared_dir + "Csv"
```
みたいに書けないので、編集がしにくく、使いまわしがしにくいと感じるのです。

人によってはそういう時に、デフォルトのkeyとvalのプレースホルダだけ作っておいて、後はテンプレートジェネレータで動的に値を与えて所要のymlファイルを動的につくってそれをロードするかもしれないですね[^1]。私としては、処理の工程が1つ増えて面倒くさいと思ってしまうのです。

[^1]: yamlの例は知らないが、caffeのprototxtで見たことがある。背景としては、caffeのpython APIのsolver(optimizerに該当)クラスはsetterメソッドを持ってないので、パラメータはファイル経由で与えなければならないためだったと思う。


# pythonファイルでのコンフィグの入力
なので、pythonファイルを直接食わせる方法を取ったらいいんじゃないか、と思いつきました。ここでいう食わせるというのは`from config import cfg`とするのではなく、

pythonで書いたコンフィグファイル

```python:config.py
# config.py

path_root = '/path/to/'

cfg = {
    'key1': path_root + 'val1',
    'key2':path_root + 'val2',
    'some_number': 1+ 3,
}
```

を、

```python
import importlib

cfg_filepath = './config.py'
hoge = importlib.machinery.SourceFileLoader('hoge_module_name', cfg_filepath).load_module()
cfg = hoge.cfg

print(cfg)  # {'key1': '/path/to/val1', 'key2': '/path/to/val2', 'some_number': 4}
```
のように、ローダーにファイルパスで渡してコンフィグの中身を読むことを指してます。  
これなら、いちいちimport文でconfigのロード先を変えなくても、引数で読ませたいコンフィグファイルを切り替えることができます。また、式の評価とか、pythonで扱うオブジェクトが扱えます。
もちろんpython以外では使えないとかの欠点はあるのですが、変数によってコンフィグファイルがすっきりした感じになります。


# 本当に使える?
書いておいてなんですが、yamlにせよpythonファイルにせよ、コンフィグファイル中のパラメータを人が直接編集して実験って普通はやらない気がしてきました。
コマンドライン越しならば引数で変更したいパラメータだけ変えたり、あるいはAIプラットフォームのGUI越しに変えたり、そもそも実験はjupyterでやっていてパラメータはセルにまとめる(実行時yamlをログとして吐く)、みたいなケースが大半を占めてそうで、コンフィグファイルを直接いじる機会はほとんどないという印象です。  

本記事のようにpythonファイルの方法は使えるか、というと、「使うこともできるけど、別の与え方を考えた方がいい」というのが正直な所です。本記事の方法で有用なケースがあったら後日追記します。

読んでいただきありがとうございました。


# 参考文献
- [Python: モジュールを動的にロードする - CUBE SUGAR CONTAINER](https://blog.amedama.jp/entry/2016/01/28/000122)