OmniAICreator/Qiita-1.07M huggingface dataset:
人から認められるエンジニアの仕事術。

春ですね。
新人エンジニアの皆さん、新しい環境はどうですか？楽しいですか？

つらいですか？

同僚や上司、取引先とうまくコミュニケーションが取れずに、悩んでいませんか？
皆通る道なので、大丈夫です。

とはいえ、つらいことは早く終わらせたいですよね。

まだまだ未熟なぼくですが、それでも社会に出て10年が経ちました。
10年間、いろいろな人達と仕事してきました。

この10年で見えてきた、「人から認められるコツ」ってのを、エンジニア目線で書いてみようと思います。

少しでも、あなたの人生のお役に立てれば、これ幸いです。

## 「自分は頑張ってる！」だけでは、認められない。
仕事は結果がすべてです。結果なき過程は、誰にも認められません。
なので、「頑張っていること」だけを評価してもらうのは、諦めましょう。

夜遅くまでコーディングしていても、締め切りに遅れたら、評価は0です。
下手すると、マイナスです。

他人は、自分が思っている以上に、自分のことを見ていません。
何かしらの「結果」が出たとき、初めて他人は、その人の「過程」に注目するものなのです。

あ、家族や友人、恋人は見てくれるかもしれませんよ？
でも、それは仕事ではないのです。

ところで、「結果」とは、なんでしょう？

仕事で「結果」というと、「売上」とか「業績」っぽいですよね。
でも、新人にそんな「結果」を出すことは、なかなか難しいと思います。

じゃあ、別の「結果」を出して、認めてもらいましょう。

## 相手が欲しいものを与える
相手がほしいものを提供すれば、相手はよろこびますよね。
それが、「結果」です。

「売上」も「業績」も、実は同じです。
会社がほしいものは、「売上」や「業績」ですよね。
だから、会社がほしいそれらを提供できた人は、評価され、認められます。

相手が欲しいものを、想像しましょう。
忖度しましょう。

同僚や上司、取引先は、あなたに何を求めていますか？
相手が欲しい電話・メール・資料を、相手が欲しい内容で、相手が欲しいときに提供しましょう。

「新人は、元気が一番だ！」なんて上司がいたら、大きな声で挨拶するだけで、それは「結果」になります。

エンジニアでいえば、たとえば、なにか技術的なミスが発生してしまったとき。
以下の2名に、状況説明のメールを出すとします。

- コードが読める上司
- コードがわからないクライアント

コードが読める上司には、再発防止のために、技術的な詳細を説明するべきでしょう。

でも、コードがわからないクライアントに、サーバーの設定や、使っているライブラリのバージョンを伝えても、混乱してしまう可能性が高そうです。

まずは誠意をもって謝罪して、技術的な説明は抽象度をあえて高めにし、復旧までのスケジュールを詳細に伝えたほうが、安心してくれるかもしれません。

## すぐには認められない
結果をひとつ、ふたつ出したところで、残念ながらすぐには認められません。

ぼくは、仕事はポイント制だと思っています。

結果を出せば出すほど、お仕事ポイントが溜まります。
逆に、ミスをすると、お仕事ポイントが減ります。

たくさんお仕事ポイントを持っている人は、たくさん結果を出した人なので、認められます。
失敗しても、たくさんポイントを持っているので、すぐには信用を失いません。

ちなみに、お仕事ポイントが少ない新人がミスしたとき、誰が不足分のお仕事ポイントを支払っているかがわかると、ポイントが溜まりやすくなります。

## 大切なのは想像力
当たり前ですが、同じ思考回路や感情をもつ人間は存在しません。
また、同じ人間でも、環境によって考えることは変わります。

明るい人、暗い人、偉そうな人、腰が低い人、うるさい人、静かな人。
眠いとき、満腹のとき、元気なとき、落ち込んでるとき、寒い時、イライラしてるとき。

その時々で、想定される事象を、想像できる限り出してみてください。
その中から、相手が一番欲しがるものを、提供してください。
「こうしたら、こうなる？」の数だけ、強くなれます。

強い人は、結果がでます。
結果が出ると、認められます。

## まとめ
- 過程は評価されない。結果がすべて。
- 相手が欲しいものを与える。
- お仕事ポイントを貯める。
- 「こうしたら、こうなる？」をたくさん出す。

## おまけ「自分の意見を通すエンジニアの仕事術」
基本は、「10我慢して、1通す」です。
我慢の数は、お仕事ポイントが増えると、減ります。
JavaScript入門してみて印象的だったこと

# はじめに
最近JavaScriptを勉強し始めたばかりですが、勉強していて個人的に印象的だっとことを復習がてらまとめます。
言語機能的な視点がメインになってる。

完全に入門者ですので間違っていることもあると思いますし、まだまだ知らないこともたくさんあるのでいろいろ教えてください。

普段はC++書いてる人です。

# セミコロンがなくてもいいらしい
ある程度はセミコロンがなくても自動的に判断してくれるらしい

```JavaScript:sample.js
    var  a = 0      //OK
    var  b = 1;     //OK
```
JS界隈の主流がわかりませんが、自分は怖いからセミコロンをつけておきたいと感じた

# undefined

```JavaScript:sample.js
    var  a;//初期化されていない(未定義値)
    console.log(a);//undefined
```
初期化されていない変数など未定義値にはそれ専用のものが用意されているようだ

###おまけ

同様にInfinity,NaN,nullとかがあるそう
# ===,!==演算子

初見で何者かと思うやつ

```JavaScript:sample.js
    var a = 1;
    var b = '1';

    console.log(a == b);    //true
    console.log(a === b);   //false
```

データ型も等しいかチェックしたい時は===や!==を使う

むしろ1 =='1'がtrueな事に驚いた

### おまけ
```JavaScript:sample.js
    console.log(null == undefined);    //true
    console.log(null === undefined);   //false
```

# for in

```JavaScript:sample.js

    var hoge = { a: 1, b: 2, c: 3 };
    
    for (var paramName in hoge)
    {
        console.log(paramName,hoge[paramName]);
    }
```

```:output
a 1
b 2
c 3
```
オブジェクトがもつメンバ変数の名前を取得できるイメージ
operator[]でその値へのアクセスができる
### class版
```js:sample.js

        class Hoge
        {
            constructor() 
            {
                this.a = 1;
                this.b = 2;
                this.c = 3;
            }
        };
        var hoge = new Hoge();

        for (var paramName in hoge) 
        {
            console.log(paramName,hoge[paramName]);
        }
```

#Arrayが便利

```js:sample.js
    [1, 2, 3]
        .map(value => value * 2)
        .forEach((value, index) => { console.log(index, value); });
```
便利そう(小並感)

### おまけ
範囲ベースforはfor ofになる

```js:sample.js
    var ar = [1, 2, 3];

    for (var elm of ar) 
    {
        console.log(elm);
    }
```

# ブロックスコープがない

```js:sample.js
    {
        var hoge = 1;
        var hoge = 2;
    }
    console.log(hoge);//2
```
変数の再宣言をしていたりスコープから外れてしまったり
こういったコードは問題なく通ってしまう

```js:sample.js
    {
        let hoge = 1;
        //let hoge = 2; error
    }
    //console.log(hoge); error
```
varではなく**let**にすればブロックスコープを実現できる
JSに不慣れな自分は基本letにすれば良いのでは？って思った

# classにアクセス指定子はない

privateとかpublicとかがないそうだ
解決策は調べるといろいろでてくる

~~そもそも昔はclass構文もなくfunctionでそれっぽいことしてたようで驚いた~~

# operatorオーバーロードはできない？
C++が好きな人はこれができると嬉しい（しらんけど）

# まとめ
完全な入門者の視点で印象的だったことをまとめた

入門者なのでいろいろ教えてください
まだまだ勉強途中なので続編はでるかも

Haskellを勉強すればJSとH勉強してるって言える
Homebrew + nodebrewでNode.jsをインストール

# 概要
Homebrew + nodebrew でNode.jsをPCにインストールする。

- Homebrewとは・・・macOS用パッケージマネージャー。
- nodebrewとは・・・Node.jsのバージョン管理用パッケージ。

## 環境
- macOS High Sierra
- バージョン 10.13.4

## 手順1. Homebrewをインストールする
```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
参考：https://brew.sh/index_ja

## 手順2. nodebrewをインストールする
### curlでインストール

```
$ curl -L git.io/nodebrew | perl - setup
```

### .bash_profileにPATHを追加する

```
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
```

### .bash_profileの変更を反映させる
```
$ source ~/.bash_profile
```

### インストールされたか確認する
```
$ nodebrew help #ヘルプ表示
```
参考：https://github.com/hokaccha/nodebrew#install

## 手順3. Node.jsをインストールする
### 現在インストールできるバージョンのリストを表示するコマンド
```
$ nodebrew ls-all
```

### バージョンを指定してインストールする
```
$ nodebrew install <version>
```
もしくは

```
$ nodebrew install-binary stable #安定版
$ nodebrew install-binary latest #最新版
```
## その他
### バージョンを切り替えるコマンド
```
$ nodebrew use <version>
```

もしくは

```
$ nodebrew use stable #安定版
$ nodebrew use latest #最新版
```

### バージョンを確認するコマンド
```
$ node -v
```

### npm(Node Package Manager)も自動で入っている。

```
$ npm -v #npmのバージョン
```
Fakerのダミーデータの漢字名とカナ名を一致させる

Fakerを使ってダミー個人情報を作ろうとすると、それぞれの項目がランダムで生成されるので、

```python

