OmniAICreator/Qiita-1.07M huggingface dataset:
やっとdduを設定できた

# 概要
 vimを使っているのであればご存じ Shougo/ddu.vim をやっと使えるようになったのでご報告
# 利用環境
　windows11
　nvimq 0.6.1
　dein.vim
# 参考資料
　[新世代のUI 作成プラグイン ddu.vim](https://zenn.dev/shougo/articles/ddu-vim-beta)
# 設定内容
まあ、よくわからない人は以下の内容をddu.tomlとしてロードすれば動くとは思うが、この内容を解析して分かったのがまあ、本日であるということだ。
```
[[plugins]]
repo = 'Shougo/ddu.vim'
hook_add = '''
call ddu#custom#patch_global({
    \   'ui': 'ff',
    \   'sources': [{'name': 'file_rec', 'params': {}},
    \      {'name': 'file'},
    \      {'name': 'colorscheme'},
    \      {'name': 'buffer'}],
    \   'sourceOptions': {
    \     '_': {
    \       'matchers': ['matcher_substring'],
    \     },
    \   },
    \   'kindOptions': {
    \     'file': {
    \       'defaultAction': 'open',
    \     },
    \     'colorscheme': {
    \       'defaultAction': 'set',
    \     },
    \   },
    \   'uiParams': {
    \      'ff': {
    \         'startFilter': v:false,
    \         'split': 'floating',
    \      },
    \   },
    \   'filterParams': {
    \      'matcher_substring': {
    \          'highlightMatched': 'Search',
    \      },
    \   },
    \ })

autocmd FileType ddu-ff call s:ddu_my_settings()
function! s:ddu_my_settings() abort
  nnoremap <buffer><silent> <CR>
        \ <Cmd>call ddu#ui#ff#do_action('itemAction')<CR>
  nnoremap <buffer><silent> <Space>
        \ <Cmd>call ddu#ui#ff#do_action('toggleSelectItem')<CR>
  nnoremap <buffer><silent> i
        \ <Cmd>call ddu#ui#ff#do_action('openFilterWindow')<CR>
  nnoremap <buffer><silent> q
        \ <Cmd>call ddu#ui#ff#do_action('quit')<CR>
endfunction

autocmd FileType ddu-ff-filter call s:ddu_filter_my_settings()
function! s:ddu_filter_my_settings() abort
  inoremap <buffer><silent> <CR>
  \ <Esc><Cmd>close<CR>
  nnoremap <buffer><silent> <CR>
  \ <Cmd>close<CR>
  nnoremap <buffer><silent> q
  \ <Cmd>close<CR>
endfunction

nnoremap <silent> xdf :Ddu file<cr>
nnoremap <silent> xdb :Ddu buffer<cr>
nnoremap <silent> xdr :Ddu file_rec<cr>
nnoremap <silent> xdc :Ddu colorscheme<cr>
'''


[[plugins]]
repo='Shougo/ddu-ui-ff'
[[plugins]]
repo='Shougo/ddu-source-file_rec'
[[plugins]]
repo='Shougo/ddu-source-file'
[[plugins]]
repo='Shougo/ddu-filter-matcher_substring'
[[plugins]]
repo='Shougo/ddu-kind-file'
[[plugins]]
repo='Shougo/ddu-commands.vim'
[[plugins]]
repo='4513ECHO/ddu-source-colorscheme'
[[plugins]]
repo='shun/ddu-source-buffer'
```

# 分かった内容
## 概念とplugin
- dduはui,source,kindという概念があるというのだが、uiとsourceしかわかっていない。
- インストールしたpluginが上記の設定ファイルの文末にある8個である。
- このうち、ddu-source-xxというのがsourceで、上の設定ファイルでは、file,file_rec,buffer,colorschemeを設定している。
- これにddu-commands.vimをinstallしてあれば、:Ddu file というようなコマンドで動作させることができる。
- ddu-file_recってのはリカーシブで配下のファイルを全部表示する。
- ddu-ui-ffというのがuiでこれも差し替えることができる。
## ddu-ui-ffの設定
- ddu-uiの設定で重要なのが2つのautocmdである。
- 最初の設定がffへのコマンド定義でcrで選択、spaceでトグル、iを入力するとフィルター画面を表示、qで終了を定義してある
- 次のddu-ff-filterってのがフィルター画面上での定義である。
## ddu#custom#patch_globalの内容
- この辺は他の例でも大体同じようで、上記の設定は'uiParams'の'split': 'floating',が少し特殊だ。
- これは普通は’horizontal’になっていると思う。'floating'はnvimのみで使える。
- 画面の大きさなんかも、設定によって変更することができるだろう。

# キーマッピング
nnoremapを読めば、xdfでfile,xdbでbuffer,xdrでfile_rec,xdcでcolorschemeにマッピングしてある。まあ、ここはお好きにどうぞというところか
Composerをインストールする意味


# 今回の記事について
未経験の枠で就職活動をしていたけど、その中で技術的な質問がいくつかあった。
答えられないことも多かったので積極的なアウトプットをしていこうと思った。

今回の記事に関してはComposerのインストール方法ではなく、インストールする必要性について記載する
※Composerで検索してこの記事にたどり着いた人もいるかもしれないのでインストール方法についての参照記事も添付する

## Composerとは
ComposerとはPHPのパッケージ依存管理ツールのことです。
つまり！！インストールすると一発で必要なパッケージがインストールされるのです！！

例えばlaravel/uiをインストールしたいときも次のような以下のようなコマンドになります

```
composer request laravel/ui
```

インストールについては、Composerはコマンドで操作ができます。インストールやバージョンの確認など全てコマンドプロンプトやターミナル上で行います。

ComposerのダウンロードはWindowsでもMaxでも可能です。

リンクです！！
https://getcomposer.org/


## Composerを使うメリット
実は今回のメインであるComposerのインストールする意味に関してはほとんど話してしまったので簡潔にまとめると

・PHPの開発において必要なツールをインストールしてくれる
・WindowsやMac、LinuxなどOS関係なくインストールできる
・コマンドの操作は必要なのでコマンドもいくつか勉強できる
【Laravel】既存カラムに onDelete cascade を追加した際のメモ

環境：Laravel 6.2
検索した感じでは8でも変わってないはず、、

## 状況

ユーザーの退会処理を作ろうと思い、`$user->delete();`を行ったところ下記のエラーが出た

**Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails**

ユーザーが投稿した記事（articlesテーブル）が外部キーでユーザーと紐づいているため、
先に該当ユーザーが投稿した記事を削除しないとエラーが出てしまうようだ

## 対応案

ユーザーの退会処理を行うメソッド内で、先に記事削除の処理を書けば一応解決はする。
しかし、articlesテーブルの外部キーにonDelete cascadeを設定してやれば、そのあたり自動でやってくれるので、今回はそちらを行うことにした。

## onDelete cascade追加用のマイグレーションファイル作成

articlesテーブルの中身がすべて消えても良いなら
ロールバックしてarticlesテーブル作成用のマイグレーションファイルを書き直せば良いが
今回は消したくなかったので、onDelete cascade追加用のマイグレーションファイルを新たに作成した。

```php:onDelete cascade追加用のマイグレーションファイル
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddCascadeToUserIdOnArticleTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->dropForeign(['user_id']);//いったん外部キーを削除する。
            $table->foreign('user_id')
                ->references('id')->on('users')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->dropForeign(['user_id']);
            $table->foreign('user_id')
                ->references('id')->on('users');
        });
    }
}

```
注意点としては、上記コードupメソッド内のコメントにも書いているが
先に外部キーを削除する必要があるので、upメソッド内に`$table->dropForeign(['user_id']);`を記述していること。

ちなみにこのdropForeignの引数は、本来であれば「リレーション**元**のテーブル名_外部キーを設定しているカラム名_foreign」なので、dropForeign(articles_user_id_foreign)となるが、今回のようにリレーション**先**のテーブル名（users）に対して、外部キーを設定しているカラム名がuser_id（usersの単数形＋_id）といった形で、Laravelの命名ルールに則っている場合は、上記コードのように`dropForeign(['user_id'])`という書き方もできる。

## 確認

もちろん`$user->delete();`を行えば動作確認はできるし、
phpmyadminでの確認やコマンドでDBにログインしての確認もできる。

![スクリーンショット-2022-04-02-163931.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/985396/47f798cd-d40a-d3c3-e17a-628de82de51a.jpeg)


ちなみに
onDelete cascade は「連動して削除する」だが
onDelete restrict は「連動せず、削除を制限する(エラーが出る）」。restrictがデフォルト。
SpringBootの値をJavaScriptに渡す方法

# はじめに
SpringBootで設定した値をJavaScriptに渡す際に、少しばかり、つまずいたため備忘録がてら記録しておこうと思います。
SpringBootとJavaScriptを用いた場合には、非常にあるあるな事象だと思うので、ご参考になれば幸いです。
ちなみに、Thymeleafでは、このことを「 **JavaScriptナチュラルテンプレート** 」と呼ぶようです。

# ControllerからJavaScriptに値を渡す方法
以下のように`Model`に登録してある値をJavaScriptに渡したいとします。

```java:SampleController.java
    @GetMapping("/index")
	public String getIndex(EasyHouseholdForm form, Model model) {

		model.addAttribute("form", form);	
		
		return "sample/index";
	}
```

これを渡す方法は`Thymeleaf`で以下のようにします。

```html:index.html
<script th:inline="javascript">
		const form = /*[[${form}]]*/"form";
        console.log(form);
</script>
```

ポイントとしては、`<script>タグ`の**th:inline属性**の値に`javascript`を設定し、`/*[[${渡したい値}]]*/`とすることでJavaからJavaScriptに値を渡すことができます。

また、定数定義の後ろの **"form";** ですが、こちらは無視される仕様となっているようです。
これを加えないとエラーとなり、連続しての定数もしくは変数の定義(以下、参照)ができないようです。
```html:index.html
<script th:inline="javascript">
		const hoge = /*[[${hoge}]]*/"hoge";
        const fuga = /*[[${fuga}]]*/"fuga";
        console.log(form);
</script>
```
上記のように「JavaScriptナチュラルテンプレート」の記載をすれば、連続して定数・変数の定義が可能です。

もちろん、JavaScriptの外部ファイル(〇〇.js)に渡したい場合も同様の内容で実装することができます。
※もちろん、HTML内で該当のjsファイルを読み込んでいないとできませんが・・・

## JSファイルに値を渡す方法
こちらも最初のやり方は同じです。
```html:index.html
<script th:inline="javascript">
		const form = /*[[${form}]]*/"form";
        // JavaScriptの関数呼び出し
        sample();
</script>
```
まずはHTMLで値を変数に代入します。
あとはこの値を使用したいJavaScriptファイルで使用するだけです。

```js:index.js
'use strict'
{
  function sample(){
    console.log(form);
  }
}
```

このようにすれば、JavaScriptファイルでもJavaの値を使用することができます。
ただし、この方法には制約があるので、その点だけ注意が必要です。

以下が、その制約です。

- `<script>タグ`に**src属性**、または**th:src属性**が指定してある場合には使用できないこと（**th:inline属性**と**src属性**ないし**th:src属性**の併用は不可）
- 上記の制約の通り、`<head>タグ`内で`<script>タグ`を作成の上、そこで**src属性**、ないし**th:src属性**を利用して、JavaScriptファイルを読み込む必要がある

とはいえ、各自の仕様や好みにもよるので、前者を使用する人が大多数かと思います。
筆者自身の場合は、HTML内でのJavaScriptの記述は最低限にして、JSファイルでJavaScriptを書く場合が多いので、後者の方法が必須となります。

このように、好みによるところもあるので前者を使うのが多くの人にとっては無難かと思われます。

# 参考文献
- [Thymeleaf](https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html)
- [Spring Bootの設定値をJavaScriptの引数に渡してみた](https://www.purin-it.com/spring-boot-to-js-args)
- [SpringBoot thymeleafでデータをjs内で受け取る](https://itsakura.com/sb-thymeleaf-js)
XMLをスライスにUnmarshalするときの罠

スライスを `Marshal` して `Unmarshal` すると、**先頭要素しか取得できません**！

```go:スライスをもとに戻せない？
package main

import (
	"encoding/xml"
	"fmt"
)

func main() {
	nums := []int{1, 2, 3}
	b, _ := xml.Marshal(nums)

	var copiedNums []int
	_ = xml.Unmarshal(b, &copiedNums)
	// 先頭要素しか取れない！
	fmt.Printf("%#v\n", copiedNums) // []int{1}
}
```

JSONのように `Marshal` と `Unmarshal` を逆変換として使うことは**できません**。XMLをオブジェクトのシリアライズに使っている場合は注意が必要です。

# バージョン

Go 1.18

# Why?

スライスをmarshalすると各要素が並んだ形式で出力されます。

```
 []int{1, 2, 3} → "<int>1</int><int>2</int><int>3</int>"
```

 しかし、unmarshalのデコーダーは最初の要素を読み終えた時点で完結したxmlと判断し終了してしまいます。

```
<int>1</int> ここでXMLが完結した！ → []int{1}
```

その結果、元々いくつ要素があろうが先頭要素しか取得できません。

issueも上がっていますが、Go1の間は[後方互換を保証する](https://go.dev/doc/go1compat)ので実現は難しいかもしれません...

https://github.com/golang/go/issues/20754

# 対処法

## 構造体でラップする

最上位の要素が１つであればいいので、`[]int` フィールドを持つ構造体をmarshal, unmarshalすれば全要素コピーできます。

```go
package main

import (
	"encoding/xml"
	"fmt"
)

// ラッパー
type IntSlice struct {
	Nums []int
}

func main() {
	nums := IntSlice{[]int{1, 2, 3}}

	b, _ := xml.Marshal(nums)
	fmt.Println(string(b)) // "<IntSlice><Nums>1</Nums><Nums>2</Nums><Nums>3</Nums></IntSlice>"

	var copiedNums IntSlice
	// IntSliceタグで包まれるので、unmarshalはXMLを最後（IntSliceの閉じタグ）まで読んでくれる
	if err := xml.Unmarshal(b, &copiedNums); err != nil {
		fmt.Printf("error: %+v\n", err)
		return
	}

	fmt.Printf("%#v\n", copiedNums) // IntSlice{Nums:[]int{1, 2, 3}}
}
```

## 自分で `Unmarshal` を実装する

以下の記事では、スライスのdefined typeにUnmarshalメソッドを生やし、XMLを最後まで読み込むようにする方法が紹介されていました。

https://blog.andreiavram.ro/unmarshal-json-xml-golang-structure-slice/

# おわりに

機会があって、XMLを使ったディープコピーを検討していたらがっつりはまりました...
構文も良く分からずJSONのノリで使っていたしっぺ返しでもあるので、これを機に勉強しようと思います :innocent:
趣味としての技術、職としての技術

<h2>興味関心から始めた技術</h2>
　私は、興味があるという理由でプログラミングを始めました。
<BR>
最初に作った物はGASで記述したウェブサイトの情報をスプレッドシートに記録するスクレイピングプログラムでした。プログラムの文法や用語はブラウザで行う「プログラミング練習サイト」で練習したこともあったのですが、実際に何か一連の流れで動くプログラムを作ることが最優先だと考えなるべく低負担で完成させられるよう、環境構築が不要のGASを選択しました。
<BR>
<BR>
　いざ始めるとなっても、私は今までソフトウェアをユーザーとして使ってきただけなのでそれを開発する側の知識はゼロに近く、当初様々な壁にぶつかりました。しかし最初は難しいと覚悟を決めていたので、図書館で借りた書籍を読み漁り、見よう見まねで完成させました。初めてプログラムが思い通りの結果に反映された時の感動を覚えています。
<BR><BR>
　完成したら完成したで他の様々なツールを使ってみたくなり、次はローカル開発環境の構築にチャレンジしました。環境はOSはWindows、パッケージはXAMPP、エディターVSCodeを使い、失敗したら再インストールし直す覚悟でトライアンドエラーを繰り返しました。とにかく低負担で小さい成功を積み重ねることで精神衛生上良いと考えなるべく広く浅く達成することを心がけました。コマンドラインによる操作、ツールはApacheのバーチャルホスト設定、MariaDB(MySQL)のコマンドライン操作、クラウドサーバですがAWSのEC2設定、AmazonLinux2操作、VSCodeのssh設定等。<BR>
言語はPHP（PDOデータベース接続)、HTML、CSS、Python( Scrapy, Django, Numpy, Pandas）、Javaを少し。
スクレイピング(BeautifulSoup, Scrapy, )やLineAPIを使ったプログラムも作成しました。
<BR><BR>
　私は理工系の出身ではありませんが、このように試行錯誤しながら勉強していく中でITの自由度やインフラとしての確かさに改めて気付かされました。今では、ITは、世界の政治・経済を構成する様々な場所で扱う情報の精度と速度を加速させる革命的な技術であると認識しています。



<h2>人の需要に応えるための技術レベル</h2>
　この流行が激しく比較的新しい分野をモチベーションを維持・拡大していきながら継続的に学習するためには、前述のような技術の可能性の広さを知りながら興味関心を中心に自分が扱うことのできる技術が増えていく体験が重要だと思います。

　一方で、興味や関心といった感情のみで培った技術を人の需要に応えるレベルまで昇華させるとなると話は変わってきます。そのためには相手の需要を満たす手段を得る必要があり、それが必ず興味のあることだとは限りません。そもそも興味関心とは、無知の知と自分の実績から更に達成できそうな期待が重なった限られた範囲で起こる一時的で不安定な感情であると考えてます。
この定義が正しいとすると、人の需要に応えるという目標を達成するには自分の興味関心を判断基準にして手段を習得していくだけでは足らず、人の需要を満たすための手段を逆算して出し、段階的に習得していくことが両者満足の最適な解決策だと考えました。


<h2>今後について</h2>
そこで実際に需要から逆算した技術を自分なりに調べてみて、自分の興味関心が社会の需要が高い技術から勉強をし始めました。
前述した技術、それに加え新しい知識を学んでいきたいと思います。
今後学習進捗やメモを記録として投稿しようと思います。
gatsby.jsのwarning解消法

warningが出ており、エラーではないので表示には支障ないが、警告が出ていた箇所を対応。
その対応方法について備忘録。

## warning① 関数名をつける

```warning  Anonymous arrow functions cause
Fast Refresh to not preserve local component state.

       Please add a name to your function, for
example:

       Before:
       export default () => {}

       After:
       const Named = () => {}
       export default Named;
```

### 修正前
```
export default () => {

}
```

### 修正後
※``Contain``は任意の定数名でOK
```
const Contain () => {

}
export default Contain
```
useSelectorのMockの仕方

## なぜこの記事を書いたか

reactに関するテストの勉強をしていて、`useSelector`のモックの仕方で詰まりました。この経験からこの記事を残そうを思います。

useSelectorのモックの仕方はいくつか記事があるとは思うのですが、具体的に今回詰まったのは、一つのコンポーネント(or カスタムフック)で**複数回**useSelectorを呼び出す場合でした。この記事では、そんな複数回のuseSelectorの呼び出しにも対応させています。


## ケース

早速ですが、複数回のuseSelectorの呼び出しとは何かというと、以下のようなケースです。

```useMyCloset.js
const useMyCloset = () => {
  const isThinkingTops = useSelector(state => state.tops.isThinking);
  const tShirts = useSelector(state => state.tops.tShirts);

  const loadMyTshirts = () => {
    if (isThinking) return null;
     return tShirts;
  }

  return {
    loadMyTshirts
  }
}

```
useSelectorによって値を取得する際は、一度のuseSelectorで、objectを取得して、その値を使用するのではなく、何度もuseSelectorを呼び出して一番小さい単位で取得することが推奨されています。[(参考)](https://redux.js.org/style-guide/style-guide/#call-useselector-multiple-times-in-function-components)

よって、先述のコードは以下のように書くと、あまりよろしくないということになります。(なぜこのようにした方が良いかは、本記事では省きます。)

```useMyCloset.tsx.js
const useMyCloset = () => {
  // ↓ 一度のuseSelector呼び出しで値を取得している
  const tops = useSelector(state => state.tops);

  const loadMyTshirts = () => {
    if (tops.isThinkingTops) return null
     return tops.tShirts
  }

  return {
    loadMyTshirts
  }
}
```

## じゃあどうするのか

さて、少し話題が逸れましたが、複数回のuseSelector呼び出しは、以下のように、`mockImplementation`を使った方法でモックできます。

 useSelectorは、引数にrootStateを取るselector関数を受け取り、それを実行するだけです。
 よって, useSelectorの振る舞いをモックした上で、selector関数でエラーが出ないように、dummyのRootStateをselector関数の引数に渡すようにします。


```useMyCloset.test.js
// 他import
import {useSelector} from 'react-redux';

jest.mock('react-redux');
const useSelectorMock = useSelector as jest.Mock;
const dummyStore = {
  tops: {
    isThinking: false,
    tShirts: ['tShirtsA', 'tShirtsB', 'tShirtsC']
  }
}

beforeEach(() => {
  useSelectorMock.mockImplementation(selector => selector(dummyStore))
});

afterEach(() => {
  jest.resetAllMocks();
});

describe('useMyCloset', () => {
  it('testA', () => {
    // some test
  });
});


```


他にも何かもっといい方法があれば教えてくださいませ〜〜！！
nmapとかtelnetとかよく分からないのでまとめてみる。

今、ネットワークの勉強をしていてwiresharkでパケットキャプチャしている。
スリーウェイハンドシェイクでsynパケットが届いているのにも関わらず、syn,ackパケットが返ってこない。
なぜだと思い、いろいろ調べてみると、nmapだのtelnetだのtracerouteだので検証している。
こいつらの違いって何なん？と思い、しかも毎回その都度調べるにも関わらず、忘れてしまっているので、ここにまとめる。

# nmapとは
まず、nmapの名前の由来だが、ネットワーク上にどのような機器やサービスが動いているかという、ネットワークの地図を作成すること（Network Mapper)に由来する。
nmapのよく使われる役割としてポートスキャンがあるが、他にも特定ポートで動作するサービスアプリケーションの種類とバージョンを検出する機能や、OSおよびそのバージョンを検出する機能など、多数の機能を備えている。
ちなみに、**ポートスキャン**とは、サーバーの特定のポートに対してパケットを送信し、その応答を確認することで、アクセス可能な外部ポートなどを検出することである。

nmapは以下のように実行する。

```
nmap <スキャン対象のホストのIPアドレス（またはホスト名）>
```
例えば、私の用意している環境で以下のように実行してみる。
```
nmap 10.0.0.2
```
すると次のように返ってくる。
```:結果
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-02 15:32 JST
Nmap scan report for 10.0.0.2
Host is up (0.0047s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh

Nmap done: 1 IP address (1 host up) scanned in 2.39 seconds.
```

↑の998 closed portsはツッコミどころではないか？と思うが、これは別の記事にあげるとしよう。
このように、ポート番号とその状態、そしてサービス名が表示される。

# telnetとは
telnetの名前の由来は、Teletype Networkである。
Telnetとは、IPネットワークにおいて、遠隔地にあるサーバやルーター等を端末から操作する通信プロトコル、またはそのプロトコルを利用するソフトウェアである。
確かに、名前その通りだ。
Telnetクライアントは、Telnetサーバとの間でソケットを開き、単純なテキストベースの通信を行う。基本的にはポート番号23番を使用する。
代表的なTelnetクライアントとして、Tera Termがある。

# tracerouteとは
tracerouteは、あるホストから別のホストまでのネットワーク経路をリスト表示するコマンドである。
ここでの経路とは、ホスト間を接続するルーターを示す。
tracerouteを使うことで、経路上にどのようなルーターが位置しているのかが表示される。

tracerouteの使い方は、以下の通りである。
```
traceroute <IPアドレスまたはドメイン名>
```
例えば、yahoo.co.jpを対象に実行してみる。
```
traceroute yahoo.co.jp
```
すると、結果は以下のように返ってくる。
```:結果
traceroute to yahoo.co.jp (182.22.25.124), 64 hops max, 52 byte packets
 1  buffalo.setup (192.168.11.1)  2.455 ms  1.810 ms  1.532 ms
 2  10.152.84.1 (10.152.84.1)  3.056 ms  4.248 ms  3.154 ms
 3  192.168.35.5 (192.168.35.5)  5.397 ms  4.282 ms  4.425 ms
 4  sjkacs001.bb.kddi.ne.jp (27.85.212.137)  6.281 ms  5.420 ms
    sjkacs001.bb.kddi.ne.jp (27.85.212.5)  5.918 ms
 5  27.85.227.93 (27.85.227.93)  4.959 ms
    27.86.47.233 (27.86.47.233)  5.769 ms  7.264 ms
 6  otejin302.int-gw.kddi.ne.jp (27.86.32.10)  5.045 ms  5.511 ms  9.096 ms
 7  111.108.12.174 (111.108.12.174)  5.170 ms  4.911 ms  5.346 ms
 8  * * *
 9  * * *
```
このように、目標のサーバまでに７つのルーターを経由することが分かる。

# まとめ
とりあえず、気になっていた3つのコマンドについて軽く調べてみた。
追記する可能性あり。
マンハッタン距離について

勉強中のメモ書きです。

# マンハッタン距離とは

2つの座標の差の総和を表したもの。2点間の距離。

|x_1 - x_2| + |y_1 - y_2|

で表せる。

例えば下記の図のような座標があったとする。
(画像は [「高校数学の美しい物語」](https://manabitimes.jp/math/1127)さんより引用)

![manhattan.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/336a86a4-8d93-ba63-40d7-20b3f234f350.jpeg)

(x2, y3) と (x5,y7) の2点間のマンハッタン距離は

|2-5| + |3-7| = 7

で、７となる。

マンハッタン距離の名称は、碁盤のように道路が張り巡らさせれているマンハッタンから由来、2点間を徒歩で歩いたらどれぐらいの距離がかかるか、を示したもの（らしい）。

# JavaScript でマンハッタン距離を計算する

以下、標準入力で「地点数」「各地点のx、y座標情報」が、標準入力で提供されているとする。

1行目に、地点の数　「n」。
2行目以降に地点情報が記述。
x, y を空白区切りで表し、2点を2行にわたって記述されている。

入力例：
```
２
2 3
5 7
```

以下のコードでマンハッタン距離の算出ができる

```javascript
function main(input) {
  const args = input.split("\n");
  const n = parseInt(args[0], 10);

  let x = [];
  let y = [];
  
  for(i = 0 ; i < n ; i++) {
     let nums = args[i+1].split(' ');
     x.push(parseInt(nums[0], 10));
     y.push(parseInt(nums[1], 10));
  }
  const manhattan = Math.abs(x[0] - x[1]) + Math.abs(y[0] - y[1]);
  console.log(manhattan) // 7 
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));
```

地点情報が2行以上にわたる場合、行数分を配列x、yに格納してそれぞれの地点間の距離を求める。


# 参考

* L1距離（マンハッタン距離）の意味と性質
    * https://manabitimes.jp/math/1127
* マンハッタン距離
    * https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%83%8F%E3%83%83%E3%82%BF%E3%83%B3%E8%B7%9D%E9%9B%A2
VirtualBoxのインストール手順（macOS）

## 概要

備忘録として、下記手順を記載する。
・VirtualBoxのダウンロード

### 前提
OS：macOS Big Sur
バージョン：11.2.1

## 手順

### 1 VirtualBoxのインストール
[公式ダウンロードページ](https://www.virtualbox.org/wiki/Downloads)にアクセス
`OS X hosts`をクリック
ダウンロードが開始される
![スクリーンショット 2021-06-19 22.19.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/90ca5fcc-6241-d83b-1f08-db86834ed244.png)
ダウンロードフォルダに、`VirtualBox バージョン OSX.dmg`のダウンロードを確認
ダブルクリックし、インストーラを起動
![スクリーンショット 2021-06-19 22.32.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/737dc2d1-abbf-700b-1944-c7313080142d.png)
インストーラに従って、インストールを行う
![スクリーンショット 2021-06-19 22.42.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/655ea7fd-8764-7910-7c20-c8d957bc6a6a.png)
インストール先を変更したい場合は、［インストール先を変更］から設定を変更する
［インストール］をクリック
![スクリーンショット 2021-06-19 22.42.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/328e3404-8daa-9e7b-0de9-5b7fd6683522.png)
`インストールが完了しました。`と表示されたことを確認
![スクリーンショット 2021-06-19 22.44.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/2bc0890e-e4fa-524a-bc4c-befb9a85fa73.png)

### 2 VirtualBoxのインストール確認
以下2点から、VirtualBoxのインストールを確認する
1. アプリケーションフォルダに`virtualBox.app`が格納されていること
![スクリーンショット 2021-06-19 22.57.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/1ca8147e-8ad7-4978-8bd6-d32b63e996ef.png)
2.`virtualBox.app`をクリックし、`Oracle VM VirtualBox マネージャー`を起動できたこと
![スクリーンショット 2021-06-19 22.58.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/d1283acc-51ce-bb0e-3f89-e6c78f043d05.png)

以上
【コピペで動く】Reactで超簡単にルーレットを作る方法

# 前書き

以前、個人アプリを開発した際にルーレット作ることがあったので今回は次回使う時用のメモとルーレットを作りたい人へのコード共有を兼ねて記事を作成します！

setIntervalを使えばできそうだなぁと思って実装したら副作用のせいでうまくできなかったのを覚えています。。笑

JavaScriptではルーレットを作れるけど、Reactでは副作用のせいでうまくできない。。！

という僕と同じ状況の方がいましたら是非ご覧ください:v:

実装イメージは以下の通りです。

![画面収録_2022-04-02_14_11_33_AdobeCreativeCloudExpress (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595428/5bc68c03-7306-5976-e7b3-ce9fe0ccc845.gif)


## 注意点

今回のコードはルーレットを動かす記述しか書いてありません。
そのため、実装イメージのようなスタイリングやアニメーションの記述は省かれております。
スタイリングやアニメーションは人によって異なると思いますので適宜お好みであててください。

## コード

```react
import {  useState, useEffect, useCallback, memo } from "react";

export const Roulette = memo(() => {
  const [start, setStart] = useState(false);
  const [index, setIndex] = useState(0);

  const rouletteContents = [
    "カレー",
    "パスタ",
    "唐揚げ",
    "天ぷら",
    "中華",
    "ハンバーグ",
    "うどん",
    "肉じゃが"
  ];

  //ボタンの文言を変更する処理
  const startRoulette = useCallback(() => {
    setStart(!start);
  }, [start]);

  //ルーレットを回す処理
  useEffect(() => {
    if (start) {
      const interval = setInterval(() => {
        setIndex((oldIndex) => {
          if (oldIndex < rouletteContents.length - 1) return oldIndex + 1;
          return 0;
        });
      }, 50);//ルーレットの中身を切り替える速度
      return () => clearInterval(interval);
    } else if (!start) {
      return () => clearInterval();
    }
  }, [start]);

  return (
    <>
      <div>
        <p>今日のメニューは・・・</p>
        <p>{rouletteContents[index]}</p>
      </div>
      <button type="button" onClick={startRoulette}>
        {start ? "ストップ" : "スタート"}
      </button>
    </>
  );
});
```

## 最後に
参考になりましたでしょうか？

この他にも[Qiita](https://qiita.com/Jackpackeeer)や[Twitter](https://twitter.com/Jackpackeeer)では文系大学生の僕がプログラミングについて発信してますのでフォローしていただけると嬉しいです！

## おすすめ記事
[【2022年版】駆け出しフロントエンドエンジニアが覚えたい用語一言メモ集](https://qiita.com/Jackpackeeer/items/27c1e1bc792980b86eec)

[【React】本番環境にデプロイして画面が真っ白になった時の解決方法](https://qiita.com/Jackpackeeer/items/4ff180f502963b5ce875)
bochsをビルド(GUIはSDL2)、試しに動かす。

<h1>bochsをビルド(GUIはSDL2)、試しに動かす。
</h1>

環境 : macOS Monterey 12.2.1

あんまり、bochsの情報が載っていない気がしたので、書いてみることにしました。以下のコマンドでbochsを使おうとしましたが、デフォルトのGUIシステムが上手く動かなかったです。

```
brew install bochs
```

そこで、SDL2でビルドし直すことにしました。

bochsのバージョンは、<a href="https://sourceforge.net/projects/bochs/files/bochs/2.6.11/">2.6.11</a>です。

<a href="https://sourceforge.net/projects/bochs/files/bochs/2.6.11/">bochs-2.6.11.tar.gz</a>をダウンロードしてきます。

解凍して、ターミナル上で

```
cd bochs-2.6.11
./configure --with-sdl2 --enable-debugger
make
```

とするだけです。--with-sdl2を渡すと、GUIライブラリにSDL2を使ってくれます。ない人は、SDL2を用意しておきましょう。--enable-debuggerはbochs内でOSのデバッグが行えるような仕組みを用意してくれます。

試しに、動かしてみることにします。

bochsは、qemuとは違って、テキストベースの設定ファイル.bochsrcを用意して、それを渡さないといけないみたいです。

```.bochsrc
floppya: 1_44=floppya.img, status=inserted
boot: floppy
romimage: file=./bios/BIOS-bochs-latest
vgaromimage: file=./bios/VGABIOS-lgpl-latest
```

意味が分からないと思うのですが、<a href="https://bochs.sourceforge.io/doc/docbook/user/bochsrc.html">4.3. The configuration file</a>を参照すれば、分かります、
BIOS-bochs-latestやVGABIOS-lgpl-latestは、bochs-2.6.11/biosディレクトリにあります。

floppya.imgは<a href="https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844">はりぼてOS</a>を入れたディスクイメージです。

試しにはりぼてOSを動かしてみることにしました。
ターミナル上で、

```
./bochs -q -f ./.bochsrc
```

と打ち込んでみてください。

すると、![スクリーンショット 2022-04-02 14.51.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/a17edf4b-fec5-be07-fb22-0427c0fc2d18.png)

上の画像のようにプロンプトが表示されると思います。

```
<bochs:1> c
```

cを打ち込むと、

![スクリーンショット 2022-04-02 14.52.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/2b5d0ee3-2a18-4195-e912-5b486268affe.png)
Android12以上の振動(バイブレーション)の実装方法

 前回API level 26以上　API level 31未満のやり方を書きました。

今回は、API level 31の振動のさせ方を書こうと思います。


# Manifestの設定

AndroidManifest.xmlでVIBRATEの許可します。


```AndroidManifest.xml
<uses-permission android:name="android.permission.VIBRATE"/>
```


# Activity
``` MainActivity.kt
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
    val vibrationEffect = VibrationEffect.createWaveform(longArrayOf(500L, 1000L),intArrayOf(200, 0), -1)
    val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
    vibratorManager.vibrate(combinedVibration)
}
```

これで振動できます。
VibrationEffect.createWaveformで振動の設定をします。

第一引数はタイミング/振幅ペアのタイミング値（ミリ秒単位）。タイミング値が0の場合、ペアは無視されます。
今回は500ms振動して1000ms振動しないとなります。

第二引数はタイミング/振幅ペアの振幅値。振幅値は、0〜255、またはに等しい必要があります。振幅値0は、オフであることを意味します。
今回は第一引数で設定した500msの間200の強さ振動をして、1000msの間0の強さの振動(オフ)となります。

第三引数は繰り返すタイミング配列へのインデックス。無期限に繰り返したくない場合は-1
今回は繰り返さないです。無限に繰り返す場合は0を入れてください。

※第一引数と第二引数のリストサイズは同じである必要があります。
※第三引数はリストのサイズまでの整数を入れる事ができます。

例:リストのサイズが５で第三引数に３を入れた場合
0->1->2->3->4->3->4->3->4


振動の設定が簡単にできるようになりました。
【Salesforce】外部オブジェクト利用時の詰まったポイント

外部オブジェクト利用時の詰まったポイントを備忘録として記録していきます。

# 設定時
- **ライセンス**
    - OData2.0 or 4.0で接続する場合、外部データソース1つにつき1つのsalesforce connectライセンスを消費する
        - 組織で複数の外部データソースを設定する必要がある場合は構成に留意する
            - ビューごとに参照可・不可を分けたい場合など
- **PK**
    - 接続先テーブルで明示的にPKが指定されていない場合、ExternalIdには各カラムを結合したものが設定される様子
        - カラム数が多すぎると検証時にエラーになる
        - 参照元の項目名がsalesforce側のAPI名称の長さの上限を超えるとPKを設定していても反映されなくなる（恐らく自動で項目名が削られるため）
- **表示ラベル・API名**
    - 項目名はデフォルトで接続先テーブルのカラム名と同じラベル名・API名が設定される
        - API名の設定の問題なのか英数字以外を設定しているとエラーになる
- **同期・検証**
    - 作成できる外部オブジェクトの上限は[200個](https://help.salesforce.com/s/articleView?id=sf.platform_connect_general_limits.htm&type=5)まで
    - 外部データソースの変更は再同期しないと反映されない
        - salesforce側で項目のラベル名やデータ型などを変更していても再同期する度に元に戻る
    - 参照先項目のデータ型が指定していない場合、salesforce側ではロングテキストエリア(32,000)と判断される
        - ビューの中でテーブルの項目同士を結合している場合などは注意が必要
        - 未定義の項目数が多すぎると1オブジェクトあたりのロングテキストエリア文字列の上限を超えてエラーになるので注意

# 実装時
- **Apex**
    - 1時間あたりに取得または作成される新しい行の上限は[10万行](https://help.salesforce.com/s/articleView?id=sf.platform_connect_general_limits.htm&type=5)まで
        - [高データボリューム](https://help.salesforce.com/s/articleView?id=sf.apex_considerations_high_data_volume.htm&type=5)が適用できないか検討        
        - データメンテナンスで大量の外部オブジェクトを参照する場合はあらかじめクエリを実行しておくと制限の対象外になる
    - IN句で条件指定時、条件が多すぎるとエラーになる可能性がある
        - URLパラメータでクエリを指定しているようなのでパラメータが長くなりすぎるとエラーが発生する
            - 外部データソースによるかも？
    - Group By句など[一部の句や集計関数](https://developer.salesforce.com/docs/atlas.ja-jp.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_limits.htm)が使えない
    - DML操作中に外部オブジェクトに対するクエリを発行するとエラーになる
    - クエリを行う度に[ODataコールアウトが実行されている](https://help.salesforce.com/s/articleView?id=sf.platform_connect_considerations_query_rate_limits.htm&type=5)
    - デフォルトだと[2,000件までしか結果が返ってこない(サーバ駆動ページングの最大ページサイズ)](https://help.salesforce.com/s/articleView?id=sf.platform_connect_general_limits.htm&type=5)
        - バッチ処理であればQueryLocatorを利用すれば制限を回避可能
    - 外部参照関係項目に値を設定する場合、IdではなくExternalIdを設定する
- **テストクラス**
    - 参照のみの外部オブジェクトではレコードをクラス中で作成することができないため、[テストデータのインスタンスを作成して引き渡す形で実装する](https://medium.com/slalom-technology/how-to-mock-salesforce-external-objects-e5d9aafc6d9d)必要がある
        - 上記の実装を行っているバッチクラスでstartメソッドがIterable<SObject>で無い場合、execute用のテストデータが作成できないため、[executeメソッド中の処理を外出ししてtestVisibleなメソッドを作成してカバーする](https://salesforce.stackexchange.com/questions/336471/how-do-i-mock-external-objects-for-the-purpose-of-testing-a-batch-apex-class)かseeAllData=trueを利用する必要がある
            - seeAllData=trueは環境内のデータに左右されるので推奨されないと思われる
            - Batch.execute(Database.BatchableContext BC, List<SObject> scope)で直接呼び出してもOK
【 Java Servletについて(また、その周辺) 】

現在書籍にてJavaを独学で学習中です。
この投稿はその備忘録になります。

## Java Servlet(サーブレット)とは?
Javaサーブレットとは、一言でいうと`プログラム`のことです。
どんなプログラムか？
・`Java`を使って作成されている。
・`サーバ側(バックエンド側)で動くプログラム`。
・動的なwebページの`配信システムを実現するためのプログラム`。

#### ■Javaサーブレットの働き■
クライアント側からのリクエストをサーブレットが受けて、
データの処理や動的なwebページを生成したりします。
【例】YouTubeで👍ボタンを押すとそれが反映されたページが構成される。

#### ■サーブレットコンテナという実行環境■
サーブレットはプログラムのため実行環境が必要になります。
その実行環境となるソフトウェアが`サーブレットコンテナ`です。

#### ■GETメソッドとPOSTメソッド(リクエストの違い)■
サーブレットはクライアント側から送られてくるリクエストに対して、
`GETメソッド`か`POSTメソッド`かを判断します。
・GETメソッド...「指定したURLの情報を送り返してほしい」というリクエスト
・POSTメソッド...「送ったデータを基に処理して返してほしい」というリクエスト

【例】~会員サイトにログインを行う場合~
まず、検索画面にURLを打ち込んで検索をする(GETメソッドによるリクエスト)。
すると、ログイン画面が表示され、IDやパスワードを入力して送信を押す(POSTメソッドによるリクエスト)。

#### ■JSPとは?■
サーブレットについて調べた時に、JSPについての解説も度々拝見したので、併せて学習します。
JSPはサーブレットとペアで使われます。
サーブレットはHTMLで静的なコンテンツを出力するのは苦手です。
そのため、サーブレットは計算処理やデータへのアクセスを担当し、
JSPはサーブレットが処理したデータを受け取り、クライアント側に返答する役割を担っています。

#### ■まとめ■
Java Servletとはサーバー側で動くJavaで書かれたプログラムの事です。
クライアントからのリクエストに対応します。
しかし、静的なコンテンツは得意ではないためJSPと役割分担をしています。
また、Java Servlerが動くためにはサーブレットコンテナという環境が必要になります。


以上です。
【非同期処理】UITableViewが`Index out of range`でクラッシュする回避策

# 環境
・Swift 5.5.2
・Xcode 13.2.1
# 発生したエラー
※一部コードを省略しています
```Swift:ViewController.Swift
override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  self.users = []
  db.fetchUsers { [weak self] result in
    guard let self = self else { return }
    switch result {
    case .success(let users):
      self.users = users
    case .failure(let error):
      print(error.localizeddescription)
    }     
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell
    cell.configure(user: users[indexPath.row])  //この行で`index out of range`が発生する
    return cell
  }
}

extension ViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("indexpath.row: \(users[indexPath.row])") //タップした時にこの行で`index out of range`が発生する
  }
}
```

# 原因
非同期でデータを受け取る前（配列がまだ空）に`cellForRowAt`や`didSelectRowAt`が呼ばれて、存在しない要素にアクセスしたため。
# 回避策
下記のように、配列が空の時は早期リターンでアクセスしないようにすることで回避できます。
```Swift:ViewController.Swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell
  guard users.count > 0 else { return cell } //このコードを追加
  cell.configure(user: users[indexPath.row])
  return cell
}
```
Pythonanywhereというものを使ってデプロイしてみる

# Pythonanywhereというものを使ってデプロイしてみる

## Pythonanywhereとは
Pythonで制作したプロダクトをデプロイすることができるPaasクラウド
IDEとして利用することもでき、ブラウザ上でコードを編集することができる

## デプロイの流れ
こちらで制作したものをデプロイする(フレームワークはFlaskです)

https://qiita.com/sayyyyyy/items/97a54834577063081723

### コンソールでGithubリポジトリをクローンする
```
git clone https://github.com/sayyyyyy/flask-api
```
![スクリーンショット 2022-04-02 13.08.07（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/c1ed5c46-71d6-b569-222c-77d9c398d338.png)

![スクリーンショット 2022-04-02 13.08.43（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/aeecc5dc-c8f0-0163-432f-3797c9a9f12b.png)

成功したらFilesの中にクローンしたディレクトリが追加されてるはず!
この時にディレクトリのPythonファイルがある位置を確認しておく

## アプリの作成
WebをクリックしてAdd a new web app選択する

フレームワークを選択する(今回はFlask)
![スクリーンショット 2022-04-02 13.12.42（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/e8569f9b-3b0d-595c-f5cb-733326a09507.png)

Pythonのバージョンを選択する(今回はPython 3.9)
![スクリーンショット 2022-04-02 13.12.47（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/86ea9963-16cb-ddc5-c5db-bf7c990d0b16.png)

pythonファイルがある位置を入力する
![スクリーンショット 2022-04-02 13.13.29（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/403a5aa7-96bd-df2c-0f9f-911346e44636.png)

Pythonファイルが更新されてしまうので指定したPythonファイルを更新し直す(もっと良い方法があるかも)

Webの中にある下記の部分をEnabledにするとHTTPSになる
![スクリーンショット 2022-04-02 14.07.33（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/741f46d3-f24e-2937-bba0-ac5e17bb4e1a.png)

WebのReload~という緑色のボタンをクリックしてアプリを最新の状態に更新する

## デプロイの確認
クリックしてデプロイできているか確認する
![スクリーンショット 2022-04-02 14.39.08（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/3b92b7e4-48bf-bcfa-f32e-283f3218aed7.png)


## 参考資料

https://www.pythonanywhere.com/
Flaskを使って10分でAPI作る

# Flaskを使って10分でAPI作る
PythonのFlaskを使ってAPIを作ってみようと思います。

## Flaskのインストール
```
mkdir flask-api
cd flask-api

python3 -m venv .venv //任意
source .venv/bin/activate //任意


pip install Flask
```


## もっとも単純なもの
- urlにリクエストが来たらdataを返すAPI
```python
@app.route('/')
def return_data():
    data = {1: "a",
            2: "b",
            3: "c",
            4: "d",
            5: "e"}
    return data
```

## 条件をつけたもの

```python
@app.route('/id=<id>')
def designated_return_data(id):

    if id == '1':
        data = {1: "a",
                2: "b",
                3: "c",
                4: "d",
                5: "e"}
    elif id == '2':
        data = {1: "あ",
                2: "い",
                3: "う",
                4: "え",
                5: "お"}
    else:
        data = {1: "Not Found"}   
    
    return data
```

## 追記
このやり方だと他のIPアドレスからアクセスされたとき拒否してしまうのでflask-corsを追加して解決した。
しかしどのIPアドレスからもアクセスできてしまうのでセキュリティ的にはあまり良くない

```
pip install flask-cors
```

```python
from flask_cors import CORS

app = FLASK(__name__)
CORS(app)
```


## 制作したリポジトリ

https://github.com/sayyyyyy/flask-api
スマートウォッチのアプリ開発#1

目的
「iphoneでアプリ内のボタンを押すとスマートウォッチが振動するアプリ」を開発する。

今回行ったこと
1）対象とするスマートウォッチの選定
2) 1)のアプリ開発を進めた。

結論
1) スマートウォッチはfitbitとした。理由は、ローカル環境での開発が可能であり、開発言語もjavascriptを使用するため、私にとって開発しやすいから。
2) NO Go（プログラムを記載したものの実行が出来なかった）理由は、おそらくハードと繋いでいないと実行できないからである。

下記 「device bridge is disconnect」はハードと接続されていない。どうやらこれを接続しないとfit bit studio内のプログラムを実行できない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606792/e2150195-dce4-dce2-eec6-3c1a1e8d6a34.png)
⇒
fitbitのofficialサイト内の、開発者どおしでのアプリ開発コミュニティでは、同じように「実行」できない場合の質問があり、電話との接続が必要と記載がある。iphoneでアプリを入れても、ハードがなければ、PCのfitbit studioとは接続できなさそう。

今後の課題
android wearでも、ios iphoneからwear操作が可能なため、android studioでアプリを公開することとまではできそう。よって、スマートウォッチの選定はandroid wearとし、アプリの開発を進める。
但し、iphoneではplay アプリをダウンロードできないので、それは別途考える。
プログラミングコンテストチャレンジブック p58 個数制限なしナップサック問題(C#)

### 問題
重さと価値がそれぞれ、wi,viであるようなn個の品物があります。これらの品物から、重さの総和がWを超えないように選んだときの、価値の総和の最大値を求めなさい。ただし、同じ種類の品物をいくつでも選ぶことができます。

### 全探索
#### 自分(正解)

```
using System;

public class Program
{
    public static void Main()
    {
        int n = 3;
        int W = 7;
        int[,] list = new int[,] { { 3, 4 }, { 4, 5 }, { 2, 3 } };
        int ans;

        //個数制限なしの解答
        //indexをMax(入れてそのまま, 入れずに次へ)にする
        //同じ品物を入れ続けた際の終了(次のindexに行く)条件は、weight - list[index,0]が0を下回ること。次の品物なら入る可能性があるが、少なくとも同じ品物ではこれ以上入れることができないので。



        ans = exec(0, W);
        Console.WriteLine("答えは、{0}", ans);

        int exec(int index, int weight)//index番目以降を使って、残り入る重さはWだけある
        {
            if (index == n) return 0;
            if (weight - list[index, 0] < 0)
            {
                return exec(index + 1, weight);
            }
            else
            {
                return Math.Max(exec(index, weight - list[index, 0]) + list[index, 1], exec(index + 1, weight));
            }
        }
    }
}
```
Adoption Botを活用して作ったBotの応答を充実させる

## この文書は？

　[Adoption Botを活用して爆速でTeamsのBotを作る](https://qiita.com/yoshi_iwa/items/f865d7e12367209b168b#adoption-bot%E3%81%AEzip%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88) で作ったBotの応答を充実させる手順についてまとめたものです。


## 背景

　Botを作ったら次は応答を充実させるべきでしょう！と色々試してみたものの、手間なのでまとめておいたほうが良いなと…。


## 応答を充実させるには？

　主に2通りあり、どちらも「トピック」と呼ばれるBotの応答を増やしていく作業になります。

1. 手動でトピックを追加
1. 「トピックの提案」を利用しWebサイトやWeb上のファイルからBotの応答を自動生成


### 手動でトピックを追加

　Power Virtual Agentsの上メニューより「ボットチャット」クリック、Botの応答を手動で作っていくモードです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/84639f61-5cff-d92a-f8bd-4d1f02ab8476.png)

　きめ細かい応答が可能ですが、パーツが増えると全体を見通すのが大変になってきます。こんな感じでゴリゴリ作っていくと、パーツ組み合わせるのがだんだんだるくなってきて、コード書いて済ませられないかな…と思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/1ecf32b9-79f9-6f11-3110-c1e70247275b.png)


### 「トピックの提案」を利用しWebサイトやWeb上のファイルからBotの応答を自動生成

　今度はこちらの「トピックの提案」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/c1da4579-fe94-02f5-e810-7d0854e4342e.png)

　以下のような画面が出てくるので、FAQがまとまっているサイトやテナントのCSVファイルを選択します。今回は[よくあるご質問（FAQ） \| Zoom NECネッツエスアイ](https://symphonict.nesic.co.jp/zoom/faq/)を取り込んでみます。

　URLを入力し「追加」→「開始」とクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/d8ff3cfb-0555-f996-8363-758cd386d798.png)

　しばらく待っていると「トピック」の「提案された」タブに対象サイトから得られたトピックが溜まっているので必要なトピックをクリックし「トピックに追加」ボタンを押し登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/f033c418-cbc1-3447-91f8-1208b13b16c0.png)

　登録後少しおいてテストしてみます。上手く行ったようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/7ce91bfa-e635-fa56-15c3-9c823785ddaf.png)




## 注意事項

　提案されたトピックをトピックに追加しただけではBotの応答にはならないので注意しましょう。トピック登録→トピックのオンが必要です。
　トピックをオンにしてしばらくは、Botの応答としてそのトピックが出てこないことがあるため、少し待ちましょう。
　登録できるトピックの上限は250となるようです。「トピックの提案」を多様する場合は1カテゴリ1Botというような運用になりそうです。
　国から出ているPDFはトピックの提案に使えないものがありました。公開PDFがトピック化できるよう、工夫してもらえるとありがたいです。


## Botの応答で充実させたいこと

　質問の内容をベースにWeb検索し、結果をサマリーして返す等できるともっと良いのですが、Power Automateなどと組み合わせる必要があるかな？


## 参考

- [オンライン コンテンツからトピックの提案を取得する \(ビデオを含む\) \- Power Virtual Agents \| Microsoft Docs](https://docs.microsoft.com/ja-jp/power-virtual-agents/advanced-create-topics-from-web)
Sanity.io  Error: Failed to communicate with the Sanity API　の解決法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/a71d04f0-7a4c-0c3d-aebc-42304e5b1588.png)

#  Error: Failed to communicate with the Sanity API

```
npm install -g @sanity/cli && sanity init 
を実行すると下記のようなエラーが発生

Error: Failed to communicate with the Sanity API:
```

このエラーが起きたときの解決法をご紹介します！

[CLI errors](https://www.sanity.io/help/cli-errors)こちらの公式ドキュメントからも確認できます。

https://www.sanity.io/help/cli-errors


# 解決法は簡単:point_up:

ターミナルで**sanity logout**と**sanity login** を実行するだけです。
Try to log out and log in again with the sanity logout and sanity login CLI commands.

```
$ sanity logout //ログアウト

　Logged out

$sanity login　//ログイン

　? Login type (Use arrow keys)
　> Google
　  GitHub
　  E-mail / password

　Login successful

$sanity init　//初期設定

　Looks like you already have a Sanity-account. Sweet!

　? Select project to use (Use arrow keys)
　> Create new project
```
改めてログインをすれば、sanity initを実行することができます:tada:
【iOS】画面遷移時にキーボードを表示させる方法

<!-- textlint-disable -->
# はじめに
キーボードを起動するためにテキストフィールドを毎回タップするのがめんどくさいなぁと感じたため、画面が開いたときにキーボードが自動的に表示される方が便利と思いました。そのため、画面遷移をした後にキーボードを自動的に表示させる方法を書いていきます。

また、これは画面遷移が完全に終わる前にキーボードを事前に表示しておく方法です。画面遷移が完全に終了した後の処理はこの後出てくる `viewWillAppear` を `viewDidAppear` にすると可能です。

# やり方
これを実現するには簡単で、新しいメソッドを `ViewController` 内に以下のコードを追加します。

```swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    textField.becomeFirstResponder()
}
```

# 詳細説明
## `override func viewWillAppear(_ animated: Bool) {` とは？
画面に表示される直前に呼ばれるメソッドです。初期表示に必要な `viewDidLoad()` とは異なり、毎回呼び出されます。

UIViewController のライフサイクルについての詳細は以下の記事をご参照ください

https://qiita.com/entaku0818/items/87d4e7225e23db0b01ff

https://ios-docs.dev/life-cycle/

## `textField.becomeFirstResponder()`
UITextField はファーストレスポンダにすることによりキーボードを表示できます。逆にファーストレスポンダをやめるとキーボードを非表示にできます。

そのため、`textField.becomeFirstResponder()` とすることにより、画面を読み込むたびにキーボードを表示できます。

### 「ファーストレスポンダ」とは？
iOS では「レスポンダチェーン」と呼ばれる仕組みが用意されています。一連のレスポンダオブジェクトの連なりで、イベントを処理できるオブジェクトを決定するために使用されます。

レスポンダオブジェクトは基本的に View 階層のかいに位置されるオブジェクトから順に評価されるため、最初にイベントを受け取るレスポンダオブジェクトを「ファーストレスポンダ」と呼びます。
<!-- textlint-enable -->
プログラミングコンテストチャレンジブック p52 ナップサック問題(C#)


### 問題
重さと価値がそれぞれ、wi,viであるようなn個の品物があります。これらの品物から、重さの総和がWを超えないように選んだときの、価値の総和の最大値を求めなさい。

### 全探索で解いた
#### 自分(正解)

```
public class Program
{
    public static void Main()
    {
        int n = 4;
        int W = 5;
        int[,] list = new int[,] { { 2, 3 }, { 1, 2 }, { 3, 4 }, { 2, 2 } };
        int ans;

        ans = exec(0, W);
        Console.WriteLine("答えは、{0}", ans);

        int exec(int index, int weight)//index番目以降を使って、残り入る重さはWだけある
        {
            if (index == n) return 0;
            if (weight - list[index, 0] < 0)
            {
                return exec(index + 1, weight);
            }
            else
            {
                return Math.Max(exec(index + 1, weight - list[index, 0]) + list[index, 1], exec(index + 1, weight));
            }
        }
    }
}
```
Python3: Cloud Firestore に ndjson のデータを追加

こちらを参考にしました。
[ドキュメントの追加](https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja#add_a_document)

```py:put_firestore_docs.py
#! /usr/bin/python
#
#	put_firestore_docs.py
#
#						Apr/02/2022
# ------------------------------------------------------------------
import sys
import json
import ndjson
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
from datetime import date, datetime
# ------------------------------------------------------------------
def file_to_str_proc(file_in):
	str_out = ""
	try:
		fp_in = open(file_in,encoding='utf-8')
		str_out = fp_in.read()
		fp_in.close()
	except Exception as ee:
		sys.stderr.write("*** error *** file_to_str_proc ***\n")
		sys.stderr.write(str (ee))
#
	return	str_out
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")

file_ndjson=sys.argv[1]
sys.stderr.write(file_ndjson + "\n")

str_in = file_to_str_proc(file_ndjson)

data = ndjson.loads(str_in)

project_id='project-apr02-2022'
collection_in='sample_collection'

cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
	'projectId': project_id
})

db = firestore.client()

count = 0
for unit in data:
	print(count)
#	print(unit['senderId'])
#	print()
	db.collection(collection_in).add(unit)
	count += 1

sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行スクリプト

```bash
export GOOGLE_APPLICATION_CREDENTIALS="key-file-apr02.json"
./put_firestore_docs.py in01.ndjson
```
サーバへのファイル送信をAWS上だけで完結させる


SSHのポート番号と聞くと、昔大学院卒の同期に年齢を聞かれ「22」と答えたら、「SSHのポート番号じゃん」と言われたのを今でも思い出します。


それはさておき、サーバにファイルを送るためには、SCPコマンドを利用してという手順があると思いますが、利用できるポートが限られる場面も少なからずあるかと思います。  

私はMacを利用しているのですが、通常なら以下の手順を取ります。
 1. ターミナル起動  
 2. `scp -i [キーペアパス] [ローカルファイルパス] ec2-user@[IPアドレス]:[サーバのパス]`でファイルのアップロード
(WindowsならTera Termを使うことが多いかと思います)

ただ、先日これを行おうとしたところ、ポート番号の問題で許可されませんでした。  
その時の代替案として、S3とSystems Managerを利用して解決しましたので、備忘として残しておきます。  

## 前提
 - EC2を利用して、Webサーバを公開している
 - PCのローカル環境からscpやsshは都合上できない
 - AWSは割と強めの権限を持っていて、ロールの付与権限などもある

大まかな手順としては以下です。  
1. S3にサーバで利用するファイルをアップロード
1. EC2にSystems Managerとの接続ができるようなロールを付与
1. System Managerに入り、S3からファイルをダウンロードするコマンドを実行し、EC2にダウンロード



## S3のバケットとファイル準備
バケット名が被らないように設定を行います。バケットの設定は初期状態のままで問題ありませんでした。  
(パブリックアクセスも全てブロックのまま)  
![スクリーンショット 2022-04-02 13.24.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/498aea23-c45b-a071-f8a2-425cfd735d38.png)

その後、必要なファイルをドラッグ&ドロップなどでアップロードすれば完了です。

## EC2にSystem Managerとの接続ができるようなロールを付与
1. EC2の画面より、対象のEC2を選択し、[IAMロールを変更]をクリック
![スクリーンショット 2022-04-02 13.33.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/c483d4d1-afd4-8c32-3d99-9e9dc97198dc.png)

2. 遷移した画面よりロールの作成に飛べますので、そのまま新しいロールを作成します。
![スクリーンショット 2022-04-02 13.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/456cda08-65ef-c93c-d09d-34716c325efe.png)

3. EC2を選択し次へ
![スクリーンショット 2022-04-02 13.37.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/94a51f8a-737e-d33c-e1ac-b31e0d4cb4ae.png)

4. 検索窓より、ssmと入力し[AmazonEC2RoleforSSM]を選択
![スクリーンショット 2022-04-02 13.39.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/78c06758-bb65-0828-369a-f0f3e97d3c9a.png)

5. その後わかりやすいロール名を記載して完了


## System ManagerよりEC2へアクセス
1. System Managerに入り[セッションマネージャー]を選択
![スクリーンショット 2022-04-02 13.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/863e05af-06b4-295f-df3b-8605cd762d1a.png)

2. セッションの開始を押す
![スクリーンショット 2022-04-02 13.47.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/095775f5-e758-fe1c-ffa2-238a25c5646b.png)

3. サーバが起動している場合は、以下のように表示がされるため選択して[セッションを開始する]を押す
![スクリーンショット 2022-04-02 13.47.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/a0640dc8-82bf-26bd-71b3-a8116a12aac9.png)

4. 以下のような画面に遷移するため、cliを利用して`aws s3 ls s3://バケット名`バケット内のファイルを確認
![スクリーンショット 2022-04-02 13.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/e892c987-1199-64b0-d34a-89dfb95d0523.png)
(Amazon linuxなら、特に何も作業せずAWS cliの利用ができました。)

5. `sudo su`で管理者権限になり、作業が行えるディレクトリに移動し、ダウンロードコマンドを実行
`aws s3 cp s3://バケット名/index.html ./ ` #現在いるディレクトリにコピー
![スクリーンショット 2022-04-02 14.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1412976/deeb52f9-d1db-3b0c-d0b0-2ce9fafe450e.png)

6. 必要に応じて`mv`を行いディレクトリの移動などをさせれば完了です。  




平日は結構遅くまで仕事をしていることが多く、勉強したり記事を書くのは休日になることが多いのですが、  
やはり奥さんから「休みの意味知ってる？」と煽られますのでぷよぷよしてきます。  


## 参考文献
https://qiita.com/akhkyamada/items/d19eb20014d1b4529625
エンジニア転職して1年。どうだった？

# はじめに
さあ、やって参りました12月目の振り返りです！
2ヶ月まとめた月もありましたが、このシリーズもなんやかんや1年経ちました。早い！
今月も振り返っていきたいと思います。よろしくお願いします！

## この1ヶ月（入社後12ヶ月）の振り返り
![](https://storage.googleapis.com/zenn-user-upload/7d1de9a6bd53-20220402.png)

桜の季節ですねえ。お花見したいですねえ。

3月のトピックといえば、チームに**新しく3名入社された**ということですね。
もともとの人数が6人だったのでそこに3名、、一気に増えました。
そしてメンターもさせていただけることになりました。
人も増え、役割も1つ任せていただき、**環境の変化を感じた1ヶ月**です。

**これまでは良かったこと、正解と思っていたことがそうではなくなる**なと、
それに伴い自分の新たな課題も認識し始め、課題克服のため日々練習、練習です。
能力も知識も経験も、まだまだまだまだ足らないなと感じます。成長痛です。（言いたいだけ）

技術面でいうと、これまた新たなチャレンジがありました。
この1年はバックエンドメイン（フロントとの割合は7:3ぐらいの感覚）の開発が多かったですが
今回はフロント：バックエンドが５：５ぐらいになりそうな開発をさせていただくことに。
更に来月からは**ペアプロ**も本格的に始動しそうです。
技術力も上げていくぞ〜と燃えています。
![](https://storage.googleapis.com/zenn-user-upload/230496256a03-20220402.png)
（燃えてます）

また、開発しながら**既存のコードから考えない**ということを結構感じた1ヶ月でした。
新規開発と並行しながら不具合修正をしていたのですが
不具合修正は特に**既存のコードをどう変更するか**を考えてしまっているなと。
それだとせっかく変更しても、一時対処になりかねないなと、、
（緊急度にもよりますが）既存コード無視してあるべきから考えられるようになりたいこの頃です。
修正するなら根本解決するべきで、どうあるべきかから考えてからだなと、、、、、、




# 1年間の振り返り
入社してちょうど1年。
1２月にも書いていましたが、１ヶ月ずつ、何があったのか簡単に振り返ってみます。

```
4月：テスト環境で障害を起こし、事業部の責任者から「祝」のスタンプをもらう（今はもう笑い話、のはず）
5月：ついに本番環境で障害を起こしてしまい、冷や汗トマラナイ。プチ開発開始。
6月：本格的に開発に携わるようになり、開発で沼にハマることを経験
7月：自分が0から関わった開発がリリースされる。達成感すごかった
8月：障害対応、不具合調査にも結構関わるように。緊張感は慣れない、、
9月：設計書を書いて依頼、進捗管理を経験
10月：ユーザーの顔が思い浮かぶようになる、知識、考えを誰かに伝える機会が増える
11月：自分の担当した開発でユーザーから便利になったと声を聞いて泣きそうになる（泣いてる）
12月：個人目標、チーム目標の数字を必死のパッチで追いかけ達成
1月：問い合わせやフォローに追われつつもリリースに向けて準備。
　　　　　　　システムに関するアワードの裏方を経験。熱量に感動する
2月：サプライズ表彰いただく。目標としていたリリース日が延期になり、悔し泣きしつつも何とか月内にリリース。
3月：チームメンバーも増え、メンターをさせていただき、業務フォローに入ることも増える
```

こう見るとあっという間でしたが、濃ゆい1年だったなと。
良い意味で感情が動くことも多かった1年です。
失敗（挑戦）を歓迎してくれる環境だからこそ、
いろんなこと経験させてもらえたなと改めて思います。
（今も相変わらずアクセル全開で突っ込んでCTOやメンターさんに優しく止められたりしています。）
エンジニアとしての1社目が今の会社でよかったなと本当に思います。
1年前の自分に声かけるなら「よくやった」と言いたいぐらいです

今は、入社当初よりできることも見えるもの増えた実感はありつつも、
一方で、当初よりも課題をたくさん感じています。
これはある意味健全かな？と思ったり。
また1年振り返るときには、この1年よりも更に濃い1年だったと思えるようにしていきたいです。


## 最後に
自分の振り返りにもなるし、、と思って書き始め、なんやかんや1年が経ちましたが
1年前（4月、5月）にこんなこと感じていたのか、、と
**自分の変化**を実感したり振り返りにもなったりしていました。

（そういえば、入社当初、パスワードの暗号化のことを文字化けしてると言ってました、
メンターをしてくださっている先輩が優しく教えてくれました、今思うと怖いこと言ってた）


一旦、月次で振り返るのは今回で終わりにしよかなと。
今後の方針を模索中ですが、振り返りは定期でしつつも、
技術面ももう少し投稿していきたいと思っています。

ここまで読んでくださった皆様、ありがとうございました！
【TypeScript入門 #9】Definitely Typed(@types)とは

# 概要

オンラインサロン IT_KINGDOM で、typescript について学んだことを備忘録としてメモしていきます。

# 学習内容

- Definitely Typed(@types)とは
- パッケージの選び方

# Next.js と React の型定義ファイル(index.d.ts）の保存場所

- Next.js の型の保存場所<br>
  node_modules > next > types > index.d.ts
- React の型の保存場所<br>
  node_modules > @types > react > index.d.ts

# 型定義ファイルの指定

config.json ファイル内の `@types/react` で指定。

```
  "devDependencies": {
    "@types/react": "17.0.32",
    "autoprefixer": "^10.4.2",
    "eslint": "8.10.0",
```

# 外部パッケージの選び方

下記の優先順位で選択すると良い

1. TypeScript 製であるパッケージ
   Github 上の `Languages` で言語を確認できる
2. JavaScript 製でも型定義ファイル(index.d.ts)がパッケージ内にあるパッケージ
   index.d.ts を人間の手で作るため、誤っている可能性がある
3. 型定義ファイルがパッケージ内にないが、DefinitelyTyped にあるもの
4. JavaScript 製で型定義ファイルが DefinitelyTyped にもないパッケージ
   自分で型定義ファイルを生成する必要があるため、初心者のうちは避ける方が良い

# 型定義ファイルの生成方法

ts ファイルまたは tsx ファイルのコンパイル時に、`-d`オプションをつける

```
npx tsc ./index.ts -d
```

# 参考サイト

[IT Kingdom](https://it-kingdom.com/)
X-XSS-Protection ヘッダー概要 メモ

HTTPヘッダーの一つであるX-XSS-Protectionの概要についてメモする。


## X-XSS-Protectionとは

* ブラウザの「XSS フィルタ」を有効にするためのHTTPヘッダー。

* 反射型クロスサイトスクリプティング攻撃を検出したときに、ページの読み込みを停止する。

  * **反射型クロスサイトスクリプティング**・・・攻撃者は偽メールや偽サイトに不正なスクリプトを含んだリンクを用意し、脆弱性のあるサイトに誘導する（リクエストさせる）ことで、ユーザのブラウザで不正なスクリプトを実行させ、情報の搾取やマルウェアダウンロードなどを行わせる攻撃

   ![xss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/898e5aae-e2f5-e082-7660-faf010014c22.png)


* ブラウザには、XSSのブロック機能を備えたものがある。しかし、ユーザの設定によっては無効になっている場合があるため、サーバ側から明示的に有効にするために使用する。

## 設定値

* `0`

  * XSS フィルタリングを無効化する

* `1`

  * XSS フィルタリングを有効化する
  * XSSを検知すると、ブラウザはページをサニタイズする

* `1; mode=block`

  * XSS フィルタリングを有効化する
  * XSSを検知すると、ページをサニタイジングするのではなく、レンダリングを停止する

* `1; report=<reporting-uri>`

  * XSS フィルタリングを有効化する
  * XSSを検知すると、ブラウザはページをサニタイズし、攻撃レポートを作成・送信する
    * 送信先は<reporting-uri>に指定する

  

## 参考情報

* [X-XSS-Protection](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection)