OmniAICreator/Qiita-1.07M huggingface dataset:
デポジットでお金を預けて、判定者を設定して、目標達成できなかったら全額没収！ ( @nodenodenode1 on Twitter )  mobet.gq が気になったので調べてみた。


# [モベット｜お金を懸けた目標はやる気１００倍](https://www.mobet.gq/)

![image](https://user-images.githubusercontent.com/13635059/51376591-0b25c580-1b4c-11e9-8fdc-0ef3f7ed539e.png)

# .gq ドメインとは？

>.gqは国別コードトップレベルドメイン（ccTLD）の一つで、赤道ギニアに割り当てられている。

らしい。

でも、言葉の響きで取得されたやつ。

# クラウドソージングかと思いきや違う？

![image](https://user-images.githubusercontent.com/13635059/51376628-209aef80-1b4c-11e9-93ff-1fa8b4b776dc.png)

# コメントがつけられる

大丈夫？ があるのがツボ

![image](https://user-images.githubusercontent.com/13635059/51376653-2f81a200-1b4c-11e9-9f69-b96ef49c96cd.png)

# 判定の日を過ぎたらどうなるの？

未達成だとお金が徴収されるらしい。

![image](https://user-images.githubusercontent.com/13635059/51376701-4b854380-1b4c-11e9-8068-545bcc29a1e2.png)

# 達成はどうやって判定されるの？

Twitterで報告とかだろうか。

どうやら判定者がいるらしい。

![image](https://user-images.githubusercontent.com/13635059/51376725-62c43100-1b4c-11e9-982a-eff7c2f02a9c.png)

# そもそもお金を預けているらしい

![image](https://user-images.githubusercontent.com/13635059/51376745-6e175c80-1b4c-11e9-89e6-2caf081fd684.png)

# 家族を判定者に

![image](https://user-images.githubusercontent.com/13635059/51376767-7a9bb500-1b4c-11e9-8f24-81bde86899f9.png)

# Stripeを通した決済

![image](https://user-images.githubusercontent.com/13635059/51376779-84bdb380-1b4c-11e9-9187-a6eefac6f677.png)

# Stripe

知らなかった

[Stripe - インターネットビジネスのためのオンライン決済処理 | 日本](https://stripe.com/jp)

![image](https://user-images.githubusercontent.com/13635059/51376796-8dae8500-1b4c-11e9-99fe-eb069a66033a.png)

# 未達成が多ければ多いほど、サービスの収益源になる？

未確認

お医者さんと同じで、サービスが稼げなければ稼げないほど、健康な人が多く、世の中平和系サービスかも。

# 思い出したこと

- 「達成できなかったら、お金を寄付する」だと、失敗しても良いことに使えてしまうので、だめ
- 「達成できなかったら、お金を、自分のポリシーに反する政党に寄付する」とかだと、死んでも目標達成したという話も聞いた

---

https://twitter.com/YumaInaura

https://github.com/YumaInaura/YumaInaura/issues








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Chrome を使った e2e テストの <input type=date> への入力に注意

以下のような日付入力欄があったとします。

```html:index.htmlの抜粋
<input type="date" name="start-date">
<input type="date" name="end-date" min="2019-05-01" max="2019-05-15">
<input type="date" name="other-date" min="2019-04-01" max="2019-05-15">
```
イメージ図: [![Image from Gyazo](https://i.gyazo.com/d9e5ebd0addccbfdd7c15362b0b25be0.png)](https://gyazo.com/d9e5ebd0addccbfdd7c15362b0b25be0)

罠1: `<input type=date>` は西暦275760年まで対応している
---------

`<input type="date" name="start-date">` に対して `20190523` という入力を行うと、 **201905年02月03日** の入力になる。これは `20190523` の `201905` が「年」、 `2` が「月」、 `3` が「日」として入力されるため。

[![Image from Gyazo](https://i.gyazo.com/4c82e12ab87cea36721c8c6a50aa2bd0.gif)](https://gyazo.com/4c82e12ab87cea36721c8c6a50aa2bd0)


こういう入力フォームを持つページを puppeteer でなにかするようなスクリプトを書くとこの罠にはまる。西暦をゼロ埋めしてあげると思った通りの入力になります。

```js:scraping.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({headless: false});
  const page = await browser.newPage();
  await page.goto('http://127.0.0.1/index.html');
  // 201905年2月3日になる
  await page.type('input[name="start-date"]', "2019-05-23");
  // ゼロ埋めしてあげると 2019年05月23日になる
  await page.type('input[name="start-date"]', "002019-05-23");
})()
```

罠2: Chrome の `<input type=date>` に `min` や `max` を指定すると、年や月のセクションが入力不可になる可能性がある
-----

`<input type="date" name="end-date" min="2019-05-01" max="2019-05-15">` に対して `20190123` という入力を行うと、 **2019年05月23日** になる。理由は以下の通り。

1. `min` と `max` として `2019-05-01` から `2019-05-15` を指定しているため、「年」と「月」が `2019` 年 `05` 月で固定されて入力を受け付けなくなっている
2. `20190123` を入力すると、「日」のみがこの入力を受け取る
3. `20190123` の最後の2つの数字(`23`)が「日」に入力される。これでも範囲外なのに！

[![Image from Gyazo](https://i.gyazo.com/9d1ed716b0645ce567331a1d1a93f42b.gif)](https://gyazo.com/9d1ed716b0645ce567331a1d1a93f42b)

同様に、 `<input type="date" name="other-date" min="2019-04-01" max="2019-05-15">` に `20190123` という入力を行うと、 **2019年02月23日** になる。 これは以下の理由による。

1. `min` と `max` として `2019-04-01` から `2019-05-15` を指定しているため、「年」が `2019` 年で固定されて入力を受け付けなくなっている
1. 「月」と「日」が入力対象セクションになっているため、月に`20190123` の `2` が入力される。
2. 「月」に対して `2` を入力すると、その瞬間 `2` 月に確定される。
2. 「日」に残りの `0190123`が入力され、末尾の`23`が入力結果として反映される。

[![Image from Gyazo](https://i.gyazo.com/e7bbee9db807ac8b42e94ee2c9317f6b.gif)](https://gyazo.com/e7bbee9db807ac8b42e94ee2c9317f6b)

Chrome を e2e テストで使うときは日付の入力に気をつけましょう
------

上記の例は puppeteer だけど、 Capybara とかでも Chrome を使ってると当然起こる。普段使うときはカレンダー型のUIを使うことが多いので、数字を直でタイプすると予想外の動きをする。

テストに使用したソースコードは[こちら(gist)](https://gist.github.com/oieioi/57b9aa1435f06e70954830d40640d750)
[Rails] link_toをボタンにして、別タブで表示する方法

##前提

DBにTwitterのURLの内容が保存されている


##やりたいこと

Twitterのiconボタンを押すと、別タブでTwitterページを表示出来るようにする。

##手順
###①アイコン設置
Bootstrap-social をダウンロードし下記コードを追加

```html

<i class="btn btn-social-icon btn-twitter"><span class="fab fa-twitter fa-fw"></span></i>
```

###②リンクをつける

```html
<%= link_to @user.twitter_url do %>
  <i class="btn btn-social-icon btn-twitter"><span class="fab fa-twitter fa-fw"></span></i>
<% end %>
```

###③別タブで表示するコードを追加
別タブで表示させるため、`target: :_blank` を追加

```html
<%= link_to @user.twitter_url, target: :_blank do %>
  <i class="btn btn-social-icon btn-twitter"><span class="fab fa-twitter fa-fw"></span></i>
<% end %>
```

##結論
上記のコードを実行すると、ボタンをクリックすることで別タブでリンクのページに飛んだ。
エンジニアのためのマネジメントキャリアパスに学ぶチーム管理者の中途採用

エンジニアのためのマネジメントキャリアパスで紹介されている、「チーム管理者の中途採用」について纏めてみました。

# 前提
エンジニアであろうと、マネージャーであろうと、「組織が求めているスキルの持ち主であるのか」、「組織の文化に合った人材であるか」を判断することは必要である。


# 確認手法
大きな問題としては、このレイヤーの候補者が果たして「結果を出せる人材」か否か、面接でのコミュニケーションの中での判断が困難なことにあります。
コミュニケーションが重要なスキルになる分野なので、面接のテクニック如何で「煙に巻かれる」可能性があります。
求めているスキルの持ち主かどうか確認するために以下の手法を使います。

## 1on1
- 応募者に「模擬1on1」をやってもらう。
- チームメンバーに1on1の相手役を務めさせ、いまチームが抱えている問題や解決したばかりの問題を提示し、問題の解決の支援を仰がせる。
- 勤務評価の批判的な面接を行わなければならない、といったような「やりにくい場面」にどう対処するか見極める。

## チームそのものに内在する「バグ」を解消できるか
- 過去にあなたのチームのPJで遅れが出たときにどうしたか尋ねる
- 辞めようと思っている部下を想定した模擬1on1をおこなう
- 成績優秀な部下をどう後押しして昇進させたか
- 部下をどの様にコーチングしたか

## 自身の経営哲学について語ってもらう
- そんなものはない。と答えるよう得あれば危険信号
- 仕事の委任はどうやっているのか？
- 現場の最新の情報はどの様に把握しているのか？

＃＃ プレゼンテーション
- 聴衆にどう向き合い、注意をどうひきつけ、考えをどう組み立てるのかを観察することができる。

## 技術スキル
- これから管理するチームのメンバーに信頼されるレベルの技術的スキルを持っていることをある程度確認する必要がある。
- コードテストも必要に応じてやる
- 技術的質問、デザインやアーキテクチャに関する質問を投げかける

## 　文化に合うかの確認
- まず、面接官が会社の価値観を正しく理解することが必要
- 身元紹介として、採用候補者の前職での働きぶりを徹底的に確認する。

実行に移すのが難しいものもありますが、擬似1on1などは効果的に思えますし、試しやすいのではないでしょうか。
5秒でGitHubを未公開設定にする方法

####ブラウザで自分のgithubアカウントにアクセス


![スクリーンショット 2019-01-18 17.36.48.png](https://qiita-image-store.s3.amazonaws.com/0/325154/8f0049f6-d8b1-4219-c1ac-22ced473ab61.png)


####Settingsをクリック&コピー 　　クリコピして下さい。
![スクリーンショット 2019-01-18 17.46.40.png](https://qiita-image-store.s3.amazonaws.com/0/325154/7e568e96-4b35-ed5a-c7fb-daecb1568f9a.png)


####一番下までスクロース&クリック           スククリして下さい。
![スクリーンショット 2019-01-18 17.48.54.png](https://qiita-image-store.s3.amazonaws.com/0/325154/c2e4c24e-48c1-772c-ba62-8ec9b05e5ef5.png)

#####Make privateを書いてありますね。プライベートにするよ〜的なことですね。




####先ほど、コピーしたものをペースト　　
![スクリーンショット 2019-01-18 17.52.54.png](https://qiita-image-store.s3.amazonaws.com/0/325154/4881c6a1-e482-011a-b6da-1e13ffec11d2.png)


#####本当にできたの？
![スクリーンショット 2019-01-18 17.56.41.png](https://qiita-image-store.s3.amazonaws.com/0/325154/47f66e82-ade0-29c5-104d-af0dbf94eebc.png)

####Privateってなってますね〜。OKです〜。

ご質問、ご指摘等あれば、コメント下さい。
よろしくおねがいしまぁぁぁすっ!!（サマーウォーズ風)
Railsで招待フォームを作成しよう1


動画で説明した内容にそって、このフォームをRailsで作成していきたいと思います。
https://youtu.be/JaMzNhCxt_I

![google_form.png](https://qiita-image-store.s3.amazonaws.com/0/39073/1e5ca859-ab1a-9782-09f5-4dcfe8503c07.png "google_form.png")



```bash:terminal
rails generate scaffold User name:string email:string sex:integer age:integer address:integer attendance:integer opinion:text
```

```bash:terminal
 vi app/models/user.rb
```

```ruby:app/models/user.rb
class User < ApplicationRecord                                                                                                                                
  enum sex: { male: 0, female: 1 }
end
```

```bash:terminal
 vi app/views/users/_form.html.erb
```

Viewファイルを、radioボタンに変更

```erb:app/views/users/_form.html.erb
<%= form.label :sex %>
<%= form.radio_button :sex, 'male' %>男性
<%= form.radio_button :sex, 'female' %>女性
```
Windows > Network > bashとncを実行できる環境の簡易構築 (seqコマンドはない, brace expansionは無効?)

```txt:動作環境
Windows 7 Pro (32bit)
```

### 目的

bash + ncを使ったUDP送信機能をWindowsで行う。
そのための環境構築を容易に行う。

### ためしたこと

Git for Windows + NMap 

これらをインストールしたが、ncコマンドは別途必要?

### 良さそうなもの

別途、下記を見つけた。
https://ltside.com/kizyo/cmd.html

cmd.zipを解凍し、`C:\cmd`として配置した。
(Note: `■コマンド`のリンク先が`C:\cmd\com.bat`となっている)

`■コマンド`のショートカットからコマンドプロンプトを開き、下記のUDP通信ができること (相手側が受信すること)を確認できた。

```
$ echo test | nc -w 1 -u 192.168.10.3 6000 
```

### 関連

- [linux > 5秒ごとにUDPで文字列を送信するbashスクリプト (不完全版)](https://qiita.com/7of9/items/1cf64a125784db309100)


### 備考1 > ショートカット（絶対パス）

~~ショートカットのリンク先を相対パスで定義しておけば、`c:\cmd\`以外のフォルダでみ使えるだろう。
ショートカットで指定するパスを相対パスで指定する方法
https://www.projectgroup.info/tips/Windows/comm_0058.html~~
(実施してみたが、ウィンドウサイズの設定が有効にならなかった。explorerで新たにコマンドプロンプトを起動した時にウィンドウサイズの設定が使われない、という推測）


または、com.bat自体を使う。
`■コマンド`にてウィンドウサイズの指定はしているようだ。`com.bat`を直接使った場合は、それらの設定は当然ない。


### 備考2 > seqコマンドはない

```
$seq
bash: seq: command not found
```

seqコマンドはないため、seqを用いたループの実装は使用不可。

### 備考3 > brace expansionは無効?

brace expansionのコード(例: 下記)でもエラーとなった。
https://ideone.com/cWsMf5
【jQuery】今更jQueryを使用する人への基本の使い方

# はじめに
今更感しかありませんが、jQueryについて業務で使用した部分をおさらいで記載します。

# 取得
## 位置
```javascript
$("要素").offset().top;
$("要素").offset().bottom;
$("要素").offset().left;
$("要素").offset().right;
```
## 高さ
```javascript
$("要素").height();           //height
$("要素").innerHeight();      //padding-top + padding-bottom + height
$("要素").outerHeight();      //border-top-width + border-bottom-width + innerHeight
$("要素").outerHeight(true);  //margin-top + margin-bottom + outerHeight
```
## 幅
```javascript
$("要素").width();            //width
$("要素").innerwidth();       //padding-left + padding-right + width
$("要素").outerwidth();       //border-left-width + border-right-width + innerwidth
$("要素").outerwidth(true);   //margin-left + margin-right + outerwidth
```

# 追加
```javascript
$("要素").append("追加要素");   //要素内部の後ろに追加
$("要素").prepend("追加要素");  //要素内部の前に追加
$("要素").after("追加要素");    //要素外部の後ろに追加
$("要素").before("追加要素");   //要素外部の前に追加
$("要素").wrap("追加要素");     //要素を追加要素で個別にそれぞれ囲む
$("要素").wrap("追加要素");     //要素を追加要素で一つに囲む
```
# 削除
```javascript
$("削除要素").remove();   //要素内部の後ろに追加

```

# CSS
## スタイル追加
```javascript
$('要素').css('プロパティ','値'); //単体
$('要素').css({'プロパティ':'値','プロパティ':'値'}); //複数
```
## 要素を非表示
```javascript
$('要素').css('display','none');
```

# ウインドウがリサイズされたら実行
```javascript
$(window).resize(function(){
実行内容
});
```

# おわりに
記載ミス等ありましたら、コメント頂けると幸いです。
動画のレスポンシブ対応メモまとめ


## 動画埋め込みと自動再生のおさらい

動画埋め込みの種類

- videoタグ
- youtube、vimeo等のiframeタグ

###■ videoタグ

```
<video controls autoplay muted loop playsinline poster="hoge.jpg">
  <source src="hoge.mp4" type="video/mp4">
</video>
```

####自動再生
autoplay属性追加。muted必須！
iOSインライン対応用にplaysinline追加。

その他のオプション
https://developer.mozilla.org/ja/docs/Web/HTML/Element/video

今回の検証で気が付いたけど、
ブラウザの可視範囲に入った時だけ再生されるようになっている（！）

とは言え、全ブラウザではないので別途jsで制御が必要。

対応

- chrome
- safari 
- Android Chrome
- iPhone Chrone

未対応

- firefox
- IE11
- Edge

### ■ youtube

iframeのコードをコピペ
リンクの共有 > 埋め込む > 動画の埋め込み

#### 自動再生
パラメータでautoplayにチェック、選択したオプションを使用してプレーヤーを更新してコードをコピペ
https://developers.google.com/youtube/youtube_player_demo

### ■ vimeo

#### 埋め込みコードをコピペ
埋め込み > オプションを適宜設定 > 埋め込みコード

#### jsで制御する場合

1.script読み込み

```
<script src="https://player.vimeo.com/api/player.js"></script>
```

2.動画読み込みの準備

```:js
 var player = new Vimeo.Player($('#hoge'), {
    id: ID,
    autoplay: true, // 自動再生
    autopause: false, // 2つの動画を埋め込む場合、同時再生を制御する
    muted: true, // 自動再生の際は必須
    loop: true, // 繰り返し
    background: true // controlを非表示にしてミュート、繰り返し再生する
  });
```

その他のオプション
https://developer.vimeo.com/player/sdk/embed

3.動画読み込み

```:js
 player.on('play', function(){
   // 再生後の処理
 });
```

## レスポンシブ対応

###■videoタグ

####直接タグに指定する

```
// widthに%で指定する

<video controls autoplay muted loop playsinline poster="hoge.jpg" width="80%">
  <source src="hoge.mp4" type="video/mp4">
</video>
```

####cssで制御する場合

```:css
video {
  width: 80%; // 適宜指定
}
```

###■iframe
youtube、vimeo等iframeで埋め込みの場合はwidthに%が対応してないので
アスペクト比の計算をして適宜調節する

```:css

// 親要素

hoge {
  width: 80%; // 適宜指定
  height: 0;
  position: relative;
  padding-bottom: 56.25%; // アスペクト比16:9 = 9/16 * 100%
}

// 該当のiframe

hoge iframe {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
```

おわり！
静的ファイルのホスティングの性能評価

firebaseかnetlifyかどちらの方が、転送が早いのか検証してみた。

# 結論

firebaseのほうが転送は高速。

# 検証結果

Google Chromeにて、数十KBのJSONファイルをaxios(XHR)の読み込みで検証。

- firebase
  - 初回: 300-400ms
  - 二度目以降: 20ms
- netlify
  - 初回: 500-600ms
  - 二度目以降: 80ms

# 余談

個人的な愚痴だが、「netlifyは簡単だ」と言われるが、結構しんどかった。

- netlifyはGitHubとBitbucketとGitLabしか対応してない
    - Azure DevOpsは対応してない
- `yarn`コマンドが失敗する
- `npm install`を毎回しないとビルドができない
    - `cd ◯◯◯ && npm i && npm run generate`ってコマンドをビルドコマンドにしている
    - つまり時間がかかる
-  Nuxtのgenerate（`npm run generate`）にも時間がかかる
-  Nuxtのサーバーサイドレンダリングで`axios`の通信が失敗する
    - 以下のログを参照
    - `127.0.0.1:3000`ってIPなんか知らんわ
    - よって、サーバーサイドレンダリングは失敗する

```
ERROR  [Axios] Response error: connect ECONNREFUSED 127.0.0.1:3000
 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14)
```

netlifyは構築が大変なうえに、転送が遅いことで、もう採用することはないなと思ってしまった･･･。
Laravel5.7 初期値投入（シーディング）

Laravel勉強し始めたのでメモです。
- [「Laravelインストール直後の設定変更、テーブル作成」](https://qiita.com/uma18/items/1105b172d4eb97c27c30)の続きです

- [参考サイト：laravel5.7 seeding英語](https://laravel.com/docs/5.7/seeding)
- [参考サイト：lLaravel 5.7 データベース：シーディング](https://readouble.com/laravel/5.7/ja/seeding.html)

# シーディングとは
- テストするためのデータを初期値として登録するための仕組み
- シーダーと呼ばれる

### 対象ファイル置き場：[app\database\seedsにファイルが生成される]

artisanでm_os_typeマスタテーブルに対応するシーダーを作成します。

```shell
php artisan make:seeder MOsTypeTableSeeder
```
MOsTypeTableSeeder.phpが、app\database\seedsに作成されます。

```php5
use Illuminate\Database\Seeder;

class MOsTypeTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}
```

追加する値をMOsTypeTableSeederに追記します。
復数レコード追加の仕方が分からないので、2つ書いています。

```php5
<?php

use Illuminate\Database\Seeder;

class MOsTypeTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $nowDate = Date('Y-m-d H:i:s');
        DB::table('m_os_type')->insert(
        [
            'id' => '1',
            'os_type_name' => 'iOS',
            'created' => $nowDate,
            'modified' => $nowDate,
        ]);
        DB::table('m_os_type')->insert(
        [
            'id' => '2',
            'os_type_name' => 'Android',
            'created' => $nowDate,
            'modified' => $nowDate,
        ]);
    }
}

```

シーダーを実行します

```shell
$ php artisan db:seed --class=MOsTypeTableSeeder
```

値を確認すると入っていました。
vimを起動した状態でシェルにいきたい時、戻りたい時

#毎回:qするのがめんどい
例えば、エラーが出力されて、vim開いて、再度エラー確認のために:qしてまた開いて・・・みたいなシチュエーションが面倒。
一回の:qならまだいいかもしれませんが、NerdTreeを使っていると、二回:q打たないといけないのが面倒です。![スクリーンショット 2019-01-18 17.15.55（2）.png](https://qiita-image-store.s3.amazonaws.com/0/257845/c8fc20c8-ac56-94e4-509a-3cbfd7fb689e.png)

タブを別で開くとか、ターミナルの画面を分割するとか解決策って他にも色々普通にありますが、そうも言ってられない時ってあると思うんです。。。タブで開くことも、画面分割も他の用途で使用してしまっていて、もうタブ増やしたくない！とか、これ以上画面を分割したら小さくなりすぎる！etc...
筆者はMac book Airを使っているので、よくこうなります。

# なので、vimにはバックグランドに行ってもらう

下記のキーを押すと、実行中のプログラムがバックグラウンドでの実行モードへと切り替わります。

```
ctrl + z
```

そうすると下記のようにシェルに戻って来てくれます。私の使っているプロンプトでは、vim-fontとの併用で、バックグラウンドに実行中のプログラムがある場合、歯車が出る仕様になっています。
![スクリーンショット 2019-01-18 17.19.29.png](https://qiita-image-store.s3.amazonaws.com/0/257845/ce1fe1ff-dd35-cc16-d318-daaafe36e9f9.png)

# vimに戻りたい時
戻りたい時は、fgコマンドを使ってバックエンドに行ったvimをフォアグラウンドに戻してあげられます。

```
#  fg
```
VisualStudio 2019 Preview でDjangoリモートデバッグ

たまたま上手くいったのでメモです。
[[remote host IP]]などは都度読み替えてください。
VS2019 Previewのインストールについては記載しません。
今回の環境は以下

```
手元の開発環境
Windows10
VisualStudio Enterprise 2019 Preview Version16.0.0 Preview1.1

リモートサーバ
CentOS7
uWSGI-2.0.17.1
Python3.6.7 (virtualenv)
Django==2.1.4
ptvsd==4.2.0
```

リモートサーバでの操作
DjangoがインストールされたPython仮想環境にptvsdをインストール(最新で問題なかった)
`pip install ptvsd`

リモートデバッグしたい任意のアプリコードに以下を追記

```views.py
import ptvsd
ptvsd.enable_attach(address=('[[remote host IP]]', 5678), redirect_output=True)

....
....

def index(request): # Djangoのビューメソッド
    ptvsd.break_into_debugger()
    ....
    ....
```

Djangoアプリを起動
デバッガが接続するための5678/tcpポートは開けておく
`firewall-cmd --add-port=5678/tcp --permanent
firewall-cmd --reload`

VSでの操作
メニュー->デバッグ->プロセスにアタッチ
「プロセスにアタッチ」ウィンドウで接続先をtcp://[[remote host IP]]:5678 として更新
一覧に表示されるプロセスを選択しアタッチ
break_into_debugger()メソッドの位置まで来たらVSにリモートのコードが表示され、ステップ実行できるようになる
Railsでカラム追加無しにcountのN+1を回避する。

countはそのままだと、繰り返しクエリーが発行されてしまう。そのためのカウンターキャッシュだが、
カウンターキャッシュは、カラム追加が必要だし、eager_loadingしても、countは無視される。
ということで、吐き出す直前で、comments_countのメソッドを定義してcount値を追加してあげる。

```
comments_count = Comment.group("item_id").count　#1
items.map{|item| item.instance_eval("def comments_count; @comments_count;end;"); #2
item.instance_variable_set(:@comments_count,comments_count[item.id].to_i);item} #3
item.comments_count # 42
```

\#1 でやっていることは、最初にグループのカウントクエリで、1クエリで全部取ってくる。
\#2 でカウンタインスタンスメソッド
\#3 でカウンタのセット

メソッドで定義することで、モデル内で処理できるので、後の出力で扱い易い。
同じ要領で特殊な集計結果も持つ場合がある場合にも、同じようにモデル内に入れ込むこともできます。
カウンターキャッシュを持たせるのが重たい場合に、検討の価値があるかと思います。
Dockerコンテナ・イメージの保存先を変更する【CentOS 7】

#概要
CentOS 7でDockerをインストールすると、コンテナ・イメージの保存先は「/var/lib/docker」に保存されます。
機械学習系の作業をしているとメインのディスクをガンガン消費して辛いので、
別のパーティションで動かすための手順をまとめました。

※yum install docker-engine でインストールしたDockerです。
※コンテナ/イメージの移行は含まれません。
※設定ファイルを触る際はバックアップを忘れないようにしましょう。

## 作業環境
```bash

[root@test01 ~]# cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core)

[root@test01 input]# docker version
Client:
 Version:      17.05.0-ce
 API version:  1.29
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:06:25 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.05.0-ce
 API version:  1.29 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:06:25 2017
 OS/Arch:      linux/amd64
 Experimental: false
 ```

#Docker ユニットファイルの設定変更

Dockerサービスを停止し、
Dockerサービスの起動を管理するユニットファイル内のExecStartの箇所を以下のように変更します。

```bash

[root@test01 ~]# systemctl stop docker
[root@test01 ~]# vi /lib/systemd/system/docker.service
~~~ 前略 ~~~
ExecStart=/usr/bin/dockerd -g /hogehoge/docker
~~~ 後略 ~~~
```
変更後、Dockerサービスを起動すれば完了です。

```bash

[root@test01 ~]# systemctl daemon-reload
[root@test01 ~]# systemctl start docker

[root@test01 lib]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 
     Docs: https://docs.docker.com
 Main PID: 18127 (dockerd)
    Tasks: 20
   Memory: 17.3M
   CGroup: /system.slice/docker.service
           ├─18127 /usr/bin/dockerd -g /hogehoge/docker
```

参考
・[Docker-docs-ja デーモンのフラグ一覧](http://docs.docker.jp/engine/reference/commandline/dockerd.html)
.NET Framework で COM を書くと CLR の Access Violation が発生するときは InterfaceTypeAttribute を書き忘れていないか確認するべし

# 前提
.NET Framework で CoClass を実装して登録し，そのクラスが外部のアプリケーションから呼び出される。

# こねくりまわした環境
.NET Framework 4.5
Windows 10 (x64)

# 結論
interface の宣言に， `InterfaceTypeAttribute` を設定していなかった。

## だめだったコード
``` cs
[ComImport]
[Guid(~~~~)]
public interface Hoge
{
  // ~~~~~
}
```

呼び出し元プロセスに Visual Studio でアタッチするとこのような例外が表示された。
![AccessViolation.png](https://qiita-image-store.s3.amazonaws.com/0/317529/76680382-de25-7b27-fa0c-fe083dd14887.png)



## うまくいったコード
``` cs
[ComImport]
[Guid(~~~~)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface Hoge
{
  // ~~~~~
}
```
[](タイトル原案: C# で COM Server を作ろうとしたら，clr.dll が Access Violation するときに確認すべきこと)
[](タイトル案: .NET Framework で COM Server を作ろうとしたら CLR の Access Violation に悩まされた話)
[](もっといいタイトルのつけ方ありませんかね……)
# 以下，解決までの経緯

## 落ちる
C# で COM に登録するクラスを作って実験していたところ，特定のタイミングで呼び出し元のアプリケーションが落ちる。
C# で書いた部分に問題があると考え，try-catch など普段通りデバッグを行ってみるも，これらのすべてに到達せずに落ちる。何の前触れもなく。

## デバッガを接続してみる
Visual Studio をそのプロセスに接続してから実験を行うと，このような表示が。
![AccessViolation.png](https://qiita-image-store.s3.amazonaws.com/0/317529/76680382-de25-7b27-fa0c-fe083dd14887.png)

:thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking:

## 落ちるタイミングの特定
実験を続けていたら，少なくともこのタイミングで落ちるということが特定できたので，コードを減らして実験をしたところ，
C# で書いたクラスのインスタンスを COM を通して外部から呼び出されるように登録するコードを実行しない，あるいは登録後すぐに登録を解除したところ，落ちないことが分かった。

## 見つける
登録メソッドに渡す引数の型を確認して，渡すクラスの宣言を確認し，インターフェースの確認をしたところで， `InterfaceTypeAttribute` をこのインターフェースだけ書き忘れていることがわかり，書き加えたところ登録をしてもアクセス違反が発生しなくなった。

# 場合によってはアクセス違反にならず，別のメソッドが呼ばれる可能性？
自分の場合は，後ろから3番目のメソッドが呼び出されるときにアクセス違反になっていたのだが，~~メソッドが4つ以上あるインターフェースの，最初に書かれたメソッドが呼び出されるような場合はもしかすると4番目のメソッドが呼び出されるかもしれない。~~

~~`IUnknown` が `QueryInterface`, `AddRef`, `Release` の3つを持っているため，3つずれた結果，自分の場合は存在しない領域を参照してしまっていたのではないかと考えている。[要検証]~~ Access Violation した。よくわからない。
【一年生の頃の私へつづる言葉②】ショートカット暗記をさぼらなければ、幸福化促進

・今となっては、当然のごとく使用していることを、ただ手紙としてしたためるだけの記事の第二弾。
・やはり「Orange」ごっこは、ただただ「時間跳躍している自分」に浸れるこの上ないひと時。
・よし。今回は会社に入社した頃の私へ、「使用頻度の高いショートカット集」を送ろう。
・「これが届いた当時の私よ。これをまずはしっかり覚えて、時間効率化と趣味極限満喫に励みなさい。」
## ショートカット
### ＜当時＞
- 「Excel」・・・日報や設計書等に、毎日使用のExcel。入社当時知っていたものは、コピーや貼り付け・切り取りや戻る等の基本的なもののみ。  
→Excel使用経験も薄かった私にとって、簡単な作業に時間かかり、残ることは茶飯事。  
- 「Google Chrome」・・・毎日自己成長に多大な貢献をしてくれるChrome。  
→多彩な対応キーがあることを知らなかった私は、これはマウス作業で行うものだと思い込み、またしても時間がかかる。
- 「thunderbird」・・・未使用日が皆無のメールツール。  
→Chrome同様に、対応キーの豊富さを知らない私は、これもマウス作業で時間かかる。
- 「Visual Studio Code」・・・文書作成や開発等、毎日使用するエディタ。  
→使用経験があったため、ある程度は使えた私だが、まだ青二才だったことを自覚しないまま、作業に時間がかかる。  

→これらの相乗効果により、この頃の私のテレビは、放送時間に見れなかった録画番組であふれかえる。　　

### ＜現在＞
下記のショートカットを覚えたことで、作業時間が大幅短縮。  
※必須であったもののみ。コピーや貼り付け等の基本的なものは対象外。   
作業を時間内に完了できる日がほとんど。堂々と楽しく放送時間内でバラエティやドラマに浸る。  

- ***Excel***

|対応キー|説明|
|:---:|:---:|
|Ctrl + PageUp|前のシートへ移動|
|Ctrl + PageDown|後のシートへ移動|
|Ctrl + D|上のセルをコピー|
|Ctrl + R|左のセルをコピー|
|Ctrl + P|印刷プレビュー|
|Ctrl + ;|日付入力|
|Ctrl ＋ :|時間入力|
|Ctrl + Space|列選択|
|Shift + Space|行選択|
|Shift + F11|シート挿入|
|Shift + F2|コメント追加|
|Ctrl + Shift + ;|セル挿入|
|Ctrl + -|セル削除|
|Ctrl + Shift +  L|フィルタ|
|Alt + Enter|セル内改行|
|Alt +  + F8|マクロ表示|
|Alt +  + F11|VBA表示|
|Alt + O + H + R|シート名変更|
|Alt + V + P|改ページ|
|Alt + W + F + F|ウィンドウ枠の固定|
|Alt + H + B + A|セルに格子罫線をつける|
|Alt + H + B + N|罫線解除|
|Alt + H + H|セルの背景色|
|Alt + O + R + A|行幅自動調整|
|Alt + O + C + A|列幅自動調整|
|Alt + E + I + S + F|オートフィル|
|Alt + Shift + =|オートサム|

- ***Google Chrome***

|対応キー|説明|
|:---:|:---:|
|Ctrl + N|新規ウィンドウ表示|
|Ctrl + T|新規タブ表示|
|Ctrl + Shift + T|閉じたタブの再表示|
|Ctrl + W|タブを閉じる|
|Ctrl + Shift + W|全てのタブを閉じる|
|Ctrl + Tab|タブ右移動|
|Ctrl + Shift + Tab|タブ左移動|
|Ctrl + 数字|タブ（数字指定）移動|
|Ctrl + L|アドレスバーへカーソル|
|Ctrl + D|ブックマーク追加|
|Ctrl + H|履歴表示|
|Ctrl + Shift + Delete|履歴削除|
|Ctrl + J|ダウンロードページ|
|Ctrl + F|検索|
|Ctrl + R|更新|
|Ctrl ＋ U|HTMLソース表示|
|Ctrl + Shift +  ;|画面サイズ拡大|
|Ctrl + -|画面サイズ縮小|
|Ctrl + 0|画面サイズ標準化|
|F12|デベロッパーツール表示|
|Shift + Esc|タスクマネージャー表示|

- ***Thunder Bird***

|対応キー|説明|
|:---:|:---:|
|Shift+ C|一括既読|
|Ctrl + R|返信|
|Ctrl + K|全フォルダからメール検索|
|Ctrl + Shift + K|特定フォルダからメール検索|
|Ctrl + N|新規メッセージ作成|
|Ctrl + Enter|送信|
|Ctrl + Shift + A|ファイル添付|

- ***Visual Studio Code***

|対応キー|説明|
|:---:|:---:|
|Ctrl + Enter|カーソル行下に空行追加|
|Ctrl + Shift + Enter|カーソル行上に空行追加|
|Ctrl + D|ハイライトされた文字列を選択する|
|Ctrl + Shift + L|ハイライトされた文字列と同じものを全て選択する|
|Ctrl + F|選択ファイル内検索|
|Ctrl + Shift + F|全ファイル内検索|
|Ctrl + H|選択ファイル内置換|
|Ctrl +Shift + H|全ファイル内置換|
|Ctrl + G|行指定移動|
|Ctrl + /|コメントアウト|
|Ctrl + B|サイドバー表示/非表示|
|Ctrl + ,|設定画面表示|
|Ctrl + @|ターミナル移動|
|Ctrl +Shift + P|設定検索|
|Ctrl +Shift + X|拡張機能表示|
|Ctrl +Shift + G|ソース管理表示|
|Alt + ↑|カーソル行上移動（↓で下）|
|Alt + Shift + ↑|カーソル行上コピー（↓で下）|

### ＜過去の私へ送る言葉＞
- <font color = "tomato">最初は大変だけど、二・三個覚えるだけでも違うから、さぼらないで。</font>
- <font color = "tomato">技術力や思考力ではなく、こういうことからしか対応できないけど、周りと比べず焦らずにやっていけば必ず身につくから。</font>
- <font color = "tomato">作業短縮と時間満喫に成功したら、その時間で絶対に好きな歌手のコンサートに行くのですよ。</font>

## まとめ
- 今回は、ショートカット集ということで、当時との成長具合を考えながら、記事を書く。
- 「これを完全に使いこなせてるか」とあらば、全肯定はできないので、今後も焦らず覚えていこう。
- まあ、「非日常浸り症」が顕著な私が、妄想に時間を割かなければの話だが。
プロキシサーバー経由でgem updateがうまくできない

前提：社内環境、プロキシサーバー、Redmineにプラグインをインストールしようとしている

プラグインをPluginフォルダに配置、インストール後、BitnamiのThin_redmineが起動できなくなる。
いろいろな問題にあったが、とりあえずgem updateの問題解決方法をメモしておく。

gem update叩くと

*ErrorHTTPxxx
no such name (https://rubygems.org/specs.4.8.gz)*

のようなエラーが表示された場合
1. プロキシサーバーを設定する
　　set https_proxy=(自分のプロキシサーバーとポート番号)
2. C:\Bitnami\redmine-3.3.0-1_1\apps\redmine\htdocs>gem update --source https://rubygems.org/
でプロキシサーバーを通って更新できた
Mac に anyenv をインストール

### 概要

1 台の Mac で複数のプログラミング言語をインストールし、かつ、複数バージョンを切り替えながら使う、といったユースケースは、よくあると思います。そうなると rbenv やら ndenv やら、言語ごとに、なんとか env が増えて、その度に .bash_profile にパスの設定をしなければならなくなります。  

そんな時は、anyenv を入れておけば、1 度だけ、.bash_profile にパス設定をしておけば OK です！
  
### 参考サイト

* [Mac に anyenv をインストール](https://stangler.hatenablog.com/entry/2019/01/18/161956)
* [riywo/anyenv](https://github.com/riywo/anyenv)
* [anyenvやrbenvのpluginsの更新などをしやすくするプラグインを作った](http://blog.n-z.jp/blog/2013-11-21-anyenv-rbenv-plugins.html)
* [znz/anyenv-update](https://github.com/znz/anyenv-update)
* [znz/anyenv-git](https://github.com/znz/anyenv-git)

### anyenv インストール
  
Git でクローンするだけです。ターミナルを開いて、以下のコマンドでを実行してください。  
  
```
% git clone https://github.com/riywo/anyenv ~/.anyenv
```

### パスを通す
  
#### .bash_profile の編集
  
以下の 2 行のコマンドを実行し、 anyenv 用のパス設定を .bash_profile に追加します。  
  
```
% echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
% echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
```
  
#### シェルの再起動

設定内容を反映させるため、以下のいずれかのコマンドを実行し、シェルを再起動します。

```
% exec $SHELL -l
```
  
or  
  
```
% source ~/.bash_profile
```

### 確認
  
以下のコマンドを実行して、anyenv が動くかどうか確認します。  
  
```
% anyenv
```

以下のような表示が出てくれば OK です。  
  
```
anyenv 
Usage: anyenv <command> [<args>]

Some useful anyenv commands are:
   commands            List all available anyenv commands
   local               Show the local application-specific Any version
   global              Show the global Any version
   install             Install a **env
   uninstall           Uninstall a specific **anv
   version             Show the current Any version and its origin
   versions            List all Any versions available to **env

See `anyenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/riywo/anyenv#readme
```

### anyenv-update インストール
  
#### プラグイン用のディレクトリを作る
  
anyenv を使ってインストールした、なんとか env を一括でアップデートするためのプラグイン「 anyenv-update 」をインストールしておくと便利です。まずは、インストール先となるディレクトリを作成しましょう。  
  
ターミナルで以下のコマンドを実行します。
  
```
% mkdir -p $(anyenv root)/plugins
```

#### インストール
  
Git でクローンします。  
  
```
% git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
```
  
#### 確認
  
正常に稼働するかどうか、確認します。  
  
```
% anyenv update
```

以下のような表示が出てくれば OK です。
  
```
Updating 'anyenv'...
Updating 'anyenv/anyenv-update'...
```

以上となります。
full pathをlsみたいに得る方法

fullpathを得るためにpwd + lsなどを使っていたが手間だったので、ls likeにfull pathを取得できるようにした。
<font color="Red">注</font> ls_fullの引数にディレクトリを指定したときに、正確なフルパスが得られずに、カレントディレクトリのなかパスにつなげて、指定したディレクトリの中身が表示されるケースがあるようです。

```
#current directoryにあるもののfull pathを得る
ls -1 | xargs -n1 readlink -f
#./hoge のdirectoryにあるもののfull pathを得る
ls -1 ./hoge | xargs -n1 readlink -f
```

.bashrcなどに関数として定義する場合

```shell:.bashrc
ls_full () {
        ls -1 $@ | xargs -n1 readlink -f
}
```
```terminal
ls_full -a #カレントディレクトリの中身のフルパスを隠しファイルも含めて表示
ls_full ./hoge
```
### 参考
http://www.koikikukan.com/archives/2018/03/27-000300.php
SlackのincomingWebhooksを使う(投稿編)

### 前提条件

- IncomingWebhooks用のURLを発行していること。
- curlを使用できること。

### 改行コード

- 改行コードを表すには**\n**を使用します。

```
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"あいうえお\nかきくけこ\nさしすせそ\nなにぬねの"}' \
<IncomingWebhooksのURLを貼る>
```

[結果]
![02_1.png](https://qiita-image-store.s3.amazonaws.com/0/239358/648562a0-1199-1dcb-15fc-2b174e29def7.png)

### 絵文字

- 使用したい絵文字を以下より参照(Qiitaでも使えます)

[https://www.webfx.com/tools/emoji-cheat-sheet/](https://www.webfx.com/tools/emoji-cheat-sheet/)

- とりあえず、:sunny::umbrella::cloud::snowman:を使ってみる。

```
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"あいうえお:sunny:\nかきくけこ:umbrella:\nさしすせそ:cloud:\nなにぬねの:snowman:"}' \
<IncomingWebhooksのURLを貼る>
```

[結果]
![02_2.png](https://qiita-image-store.s3.amazonaws.com/0/239358/66388d2a-6e98-0e19-1b3c-44b961f757fb.png)

### メンション

- **@**を使用しても正しいメンションとなりません。以下に解決策が載せられています。

[SlackのIncoming Webhooksでメンションを飛ばす方法](https://qiita.com/ryo-yamaoka/items/7677ee4486cf395ce9bc)
(質問) zipファイルをsjisかutf8かを判定する方法は？（未解決）

2019年3月21日

linux MacOS Bash unzip zip

#１．質問

Windowsで作成されたsjisのzipファイルやMac,Linuxで作成されたutf8のzipファイルがある。
どちらもunzipやzipinfoを使えば、人間が目視でき文字化けを防いで展開できる。

しかし数百あるzipをシェルスクリプトの中でsjisのzipファイルかutf8のzipファイルかを判定する方法がわからない。

シェルスクリプトの中でzipをsjisかutf8かを判定する方法を誰か教えてください。

uchardetは駄目でした

#2.仕様が判明（2019年3月21日）

[ZIPの仕様を日本語でまとめる · GitHub](https://gist.github.com/ysakasin/2edf8d3bf55c6ebf63f82851e302b030#general-purpose-bit-flag)

以上
Rubyで配列を結合して和集合取るときのパフォーマンス

配列と配列を結合して重複を取り除きたい！
そんなときに書き方で迷ったのでめも。

※追記：計測方法をBenchmarkに変更。`Set`を使った方法を追加。（コメント頂いた @takaramさん@scivolaさんありがとうございます！！！）

## どっちが効率いいの？
①`array1 |= array2`
②`array1.concat(array2).uniq!`
③`Set#merge`
④`Set <<`

## 結論
~~②のほうが2.7倍はやい！~~←Beanchmark未使用
④が優勝！
というか`Set`使った③と④が圧倒的に早い！！

すごいぞSet！！
[Setクラスでの集合](https://qiita.com/namitop/items/238ebc4dfc1a367f87a8)

#### Benchmarkを使った計測
```
                   user     system      total        real
|=            21.300000   0.110000  21.410000 ( 21.447536)
concat.uniq!  22.110000   0.030000  22.140000 ( 22.163939)
Set merge      1.090000   0.000000   1.090000 (  1.087682)
Set <<         0.250000   0.000000   0.250000 (  0.253353)
```
```ruby
n = 1_000_000
m = 1

Benchmark.bm(12) do |x|
  x.report("|=") do
    m.times do
      arr = []
      n.times { arr |= [rand(100)] }
    end
  end

  x.report("concat.uniq!") do
    m.times do
      arr = []
      n.times { arr.concat([rand(100)]).uniq! }
    end
  end
  
  x.report("Set merge") do
    m.times do
      s = Set.new
      n.times { s.merge([rand(100)]) }
    end
  end

  x.report("Set <<") do
    m.times do
      s = Set.new
      n.times { s << rand(100) }
    end
  end
end
```

#### 以下Benchmark未使用の計測
```ruby
s = Time.now
arr = []
100000.times do |i| arr |= [rand(100)] end
puts Time.now - s
# 2.124894

s = Time.now
arr = []
100000.times do |i| arr.concat([rand(100)]).uniq! end
puts Time.now - s
# 0.788314
```
Rails5.1以降でIDにhas_secure_token

#Rails5.1以降でIDにhas_secure_tokenを使う
初投稿です。
間違えなどあればご指摘お願いいたします。
よろしくお願いいたします。

---

作品を制作しているときにURLにID、例えば「edit/１」などの値が載っていることが見た目上かっこよくないなと思い
Rails５.1から実装された「has_secure_token」を使用してIDにUUIDを設定していこうと思います。
URLにIDが載ることは同じですが、IDを数値ではなく生成された重複しないIDを設定することで
URLの見栄えもよくあると思います。
多くの方法があると思いますが、自分がやってみたやり方で共感していただければ嬉しいです。

---
早速モデルの生成を行います。
そうすると
少し省略しますが、
userを作成したとします。

```
model/user.rb
migrate/xxxxxxx_create_users.rb
```
このようなファイルができますね。
まずuser.rbから変更しましょう。
はい。

```ruby:user.rb
class User < ApplicationRecord
  ...
    #has_secure_token使用する
    #:idはは明示的にid列にトークンを入れますよってことです
    #　idにpresence: trueをするとエラーになるので注意
    #DBにINSERTされた時の自動で挿入されます
    has_secure_token :id: 
  ...
end
```

```ruby:xxxxxxx_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users, id: false do |t|
      #has_secure_tokenはデフォルトで２４文字を生成します。
      t.string :id, primary_key: true, limit: 24
      ...
    end
  end
end
```

上記のように書きます。
「id: false」でいつも自動で生成されるIDを生成しないようにします。
そして、独自のIDを制作します。
この時のprimary_keyとなる命名は固定されているため特に理由がない場合は「id」を使うことをお勧めします。

---
以上の作業で作成できると思います。
お力になれていたら幸いです。
閲覧ありがとうございます。

##参考
http://www.tom08.net/entry/2017/07/06/225859
https://qiita.com/mitz/items/9dbf5017a48f5961a596
Vimのプラグイン作成に入門した話

# はじめに
こんにちは、ひがしです。
最近Vimのプラグイン作成に興味がでてきてそれでプラグインを作成しました。
Kakkonanという名前の括弧補完プラグインです。
実装の話を書いていこうと思います。

# ユーザー設定の無効化
Vimのプラグインを作っていく上でユーザーの使っている設定と自分の書いたプラグインのコードが衝突する場合があります。
それを一時無効化して処理が終わったら戻す処理を書きます。

```vimscript
let s:save_cpo = &cpo
set cpo&vim

let &cpo = s:save_cpo
unlet s:save_cpo
```

# 入力を受け付ける
今回は`inoremap`を使い、入力を受け付けることにしました。
`()`,`{}`,`""`,`''`,`[]`を補完対象にしたいので

```
inoremap <expr> ( Completion('(')
inoremap <expr> { Completion('{')
inoremap <expr> [ Completion('[')
inoremap <expr> " Completion('"')
inoremap <expr> ' Completion("'")

```

と記述しました。
`<expr>`の引数をつけることで関数を呼び出せます。
`Completion()`関しては後述します

# autoloadを使う
vimには必要になったときに読み込んでくれるautoloadという仕組みがあります。
それを使うのがプラグイン作成のマナーらしいのですが関数名の付け方が少し変わり、
普通に関数名をつけるのではなく
`プラグイン名#関数名`とつけるらしいです。

# 括弧を補完してくれる関数を作る
括弧を保管するだけなら
`inoremap { {}<left>`
でもいい気がしますが、あとあと色々な機能を付け足したかったので関数化しました。

```vimscript
function! Completion(inputObject)
  let canComp = ['(', '{', '[', '"', "'"]
  let compObject = [')', '}', ']', '"', "'"]
  let nowArrayPos = 0

  for i in canComp
    if i == a:inputObject
      return a:inputObject.compObject[nowArrayPos]."\<left>"
    endif
    let nowArrayPos += 1
  endfor

endfunction
```

`canComp`で入力された文字が補完対象の文字かを判断し、関数の返り値に`inputObject`と`compObject`の対応する要素と`<left>`を返します。

# 括弧が消されたときにもう片方も消す動作
括弧が`()`のように連続して続いて、`(`の部分をバックスペースで削除した場合、その対応している括弧も消す機能が必要です。

```vimscript
function! DeleteChar()
  let leftDelete = ['(', '{', '[', "'", '"']
  let rightDelete = [')', '}', ']', "'", '"']

  let cursorLeftChar = GetCursorChar(-2)
  let cursorRightChar = GetCursorChar(-1)

  let tmp = 0
  for i in leftDelete
    if i == cursorLeftChar
      if cursorRightChar == rightDelete[tmp]
        return "\<BS>\<right>\<BS>"
      endif
    endif
    let tmp += 1
  endfor

  return "\<BS>"
endfunction

```
対応する括弧を消す部分は先程の括弧を補完する部分を少し変えただけです。
ただ対応した括弧を探すという部分の実装が難航しました。

# カーソルのn文字前の文字を探す
先程の括弧を消す動作に必須なカーソルからn文字前の文字を取得する部分なのですが

```vimscript
function! GetCursorChar(diff)
  let cursorStr = getline('.')
  let cursorCol = col('.')

  return cursorStr[cursorCol + a:diff]
endfunction
```

と実装しました。
vimでは`getline('.')`でその行の文字列を取得することができます。
そこから`col('.')`でカーソルのある列番号を取得し、
`getline('.')`で取得した文字列の`col('.') - n`も要素を取り出すことでn番目の文字を取得することができました。

# できたもの
[Kakkonanのリポジトリ](https://github.com/higashi000/Kakkonan)
このリポジトリにおいてあります。

# 最後に
今は括弧が補完できるだけなので次はビジュアルモードで囲んだところを指定した括弧でくくれるようにしたいです

# 参考にした文献
https://vim-jp.org/vimdoc-ja/usr_41.html#41.11
https://vim-jp.org/vimdoc-ja/map.html
https://qiita.com/bonjin6770@github/items/31e60707ecf2ad6c4496
bashからfishに変更したらanyenvでエラー

bashからfishに変更した際にanyenvが既にインストール済みでそのまま利用できると思っていたがダメだった。

```
> fish -v
fish, version 3.0.0
```

## 原因
bash時代にrbenv等**env系が既に入っていた。

## 対処
anyenvで管理している**envを全てアンインストールする。

## 最後にanyenvのfish設定

``` ~/.config/fish/config.fish

set PATH $HOME/bin $HOME/.anyenv/bin $PATH
anyenv init - | source
```

## 参考
[今更だがanyenvをfishで使う](https://qiita.com/thalathalaylah/items/c2c157099f85f2120a30)
Vuforia + Hololens+ Unityで実行エラー１

# どんな問題がおきた？

Hololens上で、アプリを実行すると

```
StartVuforia
 
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)


StopVuforia
 
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)


StartVuforia
 
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)


Screen position out of view frustum (screen pos 0.000000, 0.000000, 1000.000000) (Camera rect 0 0 1268 720)
 
(Filename: C:\buildslave\unity\build\Runtime/Camera/Camera.cpp Line: 3130)


Screen position out of view frustum (screen pos 1268.000000, 0.000000, 1000.000000) (Camera rect 0 0 1268 720)
 
(Filename: C:\buildslave\unity\build\Runtime/Camera/Camera.cpp Line: 3130)


StopVuforia
 
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)


プログラム '[4216] hogehoge1.exe' はコード -1073741819 (0xc0000005) 'Access violation' で終了しました。
```
となり、アプリが落ちる

UnityEditor上では、問題なく動く。


# 解決方法
Vuforiaの設定で
眼鏡の設定をホロレンズにする。

![vuforiaconfig.PNG](https://qiita-image-store.s3.amazonaws.com/0/24266/fbde7ea2-3f6e-4b4e-8e11-3c1e2d4f9932.png)

参考： https://library.vuforia.com/articles/Training/Developing-Vuforia-Apps-for-HoloLens

# 環境
Unity 2017.4.17f1


# その他
よくある説明記事では、上記設定が記載されてないことが多く、設定抜けがおきたっぽい。
今考えると、ポジション系の注意エラーが出てるので、それもヒントになるかも。
【Docker】Dockerでよく使われるコマンド一覧 

###Docker imageの確認
```docker:command
docker images
```
###Dockerへのログイン
```docker:command
docker login
```
###Docker imageの取得
```docker:command
docker pull <Repository>
```
###Dockerコンテナの稼働状況を確認
```docker:command
docker ps
```
###コンテナの稼働
```docker:command
docker run -it d --name <コンテナ名> <Repository名>
docker exec -it <コンテナ名> /bin/bash
```

###コンテナから抜く
```docker:command
(コンテナに入っている状態)ctrl + p,q
```
###コンテナへの再度ログイン
```docker:command
docker attach <コンテナ名>
```
###コンテナの終了
```docker:command
exit
```
###コンテナの起動
```docker:command
docker start <コンテナのIDまたは名>
```
###コンテナの停止
```docker:command
docker stop <コンテナのIDまたは名>
```
###コンテナの削除
```docker:command
docker rm <コンテナID>
```
###imageの削除
```docker:command
docker rmi <image ID>
docker image prune(※TAGがNoneの場合)
```
###コンテナの保存
```docker:command
docker commit -m "commit message" <コンテナID> <imageID>:TAG
```
###Docker Hubへのプッシュ
```docker:command
docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname
```
###ファイルのコピー
```docker:command
1.ローカルからコンテナへ
docker cp file <コンテナ名>:/path/file
2.コンテナからローカルへ
docker cp <コンテナ名>:/path/file file
```
###Dockerの容量拡張
```docker:command
docker-machine rm default
docker-machine create -d virtualbox --virtualbox-disk-size "10000" default (※100GB)
```
apollo-androidでGraphQLのCustom scalar typesのマッピングを定義する

# Custom scalar types

GraphQLスキーマ言語のスカラ型で組み込み型(Int, Float, String, Boolean, ID)以外の型はCustom scalar typesとして扱われます。GitHub GraphQL API v4での例をあげると以下のクエリの`avatarUrl`は`URI!型`を返します。(ドキュメントは[こちら](https://developer.github.com/v4/object/user/#fields))

```graphql
query ShowLoginUser {
  viewer {
    avatarUrl
  }
}
```

# apollo-androidでのCustom scalar typesの扱い

[apollo-android](https://github.com/apollographql/apollo-android#custom-scalar-types)では、Custom scalar typesを「CustomType」として扱います。先ほど例にあげた`avatarUrl`は、apollo-androidによってデフォルトでは`java.lang.Object`にマッピングされます。この際次のような例外メッセージが表示されます。

```
Can't map GraphQL type: URI to: class java.lang.Object. Did you forget to add custom type adapter?
```

この問題の解決には、[https://github.com/apollographql/apollo-android#custom-scalar-types](https://github.com/apollographql/apollo-android#custom-scalar-types)が参考になります。今回の場合、次の定義をモジュールレベルのbuild.gradleに定義すればOKです。

```gradle:app/build.gradle
apollo {
    customTypeMapping = [
            "URI": "java.lang.String"
    ]
}
```

また、Date型のようなCustomTypeの場合、build.gradleへの定義に加えて、`CustomTypeAdapter`を定義する必要があります。

# 参考資料

- https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000#Scalar
Qiita投稿方法

# 概要
あるサービス利用のため、外部公開しているURLが欲しくて、Qiitaに新規登録しました。

# 見出し
「#」 1個が 「h1」に相当します。
「##」2個が「h2」に相当します。

# Code
バッククオートで「java:qiita.java　System.out.println("Hello World!");」を囲みます。

```java:qiita.java
System.out.println("Hello World!");
```

# CSS 色付き
インラインコードの中身が CSS の <color> 型の RGB 16進数表記, rgb(), rgba(), hsl(), hsla() 場合横にその色が表示されます。
`#ffce44`
`rgb(255,0,0)`
xscreensaverの自動起動設定（Xubuntu18）

#はじめに
xubuntuビギナーですが、唐突にスクリーンセーバーがほしくなりxscreensaverを入れてみました
しかし、自動起動設定にしても指定した時間にスクリーンセーバーが起動しない…
単にpathが通ってなかったってだけの話だったんですが、忘れないように自分用メモ

#環境
xubuntu 18.04.1 LTS
xscreensaver 5.36

#やったこと
```
~$ vim .profile 
```
/usr/bin を .profile の一番下に追加

```bash:.profile
if [ -d "$HOME/usr/bin/" ] ; then
    PATH="$HOME/usr/bin/:$PATH"
fi
```
##おまけ：xscreensaverの好きなやつ

<b>Barcode</b>
WinではFliqloを愛用しているのでBarcode clockが良い

<b>Circuit</b>
PartsをLotsにしてわちゃわちゃさせてしまう

<b>CubicGrid</b>
シンプルにきれい

<b>Discoball</b>
速く回すこともできる

<b>DymaxionMap</b>
地球が開いたり閉じたりする

<b>FlyingToasters</b>
謎感が良い

<b>Molecule</b>
理系だから眺めちゃう

<b>Pacman</b>
<b>Pong</b>
ついつい応援しちゃう

<b>Sproingies</b>
スピード感

<b>TopBlock</b>
Bribloが好きならおすすめ（操作はできない？）
Django REST Framework:1つのAPIViewの中でリクエストメソッド毎にpermission_classesを分ける

1つのAPIViewの中でGETはどのユーザでもリクエストできるAllowAnyにしたいけれど、POSTとかDELETEは認証済みのIsAuthenticated、もしくは独自のパーミッションに設定したい、というケースが発生した

単純にGETだけはAllowAnyにして、他のメソッドはIsAuthenticatedにしたい場合は `permission_classes  = (IsAuthenticatedOrReadOnly,)` を使用すれば良い

しかし、上記の場合だと、独自で定義したパーミッションまでカバーできないので、今回は以下の方法で対応してみた


```python:
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny
from hogehogehogehoge import MyCustomPermission

class MyAPIView(APIView):
    def get_permissions(self):
        self.permission_classes = (AllowAny, )
        if self.request.method == 'DELETE':
            self.permission_classes = (MyCustomPermission,)
        return super(MyAPIView, self).get_permissions()

    def get(self, request):
        ....

    def delete(self, request, pk):
        ....
```

このようにすると、getメソッドは誰でもリクエストができるAllowAnyとして、deleteメソッドは独自定義した `MyCustomPermission` をパーミッションとして採用することができる
他にも選択肢はある(`IsAuthenticatedOrReadOnly` を拡張したり、継承したクラスを作るとか)けれど、その方法の一つとして...
AS400 STRSDAの覚え書き

# 概要
IBMi開発で使うSDAというツールの、ファンクションキー機能のどうでもいいまとめ

# 入出力フィールドを作るとき
+6　数字表示項目
+9　数字入出力項目
+O　文字表示項目
+B　文字入出力項目

# 画面編集
F1　　　ヘルプ画面
F2　　　なし
F3　　　終了（画面編集から抜ける）
F4　　　フィールドの処理
![image.png](https://qiita-image-store.s3.amazonaws.com/0/238515/adcc2970-6bd9-25c1-3313-8e694db8c4d0.png)

F5　　　なし
F6　　　作業画面の条件付け
F7　　　なし
F8　　　なし
F9　　　追加の表示用レコードの選択
F10　　　データベースファイルの選択
F11　　　画面下に出てくる削除したカラム？のリストを表示非表示
F12　　　終了（画面編集から抜ける）


# Shift+F5の印刷画面にカラム名を表示するか選択できる
Shift+F1

# カーソルの番地を視認しやすく表示する
Shift+F2
![image.png](https://qiita-image-store.s3.amazonaws.com/0/238515/612d2b11-aab2-4935-8f33-bbf612a39273.png)


# SFLPAGやSFLLINを設定する
Shift+F3

# SDA画面を印刷する
Shift+F5

# フィールドがあるところにカーソルを飛ばす
Shift+F7(F6)
NDで見えないフィールドがある場合は、視認できないので、これを使うと便利

# サブファイルＣＴＬを緑に反転する
Shift+F8　

# サブファイルＣＴＬを非表示にする
Shift+F9
初心者がDockerでphpのtimezoneを設定した話

# きっかけ
案件の関係でDockerに初めて触れて、起動・停止の初歩の初歩からやっている最中、PHPのタイムゾーンが違うとのこと
# 基本手順はこの人の通り
https://qiita.com/prg_yukke/items/c23419d779d7f6972258

# うまくいかない
この人の書いてある通りに、修正を行い
`docker-compose down`
`docker-compose up -d`
をしているのに反映されない。

# 原因
原因はbuildしてないことでした。
`docker-compose up -d --build`
これを実行するだけで完了

１時間近くかかりました...
Hexoで作ったブログにPWAプラグイン入た時のメモ

個人的なブログを「ホームに追加」してみたくなり、
PWA対応を入れたのでそのメモです。

※PWA初心者です

## 構成
* [Hexo](https://hexo.io/)
    * A fast, simple & powerful blog framework
* [Theme - phantom](https://github.com/klugjo/hexo-theme-phantom)
* NEW♪ -> [hexo-pwa](https://github.com/lavas-project/hexo-pwa)

## install

README通りだけど
`npm install --save hexo-pwa`

後は、`_config.yml`に設定を追加・編集

## 詰まったこと
### iOSでアイコンが変わらない。。。
iOSは`manifest.json`に書いても読み込んでくれないようです。
headに別途タグを追加する必要があるようです（ﾒﾝﾄﾞｸｾｪ

Googleが**PWACompat**というものを出していた！！！
PWACompatは、headへのタグ追加をやってくれるみたいです！（感謝

ココでいいのか不安ですが、追加しました。

```html:/themes/phantom/layout/_partial/head.ejs
<!-- PWACompat -->
<link rel="manifest" href="manifest.webmanifest" />
<script async src="https://cdn.jsdelivr.net/npm/pwacompat@2.0.7/pwacompat.min.js"
  integrity="sha384-ptgwb3/v69WGur7IwSnWOowVxE7hcRB3DG/EiHdejrw2sFNwUHynFbiRMPxc4hdS"
  crossorigin="anonymous"></script>
```

結果。。。。できた！！！(ノ≧∀)ﾉわぁ～い♪

メモ終わり。

*PWA関係無かった?!*
SafuNet Luna HSM 上のEC秘密鍵を ruby の OpenSSL で利用する



```ruby
require 'openssl'

OpenSSL::Engine.load
engine = OpenSSL::Engine.by_id('gem')
#=> #<OpenSSL::Engine id="gem" name="Gem engine support">

# ECDSA 有効化
ENGINE_METHOD_ECDSA = 0x0020  # see: openssl/engine.h
engine.set_default(ENGINE_METHOD_ECDSA)
#engine.set_default(OpenSSL::Engine::METHOD_ALL) # こっちでも動作する

# HSM 上の EC秘密鍵をロード
# "ecdsa-private-key" はオブジェクトラベル名
ec = engine.load_private_key('ecdsa-private-key')

# 署名して検証
digest = OpenSSL::Digest::SHA256.digest('hoge')
sig = ec.dsa_sign_asn1(digest)
ec.dsa_verify_asn1(digest, sig)
#=> true
```
dotinstall 昔のjavascript入門メモ

# 概要
昔あったレッスンの覚え書きをコピペしただけです。自分用保管。

#別のページに飛ばす
```
window.location.href = 'http://dotinstall.com';
```

#ブラウザの高さ幅を取得
```
console.log(window.outerHeight);
```

#テキストを変更する
```
e.textContent = 'hello';
```

#文字色を赤に
```
e.style.color = 'red';
```

#スタイルを適用(スタイルを作るときはドットを忘れずに）
```
e.className = 'myStyle';
```

#タグを作る
```
var greet = document.createElement('p');
```

#テキストを作る
```
var text = document.createTextNode('hello world');
```

#タグを作って文字を埋める
```
var greet = document.createElement('p');
var text = document.createTextNode('hello world');
document.body.appendChild(greet).appendChild(text);
```

#イベントを設定する
```
document.getElementById('add').addEventListener('click',function(){
//クリックするたび文字を追加する
var greet = document.createElement('p');
var text = document.createTextNode('hello world');
document.body.appendChild(greet).appendChild(text);
});
```
(レポート)N-Agile(仮) 改め NRIアジャイルハブ #7 要件どおりにはなかなかうまく進まない！？～顧客が本当に必要だったものゲーム～ 


![cover-HE3uqyXiIRqPErOteebzcIILTsyUH8UA.jpeg](https://qiita-image-store.s3.amazonaws.com/0/192038/b01cdf8e-3256-cf8b-32ea-e22b41ecf713.jpeg)

# はじめに
社内アジャイルコミュニティの第7回目企画として、「顧客が本当に必要だったものゲーム」をやってみました。
今回はそのレポートです・・・がその前に。

# コミュニティ名決まった件
これまで「N-Agile(仮)」と称していましたが、正式名称が決まりました。
その名も **NRIアジャイルハブ**。

## NRIアジャイルハブとは
NRIアジャイルハブは、
* アジャイルにまつわる様々なプラクティスを実践・実験し、
* 多様な価値観・背景を持つ人々が知識・経験を共有し、
* 我々を取り巻くチーム・組織の文化・マインドを変革し、
* NRIを通じて世界をより魅力的にする。
そんなコミュニティです。

## 大事にする価値観
NRIアジャイルハブは
* 失敗を恐れず実験するマインド
* 変化を楽しむ姿勢
* 多様な人とのつながり
を大事な価値観としています。

・・・ということになりました。今後共よろしくお願いいたします。
Peatix のコミュニティページはこちら。ぜひフォローをば。
https://n-agile-community.peatix.com/view

# 顧客が本当に必要だったものゲームとは

さて、ゲーム。
[反社会人サークル](http://gamemarket.jp/booth/gm1503/) というサークルが作った同人カードゲームで、[例の絵](https://matome.naver.jp/odai/2133468389280396901)をモチーフに、プレイヤー（開発者）たちが木（システム）を育てていく（構築していく）ゲームです。

![画像](https://i2.wp.com/gamemarket.jp/wp-content/uploads/2018/05/DSC_1855.jpg?w=2000)
※ http://gamemarket.jp/game/%E9%A1%A7%E5%AE%A2%E3%81%8C%E6%9C%AC%E5%BD%93%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%A0%E3%81%A3%E3%81%9F%E3%82%82%E3%81%AE%E3%82%B2%E3%83%BC%E3%83%A0/ から借用

カードの一枚一枚が個々のサブシステムというイメージで、木や地面の絵が整合性が取れた状態を保持しながら一枚ずつカードを出していきます。カードはプレイヤーごとに異なる色がついています。（下の画像も参照）

このほかに「要件カード」があって、そこには「木の高さが3枚以上」「地面が4枚以上」「同じ色のカードを連続3枚」などの条件が。
プレイヤーの勝利条件は「要件カードの獲得数＋場にある隣接した2枚以上のカードの枚数」が一番多いこと、です。
つまり「お客さんの要件を満たした上で、ある程度顧客の社内システムの一部分に食い込めば勝ち」という感じでしょうか。

カードを場に出すときに、他のプレイヤーが出したカードを「上書き」することもできるので、以下に他のプレイヤーの邪魔をしていくかという戦略性が重要になってくる、なかなか深いゲームでした。

プレイのイメージが知りたい方は、VTuberがやってたのでこちらをぜひ。
【社会の闇】顧客が本当に必要だったものって？【ボドゲ実況】
https://www.youtube.com/watch?v=6CgkCK0Zdac

# ゲームの様子とレポート

今回の参加者は4人だったので、1組で2ラウンドプレイしました。

ルールを把握しつつ、顧客要件カードを徐々にオープンにしながら、1枚ずつ場に出して「木」を完成させていきます。

![IMG_4858.JPG](https://qiita-image-store.s3.amazonaws.com/0/192038/7c0ad9ac-1396-c9a1-2c21-ef4b76e50289.jpeg)

こちら、ルールを理解しながらやっていった1ラウンド目の完成図。

なんと、一つも顧客の要件が叶えられませんでした。
しかし木（システム）は一応なにか完成しているように見える、ただし継ぎ接ぎだらけで不格好・・・
という、なんだか**よくあるシステム**そのものの状態に。

気を取り直して2周目もやってみたら、みんな慣れたのか要件をそれなりに叶えつつも、他の開発者をひたすら邪魔し出したりと、白熱した攻防が繰り広げられました。

ちなみに、最後に計算する獲得ポイントの単位は***「YTK（やった感）」***という。
やっぱり成果よりやった感が大事、ということか。

# ふりかえり

振り返りがこちら。

![IMG_4859.JPG](https://qiita-image-store.s3.amazonaws.com/0/192038/85b51276-e4e4-94d3-5cf9-8f37e61b9a54.jpeg)

「全体設計」「責任分界点」「顧客要件が矛盾してる」など、実業務を振り返るようなキーワードが頻出。
また、「対戦プレイじゃなくて協力プレイしても面白そう」「顧客要件最初に全部オープンにする」など、バリエーションルールのアイデアも出て、たくさんの学び・気づきが得られた1時間となりました。

# 次回のお知らせ

すみません、#9 が終わってからこれを書いてるので #10 のお知らせです。
次回はこちら。

NRIアジャイルハブ #10 スクラム体験ゲーム ~チーム開発の光と闇~
https://nri-agile-community10.peatix.com/view

来週も金曜昼、MMでお待ちしております！
Swift：CGImage ←→ NSImage ←→ CIImage【変換Extension】

# 概要
Swift4でNSImage，CGImage，CIImageを相互変換するExtention

# NSImgae → CGImage

```swift:
extension NSImage {
    public var cgImage: CGImage? {
        guard let imageData = self.tiffRepresentation else { return nil }
        guard let sourceData = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil }
        return CGImageSourceCreateImageAtIndex(sourceData, 0, nil)
    }
}
```

# NSImage → CIImgae

```swift:
extension NSImage {
    public var ciImage: CIImage? {
        guard let imageData = self.tiffRepresentation else { return nil }
        return CIImage(data: imageData)
    }
}
```

# CGImage → NSImgae

```swift:
extension CGImage {
    public var nsImage: NSImage? {
        let size = CGSize(width: self.width, height: self.height)
        return NSImage(cgImage: self, size: size)
    }
}
```

# CGImage → CIImgae

```swift:
extension CGImage {
    public var ciImage: CIImage {
        return CIImage(cgImage: self)
    }
}
```

# CIImage → NSImgae

```swift:
extension CIImage {
    public var nsImage: NSImage {
        let rep = NSCIImageRep(ciImage: self)
        let nsImage = NSImage(size: rep.size)
        nsImage.addRepresentation(rep)
        return nsImage
    }
}
```

# CIImage → CGImgae

```swift:
extension CIImage {
    public var cgImage: CGImage? {
        let context = CIContext(options: nil)
        return context.createCGImage(self, from: self.extent)
    }
}
```