from faker import Factory

fac = Factory.create('ja_JP')
print(fac.first_name())
print(fac.first_kana_name())

```

```
康弘
リカ
```

となり、漢字名と、カナ名が一致しない。



なので、形態素解析ライブラリのjanomeを使って、漢字の読みをカナ名として使用する。

```python

from faker import Factory
from janome.tokenizer import Tokenizer

fac = Factory.create('ja_JP')
first_name = fac.first_name()
print(first_name)
tk = Tokenizer()
tokens = tk.tokenize(first_name)
for token in tokens:
    print(token.reading, end="")

```

これで、

```
篤司
アツシ
```

となるので良かったと思ったら、

```
陽子
ヨウシ
```
のように、間違ってはないけどちょっと惜しいケースや

```
裕太
ヒロシフトシ
```
のように、裕がヒロシで、太がフトシと判断されるケースが出てしまう

下記の事例にあるように、人名辞書を用意して読み込ませれば、もうちょっとまともな結果が出るかと思うけど、
[フリガナを自動入力する](https://qiita.com/kawasima/items/bf51e30d0e8c2e8103d6)

ダミーデータなので、そこまで精度は求めていないしなぁということで、とりあえずここまで。

あとは、下記の様なダミー情報データを生成するサービスからデータをダウンロードして、それをランダムで抽出するという手も。
https://hogehoge.tk/personal/

```python

import pandas as pd
import random

df = pd.read_csv('personal_infomation.csv') # https://hogehoge.tk/personal/ からダウンロードしたcsvを読み込み
no = random.randint(0, len(df)-1) # ランダムで行番号を取得
name = df.iloc[no, 1] # 2列目 氏名
kana_name = df.iloc[no, 2] # 3列目 氏名（カタカナ）
print(name)
print(kana_name)

```


```

戸塚和香
トツカワカ

```
mysql バックアップ/復元（エクスポート/インポート）

# csv エクスポート
`mysqldump -u root -p -t {database} > backup_db.sql`

# csvをテーブルごとに分割
`csplit backup_db.sql '/DROP TABLE IF EXISTS/' {*}`

# 復元したいテーブルのcsv検索
`grep -il 'create table `{database}`' ./xx*`

# テーブル復元
`mysql -u root -p {database} < xx0N`;
XUbuntu：ウィンドウを左右に2分割するショートカット


# 環境
* XUbuntu 16.04 LTS


# やりたいこと
XUbuntuで、ウィンドウを左右に2分割したいです。
Windowsで、`Win+Left` or `Win+Right`を押したときのような動きです。

# 実現方法
デフォルトでショートカットキーが割り当てられていないので、ウィンドウマネージャで設定しました。

設定→ウィンドウマネージャ→「キーボード」タブ

![Inkedxubuntu_windowmanager_shortcut2_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/37903/9ba8ea5e-4109-df05-4d45-a7bc325be906.jpeg)

私は、以下のショートカットキーを割り当てました。

* ウィンドウを画面上にタイル表示：`Super+Top`
* ウィンドウを画面下にタイル表示：`Super+Bottom`
* ウィンドウを画面左にタイル表示：`Super+Left`
* ウィンドウを画面右にタイル表示：`Super+Right`


「ウィンドウを画面左上にタイル表示」などに割り当てるショートカットキーは、考え中です。

Windows10では`Win+Left`、`Win+Top`の順に押すと、ウィンドウが左上に配置されます。
XUbuntuも同様の動きになって欲しいのですが。。。難しそうですね。
Windowsのコマンド画面カスタマイズ

# 概要
Windows のコマンド画面のフォントと色を見やすく設定します．フォントや背景色の設定は完全に私の好みなので，適宜自分の好きな設定に変えてください．

対象のコマンド画面は，PowerShell と Bash on Ubuntu on Windows の2つです．

# 詳細
## 前提
PowerShell と Bash on Ubuntu on Windows を導入済みの Windows 10

## 手順
### ColorTool の導入
[公式ページ](https://blogs.msdn.microsoft.com/commandline/2017/08/11/introducing-the-windows-console-colortool/)の [release of colortool here as a .zip] リンクから，ビルド済みファイルをダウンロードします．ダウンロードしたファイルは，解凍してPC上の好きな場所に設置しておきます．

Windowsキー + Pause で [システム情報] を表示し，[システムの詳細設定] → [環境変数] と進み，先ほど解凍したファイル中の **colortool.exe の親フォルダ** をユーザ変数の [Path] に追加します．

### Cica フォントの導入
[Cica](https://github.com/miiton/Cica/releases) をダウンロードしインストールします．Ubuntu のフォントに日本語フォントを追加して作成されているフォントです．

### PowerShell での設定
PowerShell を起動し，以下コマンドにより，現在の実行環境での色パレットを変更します．
```
PS> colortool campbell
```
タイトルバーを右クリックして [プロパティ] を選択し，[画面の色] タブを表示します．並んでいる色が標準のものから変化しているはずです．

続けて，画面の背景を **(1, 36, 86)**（PowerShell の既定の背景色）に設定し，さらに，[フォント] タブでフォントに **[Cica]** を選び，最後に [OK] をクリックします．

### Bash on Ubuntu on Windows での設定
PowerShell での設定と同様の操作を Bash on Ubuntu 上で実施します．ただし，画面の背景は **(48, 9, 36)** に設定します（Ubuntu のターミナルの背景色）．

# 参考
- https://qiita.com/Maxfield_Walker/items/25caf517f9ffd80b6574
【Google Chrome】Chrome に保存されている cookies の確認方法

Chrome に保存されている cookies は、下記の手順で確認することができます。
※ Chrome バージョン: 65.0.3325.181（Official Build） （64 ビット）

■ 詳細手順
１．Chrome 画面右上 [Google Chrome の設定] のアイコン＞[設定] の順にクリック
２．[詳細設定] をクリック
３．[プライバシーとセキュリティ] のセクションにて、[コンテンツの設定] をクリック
４．[Cookie] をクリック
５．[すべて Cookie とサイトデータを表示] をクリック

例えば、flask で書いた Web App をローカル環境で実行する場合は、中にセットされた cookies は、
ドメイン [127.0.0.1] にてその詳細を確認できます。
Swift5でUILabelのフォントやフォントサイズを変更する方法

#フォントを変更する場合
カスタムフォントを使用する場合。

```swift
label.font = UIFont(name:"fontname", size: 20.0)
```

システムフォントを使用する場合。

```swift
label.font = UIFont.systemFont(ofSize: 20.0) 
label.font = UIFont.boldSystemFont(ofSize: 20.0)
label.font = UIFont.italicSystemFont(ofSize: 20.0)
```

フォントサイズを変更したくないときは```label.font.pointSize```でフォントサイズを取得できます。

#フォントサイズのみ変更する場合
```swift
label.font = label.font.withSize(20)
```
＊笑顔の作り方＊プログラミングで作る？


　プログラミングって、どんなものがあるの？
現代の日本には、なんでもできたものが溢れています。　
お惣菜を見ても手間をかけなくてもデパートで売っています。
　お寿司もプログラミングされたマシンででてきます。

　プログラミングって何？　と聞き返す人がまだ多数派です。
そこで、　プログラミングを、初心者のぶつかる壁＝ユニークな方法で、色々試してみながら、楽しいことをしましょう。　　
　プログラミングの壁＝あなたのために、そっと伝える
概念や型＆箱にとらわれない自由な発想で、いろいろなことを試しちゃおう。
　ストレス問題解決の笑顔プログラミング、　
内緒のチアプログラミング（チアプロミー:チアラのお話）
　:white_sun_small_cloud:楽しい笑顔を作りましょう。　
![IMG_1154.jpg](https://qiita-image-store.s3.amazonaws.com/0/248242/348e50c3-f170-21c2-af2d-07ffceb9a1d4.jpeg)

:blush:

＊＊追記：　この続きのプログラミング開発を続けています。
【AWS：S3】他アカウントIAMロールからのアクセス許可

#アカウントAのIAMロールからアカウントBのS3へアクセス

EC2等から他AWSアカウントの所有するS3に対しファイルの配置や取得等のアクセスを行いたい場合は
以下の手順でアクセスを許可したいEC2にアタッチしているIAMロールとS3のバケットポリシーに許可を与えます。
1. アカウントAのIAMロールにアタッチされているIAMポリシーへのS3アクセス許可
2. アカウントBのS3バケットポリシーにアカウントAのIAMロールからのアクセス許可



## 1. アカウントAのIAMロールにアタッチされているIAMポリシーへのS3アクセス許可

~~~
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::[アカウントBのS3バケット名]"
            ]
        }
    ]
}

~~~

## 2. アカウントBのS3バケットポリシーにアカウントAのIAMロールからのアクセス許可

~~~
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Example",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[アカウントAのアカウント]:role/[アカウントAのIAMロール名]"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::[アカウントBのS3バケット名]/*",
                "arn:aws:s3:::[アカウントBのS3バケット名]"
            ]
        }
    ]
}

~~~
有理数を小数に、小数を有理数に(循環小数wolframalphaとsympy)


(参考)有理数を小数に、小数を有理数に
https://qiita.com/swordone/items/6491ecd48af76dd55bc0
(参考)■ No.1 (2001.10.17) … Mathematica の簡単な使い方 I and 循環小数 
http://www.cas.cmc.osaka-u.ac.jp/~paoon/Lectures/2001-2Semester-ExperimentMath/01.html

循環小数
1/7 = 0.142857142857... = 0.(142857)

#wolframalpha
http://www.wolframalpha.com/input/?i=x*10%5E6-x%3D142857

#sympy
制作中
Linux mint端末にSSH接続を許可するまで

# Linux mintにSSHをインストールする
- Linux mintにSSHをインストール方法を備忘録的に書いておきます。
- openssh-serverを使用

## openssh-serverをインストール
``` # apt install openssh-server ```

