OmniAICreator/Qiita-1.07M huggingface dataset:
Android app development: Kotlin WebView

Kotlin: 1.2.71
Android Studio: 3.2.1

#WebView
It's a view for showing webpage
Official information: https://developer.android.com/reference/android/webkit/WebView
##Before using
You must add internet permission on AndroidManifest.xml

```
<uses-permission android:name="android.permission.INTERNET" />
```
##Load webpage
Simply

```
webView.loadUrl("URL")
```
Layout (at least needed to show WebView on Fragment) :

```xml:webview_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragment.WebViewSampleFragment">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
```
Here is an example of loading **google.com**. (Customized with toolbar
![WebView Sample.jpg](https://qiita-image-store.s3.amazonaws.com/0/245077/54e8aaae-e130-5cd4-02f5-f6301d50afe8.jpeg)
##Set some options
Add the options you want to add.

```kotlin:WebViewSampleFragment.kt
webView.apply {
    settings.apply {
        javaScriptEnabled = true
        setSupportZoom(true)
        loadWithOverviewMode = true
        useWideViewPort = true
        domStorageEnabled = true
    }
    webChromeClient = WebChromeClient()
    webViewClient = WebViewClient()
}
```
Using **.apply** makes you and others easier to read the code.
##Control WebView
### Go Back

```
webView.goBack()
```
Also, you can check canGoBack by

```
webView.canGoBack()
```
### Go Forward

```
webView.goForward()
```
Also, you can check canGoForward by

```
webView.canGoForward()
```
###Reload

```
webView.reload()
```
##Handling WebView
###shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
This is a example of when a URL is about to be loaded in the current WebView.

```
webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
        view?.loadUrl(request?.url.toString())
        return true
    }
}
```
#Project:
Code: https://github.com/GalaxyDevGamer/Android-Samples/blob/master/app/src/main/java/galaxysoftware/androidsamples/fragment/WebViewSampleFragment.kt
Layout: https://github.com/GalaxyDevGamer/Android-Samples/blob/master/app/src/main/res/layout/webview_layout.xml
HTTPって結局なんなのか（HTTPのリクエストやレスポンスはTCP的にどう通信しているかっていう話）

# HTTPって結局なんなのか

## HTTPとは

プロトコルです。っていう答えが返ってくると思うのですが、、
リクエスト、レスポンスがあって、ヘッダがあって、ボディがあって、、まー、そういうのは知ってるんだけど通信的にどういうものなのかっていうところ。

## 答え

ただのTCPの電文です。

通信相手（HTTPサーバ）と接続した後にやりとりするTCPの電文を特定のフォーマット（HTTP）で送信（HTTPリクエスト）すると、相手がその内容に対応した応答（HTTPレスポンス）の電文を返している、っていうだけの話。

## 試してみる

試してみましょう。qiita.comの80番ポートに接続して手動で電文を送ってみます。

TCP通信するクライアントとして、teratermを使います。
※linux使ってる人はncコマンドで良いと思います。
※teratermをTCPクライアントとして使うのは↓の解説が分かりやすいです。
http://docs.olab.org/resource/teraterm.pdf

teratermでの接続時設定
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/299475/961225dd-d959-1cc4-e271-727727562dd1.png)

接続完了してもteraterm側で特に反応はないので、繋がっていると信じてそのまま↓の電文を手打ちで入力（=HTTPリクエスト）します。

```
GET / HTTP/1.1
Host: qiita.com
[空改行]
```

https://qiita.com へリダイレクトさせるための応答電文（=HTTPレスポンス）が返ってくるはず。
ここまでの一連の操作で、http://qiita.com:80 にGETのリクエストを投げてる、のとイコールになります。

ちなみにHTTPを無視した適当な電文を送信すると、400 BadRequest が返ってきます。
80ポートで接続待ちしているのはHTTPサーバなわけで、HTTPに従ってない電文が来ても処理できないって事ですね。

## つまり

GETだろうがPOSTだろうが、ファイルのアップロードだろうが、何なんだろうが、TCPの電文のやりとりをしているだけなのですね。
ということで、以上でした。

## 余談

考えを広げてみると、自分で独自に電文のフォーマットを規定して、その電文が来た時にパースして何かするようなものを作れば、独自プロトコルも自由に作れるってことですね。
Anaconda v5.3 Python3.7 verの導入に手こずったのでメモ

# 追記 (2019/07/25)
新しいバージョンのAnacondaでは,正式にPowershellに対応したとのことです.
より詳しく知りたい方はこちらの記事で確認してください.詳しく解説されています.
･ 参考リンク 
[Anaconda がやっと PowerShell に公式対応した](https://qiita.com/yniji/items/668f805a72a6ced6a2bd)

普通にインストールして,スタートメニューのAnaconda3 (64-bit)>Anaconda Powershell Promptでconda環境がPowershell上で起動します.
そして,以下のコマンドを叩く

``` shell
> conda init powershell
```
すると,通常のPowershell上でもconda環境が使えるようになります.(Powershell起動時,conda環境が起動するようにスクリプトが生成される)

ただし,**conda環境を起動する前に**pythonコマンドを叩いてしまうと,numpyをimportできないみたいです.
<font color='Red'>**先にconda環境を起動してから**</font>pythonコマンドを叩きましょう.


# 前提
普通にAnacondaをインストールして下記のようにpathを通した

```
C:\Users\hoge\Anaconda3
C:\Users\hoge\Anaconda3\Scripts
```

# 発生した問題
Anaconda Prompt上ではnumpyをimportできるのに
PowerShell上ではimportできない問題
(PowerShellを使う理由は特にないけど,なんとなく使ってみたかった)

[環境]
OS : Windows10_1803
Anaconda v5.3 python3.7


# Traceback
```
PS C:\Users\hoge> python
Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda custom (64-bit) on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
Traceback (most recent call last):
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\core\__init__.py", line 16, in <module>
    from . import multiarray
ImportError: DLL load failed: 指定されたモジュールが見つかりません。

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\__init__.py", line 142, in <module>
    from . import add_newdocs
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\add_newdocs.py", line 13, in <module>
    from numpy.lib import add_newdoc
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\lib\__init__.py", line 8, in <module>
    from .type_check import *
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\lib\type_check.py", line 11, in <module>
    import numpy.core.numeric as _nx
  File "C:\Users\hoge\Anaconda3\lib\site-packages\numpy\core\__init__.py", line 26, in <module>
    raise ImportError(msg)
ImportError:
Importing the multiarray numpy extension module failed.  Most
likely you are trying to import a failed build of numpy.
If you're working with a numpy git repo, try `git clean -xdf` (removes all
files not under version control).  Otherwise reinstall numpy.

Original error was: DLL load failed: 指定されたモジュールが見つかりません。
```

ImportError: DLL load failed: 指定されたモジュールが見つかりません。

調べてみるとmklっていうdllが見つからないらしい.
Anaconda Prompt上ではdllは見つかるので単純にPathが通ってないってことになる.

dllの場所を調べた.

```
C:\Users\hoge\Anaconda3\Library\bin
```
ここにmklのdllがあった

# 解決
さっきのPathを環境変数に追加
結果,importできた.

# 最後に
以前のバージョンのAnacondaでインストールしたPython3.6環境では,今回のような問題は発生しなかったから,何かしらの原因があるんだろうけどよくわからなかった.
結果として問題なくimportできてるから,深くは考えないことにする.
Puppeteerのテンプレ

nodejsでスクレイピングするため [cheerio-httpcli](https://www.npmjs.com/package/cheerio-httpcli) を使ってたが、弾かれるサイトが出てきたので、
Headless Chromeでスクレイピングできる [Puppeteer](https://github.com/GoogleChrome/puppeteer) に乗り換えた。

先に感想を書くと、完璧にスクレイピングできた。
PWAページでも描画されるまで待ってくれるし、取れない値はなさそう。
今後はこのPuppeteerをメインにスクレイピングするので、テンプレとしてコードを残す。

## テンプレコード

qiitaのOrganization一覧から自社である「株式会社ゆめみ」の投稿数/いいね数を取得してみる。

ついでにコードでスクショも取ってみる。

```js
const puppeteer = require('puppeteer')

try {
  (async () => {
    const browser = await puppeteer.launch()
    const page = await browser.newPage()
    await page.goto("https://qiita.com/organizations/yumemi", { waitUntil: 'networkidle2' })  //表示されるまで待つ
    await page.screenshot({path: 'qiita_screenshot.png'}) //スクリーンショット撮影

    //投稿数
    const itemSelector1 = "body > div:nth-child(4) > div.organizationHeader > div > div > div > div.col-sm-3 > div > div:nth-child(1) > div.organizationHeader_stats_value"
    var postsCount = await page.$eval(itemSelector1, item => item.textContent) //取得
    console.log(`投稿数:${postsCount}`)

    //いいね数
    const itemSelector2 = "body > div:nth-child(4) > div.organizationHeader > div > div > div > div.col-sm-3 > div > div:nth-child(2) > div.organizationHeader_stats_value"
    var thunbsUpCount = await page.$eval(itemSelector2, item => item.textContent) //取得
    console.log(`いいね:${thunbsUpCount}`)

    await browser.close() //後片付け
  })()
} catch (error) {
  console.error(error)
}
```
### 撮影したスクショ
`await page.screenshot({path: 'qiita_screenshot.png'})`で撮影した画像

![qiita_screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/52227/e3d50dbf-d5da-1670-485a-7a5de4d55e98.png)

ちゃんと撮れてる！

### 結果
```
投稿数: 1166
いいね: 31231
```

バッチリ取得できた！

## 資料リンク
- 公式ドキュメント
 - Puppeteer  https://pptr.dev/
- github
  - GoogleChrome/puppeteer: https://github.com/GoogleChrome/puppeteer
- examples
  - checkly/puppeteer-examples: https://puppeteersandbox.com
【GAS】スプレッドシートのシート移動・ソート

GAS公式ドキュメント
https://developers.google.com/apps-script/reference/

# 使い道
スプレッドシートのシート分けが多くなると、ソートや先頭に配置といったシートの移動処理がとても億劫になる これの回避策としてGASでシートの移動を行う

#考え方
シートの並び順の情報は、シート本体ではなく、スプレッドシート(ファイル)内のindex昇順という管理方法がなされている なので、使うクラスは「Sheet」ではなく「Spreadsheet」になる

#スクリプト実行時の注意点
理由が未だにわからないですが、スクリプト実行後、ソートの結果が見た目上反映されていないことがある ページの更新を行えば解決するのだが...
なぜだろう、同期のタイミング?

#サンプル
###今アクティブなシートを先頭に移動させる
```
/*
 * moveTop
 *  - 現在アクティブなシートを先頭に移動させる
 */
function moveTop()
{
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  spreadsheet.moveActiveSheet(1);
}
```

###▼五十音昇順にソート
```
/*
 * sort
 *  - シート名を元に昇順にソートする
 */
function sort()
{
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var all_sheet_list = spreadsheet.getSheets();
  var current_sheet = spreadsheet.getActiveSheet();
  var sort_info = {
    'sheet_list':{},
    'sheet_name_list':[]
  };

  try {
    for (var count = 0; count < all_sheet_list.length; count++) {
      var sheet_name = all_sheet_list[count].getName();      
      sort_info['sheet_list'][sheet_name] = all_sheet_list[count];
      sort_info['sheet_name_list'].push(sheet_name);
    }

    // シート名リストを昇順にソートする
    sort_info['sheet_name_list'].sort(function(a,b){
      a = a.toString().toLowerCase();
      b = b.toString().toLowerCase();
      if( a < b ) return -1;
      if( a > b ) return 1;
      return 0;
    });

    // 実際にソートする
    var set_index = 1;
    for (var sheet_count = 0; sheet_count < sort_info['sheet_name_list'].length; sheet_count++) {
      var sheet_name = sort_info['sheet_name_list'][sheet_count];
      var active_sheet = sort_info['sheet_list'][sheet_name];
      active_sheet.activate();

      spreadsheet.moveActiveSheet(set_index);
      set_index++;
    }

    // 関数実行時のシートに戻る
    current_sheet.activate();
    Browser.msgBox('正常終了。ページを更新してください。');
  } catch(e) {
    // エラーが発生した場合はその旨を表示してから処理中断
    Browser.msgBox(e.lineNumber + ':' + e);
  }
}
```
【GAS】メニューから作成した関数を実行させる

GAS公式ドキュメント
https://developers.google.com/apps-script/reference/

#使い道
GASで書いた処理をメニューにおいて、クリックすることで実行させるための処理

#サンプル
```
function onOpen(e){
    var func_array = [
        {name: "hogehoge関数", functionName: "func_hogehoge"}
    ];
    var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
    spreadsheet.addMenu("スクリプト", func_array);
}

function func_hogehoge() {
    // 処理
}
```
Lua5.3をVS2017でビルドするメモ

#手順
* https://www.lua.org/download.html からソースを落としてきて適当に展開する。
* 左上からファイル->新規作成->既存のコードからプロジェクトを作成
* 作成するプロジェクトの種類はもちろんVisual C++
* プロジェクトファイルの場所は展開したディレクトリ
* プロジェクト名はお好きにどうぞ
* プロジェクトのビルド方法はVisualStudioを利用する
* プロジェクトの種類はダイナミックリンクライブラリ(DLL)プロジェクト
* 完了を押したらSource Filesからlua.cとluac.cをクリアしてください
* プロジェクトのプロパティでC/C++->プリプロセッサ->プリプロセッサの定義が``<別のオプション>``になっていると思うので``LUA_BUILD_AS_DLL;<別のオプション>``みたいな感じにします。

#参考
https://qiita.com/gpsnmeajp/items/5ae55d8f79d129f7c62b
うざい侍エンジニア塾の記事をGoogleの検索結果から除外する

# README.md

ゴミ記事界隈の急先鋒たる「侍エンジニア塾」の記事をGoogleの検索結果から除外する方法です。

Chorome限定で「ゴシップサイトブロッカー」という拡張機能で検索結果からサイトを削除します。

侍エンジニア塾の記事をGoogleの検索結果から除外する
https://takap-tech.com/entry/2018/10/13/002107

勿論、このサイトに限らず、任意のサイトを自由にブロックできます。最近「Personal Blocklist」が機能しなくなり少々困っていました。しかし、代替機能を開発されている方がいらしたのでそのご紹介も兼ねています。

## こういったWebジャンクは積極的に通報しましょう

外注のライターに内容が薄い記事を大量生産してSEOをハックするWebスパムの手口なので、Googleの「[スパムレポートを送る](https://www.google.com/webmasters/tools/spamreport)」を使って通報しても良いと思います。
非同期通信　メッセージ送信　ajax

# 非同期通信で必要なもの

## ajax

1. データを飛ばすのに必要なもの
 パス,data,datatype, processData, contentType
2.  jsonに変換する
  jbuilder　
→　複数と一個の
1個

```
json.id @message.id
json.name @message.user.name
json.created_at @message.created_at.strftime('%Y/%m/%d %H:%M:%S')
json.content @message.content
json.image @message.image.url

```

複数

```
if @new_messages.present?
  json.messages @new_messages.each do |message|
  json.content       message.content
  json.image         message.image.url
  json.id            message.id
  json.name          message.user.name
  json.created_at  message.created_at
  end
end

```

## ``  記法　htmlを差し込む時に必要 

## form 

prop
https://www.sejuku.net/blog/36294#prop

disabled
https://qiita.com/pugiemonn/items/5db6fb8fd8a303406b17
Widgetをタップした時の動作の追加

MacbookProに搭載されているTouchBarをカスタマイズできるという噂の
Better Touch Toolを導入し、色々ボタンを追加している最中。
Widgetをタップした時の動作を追加できたのでメモ

#つまり
TouchBarの
<img width="1085" alt="Touch Barショット 2018-10-12 23.04.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/294938/3e8d6187-7601-7410-c6f8-478699986d81.png">
右から２番目の日付ボタンをタップしたら
こんな感じにGroupを表示したい！！
<img width="1085" alt="Touch Barショット 2018-10-12 23.54.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/294938/39df1377-87cb-a6e8-fd5f-f17b1c3caabc.png">

#設定してみる
私自身の設定
<img width="1126" alt="スクリーンショット 2018-10-12 23.17.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/294938/d04926b6-9f31-ed2d-d4f6-979761219cd6.png">

Date/Time Widgetをクリックし、
画面右下のPredenfined Actionの検索欄にGroupと入力したらありました。
<img width="1138" alt="スクリーンショット 2018-10-12 23.29.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/294938/c2feebfb-fe2a-05ad-9c75-4650ca7c7e54.png">

あとはGroupの名前を指定
<img width="1126" alt="スクリーンショット 2018-10-12 23.32.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/294938/602bbfd2-c713-cbc0-56d8-886989c40bee.png">


#あとがき
Predefined Actionを色々いじったらもっと色々できそうですね。
#参考文献

[お前らのTouch Barはダサい](https://qiita.com/2357gi/items/8235093de77aa3e5fecc)
大容量のDBに対するSELECT文のWHERE句でカラムに処理を加えると遅くなる。

例：前日のevent_idを1000件取得する

取得するDBのカラムに対して、処理しつつ取得すると遅くなります。
ついうっかりやってしまう書き方なので、備忘録として残したいと思います。

遅いSQL

```sql:遅いSQL
SELECT
  event_id
FROM
  events
WHERE
  DATE(event_datetime) = ADDDATE(CURRENT_DATE(), -1)
LIMIT 1000
;
```

実行時間：20分たっても返ってこないのであきらめました。

加工しない場合と比べると段違いの速度差です。。

```sql:早いSQL
SELECT
  event_id
FROM
  events
WHERE
  event_datetime
    BETWEEN
      ADDDATE(CURRENT_DATE(), -1)
    AND
      CURRENT_DATE() - INTERVAL 0.001 SECOND_MICROSECOND
LIMIT 1000
;
```

実行時間：約 0.012秒


~~参考：http://www.geocities.jp/mickindex/database/db_optimize.html#LocalLink-index~~
参考のリンク先、消えてました・・・。
php-master-changes 2018-10-12

今日は timelib の更新 ext/date のバグを直す修正があった！

# 2018-10-12
## derickr: Update news with further fixed bugs due to timelib upgrade
- https://github.com/php/php-src/commit/454a86c2c5b54837baab5bf4314c98b0f728eb70
- [7.3~]
- ext/date で、7.3 系で timelib を 2018.01alpha2 へアップグレードしたむねとそれで修正されたバグについて NEWS へ追記

## derickr: Upgrade timelib to 2017.08, to fix bug [#77007](https://bugs.php.net/bug.php?id=77007)
- https://github.com/php/php-src/commit/94a98f2c63926c5eafe12a717f3eef38f05fe99e
- [7.2~]
- ext/date で、7.2 系で timelib を 2017.08 へアップグレードし、そのむねとそれで修正されたバグについて NEWS へ追記
- 修正された #77007 は `\DateTime::diff()` で端数が正しくなかった問題

## derickr: Upgrade timelib to 2018.01RC1, to fix bug [#77007](https://bugs.php.net/bug.php?id=77007)
- https://github.com/php/php-src/commit/9c608bd13f780f822cd12c858f6ea271b9c7a3fb
- [7.3~]
- ext/date で、7.3 系で timelib を 2018.01RC1 へアップグレードし、そのむねとそれで修正されたバグについて NEWS へ追記
LaravelとPusher備忘録

## はじめに
LaravelとPusherでリアルタイム通信をしたいがために試行錯誤をした私への **備忘録** なのでリンク紹介＋αです。ご了承ください。

## Pusher設定
[Pusher Tutorial(Qiita)](https://qiita.com/sizukutamago/items/007c281670a17e09f74b)

注意点としては、js側の設定の際に
PusherのダッシュボードのGetting Startedタブにもあるとおり
clusterの指定が必要だということです。

難なくできたので満足。
LaravelでTwitterログインを実装する

# はじめに

Laravelでアニメの聖地の写真を共有するサイトを作ったのですが、サイトへのログインとしてTwitterログイン機能を利用したので方法を書いていきたいと思います。

作ったサイトは[こちら](https://www.holy-place-photo.com/)です。　

右上のログインから試せます。


# 前提

- Laravel version 5.6 
- Twitter Developerの登録済み

# Socialiteの設定

Twitterログインは[Socialite](https://readouble.com/laravel/5.6/ja/socialite.html)というライブラリを利用します。

まずはインストール。

```
composer require laravel/socialite
```

インストール後は`config/app.php`にprovidersとaliasの設定をします。

```php:config/app.php
'providers' => [ 
    Laravel\Socialite\SocialiteServiceProvider::class,
],
'aliases' => [
    'Socialite' => Laravel\Socialite\Facades\Socialite::class,
]
```

次に、`config/services.php`にTwitterのトークンなどを設定します。

値は適宜変更してください。

```php:config/services.php
"twitter" => [
    "client_id" => env("TWITTER_CLIENT_ID"),
    "client_secret" => env("TWITTER_CLIENT_SECRET"),
    "redirect" => env("CALLBACK_URL"),
]
```


```:.env
TWITTER_CLIENT_ID = TwitterのApi Key
TWITTER_CLIENT_SECRET = TwitterのAPI Secret Key
CALLBACK_URL = コールバックURL
```

# Laravel

設定が完了したら次はルーティングを実装していきます。

`routes/web.php`にログインURLとコールバックURLとログアウトURLを足します。

このコールバックURLは`config/services.php`で利用するコールバックURLと同じです。

```php:routes/web.php
// ログインURL
Route::get('auth/twitter', 'Auth\TwitterController@redirectToProvider');
// コールバックURL
Route::get('auth/twitter/callback', 'Auth\TwitterController@handleProviderCallback');
// ログアウトURL
Route::get('auth/twitter/logout', 'Auth\TwitterController@logout');
```

コントローラーはログイン、コールバック、ログアウトを実装します。

`Socialite::driver('twitter')->user();`で返ってくるオブジェクトはTwitterのアカウント名や、画像URLなどなどかなり多くの情報を持っています。

例で書いているのはLaravelの標準の[認証機能](https://readouble.com/laravel/5.6/ja/authentication.html)を使っています。

```php:TwitterController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Socialite;

class TwitterController extends Controller
{

    // ログイン
    public function redirectToProvider(){
        return Socialite::driver('twitter')->redirect();
    }

    // コールバック
    public function handleProviderCallback(){
        try {
            $twitterUser = Socialite::driver('twitter')->user();
        } catch (Exception $e) {
            return redirect('auth/twitter');
        }
        // 各自ログイン処理
        // 例
        // $user = User::where('auth_id', $twitterUser->id)->first();
        // if (!$user) {
        //     $user = User::create([
        //         'auth_id' => $twitterUser->id
        //   ]);
        // }
        // Auth::login($user);
        return redirect('/');
    }

    // ログアウト
    public function logout(Request $request)
    {
        // 各自ログアウト処理
        // 例
        // Auth::logout();
        return redirect('/');
    }
}

```

ビュー側は単純で、各URLに遷移させるだけで大丈夫です。

```html
<a href="/auth/twitter">ログイン</a>
<a href="/auth/twitter/logout">ログアウト</a>
```

# 終わりに

Twitter Developerの登録が英語で行う必要があり、そこに苦労したくらいで

Laravel側の実装は簡単でした。

SocialiteはTwitterの他にも、Facebook、LinkedIn、Google、GitHub、Bitbucketをサポートしているので、他のも試してみようと思います。
ESXi 6.5 ドライバのアップデート

#ドライバを更新する
##準備
- 仮想ホストはメンテナンスモードにする
- 仮想ホストはSSHサービス有効にする
- vibファイルを入手する
- vibファイルを任意のデータストアへコピーしておく

####現行バージョンの確認

```
# esxcli software vib list
Name                           Version                              Vendor  Acceptance Level  Install Date
-----------------------------  -----------------------------------  ------  ----------------  ------------
lsi-mr3                        6.910.18.00-1vmw.650.0.0.4564106     VMW     VMwareCertified   2018-11-01
```

####アップデートのリハーサルをする
要再起動とな。

````
# esxcli software vib update --dry-run -v /store/lsi-mr3-7.703.19.00-1OEM.650.0.0.4598673.x86_64.vib
Installation Result
   Message: Dryrun only, host not changed. The following installers will be applied: [BootBankInstaller]
   Reboot Required: true
   VIBs Installed: Avago_bootbank_lsi-mr3_7.703.19.00-1OEM.650.0.0.4598673
   VIBs Removed: VMW_bootbank_lsi-mr3_7.702.13.00-3vmw.650.2.50.8294253
   VIBs Skipped:
````

####アップデート本番

````
# esxcli software vib update -v /store/lsi-mr3-7.703.19.00-1OEM.650.0.0.4598673.x86_64.vib
Installation Result
   Message: The update completed successfully, but the system needs to be rebooted for the changes to be effective.
   Reboot Required: true
   VIBs Installed: Avago_bootbank_lsi-mr3_7.703.19.00-1OEM.650.0.0.4598673
   VIBs Removed: VMW_bootbank_lsi-mr3_7.702.13.00-3vmw.650.2.50.8294253
   VIBs Skipped:
```

####再起動する
※SSHサービスが無効になっているので再度Web Host Clientから有効にする。

```
# esxcli system shutdown reboot -r update-driver
```

####ドライバのバージョンを確認する

```
# esxcli software vib list
Name                           Version                              Vendor  Acceptance Level  Install Date
-----------------------------  -----------------------------------  ------  ----------------  ------------
lsi-mr3                        7.707.11.00-1OEM.650.0.0.4598673     Avago   VMwareCertified   2018-11-03                       7.703.19.00-1OEM.650.0.0.4598673     Avago   VMwareCertified   2018-11-01
```
【Vim重症患者に朗報】WebサイトのTextAreaの内容をターミナル上のVimで編集する方法

# Vim重症患者に朗報

一日の大半を **ターミナル** あるいは **Vim** で過ごす人は、徐々に指の動きがVimキーバインドで侵されていきます。

Vim使いは誰でもきっと以下のような症状に悩まされているはずです。

1. エクセルを使っていたら、いつの間にか *jjj* や *kkk* のような文字がセルに入力されていた
2. ブラウザで上下するときについつい *j* や *k* を入力してしまう
3. **Webサイトの入力フォーム上でVimキーバインドが使えずイライラする**

プライベートだけではなく、ビジネス上でもWebの入力フォームにコミュニケーション情報をプロットすることが多い近年、 **(3)** のイライラは少しつづ精神を蝕んでいきます。

これは良くない！ということでなんとかできないか改善してみました。


# GhostText

ぴったりなプラグインに出会う。

以下のようなシステム構成で、Chorme上に表示されている **TextArea** の内容を **ターミナル上のVim** で編集できる事がわかりました。

```

+-----------------------------+                       +----------------------------+
| GhostText(Chrome Extension) | =[localhost:4001]=> | ghost-text.vim(Vim Plugin) |
+-----------------------------+                       +----------------------------+

```


Chrome拡張である **GhostText** がサーバとなり、 Vimプラグインである **ghost-text.vim** と通信しあうことで **TextArea** を編集できるということ。

早速試してみた。


## 必要なもの

* Chrome
* Vim

*※自分は手元にMacしかなかったため試せていないが、WindowsやLinuxでも動くのではないでしょうか。*


## インストール

### GhostText(Chorme拡張)

[GhostText - Chrome Web Store](https://chrome.google.com/webstore/detail/ghosttext/godiecgffnchndlihlpaajjcplehddca) より、拡張をインストール

### ghost-text.vim(Vimプラグイン)

[GitHub - pandysong/ghost-text.vim: support for ghost-text in regular vim](https://github.com/pandysong/ghost-text.vim) より。

* [dein.vm](https://github.com/Shougo/dein.vim) を使っている場合は以下の１文を `.vimrc` に記載しておけばOK。
    * `call dein#add('pandysong/ghost-text.vim')`

### websockets(Python3)

[pandysong/ghost-text.vim](https://github.com/pandysong/ghost-text.vim) のページには、 **Python3** の **websockets** パッケージが必要、という記載もあるので、これもインストール。

```sh
$ python3 --version
Python 3.7.0

$  pip3 --version
pip 10.0.1 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)

$  pip3 install websockets
Requirement already satisfied: websockets in /usr/local/lib/python3.7/site-packages (6.0)

```

すでにインストールされていた。


### その他

* Vimのサポートにもいくつか制約があった。
    * `python3` がサポートされていること、
    * `channel` がサポートされていること、

```
% vim --version| grep -e python -e channel
+channel           +iconv             +packages          -toolbar
+comments          +libcall           -python            +viminfo
+conceal           +linebreak         +python3           +vreplace
```

幸い、いずれも要件を満たしていた。


## 使い方

![](https://github.com/GhostText/GhostText/raw/master/promo/demo.gif)

1. **Vim** を起動
2. ノーマルモード状態で `:GhostTextStart` と入力
3. **TextArea** が配置されているページをChromeで開く
4. **GhostText** 拡張アイコン（右上）を押す

これで、Vim上に **TextArea** 上の内容が表示される。編集するとWebページ上の **TextArea** の値もリアルタイムで変更される。
Microsoft Flowを使ってOutlookとGoogleカレンダーを同期させる


# はじめに

仕事でOutlookアカウントを使用するが、利便性を考慮すると、自分のプライベートのGoogleカレンダーに同期したい。
職場で用意されたアカウントだと、外部への共有権限がないようなことがあるが、Microsoft Flowを使って、同期を行う。

# 手順

## Outlook → Googleへの同期

1. Microsoft Flowにログインする(outlook側のアカウントで)
1. テンプレートタブから、「Outlook.comカレンダーからGoogleカレンダーへのイベント同期」を選択
1. 同期元(outlook)、同期先(google)の予定表のIDを指定して、フロー作成
1. 同期元で予定を追加等、更新を行うと、自動的に予定が転送される

なお、テンプレートを変えれば、GoogleカレンダーからOutlookへの同期も可能

## 注意点

参考リンクにもあるが、

- 同期元のカレンダーで予定を修正しないと、修正が相互に反映されない
- 更新がトリガーになって同期されるため、フローを作った時点で登録済みの予定は同期されない
 - 予定名を変えて更新した後戻せば一応同期できるが面倒
- 更新トリガーと同時に同期されるわけではなく、数分の間隔が空く


後は、技術的に可能であっても、職場の組織のセキュリティポリシー等には注意。


# 参考

- [Microsoft Flow を使って Outlook.com カレンダーと Google カレンダーを同期する](https://medium.com/%E6%9C%AC%E6%97%A5%E3%82%82%E3%81%94%E5%AE%89%E5%85%A8%E3%81%AB/microsoft-flow-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6-outlook-com-%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%81%A8-google-%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%82%92%E5%90%8C%E6%9C%9F%E3%81%99%E3%82%8B-d9c4ae92bf68)
Qiita初心者の感想

初めての<font color=red><b>Qiita</b></font>。

# 学んだこと
- 右上の![image.png](https://qiita-image-store.s3.amazonaws.com/0/309644/e3d37c0d-5b3a-7889-5b8b-62bccc2fbe50.png)で**Markdownの書き方**を見れるので忘れても安心。[<font color=#337ab7>もっと詳しく知りたい方はこちら</font>](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)に知りたい情報があるかもしれない。***折りたたみ***とか***引用***とか***3x2でテーブル自動補完***とか***数式***とか***注釈***[^1]とか***絵文字***:smile:とか`puts 'Qiita'//コードのインライン表示`とか。
- 外部へのリンクにrel="nofollow noopener" target="_blank"が自動的に付く。内部へのリンクには付かない。好きなrelを付けられないようだ。
- （ファイルではなく）画像をコピーして貼り付けると画像ファイルをqiita-image-store.s3.amazonaws.comに自動的に作成してくれる。適当なファイル名が付く。
- HTMLのfontタグで色付けできるがサイズ指定はできない。CSSは使えないようだ。
- Markdownのコードの挿入\`\`\`が良い。コードが自動的に色付けされて見やすくなる。コードを見せるのにいい。
- 編集リクエストが来ました:flushed:。「見出し(#)直下などの例外はありますが、基本的にコード記法には空行が必要です」だそうです。Markdown記法 チートシートに「コードブロック上下に空行を挿入しないと正しく表示されないことがあります」とあったので、空行を入れました。古いブラウザを使った場合ですかね。
- 編集画面で右側のスライドモードにチェックを付けるとスライドでも表示される。下書き保存後の画面ではスライドは表示されない。***---***で区切ることでスライドの次ページになる。この記事をスライドモードにしてみたが、文章が多いため見にくかった。

---

# コードの自動色付け
このようにコードが自動的に着色されて見やすくなる。

```javascript:test.js
function f() {
 console.log("test");
}
```

---

# 折りたたみ
折りたたみを自作するのが難しい。\<details\>\<summary\>タグで囲むだけで自動的に折りたたまれるのが簡単で良い。

<details><summary>サンプルコード</summary><div>

```rb
puts 'Hello, World'
```

</div></details>

---

# 気になったこと
- 編集モードで変更が自動保存されるが、編集のない版に戻す***簡単な***方法がない。差分タブを見ながら編集して戻すのが良い。初回投稿時は差分タブがなく、一度投稿してからの機能。
- ログアウトしてクッキー削除しても自動保存が残っているので、サーバーに保存されていると思われる。編集の途中内容が強制的にサーバーに保存されてQiitaの人に見られるかもしれないと思うと複雑な気分になる。
- Qiitaは、***プログラミングに関する知識を記録・共有するためのサービス***。編集モードの[「良い記事を書くには」タブ](https://help.qiita.com/ja/articles/qiita-article-guideline)の先に書かれていた。プログラムを簡単に示せると思ってユーザー登録したが、書きたい記事のテーマがプログラミングに関する知識かと言われると少しズレていたので再考中。プログラムを１つも示していない他の人の人気記事があったが、顔出し記名記事なので許されているのかもしれない。
- アップロードした画像を削除する方法がない。support@qiita.comで個別対応してくれるらしい。
- Qiitaは引用の表現方法を見直したほうがいい。はてなブログと比べて貧弱すぎる。ヘルプの「Markdown記法 チートシート」の説明も貧弱すぎる。URL、ツイッター、本の場合で出典をどのように書いたらいいかのサンプルを示すべき。

> 引用
>> 引用

[^1]: 注釈の例です。注釈はこのようになります。
プロンプトの表示を GitBash 風に改造する

## 前フリ
私がはじめて Git を使ったのは Windows の環境でした。基本的には [***gitk***](https://git-scm.com/docs/gitk) などの GUI は使わずにコマンドでの操作をメインに覚えました。そのときから私はずっと GitBash を使っており、私と git との歩みは常に傍に GitBash が居たと言っても過言ではありません。


ということで私は GitBash の配色や見た目にすっかり慣れてしまい、他の環境(Macでの作業時や、Linuxのサーバー作業)でも同じようなプロンプトで作業したいと考えるようになったわけです。そもそもデフォルトのプロンプトは個人的に見辛いというのもあります。

**■ GitBash 参考画像**
![2018-11-01_15h17_41.png](https://qiita-image-store.s3.amazonaws.com/0/70638/da1758ee-5e15-f720-8490-2937a77876c7.png)


やっぱこれですね。わたしはもうこれじゃなきゃだめな体になってしまったようです(；´Д`)ﾊｧﾊｧ

検索してみると、いろんな先人の方々がプロンプトの見た目をカスタムしている事例を見かけました。ただ、GitBash っぽい見た目をゴールにしている(奇特な)例は見た感じなかったので今回は改造例のひとつということで紹介したいとおもいます。

## Git 環境
以下の2つで検証済みです。どっちでもいけます。

1. MacBook(git version 2.19.0)
1. CentOS(6.x系)のサーバー(git version 1.8.3.1)

## 必要ファイルの準備
この2つを準備しましょう。

- git-completion.bash
- git-prompt.sh

Mac では Homebrew で git をインストールしている場合、一緒にダウンロードされるようです。
私の環境では下記にありましたので一度確認してみてください。

```sh
/usr/local/etc/bash_completion.d/git-prompt.sh
/usr/local/etc/bash_completion.d/git-completion.bash
```

もしなければネットにあるのでダウンロードしてきましょう。
保存場所は任意のフォルダでOKです。私は安直に自分のユーザー直下に落としましたｗ
一応ファイル名の頭に `.` をつけて隠しファイルにしておきます。

```sh:git-completion.bashのダウンロード
$ wget https://raw.github.com/git/git/master/contrib/completion/git-completion.bash -O .git-completion.bash
```

```sh:git-prompt.shのダウンロード
$ wget https://raw.github.com/git/git/master/contrib/completion/git-prompt.sh -O .git-prompt.sh
```

## 設定ファイルを変更
下記の記述を .git-prompt.sh と .git-completion.bash のパスを前項で取得したものに書き換えた上で、`.bash_profile` や `.bashrc` 等に追加してください。

```sh:.bash_profile(もしくは.bashrc等)
# prompt settings
source {%.git-prompt.sh のパス%}
source {%.git-completion.bash のパス%}
HOST='\u@\h'
PS1="\[\033]0;$HOST\007\]"     # set window title
PS1="$PS1"'\n'                 # new line
PS1="$PS1"'\[\033[32m\]'       # change color
PS1="$PS1"'\u@\h '             # user@host<space>
PS1="$PS1"'\[\033[33m\]'       # change color
PS1="$PS1"'\w'                 # current working directory
if test -z "$WINELOADERNOEXEC"
then
    PS1="$PS1"'\[\033[36m\]'
    PS1="$PS1"'$(__git_ps1)'   # bash function
fi
PS1="$PS1"'\[\033[0m\]'        # change color
PS1="$PS1"'\n'                 # new line
PS1="$PS1"'$ '                 # prompt: always $
```

設定のネタ元は Git for Windows インストール時に手元に出来た `C:\Program Files\Git\etc\bash.bashrc` の内容です。これをベースにちょこちょこ変えてます。

## 設定の反映
お使いのターミナルを起動しなおすか、`source` コマンドで設定を再読み込みしてください。


## 完成図
### before
![beforeMac.png](https://qiita-image-store.s3.amazonaws.com/0/70638/f8cd0a89-1540-9ee8-8c16-8c962d7bb7ef.png)

### after
![afterMac.png](https://qiita-image-store.s3.amazonaws.com/0/70638/68011416-e6b2-6646-d3e0-ba3b5d5fc29f.png)

**YESSS!!!**
ほぼ GitBash やん。控え目に言って最高かよ(自己満
ちなみに GitBash にはあった `MINGW64` の部分は特に必要なかったので移植する際にはプロンプトからカットしました。


以上です。よろしければパクって使ってやってください。


## 参考
- [Bashのプロンプト変更 - Qiita](https://qiita.com/amidaku/items/841d62335a03792424d5)
- [「Git補完をしらない」「git statusを1日100回は使う」そんなあなたに朗報【git-completionとgit-prompt】 - Qiita](https://qiita.com/varmil/items/9b0aeafa85975474e9b6)
- [プロンプトをカスタマイズしてgitブランチを表示する - Qiita](https://qiita.com/caad1229/items/6d71d84933c8a87af0c4)
Linuxを指定した時刻にshutdownする

環境はKali Linuxです。

```
$ shutdown [-h] HH:MM yyyy-mm-dd
```

例えば、2018年11月1日23時20分にshutdownしたい場合は、

```
$ shutdown -h 23:20 2018-11-01
```

となります。
秒以下の指定方法は学習中です。
rake task

## rake tast importantで呼び出す

```
Rake::Task[ファイル名].invoke

```

## rakeファイル

```
namespace :どのファイル do
  desc　"やる内容"
  task 　~~~　do
     puts "処理の始まりを通知"
    ここの中で処理 

  end
  end
end

```
Firestore exportによるバックアップの確認をして気づいたこと

Firestoreのexportを使ってデータのバックアップができるようになりましたが、実際にできるか確認した際に気づいたことを書きます。

※ export/import方法については[こちら](https://firebase.google.com/docs/firestore/manage-data/export-import#import_all_documents_from_an_export)になります。

## import実行後のドキュメントの状況

Firestore中のドキュメントに関して、export後の操作とimport後の状態は次の通りです。

| ドキュメントの種類 | import後の状態 |
|:-:|:-:|
| export後に修正したドキュメント  | export時の状態に戻る |
| export後に削除したドキュメント  | export時のものが復元される  |
| export後に追加したドキュメント  | そのまま残る  |

「import」になるのでexport後に追加されたドキュメントはそのまま残ります。

## Cloud FunctionsのonUpdateが発火する

importの際に、FirestoreをイベントトリガーにするCloud Functionsがいる場合は注意が必要です。

export後に修正されたドキュメントが、importによってexport前に戻る際に**onUpdateが発火します**。
しかし一方、export後に削除されたドキュメントが、importによって復元される際には**onCreateは発火しません**。

この理由は理解できていないのですが、自分の環境で確認した際はそのような振る舞いをしていました。

## collection-idsを指定した場合サブコレクションはexportされない(※追記あり)

collection-idsオプションを指定すると、特定のコレクションだけexportできるのですが、サブコレクションはexportされないようです。

例えば次のようにコマンドを打った場合、exportの対象はusersコレクション中のドキュメントが直接もつフィールドのみになります。もしusersのドキュメントにfollowersというサブコレクションがあった場合、followersは復元されません。

```bash
$ gcloud alpha firestore export gs://firestore-export --collection-ids='users'
$ gcloud alpha firestore import --collection-ids='users' gs://firestore-export/2018-11-01T00:00:00_00000/
```

ちなみにimportの際にcollection-idsを指定しないと`Missing input file`というエラーになってしまいました。
また、自分が試した限りではcollection-idsはトップにあるコレクションでないとimportできませんでした。

### 2020/4/25追記
collection-idsはcollection groupに対して行われるようです。なので、usersとは別にfollowersをexportすれば、サブコレクションも対応できそうです。

## exportでFirestore全体のバックアップを行うには

Firestoreの状態を完全に副作用なくexport時の状態にするには次のような手順になると思います。

- export/importはcollection-idsを指定せずに実行
- importは全データを削除してから実行

状況によってはcollection-ids指定してもいいですし、全データ削除せずにimportして大丈夫ですが、もし上の手順で行う場合は別環境でシミュレーションしてみた方がよさそうです。

## 最後に

まだFirestoreはベータですし、この辺りは振る舞いが変わる可能性が十分あると思いますので、Firestoreを導入する際にはバックアップ・リストアできるかテストしてみることをオススメします。
FCNというSemanticSegmentationで遊んでみた

# やりたいこと
最近、FCNというSemantic Segmentationを手軽に試せたので、遊んでみました。
そして、速度評価も行おうと思って、ちょっとしたラッパー（？）を作ってみた。

# 環境
1. Ubuntu 16.04.4 LTS
2. python 3(.7.0)
3. GPU : GeForce GTX 1070（メモリ： 8G）
4. カメラ付き PC(外付けでも大丈夫なはず）

# FCNの実行
まずは下記のページを見て、インストールおよび実行

https://github.com/wkentaro/fcn

実行するとモデルもダウンロードしてくれた上で、結果を出力してくれる
簡単、簡単！

# FCNラッパーの作成
githubのページ見ると、精度についてはまとめられているが、速度についてはなんも書いてない
(論文には書いているかもしれないが...)
あと、カメラからダイレクトに結果出力できたほうが楽しいし、速度も測れるのでやってみよう！

というので作ってみたのが以下

https://github.com/komorin0521/fcn_wrapper

1. pipで必要モジュールをインストール
2. configファイルにて、正しいモデルファイルのパスを設定
3. `01run_fcn_wrapper.sh` を実行

で、カメラがついていれば、動作するはず.

上記の環境では約3FPSでした。
また、GPUのメモリは2Gを少し超えるくらい(2061MiB)でした。
画像の出力結果は、イスとか人をちゃんと認識してくれていたので、githubに書いてあるように精度はけっこうよさげ。

# FCNの実装の流れとラッパーでの変更点
`fcn_infer.py`の流れとどこを変えたのかを少しだけ

`fcn_iner.py`の大まかな流れ
1. モデルをロード
2. skimageでファイル読み込み
3. inference
4. 画像保存

変更点は2と4で、2はcv2の機能でキャプチャした画像を3のインプットに変更
4は保存ではなくこれまたcv2の機能で、画面出力というように変更しました。


# 所感
darknet YOLOとかだと10FPS超えするので、ちょっと速度的には物足りない気をしてしまったが、
こんだけの精度で3FPSなら、けっこうすごいよなあ
中身をもう少し詳しく見てチューニングしたら早くなるかもなんで、時間があって興味が出たらやってみよう
serverless frameworkを触ってみた。～AWS編～

# きっかけ
Microsoftが提供するOpenHackという研修を受け、Serverless技術の手軽さが想像以上だったため。
研修はAzureでしたが、お仕事ではAWSなのでまずはLambdaから。

##serverlessを使ってみる。

研修時(Azure Functions)はVS Codeのアドインで開発しており、
Lambdaの場合は何が良いか探したらserverlessにたどり着きました。ほんと便利ですね。これ。

1. プロジェクト作成

以下の様なコマンドを実行すればプロジェクトフォルダを作ってくれます。

``` ruby:node.js版
serverless create -t aws-nodejs --path nodejs
```


``` ruby:Python版
serverless create -t aws-python3 --path lambda-python
```

ちなみに生成されるソースはこんな感じです。

``` ruby:handler.js版
'use strict';

module.exports.hello = async (event, context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  // Use this code if you don't use the http event with the LAMBDA-PROXY integration
  // return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};

```

２. デプロイ

以下コマンドでデプロイしてくれます。

``` 
serverless deploy
```

オプションを付けた方がFunctionだけデプロイするため早いそうな。慣れるまでは全部デプロイするで良いと思います。お値段変わらないし。

``` 
serverless deploy function -f Function名
```

注意点

以下コマンドでクレデンシャルを登録するのですが、システム環境変数に登録してある場合そちらの値が優先されます。
※リージョン情報は設定ファイルの内容が優先されます。

``` 
serverless config credentials --provider aws --key key --secret secret
```

IAMユーザにCloudFormationの権限が必要です。付けていないと以下のようなエラーが出ます。

``` 
  Serverless Error ---------------------------------------

  User: arn:aws:iam:::user/ is not authorized to perform: cloudformation:CreateStack on resource: arn:aws:cloudformation:us-east-1::stack//*

```

３. 試し実行

以下実行するだけでコンソール上に結果が出ます。

``` 
serverless invoke -f hello -l
```

想像より圧倒的にハードルが低かったです。

続く。
Ruby on RailsでのJavaScript等の適用範囲

## JavaScriptファイルやCSSファイルの適用範囲
デフォルトでは全てのviewに適用される。特定のコントローラ（に対応するview）に限定することも可能。
[参考：Railsガイドライン アセットパイプライン コントローラ固有のアセット](https://railsguides.jp/asset_pipeline.html#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E5%9B%BA%E6%9C%89%E3%81%AE%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88)

## ヘルパーの適用範囲
`/app/helpers/hoge_helper.rb`で定義したヘルパーは、デフォルトでは全てのviewに適用される。特定のディレクトリのviewに限定することも可能。
[参考：ヘルパを対応した名前空間のみで使えるようにする](https://qiita.com/rkosaka/items/4241f1ac286ece1d4572)
defaultを毎回生成する場合はコールバック関数として渡すという覚え書き

どうも、前回の記事後編をサボっている月歩人です。

今回はDjango使いがAPIを作成する場合に大人気のDjangoRestFlamework(移行DRF)について、
ちょっとハマってしまったが意外に調査に時間がかかった点をtipsとして記事にします。

---

条件は以下です。

* 特定のフィールドがUNIQUEである
* 特定のフィールドがPOSTされなかったらデフォルト値をuuidで入れたい
* APIエンドポイントは`api/test/`

サクッとサンプルプロジェクトを作成
---
尚、DRFの導入とurls.pyとsettings.py等の設定は省略します。

```python:api/models.py
from django.db import models


class TestModel(models.Model):
    code = models.UUIDField(unique=True)

    def __str__(self):
        return self.code
```

```python:api/views.py
from rest_framework import viewsets
from .models import TestModel
from .serializer import TestModelSerializer


class TestModelViewSet(viewsets.ModelViewSet):
    queryset = TestModel.objects.all()
    serializer_class = TestModelSerializer
```

```python:api/serializer.py
import uuid

from rest_framework import serializers

from .models import TestModel


class TestModelSerializer(serializers.ModelSerializer):
    code = serializers.UUIDField(default=uuid.uuid4())

    class Meta:
        model = TestModel
        fields = ('id', 'code')
```

はい、こんな感じです。
これでTestModelのCRUD APIができました。
DRFは神

しかし、感の良い方はお気づきでしょう。
このコードには致命的なバグがあります。

とりあえず動かす
---

```
$ python manage.py runserver
```

1. http://localhost:8000/api を開く
<img width="1236" alt="スクリーンショット 2018-11-01 22.22.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/129996/9de6337a-6f68-4711-1ee4-dfea36c61894.png">
1. Contentを空にしてPOSTする
<img width="1282" alt="スクリーンショット 2018-11-01 22.24.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/129996/2f79dda5-8d1e-4332-27f9-45cd6f311677.png">
uuidで入っているので問題なさそうに見える。
そう、問題ないと思っていた時期が私にもありました。
1. Contentを空にして2回目のPOST
<img width="1404" alt="スクリーンショット 2018-11-01 22.26.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/129996/b0d283ed-f764-c6b2-bcc4-f1056cf73d45.png">


そうです。
2回目はUNIQUEエラーになってしまうのです。
1回目はできたのに…

原因
---
```python:api/serializer.py
...
code = serializers.UUIDField(default=uuid.uuid4())
...
```
`uuid.uuid4()`という記述をしてしまうことで、`runserver`時点でuuidが生成されてデフォルトとして設定されてしまった。
なのでこの場合は内部的に

```python:api/serializer.py
...
code = serializers.UUIDField(default='492e32fc-dce5-4ac7-b13d-0b3af0236f75')
...
```
という動作になってしまっていたのです。
生成するたびにuuid作成すると思う人私以外にもいると思う(いてください)

対策
---
uuid.uuid4をコールバック関数として渡す

```python:api/serializer.py
...
code = serializers.UUIDField(default=uuid.uuid4)
...
```
こうすることで、`runserver`時点でcodeのdefaultは`uuid.uuid4`というコールバック関数を持つ為、
空で登録する際にコールバック関数が走り、uuidが生成されるので一件落着ということだ。

<img width="1281" alt="スクリーンショット 2018-11-01 22.34.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/129996/404b65cc-1505-8ee4-3f06-b234531222cd.png">

---

「知っているようで知らなかった部分」、「Documentにひっそり書かれている事を飛ばしてしまいハマった」という問題はエンジニアあるあるだと思う。
スリープ解除後にvagrantでドメイン名が解決出来ない場合の対応

# はじめに

Windows10上で動作させているvagrantにて、長時間スリープからの復帰後にドメイン名が解決出来ない状態になることが多発した。

# 環境

Windows10
VatualBox
Vagrant
CentOS 7

# 対応方法

デフォルトでは下記のようにVatualBoxのキャッシュDNSサーバー(10.0.2.3)が指定されているので、Google Public DNS(8.8.8.8)等の別なDNSサーバーに変更する。

```conf:/etc/resolv.conf
# Generated by NetworkManager
# nameserver 10.0.2.3
nameserver 8.8.8.8
```

変更後は特にサービスの再起動等をしなくても事象が改善した。
MacでWindowsを立ち上げてIEの表示確認をしてみる

## はじめに

Webサービスを開発していると表示確認をすることがあります。
Macで開発しているとChromeやFirefox、Safari等のブラウザでの表示確認は行いますが、IEやEdgeでの表示確認は疎かになったりします。
その原因としては、手元にWindows環境がないこと。
しかし、IEやEdgeを使用するユーザは少なくないので、表示が崩れていたらユーザビリティに影響が出てしまいます。
こうした状況を踏まえて、手軽にIEやEdgeの表示確認が可能な環境を用意しておいた方がいいだろうなと思い、この記事を書いています。

## ツール
* Mac
* VirtualBox
* Vagrant

## インストール
まずは必要なツールをインストールしていきます。

### VirtualBox
こちらからダウンロードしてインストールします。
https://www.virtualbox.org/wiki/Downloads

### Vagrant
こちらからダウンロードしてインストールします。
https://www.vagrantup.com/downloads.html

### WindowsOS
こちらからダウンロードします。
https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/

お好きなマシンを選択してください。
この記事では"MSEdge on Win10 (x64) Stable (17.17134)"を選択します。

<img width="731" alt="スクリーンショット 2018-11-01 21.18.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/fbda5c0e-c2a7-0e51-84e1-346ee0be4ee6.png">

今回はプラットフォームとして"vagrant"を選択します。

<img width="700" alt="スクリーンショット 2018-11-01 21.19.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/d1faf72f-9264-7ac0-84e0-d2f70a6a7e01.png">

zipファイルをダウンロードして、ファイルを開く際は公式ページで紹介されている

<img width="676" alt="スクリーンショット 2018-11-01 21.42.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/3756e069-24fb-f52c-77b5-419cc1fd955f.png">

こちらの解凍ツールを使用します。
https://theunarchiver.com/

<img width="682" alt="スクリーンショット 2018-11-01 21.51.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/c8be7832-be37-843b-4e78-54e415bcb9ca.png">


解凍して得られたファイルを扱いやすいようにリネームします。

```
// リネーム前
MSEdge - Win10.box

// リネーム後
MSEdgeWin10.box
```

そして、boxを登録します。

```
$ vagrant box add path/to/MSEdgeWin10.box --name MSEdgeWin10
```

## 設定
これでツールは用意できましたので、設定ファイルを用意していきます。

### Vagrantfile
こちらがVagrantfileのサンプルです。

```
Vagrant.configure("2") do |config|
  # VirtualBox の設定
  config.vm.provider "virtualbox" do |vb|
    vb.gui = true
    vb.memory = "2048"
  end

  # 使う Vagrant Box 名
  config.vm.box = "MSEdgeWin10"

  # ゲストの OS を指定しておかないとマウント設定などがうまく行かない
  config.vm.guest = "windows"

  # ユーザ名
  config.ssh.username = "IEUser"

  # パスワード
  config.ssh.password = "Passw0rd!"

  # ゲストに SSH 鍵を配置しない (false)
  config.ssh.insert_key = false

  # SSH ログインシェルを変更しておく
  config.ssh.shell = 'sh -l'

  # Windows に sudo の概念がないので空白に直しておく
  config.ssh.sudo_command = ''

  # 共有フォルダ (以下の設定だと無効)
  config.vm.synced_folder ".", "/vagrant", disabled: true
  # 有効にするには以下に書き換える (後述)
  # config.vm.synced_folder "./vagrant", "c:\\vagrant"
end
```
参考：[Vagrant で Mac 上に Windows の仮想環境を構築する](http://neos21.hatenablog.com/entry/2018/03/18/080000)

## 起動

```
$ vagrant up
```

コマンド実行後、しばらくするとWindowsが立ち上がります。

<img width="1176" alt="スクリーンショット 2018-11-01 21.38.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/dba10e00-1e24-088a-bf3c-b9e7dd49e1d4.png">


うまく立ち上がらない場合は、以下のコマンドで再起動してみましょう。

```
$ vagrant reload
```

<img width="1084" alt="スクリーンショット 2018-11-01 21.40.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/97975/a979b5b6-032a-8106-598a-dbdbc34f3e93.png">


これでIE、Edgeでの表示確認ができるようになりましたね。

## シャットダウン
GUIで操作してシャットダウンすることも可能ですが、
以下のコマンドでシャットダウンすることも可能です。

```
$ vagrant halt
```

## まとめ
思っていたよりも簡単にMacにWindows環境を用意することができました。
これでIEやEdgeで表示確認する敷居も下がりますね。
C++でコンパイル時合成数和

[合成数列の和 Advent Calendar](https://qiita.com/advent-calendar/2018/composite-number)へ参加するにあたって、普段使っている言語は先に取られていることも多かったので、数分間悩んだ結果として「100個しかないなら、C++でコンパイル時に処理してやろう」という結論に達しました。

## コンパイル時に処理させるには

C++の特徴として、「コンパイル時に、ソースコードで指示した形の処理を行わせる」ことが可能だという点があります。その方法にもいくつかあります。

### プリプロセッサ

`#define`や`#include`などのディレクティブを書いて、ソースコードを文字列的に置き換えていく手法です。C言語からの伝統があること、トークンを書き換えるなどC++の文法の枠外のことも可能となるなどのメリットもありますが、あくまで文字列置換なので、数値計算すら面倒です。

### テンプレートメタプログラミング

C++で入ったテンプレートを利用して、テンプレートの定義を変数の宣言、分岐は特殊化、のように解釈すれば関数型言語として、チューリング完全なプログラミングが可能となります。ただ、コードは冗長になるし、通常のC++と考え方が大きく違うプログラミングとなります。

### `constexpr`

これはC++11から入った、比較的新しい機能ですが、関数や変数などを`constexpr`と宣言することでコンパイル時実行が可能となります。少し気をつければ、ふつうのC++で書いたコードをコンパイル時実行できてしまいます。

今回は、`constexpr`で配列を作り出すことで、すべての演算をコンパイル時に解決してしまうことにしました。

## `constexpr`なコードを書いていく

### 素数の判定

C++11の`constexpr`関数は「`return 式;`の一文しか書けない」という制約があったので、「条件分岐は`? :`で書く」「ループは再帰で表現する」といった特殊な書き方が必要だったのですが、C++14では大幅に制約が緩和され、ローカル変数やループを使うなど、（引数とローカル変数以外では`constexpr`なものしか使えない点を除けば）ほとんど普通の関数として書けるようになっています。

```C++
constexpr bool isPrime(int num) {
  for(int i = 2; i * i <= num; ++i) {
    if(num % i == 0) return false;
  }
  return true;
}
```

見てのとおり、`constexpr`を付けていることを除けば、ごく一般的な関数と何ら変わりません。なお、`constexpr`関数はコンパイル時専用というわけではなく、実行時に使うことも可能です。

### 配列を作る

配列がファーストクラスでないC++という事情もあって、`constexpr`な配列を直接作ることはできない…のですが、C言語時代に「配列は代入できないけど、配列を含んだ構造体はコピーできた」のと同様、配列を含んだ`constexpr`な構造体やクラスを作ることは可能です。

C++11では、`constexpr`なクラスのコンストラクタには何も書けなかったのですが[^1]、C++14では`constexpr`関数と同程度のものが書けるようになっています。では、「合成数の和を入れた配列」を含む`constexpr`な構造体を作ります。配列の要素数はテンプレートにすることで、定数式を供給できる形となります。

```C++
template<int N> struct Syntheses {
  int ary[N];
  constexpr Syntheses() : ary() {
    int num = 6, i = 1;
    // 最初1回だけ事前に片付ける
    ary[0] = 4;
    while(i < N) {
      ary[i] = ary[i - 1] + num++;
      i++;
      while(isPrime(num)) num++;      
    }
  }
};
```

### 出来上がった定数式を使う

あとは、この`Syntheses`を`constexpr`な変数に割り当てれば、コンパイル時に生成するテーブルの一丁上がりです。入出力を付ければ完成です。

```C++
int main()
{
    constexpr auto syntheses = Syntheses<100>();
    int i;
    std::cin >> i;
    std::cout << syntheses.ary[i - 1] << std::endl;
}
```

と、9割ぐらいは普段どおりのC++コードを書いているだけで、計算をコンパイラに任せることができました。

[Wandboxでの実装結果](https://wandbox.org/permlink/XprxxSIX1neCnUCp)


[^1]: メンバの初期化にはメンバイニシャライザを使っていました。
第40話 ペル方程式

この記事は[仮面ライダービルドの数式](https://qiita.com/izmktr/items/e26a624e79bce3edccc9)の第40話です。

```math
\arg\min_y
[𝑥^2 − 77𝑦^2 = 1] = 40
```

ペル方程式と呼ばれる式です。

```math
x^2 − 77y^2 = 1
```

これは、x=351,y=40 が最小の答えになります。

```math
x^2 − ny^2 = 1
```

この式はn が平方数でなければ、必ずx=1,y=0 以外の整数解が存在します。
そして答えは無限にあるのですが、最小の数さえわかってしまえば残りの数は計算できます。

n=2 の場合でみてみます。

```math
x^2 − 2y^2 = 1
```
この最小の答えはx=3,y=2 です。これに対して次の計算をします。

```math
(3 + 2\sqrt{2})^2= 17 + 12\sqrt{2}
```

ですから、x=17,y=12 も答えになります。
このように、$x + y\sqrt{n}$のべき乗を計算することで、すべての答えを導くことが出来ます。

しかし、最小の答えを見つけるのはちょっと厄介です。
$\sqrt{n}$を連分数展開という、分数で表す方法を使います。

```math
\sqrt{2}=1+\frac{1}{2 + \frac{1}{2+\frac{1}{2 + \dots}}}
```

これを1,2,2,2…の部分を取り出し、1,(2)とまとめます。
そして、漸化式を使って求めるのですが、この辺の仕組みは一旦おいておきます。

この数は突然大きくなる事があって、100 以下の数だとn=61 のときにx,y の数が大
きな数になります。
前後なんかはそんなに大きい数ではないですから、このへんは不思議に見えます。
crkbd組んでて、ビルドで少しつまづいたのでメモ


https://github.com/foostan/crkbd/blob/master/corne-cherry/doc/buildguide_jp.md
上記URLの通りにキーボードを組んでいて、動作確認をしようとした時に、ビルドでエラーが出たのでメモ。

```
avrdude: ERROR: address 0x800412 out of range at line 1742 of .build/crkbd_rev1_default.hex
```
久しぶりではんだ付けは酷かったけれど、見た感じそれで起きているエラーという感じではない。

ググってみると、
http://s-sef.hateblo.jp/entry/2018/08/18/015534
ここで書かれてるトラブルを全て、踏み歩いていた・・・
macOSの人は気をつけたほうが良さそう。


原因としては、avr-gccのインストールは時間がかかるが、初回インストール時にネットワークが一時寸断されて、一度失敗した。
それで何度か入れ直したりしたのだけれど、古いものを更新するのはよろしくないらしい。
ということで、一度綺麗にしてから入れ直し、最新のものをリンクさせるようにした

```
brew rm avr-gcc
brew install avr-gcc@7
brew link avr-gcc@7
```

これをやった結果

```
avrdude: erasing chip
avrdude: reading input file ".build/crkbd_rev1_default.hex"
avrdude: input file .build/crkbd_rev1_default.hex auto detected as Intel Hex
avrdude: writing flash (27992 bytes):

Writing | ################################################## | 100% 2.18s

avrdude: 27992 bytes of flash written
avrdude: verifying flash memory against .build/crkbd_rev1_default.hex:
avrdude: load data flash data from input file .build/crkbd_rev1_default.hex:
avrdude: input file .build/crkbd_rev1_default.hex auto detected as Intel Hex
avrdude: input file .build/crkbd_rev1_default.hex contains 27992 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.28s

avrdude: verifying ...
avrdude: 27992 bytes of flash verified

avrdude: safemode: Fuses OK (E:FB, H:D8, L:FF)

avrdude done.  Thank you.
```

無事ビルドが完了し、キーも反応した。
みんな教えて！！スクラムアンチパターン / 聴講メモ

## ■はじめに
これは、2018/10/26のイベント、[みんな教えて！！スクラムアンチパターン](https://agile-hiyoko-club.connpass.com/event/100104/)についてのメモです。
(雑目ですm(_ _)m)

スクラムに向き合っていて、うまくいかなくて困っていることや、うまくカイゼンしたことについて、いろいろな方の意見を聞きたくて参加しました。

参加者30人くらい。2割くらいの方がスクラム経験1年以上だったかな。。
スタートアップ系の方が多い感じ。スーツな方は1,2名ｗ

[公開資料](https://agile-hiyoko-club.connpass.com/event/100104/presentation/)は、現在、LT3つのうちの1つのものと、発表の1つのものがあります。

* 発表: 僕が踏んだ！目撃した！スクラムチームの失敗とその効果
* LT2: Daily Scrum Anti-Patterns

以下は、LT1,2と発表のメモになります。
純粋に、ひっかったワードをリストしているだけに近いです。
(雑目ですm(_ _)m)

---
## ■LT
### ■■LT1: CSD Retrospective 認定スクラムデベロッパー研修を受けての振り返り
* 研修は、5日間を1スプリントとしたもの
* 前提、ルール
	* TDD
	* ペアプロ
	* コードに責任をもつこと
* 言語
	* Java
* Why TDD
	* ブラジリアの話
* 経験にみる設計力
* アーキテクチャは最初に検討してはいけない 未知だから
* TDD cucamber ド発表: what, when, then
* コードを書く我慢(テストコードを考える1st)

### ■■LT2: Daily Scrum Anti-Patterns
* Rush Hour
	* どんなこと?
		* 柔軟にずれる
		* ルーティン大事
* Fase to Fase
	* どんなこと?
		* 集中していない
		* 顔を見てない
	* 問題点
		* __
	* カイゼン策
		* ランダム
		* 前に出す
	* 用いて良い場合
		* 基本的
* Share For Share
	* どんなこと?
		* 共有のための共有
		* ふーん
	* カイゼン策
		* アクショナブルでない共有は止める

### ■■LT3: 前任から引き継いだカンバンを割れ窓にしてまい、少しずつ直した話
* __

---
## ■発表
### ■■僕が踏んだ!目撃した!スクラムチームの失敗例とその効果
* 前提
	* 受託開発
	* 3年目
	* 40人くらい、半分がスクラムチーム所属
	* スクラムと、ぽいチーム
* アンチパターンs
	* ビックバンスタート
		* はじめてをいろいろ
	* 視界2メートル
		* PBL見積を数スプリント先までしかやってない
		* 外からの信頼
	* リモートの人
		* フルリモート
		* 情報格差、仕事をふる結果に、差別っぽくなる
	* スピード最優先
		* とにかく要望と期限に答えようとする
		* 品質落として、障害対応、結局遅くなる
	* スーパースター
		* スゴイエンジニア
		* 神みたいになる、その人まかせ
		* 思考停止
		* 抜けてもらう
	* ステルス弾
		* バックログに入れずやっちゃう
		* 事故る
	* 明日の天気
		* ベロシティが上がる前提で計画する
		* 希望的観測
		* 不安は脳内糖分を消費
	* 最後のふりかえり
		* チームは解散
		* 継続しないプロジェクト
	* 3つの帽子
		* PO,SM,Dev兼任
		* ボトルネック
	* ファシレイヤー
		* スクラムマスターが熱くなって、時間超過、しかも着地しない
	* まとめ
		* よく勉強、コーチ呼ぶ、そのまま適用
		* フレームワークは全部そろってフレームワーク
		* 1こだけ選ぶとしたら、最低限、ふりかえり

---
## ■お悩み相談会
※イベントの最初に、みんなで個別に付箋に書き出した、アンチパターンや、相談事を共有し、各島ごとにフリーディスカッション

* ストーリーポイント上下
* タスク管理、入れてくれない
* ポイント見積、基準がそろわない
* WBS作っちゃう
* マルチタスク
* 時間労働(≠裁量労働)、気分があがらない
* トップダウン
* スプリント期間が変わる(1週間、2週間。。)
* 本だけ読んで始めちゃう
* クロスファンクショナル失敗、必要なスキルが無い
* WF感覚で、テスト後回し
* 上司が理解が無い、リスクが高いから、人追加できない
* あちこちから人を集めて、兼務、営業にいっちゃうとか
* 開発以外の部分がアジャイルじゃない
	* スクラムで3ヵ月で終わった、半年経営会議、のこり顧客調整
* ストーリー説明時、QAのログ残してない、あとで分からなくなる
* フライング、PBL、スプリント外のものを追記
* スプリントレビュー直前でバグ、始められない
* ベロシティを活用できていない、定量化できていない
* イベントを全部ムリしてやろうとする
* スクラムマスターが熱くなる問題

---
## ■ディスカッション結果
※お悩み相談会の結果発表。話題にしたテーマなど

* スクラム、組織の活性
* デザイナー、エンジニアのバックログ一緒に?
* 差し込みがの優先順位?こまるよね
* 準委任で受けたら、発注元にSM、会社から梯子外し
* クロスファンクショナルとコンポーネント
* ペアプロ
* 協力会社が多い場合、時間労働のモチベーション
* ためになった本

---
## ■ふりかえり・次回テーマ極め!
* 気づいたこと、学んだこと
	* CSD
	* アーキ設計
	* FM
	* モチベーションアップ
* 試せそうなアイデア
	* CSD
	* モチベーションアップ
* 次のテーマ案(※行頭の数字は、多数決の結果)
	* 12: チームのモチベーション
	* 5: QA
	* 3: 運用
	* 3: スプリントで終わらせきるには
	* 4: 開発環境
	* 1: 明日から使えるTips
* 次のテーマ決定!
	* [スクラムにおける開発チームのモチベーションの上げ方とは？](https://agile-hiyoko-club.connpass.com/event/106389/)

---
## ■私感:まとめ
* CSDを知った。これに取り組むとSMの負荷が下げられそう!
* 「アーキテクチャは最初に検討してはいけない 未知だから」ということについて掘り下げて考えてみたい
* 「フレームワークは全部そろってフレームワーク」というのは、使えるセリフ
* 「チームのモチベーションが上がらない」＝低エンゲージメントな状況には、悩んでいるので、次のテーマに(多数決だけど)選ばれたのはラッキー!!