OmniAICreator/Qiita-1.07M huggingface dataset:
Spec 2019 情報まとめ & Slack 大阪・東京イベントのご案内

# Spec - The Slack Developer Conference

Slack の本社があるアメリカ・サンフランシスコで 10/22-23 に [Spec](https://slack.com/spec) という Slack の技術カンファレンスが開催されました。これは昨年から始まったイベントで、今年が 2 回目の開催でした。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19163/a7247223-0f5a-832e-a8d4-c33c3b3c3548.jpeg" height=400/>

日本からも多くの方が参加されていて、最新のプラットフォームの情報の入手はもちろん、グローバルでの事例の紹介、ハンズオンセッションへの参加や他の開発者との交流を楽しまれていました。イベント会場の様子は [#SpecBuilds](https://twitter.com/search?q=%23SpecBuilds&src=typed_query&f=image) という Twitter ハッシュタグでアップロードされている写真を見てもらえるとわかるかと思います。

この Qiita 記事では、いち早く Spec での発表内容をキャッチアップしたい日本の方向けにすでに公開されている情報のポインターを整理してみたいと思います。また、本社から Slack チームが日本に来て登壇するイベントのご案内も最後にあります。

# 公式ブログ（日本語）

公式ブログの発表が、英語だけでなく、日本語を含む言語でも提供されています。まずはこちらを読んでみてください。

* [大きく進化した Slack アプリツールキットのご紹介](https://slackhq.com/intl-ja-jp-introducing-a-dramatically-upgraded-slack-app-toolkit)

また、このブログ記事からもリンクされていますが、一日目のキーノートでも登壇した Ellie Powers より、今回の Slack Platform のアップデートについてより技術者向けの内容を紹介しています（こちらは英語のみです）。

* [Introducing the Slack app toolkit](https://medium.com/slack-developer-blog/introducing-the-slack-app-toolkit-3d509a15f41b)

# キーノートビデオ （英語）

英語のみとなりますが、キーノートのビデオはすでに YouTube で公開されています。一日目は Platform の新機能等の発表、二日目の方は Slack エンジニアリングチームが共有チャンネル、デスクトップアプリ刷新などのプロジェクトで、どのように Slack をつくっているかについて話しています。どちらもかなり面白い内容になっていますので、ぜひご覧ください。

* [Spec 2019 Opening Keynote: Product and Vision](https://www.youtube.com/watch?v=NKv8Y8SkyUA)
* [Spec 2019 Keynote: How Slack Builds Slack](https://www.youtube.com/watch?v=zx-wuTJXjtQ)

# API ドキュメント

API ドキュメント・その他公式サイトにも新機能に関する内容が反映されています。

* https://api.slack.com/surfaces
* https://api.slack.com/authentication/basics
* https://api.slack.com/block-kit
* https://api.slack.com/tools/block-kit-builder
* https://slack.com/intl/ja-jp/features/workflow-automation

# Tiny Spec （日本でのイベントです！）

この Spec の内容を日本の方に日本語でお届けするイベントが 11/7 に大阪、11/12 に東京で開催されます。Slack 本社の Developer Relations から二人来日して登壇します :wave:

* [11/7 大阪 (WeWork LINKS UMEDA) イベント](https://slackcommunity.com/events/details/slack-osaka-presents-tiny-spec-osaka-slack-developers-osaka-kickoff/#/)
* [11/12 東京 (Slack 大手町オフィス) イベント](https://slackcommunity.com/events/details/slack-tokyo-presents-tiny-spec-tokyo/#/)

特に東京はすでに残席がかなり少なくなっています。ご興味のある方はお早めにご登録ください！

Slack Platform Community には Slack のワークスペースもあります。[こちらの招待リンク](https://join.slack.com/t/community/shared_invite/enQtNzYxNzM5NzU0Mzg3LWFhZjE3ZjY1M2JhM2MzNGNmMmE0Zjc4Y2E5NDc2NGJiODAxNDMzN2Y1MjVlYWU3ZGVlYzhlMDVhNzA0Nzg1OGY)からぜひご参加ください。参加されたら以下のチャンネルにまず入られるとよいかと思います。

* #lang-japanese
* #spc-tokyo-chapter
* #spc-osaka-chapter
* #slack-api (shared channel with Bot Developer Hangout Workspace)

皆さんにお会いできることを楽しみにしています :open_hands:
Python Gui

# 初めに

　Pythonによるローカル動作のソフトウェアにおいて、GUI実装には主に３つのライブラリにて実装される場合が多い。

- Qt
- wxWidgets(wxPython)
- Tkinter

あと、そもそもwebアプリケーション的に作成し、GUIはWebブラウザ側にお願いするという方法もある。そうなると、以下のライブラリが考えられる。

- Django
- Flask

Djangoは機能が多く、ローカル動作のソフトウェアで使用するには不要であると考えるため、今回はFlaskに絞る。

## Qt

　QtはC++で実装されたオープンソースである。Pythonによる使用には主に以下のライブラリを使用することが多い。
PyQtの場合は、ネット上の情報量も多く、使用しているエンジニア人口も多い。

- PyQt
- pyside

　QtはGPL、LGPL、商用ライセンスの３つが提供されている。PyQtはGPL、pysideはLGPLで提供され、それぞれに商用ライセンスがある。
商用ライセンスを使用しなくても、GPLおよびLGPLは特に商用利用を禁止していないが、GPLはソースコードの公開義務があるため、製品に採用するのは難しい。商用ライセンスは約●●万円であるため、引き合いが多くないとうま味はない。

## wxWidgets

　wxWidgetsは、プラットフォーム依存しないライブラリである。フォームをOS内蔵のものを使用するため、ソースコードの使いまわしが可能である。
また、「WxFormBuilder」を使用すると、ドラッグ&ドロップにてGUIを作成でき、実装工数が削減できる。しかし、作成には癖があり、それに対する情報も少ないため、一度ハマると抜け出すのが難しい。


## Tkinter

　Tkinterはpython標準に入っているGUI用ライブラリである。基本的には表のようにGUIを作成するようで、比較的プログラミングしやすい。他と違ってドラッグ&ドロップでGUIを作成する支援ソフトはないが、ハマるポイントも少ないから工数がむやみに増えない。デザインを気にする必要がなければ採用すると良い。

## Flask

　これはwebアプリケーション用のフレームワークである。デザインに重きを置いた場合、Web系の方がかっこいいので、こちらを採用した方ばいい。GUIサイドはJavascript実装になることが考えられるため、必要な知識は多いが、フレームワークを上手く使えば工数削減に繋がる。ネットワークに繋がっていること前提であればCDNでライブラリを引っ張っても良い。jinjaテンプレートを使っても良いが、可能であればGUI側はJavascriptで記載した方が管理上ごちゃごちゃしない。
【備忘録】storybookのaddon-knobsとaddon-vue-info併用時に、knobsでのprops変更が2回目以降反映されないとき

## バージョン情報

```
@nuxt　2.10.2
@storybook 5.2.5
storybook-addon-vue-info 1.3.2
```

## 問題点
タイトルの通り

- addon-vue-info  
コンポーネントの情報を表示するアドオン
- addon-knobs  
コンポーネントのpropsをstorybook上で変更して動作や見た目を確認できるアドオン

上記を併用した際に、knobsのパネルでpropsを変更したところ、
一回目は変更がコンポーネントにも反映されるが、
二回目以降反映されないというバグ？が発生

## なんか解決できた

真因はよくわからない（まだちゃんと調べてない）が、
`.storybook/config.js`に記述していた、
`addDecorator(withInfo)`と`addDecorator(withKnobs)`の順番が原因だったみたいなので備忘録。

withInfo => withKnobsの順だと、正常に動作した。
（あたまのいいひと、おしえてください！）

参考に手元の環境の`.storybook/config.js`をば。

``` .storybook/addons.js
import '@storybook/addon-links/register';
import '@storybook/addon-viewport/register';
import 'storybook-addon-vue-info/lib/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-backgrounds/register';
```

``` .storybook/config.js
import { configure, addDecorator, addParameters } from '@storybook/vue';
import { withKnobs } from '@storybook/addon-knobs';
import { withInfo } from 'storybook-addon-vue-info';
import centered from '@storybook/addon-centered/vue';

import 'normalize.css';
import '~/assets/styl/_base.styl';

// automatically import all files ending in *.stories.js
addParameters({
  backgrounds: [
    { name: 'white', value: '#fff', default: true },
    { name: 'blue', value: '#016FBC' },
  ]
});
configure(require.context('../_app/components/stories', true, /\.stories\.js$/), module);
addDecorator(withInfo);
addDecorator(withKnobs);
addDecorator(centered);
```

抜粋

``` ×：config.js
// 2回目以降うごかない
addDecorator(withKnobs);
addDecorator(withInfo);
```

``` 〇：config.js
// 2回目以降もうごく
addDecorator(withInfo);
addDecorator(withKnobs);
```

自分同様、[2回目以降動かないなーって声](https://tenderfeel.xsrv.jp/javascript/4121/#addon-knobs)はちらほらあったのですが解決策が見つからず、
ひとりあたふたしていたところ偶然直った。
情報としては少ないかもですが、もし同じ境遇の方の参考になれれば幸いです:bow:
enzymeでテキストフィールドの値が取得できない

Reactコンポーネントのテストをenzymeを使って書きます。

ボタンがクリックされたとき、テキストフィールドの入力値を引数に親コンポーネントのメソッドが呼び出されることを検証するテストです。

```jsx:Sample.jsx
class Sample extends React.Component {
    handleClickEvent() {
        const text = document.querySelector('#text-field').value
        this.props.methodExpectedToBeCalled(text)
    }
    render() {
        return (
            <div>
                <input id="text-field" type="text"/>
                <button onClick={()=>{this.handleClickEvent()}}>post</button>
            </div>
        )
    }
}
```

## うまくいくテスト
### mountメソッドで、作った要素にattachする

```jsx:Sample.test.js
test('成功するしWarningも出ないテスト', () => {
    const methodSpy = jest.fn()
    
    const component = mount(
        <Sample methodExpectedToBeCalled={methodSpy} />,
        { attachTo: document.body.appendChild(document.createElement('div')) } // ここと、
    )
    component.find('input').getDOMNode().setAttribute('value', 'hoge') // ここ
    component.find('button').simulate('click')

    expect(methodSpy).toHaveBeenCalledWith('hoge')
})
```

mountメソッドは実際にDOMを構築します。attachToでコンポーネントを追加する場所を指定することで、document.querySelectorで要素を見つけられるようになります。テストからはgetDOMNode()で要素を取得できます。

## うまくいくけどWarningが出るテスト
### mountメソッドで、bodyにattachする

```jsx:Sample.test.js
test('成功するけどWarningが出るテスト', () => {
    const methodSpy = jest.fn()
    
    const component = mount(
        <Sample methodExpectedToBeCalled={methodSpy} />,
        { attachTo: document.body } // ここ
    )
    component.find('input').getDOMNode().setAttribute('value', 'hoge')
    component.find('button').simulate('click')

    expect(methodSpy).toHaveBeenCalledWith('hoge')
})
```

attachToの対象がdocument.bodyだと以下のWarningが出ます。bodyにするな要素指定せよということです。

```console:実行結果
  console.error node_modules/react-dom/cjs/react-dom.development.js:530
    Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.
```

## うまくいかないテスト
### shallowメソッドで、changeイベントをsimulateする

```jsx:Sample.test.jsx
test('失敗するテスト', () => {
    const methodSpy = jest.fn()
    
    const component = shallow(
        <Sample methodExpectedToBeCalled={methodSpy} />
    )
    component.find('input').simulate('change', {target: {value: 'hoge}}) // ここ
    component.find('button').simulate('click')

    expect(methodSpy).toHaveBeenCalledWith('hoge')
})
```

shallowを利用した場合、実際のDOMは生成されないためDOMNodeが取得できません。そのためinput要素が取得できないという結果になります。shimulateメソッドはイベントをシミュレートするものでDOMには影響しません。

```console:実行結果
    TypeError: Cannot read property 'value' of null

      42 |     key: "handleClickEvent",
      43 |     value: function handleClickEvent() {
    > 44 |       var text = document.querySelector('#text-field').value;
         |                  ^
      45 |       this.props.methodExpectedToBeCalled(text);
      46 |     }
      47 |   }, {
```

少しハマったのでメモ。
始めてのanacondaと仮想環境作成

#初めてAnacondaをダウンロードして、仮想環境を作成するまで
初めてAnacondaの仮想環境を構築したが、少し詰まったので、備忘録として残します。

##環境
Macbook proを使用

```terminal
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15
BuildVersion:	19A583
```

##Anaconda-Navigatorインストール後の環境構築

<img width="1153" alt="スクリーンショット 2019-10-29 11.33.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460758/2e3ce339-eaf2-2c69-47f7-4a15698b0c0b.png">

Open Terminalでターミナルを起動し、環境を切り替える。

```terminal
$ conda info -e
# conda environments:
# 現在の環境に*マークがついている。デフォルトはbase環境になっている。
base                  *  /Users/user_name/opt/anaconda3
環境名                    /Users/ユーザー名/opt/anaconda3/envs/環境名
```

ここで、作成した環境に変更する際に以下のエラーが出る可能性がありますが、同じエラーが出た場合はbash

```terminal
# conda activate 環境名　で環境を変更
$ conda activate tf141

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
To initialize your shell, run

    $ conda init <SHELL_NAME>

Currently supported shells are:
  - bash
  - fish
  - tcsh
  - xonsh
  - zsh
  - powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.
```
このようなエラーが出た場合は、エラーに書いてある通り、conda init bashを実行します。


```terminal
$ conda init bash
$ source .bash_profile
$ conda activate 環境名
```

これで、仮想環境を切り替えることができました。あとは、TensorFlowをインストールするだけです。

```terminal
$ conda install tensorflow
# エラーが出なければインストール完了

$ python
# pythonを起動して、tensorflowがインポートできるか確認します。
```

```python
Python 3.7.4 (default, Aug 13 2019, 15:17:50) 
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow
>>> この表示が出てくれれば、インストールできています。

```
巻き上げってなんぞや

「巻き上げ」という概念をご存知だろうか。
これを知らないと思わぬ落とし穴にハマる、ってじっちゃんが言ってたので理解してみた。


## 巻き上げって？
MDNではこう説明されている。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/var
>変数の宣言 (および一般的な宣言) はコードを実行する前に処理されますので、変数はコード内のどこで宣言しても、コードの先頭で宣言したものと等価になります。また、変数を宣言する前に変数を使用することもできます。この動作は、変数の宣言が関数やグローバルのコードの先頭に移動したように見えるため、"巻き上げ (hoisting)" と呼ばれます。

ふむふむ？
言葉だけだとピンとこない。


## 実際に書いてみた

```javascript

var test = "hoge";
 
function func() {
    console.log(test);    
    var test = "fuga";
    console.log(test);    
}
 
func();
```
ここでの出力は以下を期待している。

```
hoge
fuga
```
が、実際の出力は以下になる。

```
undefined
fuga
```

## なんで？
グローバル変数で「hoge」を定義しているのになぜ？
となるが、こいつが巻き上げらしい。

>変数の宣言 (および一般的な宣言) はコードを実行する前に処理されますので

そしてこいつが原因っぽい。
つまり、さっきのコードは実際には以下のように処理されてしまう。

```javascript
 
function func() {
    var test;  // ここで変数の宣言がされてしまう
    console.log(test);    
    var test = "fuga";
    console.log(test);    
} 
```

## どうすればいい？
グローバル変数を引数として渡してやればOK

```javascript

var test = "hoge";
 
function func(test) {
    console.log(test);    
    var test = "fuga";
    console.log(test);    
}
 
func(test);  // 引数を渡す
```
期待している通りの結果が返ってきた

```
hoge
fuga
```
jQuery、スクロールでアニメーションを発火

## jQueryでパララックスアニメーションをやりたい！！！

パララックス＝視差効果
スクロールに応じてアニメーションが動いたり、背景固定でウィンドウがスクロールされてくる、などのエフェクトのことを言います。

今回は、スクロールされたタイミングでアニメーションを発火させる方法についてです。

## 方法

まずベースとなる「ブザウザで現在表示されている画面の高さ(=縦幅)」を取得しましょう。

```JavaScript
let windowSize = $(window).height(); //<- 画面の縦幅
```
スクロールのタイミングとアニメーションを合わせるには、
この発火させたいアニメーションのある要素のTopの高さから、
`windowSize`を引いた値を基準にします。
(=jQueryのscrollTopが取得する値はブラウザ画面の一番上端を0とするので、ブラウザ画面の高さを差し引いてあげないと要素が画面の上部を超えたときに発火してしまう）

この基準を、スクロールの位置が超えた時点でアニメーションを発火させてやりましょう。
具体的には、次のようにします。

```JavaScript
let windowSize = $(window).height(); //<- 画面の縦幅

// スクロールされるたびに発火する
$(window).scroll(function() {
    // 以下の処理で、現在のスクロール位置を求める
    let scrollPosition = $(this).scrollTop();
    // .offset().topでその要素がある位置を求めます。
    if (scrollPosition > $('要素名').offset().top - windowHeight) {
        // スクロール位置がアニメーションしたい要素の位置を超えたタイミングで、発火！
        $('要素名').addClass('アニメーションのClass名');
    }
}
```

あとはこれを応用して、同一のアニメーションなら配列に入れてそれをforeachでぶん回したり、

```JavaScript
let windowSize = $(window).height(); //<- 画面の縦幅

// 同じアニメーションを適用させるのを配列に入れて
let fadeInAnimation = [
    '.className1',
    '.className2',
    '.className3 a',
    '.className4',
    '.className5.className6',
    ]

// あとは同じやり方
$(window).scroll(function() {
    let scrollPosition = $(this).scrollTop();
    //forEachで配列を回してあげる
    fadeInAnimation.forEach((className) => {
        // 今回はthisでその個々の要素を取得する
        if (scrollPosition > $(this).offset().top - windowHeight) {
        $(this).addClass('アニメーションのClass名');
        }
    });
}
```

forEachの対象を配列じゃなくてhtml要素のlistとかでも同じ感じにできます。

## 初回読み込み時にも発火させたい！

上記のやり方だと、そもそもの発火条件がスクロールしたタイミングなので、
ロードした時点でもう画面にアニメーションさせたい要素が入っていた場合対応できない…

初期に読み込ませる要素がすでにわかっていれば、単純に

```JavaScript
if (windowHeight > $('Classとかの要素名').offset().top) {
	$('Classとかの要素名').addClass('アニメーションのClass名');
}
```

これでいいけど、例えば対応ブラウザの画面サイズが複数あるとか、
真ん中くらいでリロードされたとき、それ以前のアニメーションは発火されて欲しいとか。

そういう場合は、もうJS側で勝手にスクロールさせちゃいましょう。

```JavaScript
// 1pxだけ下に自動スクロールさせる。これを読み込み時に走らせてやればいい
$(this).scrollTop(-1);
```

以上、スクロールでアニメーションを発火させる方法でした！
PowerShellでコマンドのパラメータを一覧で表示する方法 | 新人SEの備忘録

SEに必須なドキュメント作成の自動化を目論んでいます。

PowerShellを使用していますが、作業の際に多種多様なコマンドを使用します。
このコマンドのパラメータの一覧が欲しくなる時が多々あるので、一覧の表示方法をメモします。

# そもそもパラメータとは
パラメータとは、**コマンドの追加効果**です。
僕は追記の[-Append]や、文字コードを変更する[-Encode]をよく使います。

ただパラメータという単語が頭に浮ばず、検索に苦労した思い出がたくさんあります。
この記事よ、PowerShell初心者に届け！（届かない）

# 一覧を表示する方法
**[Get-Help (コマンド) -Detailed]**を使用することで表示できます。

```
# exsample [Get-Help]
PS C:\> Get-Help Get-Service -Detailed

名前
    Get-Service

構文
    Get-Service [[-Name] <string[]>]  [<CommonParameters>]

    Get-Service  [<CommonParameters>]

    Get-Service  [<CommonParameters>]


パラメーター
    -ComputerName <string[]>

    -DependentServices

    -DisplayName <string[]>

    -Exclude <string[]>

    -Include <string[]>

    -InputObject <ServiceController[]>

    -Name <string[]>

    -RequiredServices

    <CommonParameters>
        このコマンドレットは、次の共通パラメーターをサポートします: Verbose、
        Debug、ErrorAction、ErrorVariable、WarningAction、WarningVariable、
        OutBuffer, PipelineVariable、および OutVariable。詳細については、
        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216)
        を参照してください。


エイリアス
    gsv


注釈
    Get-Help を実行しましたが、このコンピューターにこのコマンドレットのヘルプ ファイルは見つかりませんでした。ヘルプの一部だけが表示されています。
        -- このコマンドレットを含むモジュールのヘルプ ファイルをダウンロードしてインストールするには、Update-Help を使用してください。
        -- このコマンドレットのヘルプ トピックをオンラインで確認するには、「Get-Help Get-Service -Online」と入力するか、
           https://go.microsoft.com/fwlink/?LinkID=113332 を参照してください。
```

参考
PowerShell/コマンドレットのヘルプの引き方・Get-Help | PukiWiki 1.5.1
https://win.just4fun.biz/?PowerShell/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E3%83%98%E3%83%AB%E3%83%97%E3%81%AE%E5%BC%95%E3%81%8D%E6%96%B9%E3%83%BBGet-Help
Node.jsでSOAP Clientを生成する際のoverridePromiseSuffixオプションについて

[公式のgithubに書いてある](https://github.com/vpulim/node-soap#options)んだけど、備忘のために記載する。

node-soapでクライアントを生成すると、自動で「（オリジナルメソッド名）＋Async」という非同期用のメソッドが生成される。
が、対象となるWSDLに「（オリジナルメソッド名）」「（オリジナルメソッド名）＋Async」の２種類がもともと定義されてると、node-soapが作ろうとする「（オリジナルメソッド名）＋Async」と元の定義がぶつかってエラーになってしまう。
このための回避オプションとして`overridePromiseSuffix`というのが用意されている。
`overridePromiseSuffix`でnode-soapがつくるメソッドのSuffixを書き換えることができる。

```
let option = {
       overridePromiseSuffix:"Async2"
    };
let client = await soap.createClientAsync(wsdl_url , option );
```

みたいな感じ。

ちなみに、これやってないと[Promise側のエラー（Error: Cannot promisify an API that has normal methods）](http://bluebirdjs.com/docs/error-explanations.html#error-cannot-promisify-an-api-that-has-normal-methods)が出る。
ここに実例が書いてあるので参考にしましょう。（ここに記載されてるのはnode-soapではないけど）
WSL + ubuntu + docker で Composer 実行時にerrorする場合

こんなエラーが出た。

```shell
[ErrorException]
  file_put_contents(/var/www/vendor/bin/psysh): failed to open stream: No such file or directory
```
コンテナ内でシンボリックリンクが張れていない。

```shell
root@380bcf931eed:/var/www# ll /var/www/vendor/bin/psysh
ls: cannot read symbolic link '/var/www/vendor/bin/psysh': No such file or directory
l--------- 1 root root 0 Oct 28 02:57 /var/www/vendor/bin/psysh
```

マウント元確認

```shell
lrwxrwxrwx 1 erySandriver erySandriver   22 Oct 28 11:57 psysh -> ../psy/psysh/bin/psysh*
```

コンテナ内で同様に貼りなおす

```shell
root@380bcf931eed:/var/www/vendor/bin# rm psysh
root@380bcf931eed:/var/www/vendor/bin# ln -s psysh ../psy/psysh/bin/psysh
```

手動で無理やり感満載だけど、できた。

```shell
root@380bcf931eed:/var/www# composer update
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: barryvdh/laravel-debugbar
Discovered Package: encore/laravel-admin
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
【勉強用】GitHubへ公開鍵を登録するときのメモ

##免責事項
この記事は初心者視点でザックリとした説明をしています。正確性に欠ける可能性がございますが、ご了承ください。「明らかに違うよ」ということがありましたら、ご指摘くださると幸いです。

##環境
OS：最新版ではないMacOS
VirtualBox：5.2.26
Vagrant：2.2.6
Ubuntu：ubuntu/bionic64 v20181129.0.0


##目次
1. 公開鍵認証の解説
2. Githubへ公開鍵を登録


#1. 公開鍵認証の解説
###公開鍵認証とは
公開鍵認証とは、サーバーへのログイン時に認証を行う仕組みであり、ユーザー名とパスワードを使用した認証と比べ、よりセキュリティや柔軟性が高いのが特徴です。 いっぽうで、若干設定が難しいという欠点もあります。 パスワードを使った認証では、ユーザー名とパスワードという2つの情報だけで認証を行います。

このとき、パスワードは暗号化されずに直接サーバーに送信されるため、たとえばサーバーがハッキングされていたり、別のサーバーによって成りすまされていたりといった場合、パスワードは簡単に盗まれてしまいます。

公開鍵認証を利用することで、このような問題を解決することができます。

###公開鍵認証の仕組み
公開鍵認証では、「公開鍵（public key）」と「秘密鍵（private key）」という、2種類の鍵情報を利用して認証を行います。

「秘密鍵」は、その名の通りクライアント側のPCや端末等に格納され、秘密（非公開）にしておく認証情報です。
「公開鍵」は認証を行うサーバー側にあらかじめ何らかの方法で渡しておく認証情報です。

また、公開鍵を利用することでデータを暗号化することができます。
秘密鍵（とパスフレーズ）を利用することで、公開鍵で暗号化したデータを複合することができます。

（引用：https://ja.osdn.net/projects/winscp/wiki/public_key）

これらの仕組みを使うことで、秘密鍵とパスフレーズの2重の認証が必要なので安心です。

#2. Githubへ公開鍵を登録
今回は、クライアント側でLinux（Ubuntu）のSSHを利用し、公開鍵と秘密鍵を作り、公開鍵をGitHubサーバーに登録します。

###①公開鍵と秘密鍵を作る。

コンソールで以下のように入力してください。

```
$ ssh-keygen
```
すると、コンソールに以下のように表示されます。

```
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ユーザー名/.ssh/id_rsa):
```
作成するファイル名がid_rsaで良いかを尋ねられていますが、そのままでよいのでEnterキーを押します。
（~/.sshディレクトリがない場合、ディレクトリが作成されます。）
続いて、以下のように表示されます。

```
Enter passphrase (empty for no passphrase):
```
この鍵を利用するためのパスフレーズを入力します。公開鍵を使うたびに毎回聞かれるので、忘れないようにしておきましょう。

```
Enter same passphrase again:
```
再度確認のパスフレーズを入力すると、以下のように表示されます。

```
The key fingerprint is:
The key's randomart image is:
```

これは指紋（finger print）で、SSHクライアントからSSHサーバーへ最初に接続するとき、SSHサーバーを識別するのに利用されます。

例えば、アリスがボブの公開鍵を検証したい場合、彼女は電話や直接会うなどの方法でボブと連絡をして、ボブの公開鍵の指紋を読み上げてもらうか、指紋が書かれた紙を渡してもらう。アリスはこの信頼できる指紋が入手した公開鍵の指紋と一致するかを確認することができる。
（ウィキペディアより）

さて、これで公開鍵と暗号鍵が完成しました。
鍵は ~/.ssh の中に保存されていますので、下記のコマンドで確認してみましょう。

```
$ ls ~/.ssh
```
すると、以下のように表示されます。

```
authorized_keys  id_rsa  id_rsa.pub
```
id_rsaが秘密鍵、id_rsa.pubが公開鍵を意味します。

#2. 公開鍵をGitHubに登録
続いて、GitHubサーバーに公開鍵を登録していきます。
以下のコマンドで公開鍵を表示します。

```
$ cat  ~/.ssh/id_rsa.pub
```
すると、

```
ssh-rsa AJNFUF2373IFIJOFKP82jsIjoffh.......
```
のような公開鍵情報が表示されます。

GitHubを開いて、Settingsページに入ります。
![スクリーンショット 2019-10-29 11.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374924/adfafb1b-fd9c-597c-3d03-041003b106c0.png)

Settingsページの左側のSSH and GPG keysという箇所をクリックします。
![スクリーンショット 2019-10-29 11.50.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374924/520f8b4d-d7a4-48a4-83bb-8171617c5329.png)

右上のNEW SSH keyという緑色のボタンをクリックし、
好きなTitleを入力します。Titleはクライアントユーザーの名前などが良いでしょう。
次にKeyに先ほど作った公開鍵を入力します。
![スクリーンショット 2019-10-29 11.53.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374924/f12738fb-bd58-45d4-2cef-19c1e838e4b7.png)

入力したら、Add SSH keyボタンをクリックします。
これで、GitHubサーバーとクライアント（あなたのPC）がSSHを利用した暗号化通信をできるようになりました。

gitでpushやpullをする際に、先ほど秘密鍵を生成した際に入力したパスフレーズが毎回聞かれるので忘れないようにしておいてください！

##参考
「N予備校 プログラミングコース」
https://www.nnn.ed.nico/
「ssh-keygen - 認証用の鍵を生成 - Linuxコマンド」
https://webkaru.net/linux/ssh-keygen-command/
「【Linux】SSH 公開鍵認証の設定手順【図解】」
https://go-journey.club/archives/5222
GCPのGPUが利用できるリージョン・ゾーンを表にした

[公式](https://cloud.google.com/compute/docs/gpus/?hl=ja)に書かれているけど、リージョンだけじゃなくゾーンによっても有る無しが有り過ぎた。
どこのゾーンが一番GPUを利用しやすいのか考える時に毎回見るの辛い問題があったので、表に落とす。

もし更新があれば編集リクエストください。

# GPUのリージョン・ゾーン毎のGPU利用可否表（2019/10/29時点）

| Region | Zone | V100 | P100 | K80 | P4 | T4 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| us-west1 | a | ○ | ○ |   |  | ○ |
|          | b | ○ | ○ | ○ |  | ○ |
|          | c |   |   |   |  |   |
| us-west2 | a |   |   |   |   |   |
|          | b |   |   |   | ○ |   |
|          | c |   |   |   | ○ |   |
| us-east1 | b |   | ○ |   |  |   |
|          | c |   | ○ | ○ |  | ○ |
|          | d |   |   | ○ |  | ○ |
| us-east4 | a |   |   |   | ○ |   |
|          | b |   |   |   | ○ |   |
|          | c |   |   |   | ○ |   |
| northamerica-northeast1 | a |   |   |   | ○ |   |
|                         | b |   |   |   | ○ |   |
|                         | c |   |   |   | ○ |   |
| southamerica-east1      | a |   |   |   |   |   |
|                         | b |   |   |   |   |   |
|                         | c |   |   |   |   | ○ |
| us-central1 | a | ○ |   | ○ | ○ | ○ |
|             | b | ○ |   |   |   | ○ |
|             | c | ○ | ○ | ○ | ○ |   |
|             | f | ○ | ○ |   |   |   |
| europe-west1 | b |   | ○ | ○ |  |  |  |
|              | c |   |   |   |  |  |  |
|              | d |   | ○ | ○ |  |  |  |
| europe-west4 | a | ○ | ○ |  |   |   |
|              | b | ○ |   |  | ○ | ○ |
|              | c | ○ |   |  | ○ | ○ |
| asia-east1 | a |   | ○ | ○ |  |  |  |
|            | b |   |   |   |  |  |  |
|            | c | ○ | ○ | ○ |  |  |  |
| asia-northeast1 | a |   |   |   |   | ○ |
|                 | b |   |   |   |   |   |
|                 | c |   |   |   |   |   |
| asia-southeast1 | a |   |   |   |   |   |
|                 | b |   |   |   | ○ | ○ |
|                 | c |   |   |   | ○ |   |
| asia-south1 | a |   |   |   |  |   |
|             | b |   |   |   |  | ○ |
|             | c |   |   |   |  |   |
| australia-southeast1 | a |   |   |  | ○ |  |  |
|                      | b |   |   |  | ○ |  |  |
|                      | c |   |   |  |   |  |  |

※ ここに記載の無いリージョンではGPUは提供されていません。

こうやって見ると、 us-central1 が GPU毎に最低2ゾーンで展開されている。可用性考えるならここかな。

欲を言えばすげぇ歯抜け感あるし管理が面倒なので、ゾーン死亡時の影響や Design for failer を考えると、リージョン単位で良いので全てのゾーンをカバーして考えないようにして欲しい。  ~~GPUが高いからアレなんだろうけど~~

とはいえ、AWSも新しめのゾーンにはGPU無かったり少なかったりするし、でかいGPUも物量が少なかったりするし、見えにくいだけでそこまで変わらないかな。
Capacitorパッケージ名変更手順

# Capacitorパッケージ名変更手順

## android/ios配下に手を加えていない場合

### パッケージ名変更

```diff:capacitor.config.json
- "appId": "xxx.xxx.xxx",
+ "appId": "yyy.yyy.yyy",
```

```npx cap sync;```では反映されていない様子。
android/ios配下を削除し、android/ios追加からやり直す。

```bash
rm -rf android/; npx cap add android;
rm -rf ios/; npx cap add ios;
```

## android/ios配下に手を加えている場合

### パッケージ名変更

Visual Code などで各ファイル一括置換

### ディレクトリ構成変更

android/app/⁨src/⁨main⁩配下のディレクトリ構成を
パッケージ名に合わせて変更

これで上手く行った様子
Djangoでwebサイト作成時のHtmlのデフォルトでの日時の指定をする場合の書き方

Djangoでメモアプリを作成しており、日時を2019/12/31とsubmitしようとしたところ、Enter a valid date. という表示が出て??になった。
調べたところHtmlでのデフォルトでは/ではなく、-で間をつなぐのが正解らしく2019-12-31と打ち込んだら無事submitできた。
しょうもないミスだが備忘録として
【駆け出しWEBエンジニアのためのメモ】オススメサイトと検索方法（Google,Railsなど）

#背景
最近、10年のブランクをへてプログラムを猛勉強中でして、特に未経験のWEBプログラミング（Rails）に挑戦しております！

やはりわからないことが多すぎて大変です^^;
聞ける人が周りにたくさんいるわけではないので、そんな時はネットで調べる必要がありますよね。

ただ、ネットには情報が溢れてますし、どの情報を参照すれば良いのか、またどのように取り出せば良いのか困ることもしばしば。

そんな中、信用度の高いオススメの情報源・WEBサイトや、知っておくと便利な検索方法について学びましたので、備忘のため、こちらにメモしておきます（TECH::EXPERTでの学びを参考にしております）。
※他にも見つけたら随時更新させていただきます。

#オススメのWEBサイト（Railsなど）
●　Qiita（キータ）：https://qiita.com/
本記事も掲載させていただいてる、こちらのサイトですね。
日本発の日本で最も有名なプログラマの技術情報共有コミュニティと言われております。
日本語で検索しやすいのが良いですね。
気に入った記事はストックしていつでも見れますし、熱心な方も多いので、間違っている情報があれば指摘しあって質を高めあっております。
現在はユーザー数約250万人、日々の投稿数約200件、これまでに投稿された記事数17万件だそうです、すごい！

●　Stack Overflow（スタック オーバーフロー）：https://stackoverflow.com/
世界で最も活用されるエンジニア専門のQ&Aサービスと言われております。
ほとんどが英語のページになりますが、技術的な問題に対する回答が最も多く集まっております。
現在は700万もの記事をまとめているそうで、日本からの利用者も60万人を超えているそうです。
日本からのアクセスも多いことから日本語版も用意されております（https://ja.stackoverflow.com/ ）。

●　Railsガイド：https://guides.rubyonrails.org/
Railsの解説をまとめたものになります。
更新頻度もそれなりに早いそうですので、最新の一次ソースを得ることができます。
こちらも日本語版がございます（https://railsguides.jp/ ）。


#便利な検索方法（Google）
●　マイナス検索
検索キーワードの頭に「-」をつけることで、そのキーワードを除外できる。

●　フレーズ検索
検索キーワードを「" "」で囲むことで、検索キーワードと完全一致の情報を検索できる。

●　期間指定（検索ツール）
「1年以内指定」などに設定することで、最新記事を見つけやすくなる。

●　複数キーワードでの検索
情報のヒット率をあげるためです。
検索キーワードを4つにしたり、「とは」を併記するのもコツだそうです。

●　英語での検索
英語の方が情報が多いそうです。例えば、「devise ログインURL 変える方法」で検索すると約6700件であったのに対し、「how to change devise login url」で検索すると約60万件だったそうです（TECH::EXPERTでの学びを引用させていただきました）。圧倒的！
　
　
以上です。
コピペ爆速で各言語環境を構築する方法

とりあえずさくっと言語環境だけ入れたいことはままある。ググるのすらめんどくさい！なので、各言語ごとにコピペ(大事!)で出来る環境構築方法をまとめる。※随時更新予定

# 対応言語
- Node.js
- Ruby

# Node.js
```
git clone git://github.com/creationix/nvm.git ~/.nvm
echo 'source ~/.nvm/nvm.sh' >> ~/.bashrc
nvm help
nvm ls-remote
nvm install v10.16.3
node -v
npm install yarn -g
```

# Ruby

```
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build 
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
rbenv --version
rbenv install --list
rbenv install 2.6.5
rbenv global 2.6.5
```

# 参考サイト
- ruby
    - https://dev.classmethod.jp/server-side/language/build-ruby-environment-by-rbenv/
GoogleChromeをキオスクモード実行ショートカット

Chromeでキオスクモードしたかったのでメモ

##Chromeのショートカット作成してリンクを編集

![NoName_2019-10-29_11-27-43_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/b0fb206e-ad75-779e-38b3-bc613e0a96fe.png)

Chromeのショートカット作成して
「リンク先」の末尾に下記のコード追加、URLのところは任意

```
 --chrome-frame --kiosk "http://127.0.0.1:7000/pageA"
```

全部

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --chrome-frame --kiosk "http://127.0.0.1:7000/pageA"
```

一度、すべてのChromeを閉じないと
効果が発揮されないようでした。


##位置を指定したい場合

```
--window-position=-3960,0
```

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --kiosk --window-position=-3960,0
```


##参考サイト

キオスクモードで最新のChrome for Windowsを実行する
https://kotaeta.com/70985394
[メモ] php開発環境 (Windows10, Vagrant, Docker, VSCode)

普段Web関連の開発<font color='red'><b>してない</b></font>個人の開発環境メモ.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/db85454c-c3e1-5198-617e-b55708fae436.png)



# 概要
Vagrantにて、VirtualBoxで centos/7 を起動して、Docker環境をインストール。
php(php:7.3-apache-stretchベース) + mysql(mariadb:10) + phpmyadminの環境を入れる。
Visual Studio Codeで、デバッグする。


# 環境
- Windows 10 64bit

# 手順

1. ホスト側の環境のセットアップ<br>git、Vagrant、VirtualBox、phpとvscodeをインストール

	Power Shellを管理者で開いて、以下を実行

	```bash
	Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
	cinst -y git vagrant virtualbox php vscode
	```

2. ゲスト側の環境のセットアップ<br>Git Bash (コマンドライン) を開いて、以下実行。<br>(ネットワークインターフェースが複数あると、`vagrant up`時に、どれを使うか聞かれる。番号入れて、`[Enter]`)

	```bash
	mkdir -p /c/Vagrant
	cd /c/Vagrant
	git clone https://github.com/mt08xx/phpdev2019.git
	cd phpdev2019
	vagrant plugin install vagrant-vbguest
	vagrant up && vagrant halt
	# しばらく待つ: 15分~ (PC,ネット環境によりけり)
	```

3. php-apache, mysql, phpmyadminのコンテナ起動。<br>以下、実行

	```bash
	cd /c/Vagrant/phpdev2019
	vagrant up
	vagrant ssh
	cp -rv /vagrant/wwwphp /home/vagrant
	cd wwwphp
	rm -rfv www
	ln -sf /vagrant/wwwphp/www .
	docker-compose up -d
	```

4. ブラウザでアクセス<br>ゲスト内で、`ip addr show eth1` にて、IPアドレスを取得して、ホスト側(Windows)のブラウザを開いて、アドレスバーに、IPを入れる (phpinfo()が表示されるハズ)
  - http://xxx.yyy.zzz.www で wwwphp/www 内の index.phpを表示
  - http://xxx.yyy.zzz.www:8081 (8081番ポート)で phpmyadminが起動する

	```shell-sesstion:実行例(192.168.1.123がIP)
	[vagrant@localhost wwwphp]$ ip -4 addr show eth1
	4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
		inet 192.168.1.123/24 brd 192.168.1.255 scope global noprefixroute dynamic eth1
		   valid_lft 685178sec preferred_lft 685178sec
	[vagrant@localhost wwwphp]$
	```



5. VSCodeの整備
	1. VSCodeを起動<br>エクスプローラーで、`C:\Vagrant\phpdev2019\wwwphp\www`を開いて、右クリック。<br>`Open with Code`(VSCodeでフォルダを開く)
	2. Extensionをインストールする<br>`Ctrl + Shift + X` を押して、以下のExtensionを探して、インストール<br>(PHP IntelliSenseとphpfmtは、ホストにphpの実行ファイルが必要らしい)
		- PHP Debug
		- PHP IntelliSense  
		- phpfmt   (phpのファイルを開いたら、[F1]をおして、`phpfmt+[Enter]`すると、整形される)
		- HTMLHint
		- IntelliSense for CSS class names in HTML
	3. `index.php`を開く(`Ctrl + Shift + E`で、VSCodeのExplorerを開いて、クリック)
	4. `phpinfo();` の行に、ブレークポイントを張る（行番号の左側のほうをクリック)
	5. デバッグ開始: メニューの Debug > Start Debugging または、[F5] を押す。
	6. ブラウザで、該当のページをひらく。　http://xxx.yyy.zzz.www
	7. 該当箇所で、止まってるはず。あとは、ステップ実行したりして、楽しむ。
	


# その他
- ゲストは、2GBとかでもだいじょぶそう。。<br>`Vagrantfile`の `VM_MEMORY=4096` => `VM_MEMORY=2048`
- ネットワークがいちいち聞かれて面倒なら<br>`config.vm.network "public_network", bridge: ""Realtek USB GbE Family Controller"`<br>のようにしてしまうとよい。
C/C++とC#のファイル共有モード

ずっとC/C++を使ってて、このごろC#も使っているのですが、C/C++とC#でファイルのオープンした後の挙動ががなんか違うぞ、という事に気づきました。
C/C++では他のアプリケーションで使用中のファイルを普通に開くことが出来たのに、C#ではオープン時エラーになります。
コード書いて試してみたら、C/C++とC#でデフォルトのファイル共有モードに相違がありました。なんてこったい(・o・)

環境はWindows/VisualStudioです。

#試したコード
以下はC/C++/C#でテキストファイルに追加書き込みする簡単なコードです。
エラーは省略しています。

```c:C
#include <stdio.h>

void write_c(const char* fname)
{
	FILE *fp;
	fopen_s(&fp, fname, "a+");
	fprintf(fp, "this is c file.\n");
	fclose(fp);
}
```
```C++:C++
#include <fstream>

void write_cpp(const char* fname)
{
	std::ofstream ofs(fname, std::ios::app);
	ofs << "this is cpp stream" << std::endl;
}
```
CとC++では使用中ファイルのオープンに成功して、書き込みも出来ます。

```C#:C#
static void write_sc(string fileName)
{
	using (StreamWriter sw = new StreamWriter(fileName, true))
	{
		sw.WriteLine("this is cs");
	}
}
```
C#では他のアプリケーションで使用しているファイルをオープンすると例外が発生します。

#C#で共有モードを設定して、オープン時のエラーを回避する

```C#:C#
static void write(string fileName)
{
	using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Write))
	using (StreamWriter sw = new StreamWriter(fs))
	{
		sw.WriteLine("this is cs");
	}
}
```
FileStreamコンストラクタの最後のパラメータのFileShare.Writeで書き込み共有を設定しています。これでC/C++と同様に他のアプリケーションで使用しているファイルもエラーなくオープンできます。
CakePHP2.xで論理削除を実装する方法

#はじめに
今更ながらCakePHP2.xでの論理削除を実装したのでメモします。
論理削除の実装にはCakeDC/utilsのSoftDeleteBehaviorを使わせて頂きました。

今回論理削除を実装するにあたり色々調べたのですが、
githubからSoftDeleteBehavior.phpのファイルをダウンロードして、
直接プロジェクトのModel/Behaviorディレクトリに配置する方法は情報があったのですが、
composerでCakeDC/utilsをインストールして
Pluginディレクトリから使用する方法が見当たらなかったので記事にしようと思いました。

もはや需要はないかもしれない…

#環境
Windows7にて作業

PHP 7.3
CakePHP 2.10


#今回使用するプラグイン
[CakeDC/utils](https://github.com/CakeDC/utils)

#実装方法
###１．CakeDC/utilsをcomposerでインストール
プロジェクトディレクトリのルートにて以下のコマンドを実行する。

```
composer require cakedc/utils
```
成功するとプロジェクトのPluginディレクトリにUtilsディレクトリが配置されます。
※php7.3を使う場合composerのバージョンが低いとエラーが出るので注意

###２．テーブルにカラムを追加
論理削除を実装したいテーブルに削除フラグ・削除日時のカラムを追加する。
私の場合以下の設定にしました。

__削除フラグ__
>
名前：deleted
型：tinyint(3) unsigned
※デフォルト値：0

__削除日時__
>
名前：deleted_date
型：timestamp

###３．モデルにSoftDeleteBehaviorを追加
まずはcakedc/utilsプラグインをbootstrap.phpでロードします。
CakePlugin::loadAll()を記述している人は以下のコードはいらないです。

```php:Config/bootstrap.php
CakePlugin::load('Utils');
```

次に、対象のモデルでSoftDeleteBehaviorを利用できるようにします。

```php:Model/User.php
class User extends AppModel{
	public $actsAs = ['Utils.SoftDelete'];
}
```

最後にModel/AppModel.phpに以下のコードを追記します。
このコードの意味合いは、
[CakeDC/utils](https://github.com/CakeDC/utils)のreadme.mdに説明が書いてありますのでそちらを読んでください。


```php:Model/AppModel.php
public function exists($id = null) {
	if ($this->Behaviors->loaded('SoftDelete')) {
		return $this->existsAndNotDeleted($id);
	} else {
		return parent::exists($id);
	}
}

public function delete($id = null, $cascade = true) {
    $result = parent::delete($id, $cascade);
    if ($result === false && $this->Behaviors->enabled('SoftDelete')) {
       return (bool)$this->field('deleted', array('deleted' => 1));
    }
    return $result;
}
```

これで論理削除の実装完了です。


###４．独自のカラム名に変更
SoftDeleteBehaviorで定義されている
デフォルトのカラム名は
削除フラグ：deleted
削除日時：deleted_date
ですが、以下のコードで独自のカラム名に変更ができます。


```php:Model/User.php
class User extends AppModel{
	public $actsAs = ['Utils.SoftDelete'=>['削除フラグ名'=>'削除日時名']];
}
```

###５．削除済みのデータの取得について
findの実行前に以下のコードを実行すれば削除済みのデータも取得できます。
このコードを実行した後にdeleteを実行してしまうと物理削除されるので注意です。
deleteする際は引数をtrueにして再度実行してからであればOKです。（そんな状況があればですが）

```
$this->User->softDelete(false);
```
※User（モデル名）は自分が論理削除を実装したモデル名に変更してください。

#参考
今回の作業の参考にさせて頂きました。

http://www.tailtension.com/cakephp/398/
[cakePHP CakeDCのsoftDelete](https://qiita.com/f_uto/items/9ab67e2bfd7f3de17345)
AngularからFlutterに入る時の勘所（随時更新）

AngularユーザーがFlutterを覚える際、Angularでいうところの〇〇。みたいな思考でスピードラーニングできる箇所があるので詰まりどころと合わせて勘所を随時更新していきます。TSとDartの連想がメインになりそうです。

随時更新していきます。間違った理解があればご指摘いただければと思います。

## Interfaceはない

形はすべてClassとして定義。

## anyはdynamic

any同様基本使うべきでないという認識

## JSON（オブジェクト）をそのまま扱うことはできない

TSの場合Firestoreからの値はオブジェクトとして使えるが、Dartの場合一度Classにマッピング（デシリアライズ？）する必要がある。
デシリアライズは自動化パッケージがたくさんあるが、Fireshipでは手動が[信頼性高い](https://fireship.io/lessons/advanced-flutter-firebase/)とのこと。僕もパッケージを使いましたがうまくいかないシーンがあったので手動を採用しています。エディタの複数カーソルを利用して効率的に行いましょう。

## Nullチェックがめんどい

こういう書き方はできない。

```Bad.dart
if (users?.length) {
  print('$users.length人います');
}

if (users && users.length) {
  print('$users.length人います');
}
```

こうやって書いたら通る（もっといいやり方ありそう・・）

```Good.dart
if (users != null && users.length) {
  print('${users.length}人います');
}
```

## 型の位置

型は変数や関数の前にくる 

TSの場合

```typescript
cosnt demo = (index: number): number => {
  return number;
};
```

Dartの場合

```dart
Number demo(int index) {
  return number;
}
```

## letとかない

[Dartの変数定義時の修飾static/final/const、そしてconst constructorについて](https://qiita.com/uehaj/items/7c07f019e05a743d1022)

### final と constの違い

両方定数。オブジェクトの値を書き換えられるか否かの違い

```dart
final demo = [1, 2, 3];
demo[0] = 4; // OK

const memo = [1, 2, 3];
memo[0] = 4; // NG
```

## private / public

頭に`_`をつけるとprivate的に振舞う（Classの外から使えない）
Windows用コマンドラインインストーラのScoopを使う

scoopは、homebrewとかapt的な位置づけ、Windows用のパッケージマネージャです。公式にはcommand line installerと書いてあります。

- [Scoop](https://scoop.sh/)
- [lukesampson/scoop: A command-line installer for Windows.](https://github.com/lukesampson/scoop)

## scoopのインストール

powershellで以下コマンドを打つだけ。

``` Powershell
iwr -useb get.scoop.sh | iex
```

> Scoop was installed successfully!

と表示されたらOKです。

もしエラーが出た場合は、以下を実行してからリトライになるそうです。

``` Powershell
Set-ExecutionPolicy RemoteSigned -scope CurrentUser
```

なお、インストールにはPowershell必須ですが、インストールが済めばcmdでもscoopが使えます。

## scoopの簡単な使い方

- `scoop list`
  - インストール済のパッケージ一覧を表示
- `scoop install hoge`
  - パッケージhogeをインストール
- `scoop uninstall hoge`
  - パッケージhogeをアンインストール
- `scoop cleanup`
  - インストール済のパッケージの古いバージョンを削除
- `scoop update`
  - scoop自体のアップデート
- `scoop update hoge`
  - パッケージhogeのアップデート

## 参考

- [scoop Wiki](https://github.com/lukesampson/scoop/wiki)
- [Scoop と PackageManagement を使った Windows 環境の構築 - Qiita](https://qiita.com/kikuchi_kentaro/items/77793e4a21db6ffdb7cd)
- [ScoopでWindowsにおける開発環境構築を最適化しよう | さにあらず](https://blog.satotaichi.info/scoop/)
Electronのビルド周りでつまづいたので、切り分けの流れを書いてみる

## 前置き

[electron-vue](https://simulatedgreg.gitbooks.io/electron-vue/ja/)でアプリ作ってた
軽い気持ちでCatalina（OS）に上げたらビルドでエラー吐いた
serveは通る

## ビルドできない問題対処のためにやったこと

### 導入ライブラリのバージョンアップ

ncuを入れてやってみたが、serveすら通らなくなった

### electron-vueでアプリ作り直し

初期と変わらず。
HalloWorldの状態でもビルド不可

### vue createでアプリ作って、electron-builderをadd

HalloWorld -> ビルドOK、アプリも正常に表示されている。
ライブラリ入れてコード移設してビルド -> OK、だが、アプリを開くと白い画面のまま動かず。
serveは正常表示。

とりあえずビルドはできるので、当初の問題は解決。
次の問題解決のための切り分け開始。

## 白い画面問題対処のためにやったこと

### publicPathの追加

vue.config.jsへbaseUrlの追加で解決した、という記事を見かけたため、

```javascript:vue.config.js
module.exports = {
  publicPath: '/'
}
```

を追加してみたが解決せず。
＃baseUrlではプロパティエラーになった

```javascript:vue.config.js
module.exports = {
  publicPath: './'
}
```

```javascript:vue.config.js
module.exports = {
  publicPath: '.'
}
```

上記も試したがNG

### 切り分けのため、背景色を変えて読み込まれているか確認する

TOP画面に表示されるはずのコンポーネントの背景色を変更
serveでは変更を確認できたがビルド後は変わらず

### 導入ライブラリを減らす

vue-routerの削除で解決しました。
これが原因、というか、うまく設定できてなかったようで、外したら問題なく表示されました。

## まとめ

- OSのアップデートをするときはよく考えましょう
- ライブラリを一気に導入するのはやめましょう
テストでアカウント発行するときのメールアドレス（gmailの機能）

自分のメールアドレスが

`ikts.siaavh20@gmail.com`

だった時、

`ikts.siaavh20-test@gmail.com`

ってやると、アカウントとしては一意のユーザを再現できておしらせメールなどは

`ikts.siaavh20@gmail.com`

に届く。（gmailの機能）
コマンドプロンプトでフォルダのファイル数が1件以上の時だけ処理実行する判定の実装

# 課題
* バッチ処理で、targetフォルダにあるフォルダをすべてbackupフォルダに移したい。
* ファイルがなければ実行したくない（ログ出力の関係で）（今回はログ出力は省略）

# 解答
```dosbatch
FOR /F %%i in ('dir /B /S target ^| find /c /v ""') do set DIR_COUNT=%%i
if not %DIR_COUNT%==0 move /Y target\* backup\

pause
```

# 参考サイト

* [ファイル数をカウントする](https://commandprompt.noyokan.com/command/count.html)
* [.bat（バッチファイル）のforコマンド解説。](https://qiita.com/sawa_tsuka/items/67be34bab1fdf3fb87f9)
* [パイプを含むコマンド実行結果を変数に代入したい](http://fpcu.on.coocan.jp/dosvcmd/bbs/log/cat3/set_path/4-0808.html)

# 感想
* ファイルのカウントの仕方
* forコマンドによる代入の仕方
* その際にパイプを含むコマンドを使う場合の対処

これを理解していないとダメだった。
Gitで特定ファイルのcommitを禁止 (Windows)

対象プロジェクトの .git\hooks\pre-commit (UTF-8)

```
#!/bin/sh
for FILE in `git diff --cached --name-only`; do
  if [ $FILE = "XXX" -o $FILE = "XXX/XXX.XXX" -o $FILE = "XXX/日本語.XXX" ]; then
    echo $FILEをコミットしてはいけません。
    exit 1
  fi
done
```
【転載】HADOの技術について

# HADOとは？
[HOW TO START HADO](https://www.youtube.com/watch?v=NTDqqNdZEnU)

# 技術紹介
[HADO戦士を生み出したテクノロジー](https://www.slideshare.net/YasuyukiKado/hado-91654502)
#docker + #Centos で headless #GoogleChrome  を使って URL指定でキャプチャ画像を作成する

```
docker run -it centos
```


```
yum -y install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

yum -y install https://rpmfind.net/linux/centos/7.7.1908/os/x86_64/Packages/ipa-gothic-fonts-003.03-5.el7.noarch.rpm

google-chrome --headless --disable-gpu --no-sandbox -window-size=1024,768 --hide-scrollbars --screenshot='yahoo.png' https://www.yahoo.co.jp
```

```
docker ps 

docker cp <CONTAINER_ID>:/yahoo.png ./ && open yahoo.png
```

![image](https://user-images.githubusercontent.com/13635059/67725956-8abfb980-fa27-11e9-9f82-8131686aa85c.png)

# 参考

[Amazon Linux 2 で Headless Chrome を動かしてみた - Qiita](https://qiita.com/aibax/items/fade7e417f6c096a879b)

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
#git diff を横並びで表示する  ( pip install icdiff -> git icdiff )

- `pip install icdiff`
- `git icdiff`

![image](https://user-images.githubusercontent.com/13635059/67725523-0a4c8900-fa26-11e9-8174-c791bcffa1a9.png)


# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
input type password の autocomplete="new-password" 調査

Firefox 70から新しい属性機能が追加されました。

>以下の状況で、安全に生成されたパスワードを Firefox がユーザーに提案できるようになりました:
>
>    autocomplete="new-password" 属性を設定した <input> 要素。
    新しいパスワードを意図したかにかかわらず、パスワード入力要素でユーザーがコンテキストメニューを開いた。

[Firefox 70 for developers - Mozilla | MDN](https://developer.mozilla.org/ja/docs/Mozilla/Firefox/Releases/70)

developersで失礼。リリース版は
[Firefox 70.0, See All New Features, Updates and Fixes](https://www.mozilla.org/en-US/firefox/70.0/releasenotes/)

便利そうでちょっと気になったのでテスト


# 簡易テスト

## コード

```html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Sample</title>
    </head>
    <body>
        <input type="password" autocomplete="new-password" name="test">
    </body>
</html>
```

## 実行結果

![pass.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/e58da75d-29a3-1766-3949-08f797e82158.png)

表示されたパスワードを選択した時点で、**可視化**された状態でinputに入力され、

![pass2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/6008c615-496b-8ac1-73ca-4604dabcb887.png)

フォーカスを外すと●の表示になる。

また、選択時点でFirefoxにパスワードが記録される。

![pass3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/f42face1-eb7d-7aa8-ec6d-c314c74adf5a.png)


![pass4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/d1fbfad5-873f-e3f9-c5ad-f3c3ebd7297c.png)

input上での右クリックからでも提案を受けることができるが、この場合は選択するまでどのような値が入るかは不明。
ただし値はクリックで提案されるものと同一である。

![pass5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/91b867b2-ce83-7457-f7e2-6b570a0a75f0.png)


このパスワードはサイトリロードや記録されたパスワードの削除を行っても、再び同一のパスワードが提案される。
そのため毎回ランダムな値を生成しているわけではなさそう。

# patternテスト

`pattern`属性で制限された場合、考慮してくれるかを見ておく


```html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Sample</title>
    </head>
    <body>
        <form>
            <input pattern="\d+" type="password" autocomplete="new-password" name="test">
        </form>
    </body>
</html>
```

大方の予想通り値は変わらなかったので、使えない場合も多々ありそう。
まあサーバー側のパターン制限が見えないのでたいした意味はありませんね。

![pass6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62354/36cc9850-593e-9aeb-5642-d9308f5aaeb2.png)

# textでテスト

```html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Sample</title>
    </head>
    <body>
        <form>
            <input pattern="\d+" type="text" autocomplete="new-password" name="test">
        </form>
    </body>
</html>
```

typeをpassword以外にしても動作するかをみましたが、これは当然動作せず。

匿名ユーザーの一時ユーザー名生成などに使えるかなと思ったのですが、かなり用途外ですね。

# 補完条件

MDNでは

[HTML の autocomplete 属性 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete)

>
自動補完を提供するために、ユーザーエージェントは <input>/<select>/<textarea> 要素に次のことを要求することがあります。
>
name や id 属性を持つこと
<form> 要素の子孫であること
フォームが submit ボタンを持つこと

とあるが、サンプルコードでは単体のinptutで動作した。


# 参考

* [フォームの自動補完を無効にするには - ウェブセキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion#Preventing_autofilling_with_autocompletenew-password)
* [パスワード生成機能搭載内蔵の「Firefox 70」正式版リリース、開発者ツールの機能も強化 - GIGAZINE](https://gigazine.net/news/20191023-firefox-70/)
Jupyter Notebookで再現性を確保する10の方法

# はじめに
- 自己紹介：UbuntuでPythonを書いてデータ分析とか異常検知してます
- Jupyter Notebookで再現性を確保する10の方法というpaperが良かった
- https://arxiv.org/abs/1810.08055
- 翻訳しました

# 目次
1. ストーリーを伝える
2. 結果だけでなく過程もドキュメント化する
3. ステップを明確にする
4. コードをモジュール化する
5. 環境の依存関係を記録する
6. バージョン管理する
7. パイプラインを作る
8. データをシェアし、説明する
9. notebookを公開する
10. スタックは共有してOSSに貢献する

# ストーリーを伝える
ストーリーを伝えたい人のレベルに合わせて伝えよう。
「伝えたい人」はエンジニアなのか？技術の知識がない人なのか考えること。
もしかしたら1ヶ月後の自分かもしれない。
 
# 結果だけでなく過程もドキュメント化する
「なぜ」「何を」「どのように」行ったのか記入しよう。

# ステップを明確にする
コードをセル毎にモジュール化し、その上にマークダウンでラベルを付けよう。
各セルは、1つの段落、1つの機能、または1つのタスクを行うように区切ろう。
notebookが長くなりすぎたら、別のファイルに分けても良い。

# コードをモジュール化する
コードのコピペはやめよう。(修正の時が大変だ!)
関数やクラスを作ってそれを呼び出すようにしよう。

# 依存関係を記録する
Condaのenvironment.ymlやpipのrequirements.txtを使って、依存関係を明示しよう。

# バージョン管理する
GitやGitHubを活用しよう。
nbdimeなどのツールで差分を明確化しよう。

# パイプラインを作る
汎用のパイプラインを作ろう。
複雑な分析の実行を長いnotebookで行うのはやめよう。
「欠損処理用」「自然言語のクリーニング用」など小さなnotebookに分割して行おう。
訳注:おすすめEDAスニペット
https://qiita.com/TaigoKuriyama/items/8f9286b5c882819adebb
papermillやMakefileなども試してみよう。
大切なことは継続的インテグレーションだ！

# データをシェアする
結果だけでなく、データセット全体をnotebookそのものを相手と共有しよう。

# notebookを公開する
可能であれば、外部の人にもnotebookを公開しよう。
Github, Docker, Nbviewer などのツールを使ってみよう。

# スタックを共有してOSSに貢献する
再現性は共同研究の重要ポイント。
必要ならば再現性の確保に専念してみよう。
また、問題に突き当たったり、それを解決したときは、ぜひ共有してコミュニティ全体に貢献しよう！

#終わりに
- 「ここがまちがってる」「「こういう資料もあるよ」などコメントお待ちしてます
Laravel 入門　ルーティング

今回は、Laravelのルーティングについて記述していきます。

## ルーティング
特定のアドレスにアクセスしたとき、どの処理を呼び出して実行するかを管理するのがルーティング
ルーティングは各Webページを管理する基本となります。



### routesフォルダ
本来Webサイトは、Webサーバー上にディレクトリとファイルを用意しておくと、そのパスがURLになります。
しかし、Laravelでは特定のアドレスにアクセスすると、そのアドレスに割当てられたプログラムが実行され、それにより必要な処理や画面表示が行われます。

あるアドレスにアクセスすると、ある処理を呼び出すという関連付けを記述しているのがルーティング

routesフォルダには複数のファイルが用意されている

```
api.php  :  APIルーティング
channels.php  :  ブロードキャストチャンネルのためのルーティング
console.php  :  コンソールプログラムのためのルーティング
web.php  :  一般的なWebページとしてアクセスするためのルーティング
```

Web公開するものは、web.phpで設定する。

#### ルート情報の基本構文

```
Route::get( アドレス , 関数やコントローラなど );
```

GETアクセスのルート情報は、Routeクラスの get という静的メソッドを使って設定します。
第一に割り当てるアドレスを、第二引数にはそれによって呼び出される処理を用意し、
処理は関数やコンロトーラを指定します。

ちなみに、Laravelは、デフォルトでトップページの表示が用意されています。

```
<?php
Route::get('/', function( ){
 return view('welcome');
});
```

デフォルトで用意されているトップページのルート情報、
第一引数に'/'というトップページを表すアドレスを設定しており、
第二引数に関数を指定、この関数は以下のように記述されています。

```
function(){
  return 値;
}
```

引数なしの無名関数になっており、
内部ではreturnで戻り値を指定していて、このreturnで返される値が、そのアドレスがアクセスした際に表示される内容となります。
ここではviewという関数を使って戻り値を用意しており、以下のように利用します。

```
view( テンプレート )
```

このviewは、指定したテンプレートファイルをロードし、レンダリングして返す働きをします。
つまり、このviewにテンプレートを指定すると、それがレンダリングされて返され、ブラウザに表示される仕組みになっています。

### パラメータの利用
パラメータを設定し、値を渡すことができます。

```
Route::get('/xx/{パラメータ}', function($受け取る引数){...});
```

第一引数のアドレス部分にの{パラメータ}に指定されたテキストがパラメータとして取り出せるようになります。
第二引数では、パラメータの値を受け取る変数を引数に用意しておく（パラメータと同じ名前でなくて良い）、{パラメータ}で指定されたパラメータの値は、そのまま関数の引数に渡せます。



参考資料
PHPフレームワーク Laravel入門　著者:掌田津耶乃
python pylibdmtx でdata matrixを作成する

# インストール

```
pip install pylibdmtx
```

# data matrixのコード作成

```Python
from pylibdmtx.pylibdmtx import encode
from PIL import Image
encoded = encode('Hello World', size='16x16')
img = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
img.save('dmtx.png')
```

encode関数のパラメーターはschemeに以下のパラーメーターを指定できるはずだが、なぜかできない。
誰か教えて下さい。

* 'Ascii'
* 'AutoBest'
* 'AutoFast'
* 'Base256'
* 'C40'
* 'Edifact'
* 'Text'
* 'X12'

sizeによって作製できる情報の量が決定される。
sizeには以下のパラメーターを指定できる

* 'RectAuto'
* 'SquareAuto'
* 'ShapeAuto'
* '10x10'
* '12x12'
* '14x14'
* '16x16'
* '18x18'
* '20x20'
* '22x22'
* '24x24'
* '26x26'
* '32x32'
* '36x36'
* '40x40'
* '44x44'
* '48x48'
* '52x52'
* '64x64'
* '72x72'
* '80x80'
* '88x88'
* '96x96'
* '104x104'
* '120x120'
* '132x132'
* '144x144'
* '8x18'
* '8x32'
* '12x26'
* '12x36'
* '16x36'
* '16x48'
ComposeのSwitch/Checkboxの状態管理

ちょっと面白かったのでメモしておきます。
以下の様の置いてみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/2bfb037c-2741-76c5-e8d2-8848c7bc024f.png)


```kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                App()
            }
        }
    }
}

@Composable
fun App() {
    Switch(
        checked = false,
        onCheckedChange = {}
    )
}
```

そしてチェックをタップして変更しようとしてみます。

![check.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/51dc85ab-57be-5f65-af30-e633df6ea799.gif)

**変更できません。**

# 理由

これまでのAndroidのCheckboxではWidget側に状態がある形になっていましたが、これからは自分で管理したデータを利用する必要があります(そのほうが嬉しい)
TextFieldがまだクラッシュして使えなかったのですが、おそらくテキストの入力などもそうなるのではと思っています。
(確かI/O 2019で説明があった気がします)

# 解決策

以下のように管理するインスタンスを作ってあげて、そこの値を変更することで、変更することができます。
`@Model`をつけることで、プロパティがComposeから観測可能になります。
設計によりそうですが、実際のアプリではViewModelなどに持つ感じになるかもしれません。

```kotlin
@Composable
fun App() {
    Switch(
        checked = UiModel.checked,
        onCheckedChange = { checked -> UiModel.checked = checked }
    )
}

@Model
object UiModel {
    var checked: Boolean = false

```

![checkedchange.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/c6c95522-4b2c-9301-0fc7-fa589964da02.gif)