## SSHのデーモンを起動する。
Linux mintの場合は**sshd**ではなく**ssh**という名前なので注意する
``` 
$ service ssh status 
Active: active (running)
```
ならOK。
Ruby の変な Range･･･?

## まずは復習

Ruby を使っていれば、範囲オブジェクトを必ず一度は目にすると思います。

範囲オブジェクト (もしくは `Range` オブジェクト) を生成する演算子には `..` と `...` の 2 種類があり、`..` は終端を含みますが `...` は終端を含まないという違いがあります。実際に for 式で調べてみれば明白ですね。

```ruby
i = 3
for k in 0..i   # 0 から 3 までが出力される
  p k
end
for k in 0...i  # 0 から 2 までが出力される
  p k
end
```

## さて･･･

上の例では、`0..i` と `0...i` という 2 つの範囲オブジェクトを使っていますが、実はこの `0` を `$` という特殊な記号に置き換えてもオブジェクトが作れます。ご存知でしたか?

知らなかったという方は、下のコードの実行結果がどうなるか予想してみてください。

```
i = 3
p $..i
p $...i
```

解答は下の方にあります。

　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　

# 解答

```
(0+0i)
0..3
```

真面目に考えた方、ごめんなさい･･･。

# 解説

まず、Ruby では **`$` だけが意味をなすことはありません**! 上の文章を読むと `$` が単独で何か意味があるように感じるかもしれませんが、これは意図的なミスリーディングです。

Ruby には `$.` という特別な変数が用意されていて、これは何らかの `IO` オブジェクトが最後に読み込んだ行の行番号を返します。何も読み込んでいない場合は 0 を返すことになっているので、`$..i` は `0.i` と等価です。これは、`0` という `Integer` オブジェクトに対し `i` という名前のメソッドを呼んでいると解釈されます。このメソッドは、実部が 0 で虚部がレシーバ自身となるような `Complex` オブジェクトを返すので、`0.i` の評価結果は `0+0i` となるわけです。

一方、`$...i` は上で述べたのと同様に `0..i` と等価です。今、変数 `i` の値は 3 なので、これは `0..3` という `Range` オブジェクトになります。

･･･ということで、ちょっとしたジョークでした。
jupyterlabのexternal extensionを作ってみた。

# 概要
jupyterlabのextensionには2つのtypeがある。

1) jupyterlabの既定packagesだけ使うextension <- extensionだけbuildすればOkay
2) jupyterlabが提供するpackages以外のpackagesを必要とするextension <- extensionを`jlpm run add:sibling <directory>`してからjupyterlabをbuildする

私は1)番を`external extension`、2番を`embeded extension`と呼ぶ。

この文書は1)番のextensionを作る基本的な手順を説明する。

referenceはここ http://jupyterlab.readthedocs.io/en/stable/developer/extension_dev.html

# conda install cookiecutter
`conda install cookiecutter`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/da82b27a-737e-5942-b2d4-70d7ed6caf78.png)

Proceed ([y]/n)? y

![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/d1d97e58-542c-afcc-83cc-0ef1e001c1c4.png)

# cookiecutter
`cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/055d3b82-2ab8-69bb-2e95-4986361ae143.png)

# jlpm install
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/c56338ba-10c2-7fcd-ca67-d3007f1560da.png)

Macで見るとこんなに面白いアイコンも出る(yarnが出すのですが。)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/3dd0f288-6925-b5f6-feac-3bec9b6f32b5.png)

# webstorm
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/f20d1024-7fef-17c1-9cf2-0f0663d7c6cf.png)

# jlpm run build
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/809fcabb-3cd3-076a-87bd-2aa37e0da5d4.png)

# jupyter labextension install
```
jupyter labextension list
jupyter labextension install
jupyter labextension list
```

`jupyter labextension list`
`jupyter labextension install`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/51d3d12e-ae73-bb41-9f8d-b30942dcaa7d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/fe2a91f8-b7b1-cedd-e303-42ef6c059a77.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/dcdfd3da-53c6-d838-1014-217bf529a16d.png)
`jupyter labextension list`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/1a5e1c3b-5921-9481-36f7-e62dd00a6db3.png)

# jupyter lab
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/d4574dba-d20d-8f65-236c-589e76c98434.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/9e7bce09-cd62-41af-4024-9a20acca48d1.png)

# コード修正
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/c580d679-8460-df21-c961-19960f599681.png)


# jlpm run build && jupyter lab build
`jlpm run build`
~~`jupyter lab rebuild`~~ (rebuild command was removed.)
`jupyter lab build`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/f14ffb03-192e-b3db-fe15-11829629fc58.png)

# jupyter lab
`jupyter lab`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/18923ef7-6553-1b45-da10-0b536cc58f3f.png)



# reference
http://jupyterlab.readthedocs.io/en/stable/developer/extension_dev.html
新しもの好きのためのpyenv&clangでpython3をソースからインストールする方法

# 読まなくてもよいまえがき
私のような新しもの好きは何かと最新バージョンを使いたがります。
chromeもcannaryを使います。
もちろんバグを踏むこともありますが笑い飛ばします。

少し前まではArchLinuxで様々なソフトウェアの新しいバージョンを手軽に**楽しく**使ってきましたが、
実際これから例えば仕事でArchLinuxを使うことなんて普通に考えてありません。
せいぜいUbuntuとか~~CentOS~~とかDebianでしょう。

するとpython2 ~~とかいう負の遺産~~がまだまだ現役な環境でpython3を使わなくちゃいけなくなります。
~~新しもの好きには苦行でしかありません。~~

~~”私は普段ArchLinuxなんでUbuntu不慣れです”とか口が裂けても言えるわけはないし、そもそもArchLinux使う人ならほかのLinuxディストリビューションにも造詣があるのが普通~~

# pyenv
pythonのバージョンを切り替える~~（パスを乗っ取る）~~ためのツールです。
詳しくは他の記事を参照

pythonの最新バージョンがでたら前のバージョンを残した状態でそのままサクッと乗り換えられますし、Cコンパイラを変えたりもできます。
**新しもの好きには必須ツールでしょう。**

# clang
私のような新しもの好きはただのclangでは満足できません。
**最新のclangがいいのです。**

大体の有名どころのソフトウェアは公式に（たまに有志が）debとかrpmのパッケージを公開していたりします。
Ubuntuなら鍵を登録して``/etc/apt/sources.list.d/``に追加のリポジトリを登録するためのファイルを追加すると思います。
**鍵の登録は自己責任で**

nginxのmainlineをインストールしようとしたことのある人ならだいたいわかるでしょう。

# gcc
gccが好きな人は

```
sudo add-apt-repository ppa:jonathonf/gcc-8.0
```
で追加すればgcc-8が使えます。
他に色々入れているともしかしたら依存関係が壊れるかもしれないので

```
sudo add-apt-repository ppa:jonathonf/gcc-7.3
```
でgcc-7.3で~~我慢する必要があるかもしれません~~

# 鍵登録

```
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
```

# リポジトリの追加

```
echo -e "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main \ndeb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" > /etc/apt/sources.list.d/llvm.list
```

**新しもの好きはUbuntu16.04なんて使いません。**
beta版の18.04(bionic beaver)を使います。
コードネームのところは16.04なら適宜``xenial``とかで読み替えてください。

これで最新のclangがaptでインストールできます。

# 2018/04/10現在のclang
clang-5.xがstableでclang-6.xがqualificationです。（qualificationってなんて訳せばいいんでしょうか 認定とか？）
clang-7が現在進行形のunstableと呼ばれるブランチです。
好きなのをインストールしましょう。

```
apt install clang-XXX
```

```sudo apt update```を実行すると大体毎日新しいのが降ってきます。

# pythonをソースからインストール
環境変数でCコンパイラを差し替えておきます。

```
export CC="hoge" # gcc-7 とかclang-6.0とか
pyenv install XXX
```
``pyenv install`` に``-v``オプションをつけて実行するとビルドがどんな感じで進んでいるか確認できます


ビルドがこけたら素直にバージョンを変えましょう

# 終わりに
私は別にそこまでディープな開発者でもないので最新版の恩恵にあずかることは***ほぼありません***

私は英語は得意ではないですし知識もないただのコミュ障なので、OSSの怖い人たちに絡んだこともありません。

ちなみに試しにWSLのUbuntu16.04上でclang-7でpython3.8-devをビルドしようとしましたが当たり前のようにこけました。

こういうのは動かなくても文句言ってはいけません。なにか起こっても自己責任です。
~~そもそもこのバージョンのコンパイラってサポートされてないんじゃないのか~~
**原因の切り分けなどができる人向けです。**

私は端末で動かす小さなネットワークモニタリングツールの開発を行っていますが、（https://github.com/johejo/ppping コメントがいただけるとうれしいです）
WSL上でpythonをソースからビルドするとutf-8の記号がうまく出なくなったりしちゃって困っています。
google翻訳を使ってみた「吾輩は猫である」「吾輩は猫である。」



(参考)google 「吾輩は猫である 英語」
https://www.google.co.jp/search?ei=ZprMWt2JCYKl8QW4rprgCw&q=%E5%90%BE%E8%BC%A9%E3%81%AF%E7%8C%AB%E3%81%A7%E3%81%82%E3%82%8B+%E8%8B%B1%E8%AA%9E&oq=%E5%90%BE%E8%BC%A9%E3%81%AF%E7%8C%AB%E3%81%A7%E3%81%82%E3%82%8B%E3%80%80&gs_l=psy-ab.1.1.0l8.2348.2348.0.5528.1.1.0.0.0.0.93.93.1.1.0....0...1c.1j4.64.psy-ab..0.1.93....0.abagxe90CXs
(参考)「吾輩は猫である」をどう訳す？
http://blog.livedoor.jp/torotoro5/archives/51057740.html

吾輩は猫である 英語＞It is a cat＞それは猫です

googleで 。がつくと　google翻訳はでませんでした。win7でieの時


(参考)google 「吾輩は猫である。 英語」
https://www.google.co.jp/search?ei=9JzMWp7cD5TS8wXOt5kQ&q=%E5%90%BE%E8%BC%A9%E3%81%AF%E7%8C%AB%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82+%E8%8B%B1%E8%AA%9E&oq=%E5%90%BE%E8%BC%A9%E3%81%AF%E7%8C%AB%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82+%E8%8B%B1%E8%AA%9E&gs_l=psy-ab.3...73664.75384.0.76423.10.6.0.0.0.0.143.395.3j1.4.0....0...1c.1.64.psy-ab..8.1.143...0.0.Aa3iLRWjIOA
rubyのArray classの役にたったメソッドを貯めていく

##map(=collect)
配列の各要素に対してブロックで指定した操作をして配列を返す
##filter,select(<=> reject)
配列の各要素に対してブロックに記述した条件によって絞り込みをして、条件に合うものだけを残した配列を返す。
##filterとmapの違い
要素数が変化するかどうか
mapは各要素に対して、ブロックの操作を行うだけ、filterは条件に合わない奴は返さない。

##sort

##zip

##product

##transpose

##index
Chart.jsでカーソルを表示するpluginを作成しました

JavaScript最高！JavaScriptは神！
今回はグラフを描画するライブラリであるChart.jsのプラグインを作ってみたよというお話です。

## テスト環境 ##
Google Chrome
Chart.js 2.5.0

## Chart.jsとは ##
htmlのcanvasタグを使ってグラフを描画してくれる粋なやつで、例えばsin波形のデータを入れるとこんな感じになります
![default.PNG](https://qiita-image-store.s3.amazonaws.com/0/211445/be7cc970-e65f-517d-19a3-0e34fe1f3f5f.png)
グラフ描画の際にアニメーションがついていたりしてて非常におしゃれなのですが、欲しい機能がなかったりします。範囲選択ができる機能がデフォルトでないので、作ってみました！

## 完成したもの ##
githubのリンクは[こちら](https://github.com/overheattrigger/chartjs-plugin-cursor)
![result.PNG](https://qiita-image-store.s3.amazonaws.com/0/211445/078c7d07-2190-7ec2-0e73-6babb1660674.png)

## プラグインの作成について ##
Chart.jsのプラグインは必要なAPIを実装したオブジェクトを以下のようにchartに渡してやるだけです。

```js
var plugin = { /* plugin implementation */ };
var chart = new Chart(ctx, {
    plugins: [plugin]
});           
```
また以下のようにChart.jsに登録してしまうこともできます。

```js
Chart.pluginService.register(plugin);
var chart = new Chart(ctx, {
    pluginOptions: { ... } 
});           
```

プラグイン用のAPIは[ここ](https://www.chartjs.org/docs/latest/developers/plugins.html)に一覧が載っています。一覧を見てもどれがどのタイミングで呼ばれるのかがわかりにくいですが、グラフ上に何かを表示する系のプラグインなら以下の2つで充分でしょう。

|API名|使い方|
|:---|:---|
|beforeInit|プラグインを初期化するのに使う。ここでEventListnerとか登録する。|
|afterDraw|update()をしたときにグラフの描画が終わってから呼ばれる？|

これらの関数は名前の通りのタイミングで呼ばれて、引数にChartのインスタンスが入ります。
これを使ってcanvasのeventListnerを登録したりするんですね。

```js
var node = chartInstance.chart.ctx.canvas;
var ctx = chartInstance.chart.ctx;
```

ここでいうnodeでaddEventListerをすると、グラフ描画に使っているcanvasにeventを追加できます。

## プラグイン作成に役立ちそうなTips ##
### 線を描画する ###
```js
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(0, 0, 0, 1.0)';
ctx.moveTo(50, chartInstance.chartArea.top);
ctx.lineTo(50, chartInstance.chartArea.bottom);
ctx.stroke();
```
これはcanvasのoffsetXが50のところに直線を引きます。chartAreaのtop,bottom,left,rightでグラフの描画エリアのoffsetがわかります。`ctx.setLineDash([5, 10])`みたいにすると破線を描画することも可能です。詳しくは[ここ](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)とかcanvasについて調べるとよいでしょう。

### 座標を取得する ###
グラフが描画されている場合に値に対応するcanvas内でのoffset値を取得できます。

```js
let scale = chartInstance.scales['x-axis-0'];
let pixel = scale.getPixelForValue(value);
```

ここのchartInstanceというのはbeforeInitとかのプラグインの引数です。x-axis-0というのはx軸のデフォルトの名前で、自分で名前を付けることもできます(僕が作ったプラグインは名前変えたら使えなくなります・・・)。また、以下のようにすればoffset値からグラフでの値を取得することも可能です。

```js
let value = scale.getValueForPixel(pixel);
```

## 参考 ##
* [Chart.js Documents](https://www.chartjs.org/docs/latest/developers/plugins.html)
* [pluginのlink集](https://www.npmjs.com/search?q=chartjs-plugin-)
* [chartjs-plugin-zoom](https://github.com/chartjs/chartjs-plugin-zoom)
ご注文はMastodonBotですか？ 今すぐ動かしてみたい初めての方に☕

#前置き
ココアさん、🎂ハッピーバースデーです🎂
![ココア.png](https://qiita-image-store.s3.amazonaws.com/0/219279/b84e4ac8-6b6c-b3ac-d29e-82b4f9870174.png)
今年もよろしくお願いいたしますね☕

ということでPythonを主に使用してAPIを駆使していきます。なぜなら私がPython使いだからです。
一応Windowsを想定した初心者向けのつもりで記載しますが、わからないことがありましたらコメントください。（色々調べると記事が出てきますよ、と言えばこの記事の意味がないですが）
ということで興味があればココアさんも是非試してみてください！

#導入
では、PythonでBotを動かすための環境を作りましょう。
###pythonを導入します☕
https://www.python.org/downloads/
こちらの最新安定版の3.6.5VerをDLしていただければ大丈夫です。
下の方のRelease一覧から選ぶと64Bit版やMac版など、install形式が選べます。
うっかり背伸びしてベータ版の3.7を導入しないようにご注意ください。

次にDLしたファイルを実行してsetupしましょう。
まずはAdd Python　3.6.5 to PATH と書いてるような項目にチェックを入れて、Pathは通すようにしておきます☕
パスは通さないと次のプロンプトでの操作で認識してくれないからです。
特にカスタマイズしない場合はこのままInstall Nowでインストールして行きましょう☕
#####Customize installしたい場合
カスタマイズをクリックしたあとは、pipが必ずチェックに入ってることを確認してください。あとは後の説明に使用するため、IDLEにもチェックが入ってると助かります。
nextして、好きな保存場所をinstall locationの欄に記入しましょう。
install for all usersをチェックするとプログラムフォルダ内に作成されます。この項目は全ユーザーが使用できるようになるので、PCを複数人で共有してる人はご注意下さい。
他の説明は特に触れないので気になる方は各自で調べてください！（ぶん投げ）
ということで上記の設定が終わればいざinstallです！

###Mastodon.pyをpipします☕
まずはプロンプトあるいはターミナルをたちあげます。
Windowsならファイル検索に**「cmd」**と打つと起動できかとおもいます。ちなみにエクスプローラーのアドレス欄から**「cmd」**を入力すると、その場所のディレクトリからプロンプトを起動できるそうですね。
次はpipのモジュールの確認です。`python -m pip -V`と入力していきましょう。
pip　x.x.x の後にアドレスパスが記載されてるならpipが導入されていますので、このまま`pip install mastodon.py`と入力してインストールです。
アップデートする場合は`pip install mastodon.py -U`という記載になります。
#####もし何かの手違いでpipが入ってなかった場合
下記のリンクからダウンロードします。
https://bootstrap.pypa.io/get-pip.py
DLしたpyデータにある場所のアドレスを`cd /d `の後に記入します。
`cd /d C:\chino`といった記入です。
ちなみにエクスプローラーのアドレス欄から**「cmd」**を入力した人は、そのエクスプローラーで開いてる場所へget-pip.pyをコピーあるいは移動するだけで大丈夫です。
そして`python get-pip.py`と打ち込めば導入完了です。

###Botを動かすためのアクセストークンを入手します。
IDLEを起動します。ファイル検索で**IDLE**と入力ですぐに起動できます。
FileタグからNew Fileでエディタが現れます。
次に下記のコードをコピペしてお好きな場所にSave Asして保存しましょう。

``` setup.py
from mastodon import Mastodon
# Register app - 一回だけで問題ないです。
url = 'https://knzk.me'  #インスタンス先です
Mastodon.create_app(
     u'ラビットハウス',  #クライアント名
     api_base_url = url,
     to_file = 'client.secret'  #appを保存するファイル名になります
)
# Log in - アクセストークンを取得します。
mastodon = Mastodon(
    client_id = 'client.secret',
    api_base_url = url
)
mastodon.log_in(
    'my_login_email@knzk.me',  #メールアドレス
    'password',  #パスワード
    to_file = 'user.secret'  #こちらがアクセストークンです
)
```

メールアドレス、パスワードは動かすためのアカウントを使用してくださいね。
あとは保存ができたらF5を押して動かしましょう！

成功すると保存したpyの場所に新しく**client.secret**と**user.secret**が生成されてます。
エラーが出ると赤くなります。英語が読めるとどのようなエラーなのか記載されています。もし分からなかった場合はコメントを残してください。気が向いたら返答します。

これで、なんでもできますね！　　　ん？


# Botを動かします
```
from mastodon import Mastodon

cocoa = Mastodon(
    client_id = 'client.secret',  #app情報
    access_token = 'user.secret',  #ログイントークン
    api_base_url = 'https://knzk.me'  #インスタンス名
)
cocoa.toot('チノちゃん！')
```
はい、簡単ですね☕

#いかがだったでしょうか☕

今回は本当に初心者向けだったので簡単な事項しか書いてません。
ここからもう少し充実した機能を追加したい場合は、どんどん調べていって好きなように作っていきましょう！きっとPythonなら自由自在のはずです！
もし何かしら要望があれば記事を作ってみますのでどこかでコメントいただけると助かります。
それでは楽しいひととき、Mastodonライフをお楽しみください。またのお越しをお待ちしてます☕

※2018-04-10時点での情報です
![2018-03-19_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/219279/a7e74582-7210-70a2-84d7-5268b4068456.jpeg)
EventKitはmacOSとiOSで異なる

EventKitはカレンダーやリマインダーのデータを読み書きするためのフレームワークで、iOSでもmacOSでも使えます。ただし両者には違いがあるので注意が必要です。

#EventKitUI

一番大きな違いは`EventKitUI`フレームワークがiOSにしかない点です。そのためMacアプリで`EKEvent`を表示させるには自前でビューワーを作る必要があります。

尚、`EventKitUI`は`EKEvent`のプライベートAPIにアクセスしており、`EKEventEditViewController`では招待者を追加したり、`EKEventViewController`では添付ファイルを表示することができます。`EKEvent`では招待者（`attendees`）は読み込み専用になっており、また添付ファイルにはアクセスすることすらできません。

#endDateの違い

`EKEvent.isAllDay`が`true`（終日予定）の場合、`endDate`の値がiOSとmacOSでは異なります。例えば2018年4月10日の終日予定の場合、`endDate`の値は以下のようになります。

|  iOS  |  macOS  |
|:--------:|:---------:|
|`2018-04-10 23:59:59 +0900` |`2018-04-11 00:00:00 +0900`|

つまりiOSの場合、`endDate`は2018年4月10日午後11時59分59秒となりますが、macOSの場合は2018年4月11日午前0時0分0秒となります。`endDate`を読み込む場合は注意が必要です。

#`hasAlarms`のバグ

macOS 10.13.1で`EKEvent.hasAlarms`を呼ぶと常に`true`が返されるというバグがあります。iOSでは発生しません。

この問題は`EKEvent.alarms`が`nil`もしくは空のリストであることをチェックすることで回避可能ですが、`alarms`を初めて呼び出すときは`EKEventStore`にアクセスしているらしく、値を取得するまでにやや時間かかかります。
goo.glも終わるしGoとGAEで短縮URLサービスをつくろう

goo.glは終わってしまうようなので、短縮URLサービスをみんな自分で作るといいと思います。QRコードも表示できるので、スマホにURLを送るときも簡単です。

ソースコード：[juntaki/url-shortener](https://github.com/juntaki/url-shortener)
完成品：[https://s.juntaki.com](https://s.juntaki.com)

![38465564-40d7b79e-3b58-11e8-978f-304193d4f5c3.gif](https://qiita-image-store.s3.amazonaws.com/0/69350/10984965-7cf8-dc3b-0dac-b099b3bd8e2b.gif)

## 前提

* GAE
* 短めのドメイン
 
## つかいかた

reCAPTCHAを使うので、登録しておきましょう。Invisibleなやつを選んでおきます。
[reCAPTCHA: Easy on Humans, Hard on Bots](https://www.google.com/recaptcha/intro/android.html)

ソースコードはここから入手してください。
[juntaki/url-shortener](https://github.com/juntaki/url-shortener)

app.ymlを編集して、URLを自分のドメインに、SITE_KEYを先程取得したものに変更します。

~~~yaml
env_variables:
  BASE_URL: "https://s.juntaki.com"
  RECAPTCHA_SITE_KEY: "6Lc48lAUAAAAAFehXaHNp0Ys-lS1iUfNtUXd_-eR"
~~~

secret.ymlのファイルを作ります。

~~~yaml
env_variables:
    RECAPTCHA_SECRET: "<your-recaptcha-secret>"
~~~

あとは適当なプロジェクトにデプロイしたら完成です。

~~~
gcloud config set project <project-name>
gcloud app deploy
~~~

## 技術的な解説


### 短いURLをつくる方法

適当なハッシュ関数で〜と考えていましたが、ぶつからなくても、長くなっては意味がないです。単純ですが、既存のURLとぶつからなくなるまで、下記の文字から3つランダムで選びます。

~~~go
var letters = []rune("23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz")
~~~
文字は、[Base58](https://ja.wikipedia.org/wiki/Base58)から数字の1と小文字のoの2文字を取り除いたBase56のセットになっています。発表スライドなどでパッと見せても見間違えにくいです。
56*56*56=17万通り近くあるので、そんなに枯渇することもないでしょう。

### QRコードを作る

[skip2/go-qrcode: QR Code encoder (Go)](https://github.com/skip2/go-qrcode)
これを使いました。Base64エンコードして、テンプレートに組み込んでしまえば、画像の配信を考えなくて良いので簡単です。


### reCAPTCHAを使う

単に使ってみたかっただけですが、お手軽さとスパム対策を考えると、ちょうどよい選択肢でした。
`button id='submit'`とあるサンプルをコピペして使うと、そのまま使えないシンプルな罠が仕掛けてあったり、このサンプルは本当に使わせる気があるのだろうか・・・
[Developer's Guide  |  reCAPTCHA  |  Google Developers](https://developers.google.com/recaptcha/intro)
[jquery - javascript submit() is not a function? - Stack Overflow](https://stackoverflow.com/questions/6525790/javascript-submit-is-not-a-function)

## まとめ

GAEなので維持費0円でURL短縮サービスがつくれました。いいかんじの背景画像などをつけると、独自感が出てよいのではないでしょうか。
リダイレクトするときに、ログを取っておくとアクセス解析みたいなことも簡単にできると思います。
poiでvueにaliasを貼りたい

# poiとは
webpackで動くzero config bundlerです。
ある程度のテンプレート設定を素早く構築するためのツールです。

# こんなんでた
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

# 結論
https://www.npmjs.com/package/poi-preset-resolve-alias
npmがあるのでこれを使ってください

```poi.config.js
    require('poi-preset-resolve-alias')({
          'Vue': 'vue/dist/vue.esm.js'
    })
```

# なぜ発生するか

[公式を見るとわかりやすいです](https://jp.vuejs.org/v2/guide/installation.html#%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0-%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A8%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E9%99%90%E5%AE%9A%E3%81%AE%E9%81%95%E3%81%84)
QObject のインスタンスを delete する時にわざわざ disconnect する必要は無い

タイトルの通りですが、意外と書いていないので。

QObject （の派生クラス）のインスタンス obj1 を解放するとして、 delete の**直前**に obj1 に connect されたシグナル・スロットをわざわざ disconnect する必要はありません。

```cpp
disconnect(obj1, シグナル, 別のオブジェクト, スロット);
disconnect(別のオブジェクト, シグナル, obj1, スロット);
// ↑ これを呼ぶ必要は無い！！！
delete obj1;
```

obj1 のコネクションはすべて QObject のデストラクタの中で解除されるからです。

> [QObject::~QObject()](http://doc.qt.io/qt-5/qobject.html#dtor.QObject)
> All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue.

常識的に考えて、delete する前にユーザーがすべてのコネクションを調べて、それを明示的に解除する必要があるなんてバカな設計になっているはずがない（そもそも Qt はマルチスレッドを前提にしているので、競合を起こさずにそんなことをすることは不可能）のですが、初心者の方にはどうしてもそういう事をやってしまう人がいるようです。
やってもほとんどの場合※害はありませんが、何事も理屈を理解した上でプログラミングしましょう。
こういうコードを書く人は、Qt のシグナル・スロットの仕組みやマルチスレッドプログラミングの基本を十分理解せずにコーディングしている可能性が高いので、指導する立場にある方は十分注意してレビューしてください。

※害がある時とはどんな時でしょうか。考えてみましょう。
Excel 少しマイナーなショートカットキーとコマンド集

私の仕事はMicrosoft Excelが無いと成り立ちません。
私はキーボードからマウスに持ち替えるのが煩わしいのでほとんどの操作はキーボードでやってしまいます。
Excelの場合は、オートシェイプの細かな調整以外はキーボードでできてしまいます。
今回は私が作業中によく使用するかつあまり使用している人を見ないキーボード操作をまとめます。

### 動作確認環境

- Window10
- Microsoft Office2016 Excel


## ショートカットキー
|内容|ショートカットキー|
|:-:|:-:|:-:|
|真上のセルの内容を複製|ctrl + D|
|左隣のセルの内容を複製|ctrl + R|
|行の選択|shift + space|
|列の選択|ctrl + space|
|行または列の挿入|shift + ctrl + +(プラス)|
|取り消し線|ctrl + 5|
|セルに設定されている式を表示|shift + ctrl + @|
|選択している範囲にフィルターを設定する。|shift + ctrl + L|
|ハイパーリンクの挿入|ctrl + K|


## ショートカットコマンド

※同時に押すのではなく、順に押してください。

|内容|ショートカットコマンド|
|:-:|:-:|:-:|
|選択範囲に格子罫線|alt - H - B - A|
|選択範囲の罫線を削除|alt - H - B - N|
|選択範囲の外枠罫線|alt - H - B - S|
|選択範囲の外枠太罫線|alt - H - B - T|
|選択範囲の塗りつぶしを削除|alt - H - H - N|
|シート名を変更|alt - H - O - R|

## まとめ
本当はコードが書きたいのにExcelばかりで嫌になることがあるかもしれません。
そんな時はショートカットでも覚えて、気を紛らわせましょう。
【Rails】ngrokを使わずにLINEログインを開発環境で実装する方法

この記事（[【Rails4, OmniAuth】世界一丁寧なLINE LOGIN導入講座](https://qiita.com/YuitoSato/items/a9e613370f418d5c322c)）を元にRailsでLINEログインを実装していたんですが、一つ気になる点がありました。

**ngrokの設定面倒くさくね？:cry:**

無料版だと設定しなおすたびにURLが変わる仕様なので、一旦URLが変わるとなるとLINEのページの方のURLも変える必要があるんです。

これは面倒くさい。時間にすると2,3分もかからない作業だとは思いますが、**やらなくていいことは極力やりたくない。**

## 要はhttpsであればいい:bulb:

httpsにしたらいいのなら、`https://localhost:3000`とかにすればいいんじゃね？

ということで試しに登録して見たところ、localhostでも問題なく登録できました。

![スクリーンショット 2018-04-10 22.51.33.png](https://qiita-image-store.s3.amazonaws.com/0/121571/c74537f0-a023-a4d6-d36b-c4d88c27352b.png)

開発環境下でのログイン認証も問題なく行えます。

## ローカルでhttpsにする方法 :key: 

ググったら何でも出てきますが、一番簡単なのがこちら（[Railsのローカル環境でSSL(https)を使う](https://qiita.com/ironsand/items/0056d718b9174f516f7b)）で紹介されているgemのthinを使う方法です。

インストールして`thin start --ssl -p 3000`などとするだけでhttpsになりますので、何も考える必要がありません :smile: 

pumaがお好みの方は（[Rails5 + pumaのローカル環境でSSL/HTTPSを有効にする](https://qiita.com/zaru/items/ccf328e87c768168134d)）を参考にやってみると良いと思います。
Twitterで「Flawless App」というサービスに絡まれたので人柱した

# やること
Twitterで「Flawless App」というアカウントから、「自社サービスの開発者⇄デザイナーのコラボレーションツールを見てみない？」っていう宣伝@ツイート来たので面白がって人柱してみた。

# 結論
結論を最初に言うと**「iOS Simulatorにデザインファイルや画像を重ね合わせて、分かりやすく見比べることが出来るツール」**でした。

# 前書き
こんにちは！桜も散ってだんだんと暖かくなって来てきますね。
今年は花粉がすごくて、花粉症用のマスクと花粉症に効くお茶を常備していないと辛い日が続きます。

帰宅して、布団の中でそろそろお風呂に入ろうかと考えていたらこのような@ツイートが飛んできていました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/seijin4486?ref_src=twsrc%5Etfw">@seijin4486</a> こんにちは 🙂<br>We saw you are interested in сollaboration tools for developers and designers!<br><br>🔥 We want to show you our tool, that helps to compare initial design with your implementation right on iOS simulator: <a href="https://t.co/bGftZpuzi8">https://t.co/bGftZpuzi8</a><br><br>P.S.: we also support Zeplin <a href="https://t.co/kF5LBhmmyK">pic.twitter.com/kF5LBhmmyK</a></p>&mdash; Flawless App (@flawlessappio) <a href="https://twitter.com/flawlessappio/status/983677127995412480?ref_src=twsrc%5Etfw">2018年4月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


適当翻訳(right on の正しい役がわからなかった)

> こんにちは😀
あなたがデザイナーと開発者のコラボレーションツールに興味があるのを拝見いたしました。
私たちは、初期デザインと右のiOSシュミレーターの実装を比較するような補助ツールをお見せしたいです。
追記: 私たちは他にも[Zephin](https://zeplin.io)をサポートしています。

スパムメールかな？と思いましたが、確かにZeplinのアカウントはフォローしてますし、デザイナーと開発者間のコラボレーションツールには興味があったので、面白半分試してみようかなぁと思いました。

# Flawless AppのWebサイト
[Flawless App](https://flawlessapp.io)

![スクリーンショット 2018-04-10 21.32.59.png](https://qiita-image-store.s3.amazonaws.com/0/114709/701ef891-9f10-43ee-161a-578e580b751a.png)

## サイトのトップの内容
> 可能な限り最高の視覚品質を達成します。
期待したデザインと実装したデザインのリアルタイム比較。 iOSシミュレーター上で動作します。私たちは、モバイルアプリの品質に夢中になっている人たちのためにFlawlessを作りました。

**iOSシミュレーター上で動作します！？** ここでだいぶ気になりました。

# 料金
30ドル
(フリートライアルあり)

# 対応ファイル
sketch, gif, tiff, jpg, png, jpeg
とのこと。

# 使ってみた
とりあえず試して見ないと全く分からないので使ってみたのでレポートいたします。

インストールすると、「iOSシミュレーターを開く」というボタンが出て来ます。
ボタンを押すとシミュレータが再起動されます。

![スクリーンショット 2018-04-10 21.59.36.png](https://qiita-image-store.s3.amazonaws.com/0/114709/07f0ed01-b2fb-e0de-43dd-f99e91e50278.png)

-----------------------------------------

Macのトップバーにアイコンが追加されました。
![スクリーンショット 2018-04-10 22.03.23.png](https://qiita-image-store.s3.amazonaws.com/0/114709/5b5e1c50-a4ee-556c-718b-8ade57b405b5.png)

**CHOOSE IMAGE**は比較したいデザインファイルを選択します。

**MODES**は

- 分割表示
- 透過表示
- 非表示

この３種類が使えるようです。

以下、全てXcodeのSimulatorでのスクショです。

## 分割表示

![スクリーンショット 2018-04-10 22.04.27.png](https://qiita-image-store.s3.amazonaws.com/0/114709/283952f8-b9b7-2e4e-3a33-b4ac740d76ad.png)

## 透過表示

![スクリーンショット 2018-04-10 22.04.41.png](https://qiita-image-store.s3.amazonaws.com/0/114709/3ef32efe-539c-8da8-87b5-ce0c48518652.png)

# 以上！まとめ

どうやら「Flawless App」というアプリは、iOS Simulator上にデザインファイルや画像を重ねて比較できるアプリのようです。

確かに１つのVCをゴリゴリ開発している時は、デザイン設計との視覚的な比較がとてもやりやすそうだと思いました。

ただ「全然デザイナーとエンジニアのコラボレーションツールじゃないやん！」と正直思いました。「エンジニアが楽にデザインの比較を行えるツール」ぐらいの感じ。

あとは画面遷移させながら色々確かめる時に、一々画像の再設定なんか面倒臭くて使うのやめちゃいそうだなーと思いました。

まだまだローンチしたばかりのようなので、これから便利になっていけば利用を検討しよう！という感想です。

無料で試せるので、気になるiOSエンジニアの方はお試しください！
Google Cloud Vision APIで画像内の文字を認識してみる

Google Cloud Vision APIで画像内の文字の認識を目指します

#1. Google Cloud Vision APIを使用可能にします
-[Google Cloud Vision API を有効にする ](https://cloud.google.com/vision/docs/before-you-begin?authuser=1&hl=ja)を参照し、Google Cloud PlatformコンソールでCloud Vision APIを使用するプロジェクトを用意し、Cloud Vision APIを有効化します

#2. Google Cloud Vision APIの認証
- [Google Cloud Vision API に対する認証]（https://cloud.google.com/vision/docs/auth?authuser=1&hl=ja）の「サービスアカウントの使用」を参照し、Google Cloud Platformコンソールで前項で準備したプロジェクトが選択されていることを確認し、画面左上の三本線から「APIとサービス」を選択します

<img width="282" alt="スクリーンショット 2018-04-10 22.39.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/c5d09c1e-8479-d3a0-8541-2f92ab05ab5c.png">

- 「APIとサービス」画面で「認証情報」を選択します
- 「認証情報」の画面で「サービスアカウントキー」を作成します

<img width="775" alt="スクリーンショット 2018-04-10 22.39.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/227122ee-590d-47d1-a8b6-aed09e94b926.png">

- 「サービスアカウントキーの作成」画面で、サービスアカウントを選択もしくは新規作成し、「JSON」形式でキーファイルを生成し、ダウンロードします。`プロジェクト名-xxxxx.json`ファイルがダウンロードされます

<img width="737" alt="スクリーンショット 2018-04-10 22.40.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/9e21ae7a-ae44-f304-9723-91d799b3de9b.png">

#3. サンプルアプリを用意します
- [Google Cloud Vision API - ドキュメント テキスト検出のサンプル](https://cloud.google.com/vision/docs/detecting-fulltext?authuser=1&hl=ja#vision-document-text-detection-python) を参照し、[GoogleCloudPlatform/python-docs-samples](https://github.com/GoogleCloudPlatform/python-docs-samples)のページからサンプルプログラムを含むzipファイルをダウンロード（緑色のボタン）もしくは`git clone`します。
- このデモで使用するのは[GoogleCloudPlatform/
python-docs-samples/vision/cloud-client/detect/detect.py
](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/vision/cloud-client/detect/detect.py)です

#4. 実行環境を準備します
- 下記のコマンドで環境変数として前々項でダウンロードしたjsonファイルを指定して認証情報を設定します

```
export GOOGLE_APPLICATION_CREDENTIALS=XXXXX-XXXXXXXXXXXX.json
```
- ターミナルを開き、上記のファイルをダウンロード／解凍したフォルダへ移動し、

```
pip install -r requirements.txt
```
で必要な道具をインストールします

- 下記のコマンドを実行し、対象画像ファイルに含まれる文字列を取り出します

```
python python-docs-samples-master/vision/cloud-client/detect/detect.py text 対象画像ファイル名

Texts:

どれみ
ふぁそら
しど
:

```


#参考情報
1. [Google Cloud Vision API ドキュメント ](https://cloud.google.com/vision/docs/?authuser=1&hl=ja)
Ansible: 複数のステージに対応する際のポイント


# この記事で考察すること

production、staging の２つの環境があるとします。

やりたいことは、Ansible の一つのソースで、両方に対応できるようにすること。
つまり、次のようにコマンドで環境を使い分けて実行できるようにします。

```shell
# production を対象にする
$ ansible-playbook -i production_hosts site.yml

# staging を対象にする
$ ansible-playbook -i staging_hosts site.yml
```

# 今回作成する Ansible ソースのポイント

ポイントを簡単に箇条書きにします。

* ステージごとにインベントリファイルを用意（staging_hosts, production_hosts）。このファイル中で、変数 stage にステージ名を設定します。
* web, db という粒度でプレイブックを作成(web.yml, db.yml)。これらのプレイブックから、ステージに応じたロール、変数ファイルを呼び出します。


### ディレクトリ構成

```
|-- production_hosts
|-- staging_hosts
|
|-- site.yml
|
|-- web.yml
|-- db.yml
|
|-- roles
|   |-- staging_pretask/
|   |-- db/
|   `-- web/
|
`-- vars
　　　　|-- common.yml
　　　　|-- production
　　　　|     |-- web.yml
　　　　|     |-- db.yml
　　　　`-- staging
　　　　      |-- web.yml
　　　　      |-- db.yml
```


# inventory

ステージごとにインベントリファイルを用意します。
特徴的なのは、ここでステージの環境変数を設定しています。

### production_hosts

```yaml
[web]
web.prd.example.com

[db]
db.prd.example.com

[all:vars]
stage=production
```

### staging_hosts

```yaml
[web]
web.stg.example.com

[db]
db.stg.example.com

[all:vars]
stage=staging
```

# Playbook

### site.yml

web, db のプレイブックを import するだけの内容です。（余談ですが、include はバージョン 2.8 で無くなります。）

```yaml
- import_playbook: web.yml
- import_playbook: db.yml
```

### 上位プレイブックで環境の制御

web, db という粒度でプレイブックを作成します。この中で必要なロール、変数を設定します。
ポイントは、vars_files でステージに対応した変数を読み込んでいること。


##### Tips

* tags をロールごとに設定しておくと、プレイブック実行時に指定ロールのみの処理を実行可能です。
* 特定ステージでのみ実行したいロールがある場合は、when を使ってステージを指定します。

##### web.yml

```yaml
- hosts: web
  become: yes
  vars_files:
    - vars/{{ stage }}/web.yml
    - vars/common.yml
  roles:
    - { role: staging_pretask, tags: staging_pretask, when: stage == 'staging' }
    - { role: common,      tags: common }
    - { role: web,         tags: web }
```

db.yml も同じような考え方で作成します。

### タスク単位で、環境ごとに動作を変えたい場合

片方の環境でのみ実行したい処理は、when 句によってステージを指定します。

#####  roles/common/tasks/main.yml 

```yaml
- name: xxxxxx
  ...
  when:
   - stage == "production"
```


### プレイブック実行

##### コマンド

-i でステージング、プロダクションを切り替えます。

```shell
# production を対象とする。
$ ansible-playbook -i production_hosts site.yml

# staging を対象とする。
$ ansible-playbook -i staging_hosts site.yml

# staging を対象とする。web サーバのみ。
$ ansible-playbook -i staging_hosts web.yml

# staging を対象とする。web サーバを対象に、common ロールのみ。
$ ansible-playbook -i staging_hosts web.yml --tags common
```

# 補足: なぜ group_vars を避けたか

Ansible がよしなに必要な変数ファイルを読み込んでくれるのですが、意図どおり読み込まれないことがありました。それならば、vars_files で自分が必要なものを明示的に呼びだそうと考えました。




# 参考

[Ansible公式: Best Practices](http://docs.ansible.com/ansible/latest/playbooks_best_practices.html)

[Ansible inventoryパターン](https://dev.classmethod.jp/server-side/ansible/ansible-inventory-pattern/)

[Qiita:Ansibleのインベントリファイルでステージを切り替える](https://qiita.com/NewGyu/items/5de31d76d2488ab27ed6)
LaravelでStorybook（for Vue.js+PostCSS）

laravel mix を使うとPostCSSの設定は
例えば、

```js:webpack.mix.js
mix.options({
  postCss:[
    require('postcss-import'),
    require('postcss-cssnext')
  ]
});
```
の様に書く必要があるため、StorybookがPostCSSの設定を共有できないので、
Storybookのために

```js:postcss.config.js
module.exports = {
  plugins: {
    'postcss-import': {},
    'postcss-cssnext': {}
  }
}
```
とファイル作成・設定することで一旦解決。
DRYに書きたい。

### 参考
[laravel-mixでvueにカスタムなPostCSS設定を使う](https://qiita.com/terrierscript/items/8b48fc931744e1c9c730)
expect()よりunwrap_or_else()を使うべき場合


パフォーマンス上の問題から、`expect()`より`unwrap_or_else()`と`panic!()`の組み合わせを使うべき場合がある、という話。

# expect()の失敗時に表示される文字列
`Option`型のメソッドである`expect()`は、値が`Some`の場合はその中身を取り出し、そうでない場合は引数として与えられた文字列を表示してパニックを起こします。この文字列の型は`&str`であるため、実行時にエラーメッセージを生成したい場合は、`format!()`マクロを用いて一旦`String`型の値を生成し、その参照を渡してやる必要があります。

例として、次のコードを実行してみます。

```Rust
fn main() {
    foo(0);
}

fn foo(n: i32) {
    let a = bar(n).expect(&format!("n = {}", n));
    println!("{}", a);
}

fn bar(n: i32) -> Option<i32> {
    if n == 0 {
        None
    } else {
        Some(1000 / n)
    }
}
```

この出力は次のようになります。

```
thread 'main' panicked at 'n = 0', libcore/option.rs:916:5
```

このように、n = 0だから失敗したのか、とエラーメッセージから判断しやすくなります。

# format!()のコスト

上記のコードはこれはこれで正常に動きますが、`foo()`が頻繁に呼び出される場合に問題が発生します。というのも、`bar()`が正常に`Some`を返してくれる場合でも、`format!()`が呼び出され、その分余計な処理を行うことになってしまうからです。`format!()`はヒープを確保して文字列を整形してくれる分、その実行コストはなかなか大きいです。つまり、頻繁に実行される部分では、expect+formatの組み合わせを用いるのはよろしくないということです。

というわけで、実際に`None`が返されたとわかった場合のみエラーメッセージを生成するようにしなければなりません。この簡単な解決策は、if let文を用いることです。if let文を用いれば、上記の`foo()`は以下のように書けます。

``` Rust
fn foo(n: i32) {
    let a = if let Some(a) = bar(n) {
        a
    } else {
        panic!("n = {}", n);
    };
    println!("{}", a);
}
```

`panic!()`マクロが実行されると即座にパニックを起こします。またこのマクロは`println!()`や`format!()`と同じように文字列を整形し、エラーとして表示してくれます。

# unwrap_or_elseと組み合わせる

if let文を用いる方法でパフォーマンス上の問題は無くなりましたが、いささか冗長になってしまいます。できれば1行で簡潔に書く方法が欲しいところです。そこで、`Option`型のメソッドの1つである`unwrap_or_else()`を用います。`unwrap_or_else()`はクロージャを引数として受け取り、`Option`の中身が`None`であった場合、代わりの値をクロージャで生成して返してくれます。また、`Option`の中身が`Some`であった場合、クロージャは実行されません。この性質を用いると、`foo()`は以下のように書けます。

``` Rust
fn foo(n: i32) {
    let a = bar(n).unwrap_or_else(|| panic!("n = {}", n));
    println!("{}", a);
}
```

クロージャであることを表す`||`という記号が残ってしまいますが、これで1行におさめることができました。

なお、本来`unwrap_or_else`に渡すクロージャの戻り値は、`Option<T>`の`T`と同じでなければなりませんが、`panic!()`は "`!`" という特殊な型として扱われるため、問題なくコンパイルが通ります。

# Resultの場合

`Result`にも`unwrap_or_else()`があるため、同じく`panic!()`と合わせた書き方が可能です。その場合、`unwrap_or_else()`にわたすクロージャがエラーの中身を受け取るので、`||`の部分を`|_|`等に書き換えます。もっとも、`Result`の`expect()`は、`Err`であった場合にその中身のエラー値のデバッグ情報(`Debug`トレイトによるもの)を出力してくれるため、それで十分な場合も多いです。

## 参考
`&str`ではなく遅延評価されるような引数を受け取るようにする`expect()`が欲しい、というRFCがあがっていたようです。
[Allow any Displayable type for expect.](https://github.com/rust-lang/rfcs/pull/1968)
Closeされた経緯を見る限り、`unwrap_or_else()`を使うやり方で十分、ということのようです。
シェルの引数を検索条件にしてPostgreSQLからデータをCSV形式で出力する

# シェルの引数を検索条件にしてPostgreSQLからデータをCSV形式で出力する。

サクッとサーバへログインしてデータベースを検索したい時に使うシェルです。
シェルの引数を検索条件にできるため、複雑なSQLを毎回コピペしなくてもいいので便利です。

<<EOFからEOFの間にSQL文を書いて、引数を\$1、\$2などにします。

```
###
###  PostgreSQLからよく使うSQLをCSV形式で出力するシェルです。
###  使用例：
###  ./find-name.sh　検索名
###
psql -A -F, -Upostgres -hlocalhost database <<EOF

select  * from table where name = '$1';

EOF
```
Laravel5.6で php artisan jwt:generate が失敗する

QiitaでLaravel5.4の記事を見ながらLaravel5.6で`tymon/jwt-auth`試そうとしたらハマった。
`php artisan jwt:generate`を叩くとエラーを吐く。

公式ドキュメントを漁ったら先に進めた。

http://jwt-auth.readthedocs.io/en/develop/laravel-installation/
https://github.com/tymondesigns/jwt-auth/wiki

# バージョンが違った

Laravel5.6系だと1.0.*を使わないといけない。
ここが最初0.5系になっていたので直した。

```json:composer.json
"tymon/jwt-auth": "1.0.*"
```

```bash
composer update
```

# コマンドが変わってた

`generate`から`secret`に変わった(?)っぽい。

```bash
php artisan jwt:secret
```
「いいね！」できるKPTをスプレッドシートで作る！

# スクラムと KPT
こんにちは新規事業で[スクラム](https://www.scrumguides.org/docs/scrumguide/v2016/2016-Scrum-Guide-Japanese.pdf)マスターをやっている halhorn です。
私のチームではスクラムの振り返りに KPT を使っています。
KPT は Keep Problem Try の略称で、良いことや問題点、改善方法を洗い出してチームをより良くする手法です。

- Keep: 続けたいこと。良いこと。
- Problem: 問題点。改善すべきこと。
- Try: これからやりたいこと。

Problem があれば、対になる Try を書いた人が考えたり、チームで考えたりします。
これを定期的に行うことで、継続的にチームの良い部分をみんなで認め文化を定着させ、悪いところを改善していくことができます。

私のチームでは、この KPT にスプレッドシートを使っています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/e6058c3a-1987-67f6-aa70-bd1d1fcdd73b.png)
KPT に付箋や Trello、その他ツールではなくスプレッドシートを使う理由としては以下の点があります。

- Problem (や Keep) に対応する Try がどれか見やすい
- みんな使い慣れた SpreadSheet なので学習コストが低い

# KPT でいいねしたいよね！
KPT では、「ああ、それ私も問題と感じてたんだ」「それ、ほんといいよね！」といった共感をチームで共有できることが大事です。
KPT を話す場で口に出して共感するのがもちろん良いのですが、残念ながらみんなシャイなのであまり口に出して「それな」って言ってくれません。

そこで、スプレッドシート上で共感を示す「いいね」をできるようにしましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/bec45127-3a1d-b9d9-db4e-966bef4c2a80.png)

- 行の右の方に共感した人たちのアイコンが並ぶ
- 右上の :thumbsup: ボタンを押すと、カーソルをあててる行に共感したことになる
- 消す時は消したいセルを普通に消すだけ

# 作り方
スプレッドシートと GAS (Google Apps Script) で作ります。
簡単な js が書けることが必要になります。

## スプレッドシートを作る
スプレッドシートを作って、上の画像のように列と行を作ってください。

- 背景色を分けると楽しさがでておすすめ
- 1行目のヘッダーとName の列は固定にしておきましょう。
    - メニューの、表示 -> 固定 でできますよ。
- 右の方の列は全部幅を狭めにしておいてください。（1行の場合に正方形になるくらい）

## GAS でコードを書く
スプレッドシートのメニューから、ツール -> スクリプトエディタ を選択します。

以下のサンプルを適宜いじったものを入れてくださいください。

```js
function addMyIcon() {
  iconStartCol = 5  // アイコンを並べる最初の列。1から始まるよ。
  var iconMap = {
    'Aさんのメールアドレス': 'AさんのアイコンのURL',
    'Bさんのメールアドレス': 'BさんのアイコンのURL',
  }
  var sheet = SpreadsheetApp.getActiveSheet();
  var row = sheet.getActiveCell().getRow()
  var iconColValues = sheet.getRange(row, iconStartCol, 1, 100).getFormulas()[0] // カーソル行のアイコンの列の配列
  var col = iconStartCol + iconColValues.indexOf('') // 空になっている最初の列
  
  var userImage = iconMap[Session.getActiveUser().getEmail()]
  sheet.getRange(row, col).setFormula('=IMAGE("' + userImage + '")')
}
```
変更すべきは以下の2点です。

- `iconStartCol`: アイコンを並べる最初の列を入れてください。
    - 私と同じスプレッドシートの作りなら5列目からアイコンが入る列になるので5です。
- `iconMap`: いいねする人のメールアドレスからアイコンURLへのマッピングです。
    - 例： `'halhorn@fake.com': 'http://hogehoge.com/halhorn.png'`
    - 残念ながらユーザーが増えるたびに変更が必要です。 Google のアイコン取ってくる方法だれか教えて

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/8910d160-0a5a-22b0-70c9-69681e5c3864.png)

完成したら、スクリプトエディタの再生ボタンぽいやつを押して動かしてみましょう。
何も表示されないと思いますが、スプレッドシートの方に戻ったら自分のアイコンがカーソル行に追加されてるはず・・！
されてない、という人は [Google Apps Scriptを実例交えて基礎からざっくり学ぶ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/gas_beginner) あたりを見ながらデバッグしてみてください。

## スプレッドシートにボタンを作る
最後に、いいねボタンを作ってそれをクリックしたときに上で作ったスクリプト `addMyIcon` を実行するようにしましょう。
スプレッドシート上で以下を行います。

1. メニューから、 挿入 -> 画像 でてきとうなボタン画像を挿入する
    - 図形とかでも OK
    - ボタンは、固定したヘッダの行あたりに置いておくのがおすすめ
2. ボタンの「・・・」をクリックして、「スクリプトを割り当て」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/f8d5ac72-452f-2077-4d25-8f0c3a950711.png)

3. `addMyIcon` と入力

これでボタンをクリックすると、その時選択していた行に自分のアイコンがたされるはず！めでたし！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/bec45127-3a1d-b9d9-db4e-966bef4c2a80.png)

最後にチームに周知してみんなでいいねする雰囲気を作りましょう。
文化を作るのは、人間とツールですよ。
[Swift]returnの前に空行がなかったら怒られたい[Lint]


swiftlintで`return`の前に空行がなかったら怒られたい人用

```yml
custom_rules:
        blank_before_return:
                name: "Needs blank bfore return"
                regex: '\S+\R[ \t]*return'
                severity: error
```

でも、switch-caseでcaseにreturnだけだったら怒られたくない人用

```yml
custom_rules:
        blank_before_return:
                name: "Needs blank bfore return"
                regex: '\S+[^:]\R[ \t]*return'
                severity: error
```

下のだと、これは怒られない

```swift
switch value {

    case 1:
        return 1

    default:
        return 0
}
```