OmniAICreator/Qiita-1.07M huggingface dataset:
正規表現の読み方【初心者向け】

正規表現について勉強したのでまとめます。

## 正規表現とは
正規表現とは「いくつかの文字列を一つの形式で表現するための表現方法」のこと。
ログ分析やバリデーションなどで使用されます。
## 具体例
例えば「いしだ　ゆうき」さんをローマ字で表す場合は、いくつかのパターンが考えられます。
 ヘボン式では「ishida yuki」と表現します。
しかし、「し」を「si」、「ゆうき」を「yuuki」と表現するパターンがあります。
また、姓と名の間を半角スペースではなく全角スペースで表すパターンもあります
全てのパターンの組み合わせを書くのは大変ですが、正規表現で表現すると以下のようになります。

```
ish?ida[␣□]+yuu?ki
```

␣を半角スペース　□を全角スペースとする

## 解説

「ish?ida」の「?」は前に書かれている文字があってもなくても大丈夫という意味になります。
つまり「h」を含む「ishida」でも、「h」を含まない「isida」でもいいということです。
「yuu?ki」も同様で「yuuki」でも「yuki」でもかまいません。


<br>
「ish?da」と「yuu?ki」の間にある[␣□]は「半角スペース」と「全角スペース」どちらか一文字を表すという意味になります。
ブラケットと呼ばれる半角カッコの 『　[　』 と 『　]　』 中で文字を列挙すると、その中のどれか1文字を表すことができます。
「ishida␣yuuki」でも「ishida□yuuki」のどちらでもいいということです。

ちなみに文字の間を-(半角ハイフン）で繋ぐと以下のようになります。

- [1-9]は数字の1~9のどれか1文字という意味になります。
- [a-z]はアルファベットのa~zのどれか1文字を表します。

## その他<br>

- 「.」で任意の1文字を表すことができます。　　
    - 例） a. → aBやa9 
    
- 「+」ではその直前に置かれたパターンを繰り返すことをイメージします。
    - 例）　a+　→ aaやaaaaaaa
    - 例）　[a-z]+　→ hello
    - 例）　[0-9␣-]+ → 090-3333-2222(電話番号）や020␣010␣01300


## 終わりに
難しいイメージがあった正規表現ですが、一つ一つ勉強してみると非常に便利なものであることがわかりました。
他にもいろんな表現方法があるので覚えていきたいと思います。

## 参考
- Software Design ６月号　特集　「使いどころのわかる正規表現入門」　　技術評論社出版　　著者　結城 洋志
target="_blank" の危険性？　rel="noopener"をつけよう

今回は「target="_blank"」の危険性についてです。

aタグによく使われるのが「target="_blank"」ですね。
「target="_blank"」はaタグの中に記述すると、そのリンクから飛ぶ際に新しいタブを開くことができます。

結論から言うと「target="_blank"」をつける場合は**「rel="noopener"」**も付けてあげましょう。

なぜかというと、どうやらセキュリティ上の危険があるようです。
簡単に説明すると、「rel="noopener"」を付けなかった場合、リンク先でJavaScriptを使えばリンク元のサイトを操作することができてしまいます。
具体的にはウイルスを仕込まれる、と言うことがあるみたいですね。

お恥ずかしながら私は最近知りました…
ウイルスを仕込まれるなんて、たまったもんじゃないですね。

皆さんも気をつけましょう〜
2021年の外国のプログラミング学習Webサイト ベスト5

ソフトウェア開発は急速に発展する分野です。プログラミング技術も絶えず更新されています。この文章で、ベスト5のプログラミング学習サイトを集めました。プログラミングは絶えず勉強しなければなりません！
##1.Codegym
CodegymはJava中心のWebサイトです。理論的知識と実践的知識を組み合わせており、1,200を超える実践プロジェクトを見つけることができます。ゲーミフィケーションとストーリーテリングを通じて学習を楽しくします。もう1つのハイライトは、オンラインIDEを提供し、タスクをクリアすることで学習します。アクティブなJavaコミュニティがあり、お互いに交流できます。

**アドレス：https：//codegym.cc/（Googleアカウントでの直接ログインをサポート）**
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/bddcec49-7b59-ea4f-1655-c5b8d282c93e.png)

##2. Treehouse
Treehouseは、プログラミングの知識を簡素化するもう1つのプラットフォームです。APPの作成、WordPressブログの作成など、特定のプロジェクトに対処するために必要なスキルを学びます。

**アドレス：https://teamtreehouse.com/ （アカウントを新規作成が必要）**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/fb79dd99-fb4b-5517-d502-3da4c1568e4b.png)

##3. Khan Academy
Khan AcademyにはJavaまたはPythonのチュートリアルはありませんが、プラットフォームはコンピュータサイエンスの基本概念を理解するための良い出発点です。ウェブサイトの課程を完成したら、データ構造とアルゴリズムに関する知識を理解し、「プログラマー思考」を獲得します。

**アドレス：https://www.khanacademy.org/computing/computer-science（Googleアカウントでの直接ログインをサポート）**
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/8d544d8f-3ebd-d4f5-717f-bb3103c9e997.png)

##4. Code4Startup
創業分野でより多くの実務経験を得たいなら、Code 4 Startupは開発スキルをうまく利用できるプラットフォームです。このプロジェクトにより、初級プログラマが実際のスタートアップ会社のためにコードを作成することができます。同時に、企業は人材募集の費用を節約できます。

**アドレス：https://code4startup.com/（Google/Githubアカウントでの直接ログインをサポート）**
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/da9d6873-b158-ab2f-f9a6-16805a525f16.png)

##5. Freecodecamp
非常に幅広いチュートリアルとコースを備えた最大の技術コミュニティの1つです。ここで実用的なプロジェクトベースの作業を見つけます。しっかりとしたプログラミング理論を身につけたら、Freecodecampを推薦します。

**アドレス：https://www.freecodecamp.org/（Google/Githubアカウントでの直接ログインをサポート）**
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/69e7c870-5dd0-95a2-cd21-901293c8657b.png)
Laravel input type="time"を使ってcreated_atカラムを検索する

絞り込み検索などを実装する際、年月日は置いておき、時間だけで検索したい！
という時に実装した事を忘備録としてまとめます。

抽象化するとわかりにくいので、具体例を用いてまとめます。
Laravelでブログを制作し、記事一覧ページなどから投稿記事を「作成時間」で検索する（あまり時間で検索することはないかもですが。。）機能を作るというシーンとします。
○時×分〜□時△分に投稿された記事を検索するイメージです。

## 形式の違い

### timestamps　（検索参照先）

Laravelでブログサイトなどを作る時、普通は記事のテーブルに`timestamps()`で`created_at`と`updated_at`のカラムを作成するかと思います。
今回はこの`created_at`を参照して記事を検索します。

`created_at`や`updated_at`など、`timestamps()`で作成された値は、特別何も指定しなければ、Y-m-d H:i:sの形式（ex.2021年6月7日15時40分10秒に記事を作成したら`2021-06-07 15:40:10`）で保存されます。
時間だけで検索したいのに、、、Y-m-d が邪魔で実装しにくそう。。

### input type="time"　（検索入力元）

inputタグにはtype="time"という便利なオプションがあります。
時間の入力を`input type="time"`を使うと、H:iの形式（ex.`15:40`）という値を簡単に入力する事ができます。
今回はこれを使います。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/time

### 形式の違いまとめ

|    |  形式  |
| ---- | ---- |
|  timestamps() ※created_at   |  Y-m-d H:i:s  |
|  input type="time"  |  H:i  |

ここまでで上表の通り、表記の違いが生じる事がわかりました。
timestampsでは年月日に加えて秒まで記録してくれてます。今回に関しては余計な事を...!って感じです。
検索時にはこれを合わせなければなりませんが手間が掛かりそうですよね。


## whereTime()を使う


そんな時に便利なのが、`whereTime()`です。
Laravelクエリビルダには時間に関係する色々なWHERE節が用意されています。
（whereDate / whereMonth / whereDay / whereYear / whereTime）

https://readouble.com/laravel/5.8/ja/queries.html

## 実装

検索フォームについて詳細は省略しますが、時間入力の部分はこんな感じにします。

```list.blade.php
<input type="time" name="from_time">
<span>〜</span>
<input type="time" name="to_time">
```

○時×分〜□時△分の記事を検索。
nameの値は ○時×分：`from_time` □時△分：`to_time`とします。

では、Controllerの実装です。

```ArticleController.php
    public function list(Request $request)
    {
        // それぞれの入力値を取り出す
        $from_time = $request->from_time; //○時×分
        $to_time = $request->to_time; //□時△分

        // 両方の入力フォームに入力があった時のみ検索
        if(!empty($request->from_time) || !empty($request->to_time)){
            $query->whereTime('created_at','>=',$from_time.':00')->whereTime('created_at','<=',$until_time.':59');
            $articles = $query->get()->sortByDesc('created_at');
        }else{
            $articles = Article::all()->sortByDesc('created_at'); //検索がない時は全ての記事を取得
        }
        return view('article.list', ['articles' => $articles]);
    }
```

これで時間だけを指定して検索する事ができます。

### 解説

`$query->whereTime('created_at','>=',$from_time.':00')->whereTime('created_at','<=',$until_time.':59');`この一文についてですが、、、

#### ポイント①
まず`whereTime('created_at','>=',$from_time.':00')`で`$from_time`(○時×分)以降の記事を検索し、その記事群から`whereTime('created_at','<=',$until_time.':59')`で`$to_time`(□時△分)までの記事に絞り込むイメージです。
比較演算子が使えるのでwhereBetweenを使わなくても範囲指定できます。


#### ポイント②
形式の違いを確認した際、秒の有無がありましたが、これは`$from_time.':00`と`$until_time.':59`で秒を無理やり付け足して解決です。
Next + Storybook で「 importSource cannot be set when runtime is classic」

Gatsbyに関しての記述はまぁまぁ見つかったのですがNextを使う時の記事が見つからなかったのでメモ
## 環境
- Nextjs(10.0.6)
- storybook(6.2.9)
- theme-ui(0.9.1)

## 状況

```Sample.tsx
/** @jsxImportSource theme-ui */

type Props = ComponentProps<'div'> & {};

export default function Sample(props: Props): JSX.Element {
  return <div sx={{ backgroundColor: '#ddd'}}} {...props} />
}
```
こんな感じのコンポーネントをStorybookで表示しようとするとエラーが出ました

```sh
$ yarn storybook
...省略
ERROR in ./lib/components/sample/Sample.tsx
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /Users/username/project/path/sample/Sample.tsx: importSource cannot be set when runtime is classic.
```

## 原因

「when runtime is classic」と書いてあるので＠babel/preset-reactの設定を変えてruntimeをclassicじゃない何かに変えてあげればいいことはわかるのですが...

storybookの`main.js`をいろいろいじって@babel/preset-reactの設定を変えても治りませんでした

結果気づいたのが、実はエラーの出たプロジェクトではルートディレクトリに`.babelrc.json`を作っていたんですよね

↓実際の`.babelrc.json`

```.babelrc.json
{
  "presets": ["next/babel"],
  "plugins": [
    [
      "prismjs",
      {
        "languages": [
          "javascript",
        ],
        "plugins": ["line-numbers", "diff-highlight"],
        "css": true
      }
    ]
  ]
}
```

この設定のnext/babelの中で@babel/preset-reactが使われてるのがエラーの原因でした

## 解決策

結果としてnext/babelを設定して@babel/preset-reactの設定を変えてあげればエラーが出なくなりました

```.babelrc.json
{
  "presets": [["next/babel", {"preset-react": {"runtime": "automatic"}}]]
}
```

## まとめ

[公式](https://nextjs.org/docs/advanced-features/customizing-babel-config)の説明を読むと「next/babelが内包するpresetsについては[このファイル](https://github.com/vercel/next.js/blob/canary/packages/next/build/babel/preset.ts)読んでね！」みたいな記述があるのですが、「英語だ！コードだけ追えばいいや！」と考え完全に見落としてました（何回やるんだ...）

とはいえ、この設定なしでもNextがビルドできているのは何故だろう...

## ついでに

実はコンポーネントを作るたびに毎回`/** @jsxImportSource theme-ui */`と書いていたので、書かなくていいように設定加えました

```.babelrc.json
{
  "presets": [["next/babel", {"preset-react": {"runtime": "automatic", "importSource":"theme-ui"}}]],
}
```
OpencvのGauss関数

# 1.ガウスフィルタ法(Gauss Filter)

 ガウスフィルタリング（Gauss Filter）は、線形フィルタリングの一種である。OpenCV画像フィルタ処理では、平滑化画像、または像ブレ処理にガウスフィルタリングが用いられます。画像処理の雑音低減過程において，特にガウス雑音によって汚染された画像に広く適用されている。

 ガウスフィルタリングの基本的な考え方は、画像上の各ピクセルポイントの値は、その自身と近傍の他のピクセルポイントの値によって加重平均された後に得られる。具体的な動作は、画像の各画素点を一つの核（畳込み核、マスク、行列ともいう）で走査し、隣接する領域の各画素値を対応する位置の重みと一致させて加算することである。数学的な観点から，ガウスフィルタリングの過程は，画像とガウス正規分布の畳み込み動作である。

# 2.ガウス関数の原理

 ガウスフィルタリングは、名前の通りガウス正規分布に基づくフィルタです。まずガウス関数を理解します。
## 2.1 一次元ガウス関数
       G(x)=  (1/(√2π)σ)*e^(-x^2/2σ^2)  

 G（x）のはsigmaの採値と大きな関係があります。sigmaの値が大きいほど、画像は緩やかになり、sigmaの値が小さいほど、画像は鋭くなります。
![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234182/b99bc117-c609-f8ef-96cd-3dd2304eac4d.jpeg)

## 2.2 二次元ガウス関数
       G(x,y)=  (1/2π^2)*e^(-(x^2+y^2)/2σ^2)  

 二次元ガウスはガウスフィルタを構築する基礎である。G（x，y）のx軸y軸上の分布は突起の帽子の形です。ここでのsigmaは2つの値、1つはx軸上の成分sigmaX、もう1つはy軸上の成分sigmaYと見なすことができる。画像処理に対しては、sigmaを直接使用して画像の行列を操作しても良いし、sigmaXで画像のラインを操作して、sigmaYで画像の列を操作しても良いです。それらは等価です。

 sigmaXとsigmaYが大きいほど、全体の形は扁平に近いです。sigmaXとsigmaYが小さいほど、全体の形状が突起します。  

![22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234182/f62dc20c-7f42-e75b-1bd1-b699e9b76c5f.jpeg)

## 2.3 ガウスフィルタテンプレート

3×3のガウスフィルタテンプレートを例にとって、テンプレートの中心位置を座標原点としてサンプリングします。テンプレートの各位置の座標は、以下の通りです。
	
<table border="1">
<tr>
<td>(-1,1)</td>
<td>(0,1)</td>
<td>(1,1)</td>
</tr>
<tr>
<td>(-1,0)</td>
<td>(0,0)</td>
<td>(1,0)</td>
</tr>
<tr>
<td>(-1,-1)</td>
<td>(0,-1)</td>
<td>(1,-1)</td>
</tr>
</table>


このようにして、各位置の座標を二次元ガウス関数Gに持ち込んで、得られた各値を位置順に並べば、テンプレートが得られます。

例えば、ガウスの核を生成するのは3です。σ = 0.8のテンプレート

<table border="1">
<tr>
<td>0.057118</td>
<td>0.12476</td>
<td>0.057118</td>
</tr>
<tr>
<td>0.12476</td>
<td>0.2725</td>
<td>0.12476</td>
</tr>
<tr>
<td>0.057118</td>
<td>0.12476</td>
<td>0.057118</td>
</tr>
</table>

以上の説明から，ガウスフィルタリングテンプレートにおいて最も重要なパラメータは，ガウス分布の標準偏差σであることを示した。データの離散度を表しています。σ小さい場合は、生成されたテンプレート中心係数が大きいほど、周囲の係数が小さいほど、画像の平滑化効果はそれほど顕著ではない。反対にσ大きい場合は、生成されたテンプレートの各係数の差は大きくなく、平均テンプレートに似ているので、画像の平滑化効果が比較的大きいです。

# 3.Opencvのガウス関数

関数のプロトタイプ:

    void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);

パラメータの詳細は以下の通りです：

src，画像を入力すると、ソース画像となります。Mat類のオブジェクトを記入すればいいです。これは単独で任意のチャンネル数の写真でもいいですが、画像の深さはCV_であるべきです。8 U，CV_16 U，CV_16 S，CV_32 F及びCV_64 Fの一つ。

dst，ターゲット画像です、ソース画像と同じサイズとタイプが必要です。例えばMat::Cloneを使用して、ソース画像をテンプレートとして、偽のパケット交換のようなターゲット図を初期化することができます

ksize，ガウスカーネルの大きさ。その中でksize.widthとksize.heightは違ってもいいですが、彼らは正数と奇数でなければなりません。あるいは、それらはゼロであってもよく、それらは全部sigmaで計算されています。

sigmaX，Gauss核関数のX方向の標準偏差を表します。

sigmaY，ガウス核関数のY方向の標準偏差を表します。sigmaYがゼロであれば、それをsigmaXとし、sigmaXとsigmaYが0であれば、ksize.widthとksize.heightから計算します。
【LeetCode】就活に向けたコーディングテスト対策 #06

#はじめに
こんばんは．
M1就活生が[LeetCode](https://leetcode.com/)から，easy問題を中心に**Python**を用いて解いていきます．

https://leetcode.com/

↓では，解いた問題のまとめを随時更新しています．
[まとめ記事](https://qiita.com/halpi/items/43761b89a1873dcc9a5c)

https://qiita.com/halpi/items/43761b89a1873dcc9a5c

#問題
今回解いたのは，難易度easyから [問題20のValid Parentheses](https://leetcode.com/problems/valid-parentheses/) です．
問題としては，括弧文字からなる入力文字列`s`が与えられたとき，開いた括弧が同じ種類の括弧かつ，正しい順序で閉じられているかどうか判定するというもの．

入力例と出力例は以下の通りです．

Example 1:

```python
Input: s = "()"
Output: true
```

Example 2:

```python
Input: s = "()[]{}"
Output: true
```

Example 3:

```python
Input: s = "(]"
Output: false
```

Example 4:

```python
Input: s = "([)]"
Output: false
```

Example 5:

```python
Input: s = "{[]}"
Output: true
```

#書いたコード
とりあえず，思いついたままに書いてみました．

```python
class Solution:
    def isValid(self, s: str) -> bool:
        left_parenthesis  = ["(", "{", "["]
        right_parenthesis = [")", "}", "]"]
        parenthesis_map   = {"(": ")", "{": "}", "[": "]"}
        stack = []
        
        for parenthesis in s:
            if parenthesis in left_parenthesis:
                stack.append(parenthesis_map[parenthesis])
            elif parenthesis in right_parenthesis:
                if parenthesis != stack.pop():
                    return False
        return True
```

入力文字列`s`から，1文字ずつ見ていき，開き括弧であれば，それに対応する閉じ括弧を`stack`の末尾に追加，閉じ括弧であれば，`stack`の末尾から取り出します．閉じ括弧の場合に，取り出したもの（開き括弧に対応する閉じ括弧）が，異なれば`False`を返すことで，有効な括弧の判定を実装しました．最後まで走査できれば，有効な括弧ということで`True`を返します．

今回書いたコードでは，用意したリストが，辞書の内容と重複しています．辞書だけを利用してうまく書き直せないか調べたところ，`keys()`と`values()`というメソッドが有効そうであったのでこちらで書き直しました．

```python
class Solution:
    def isValid(self, s: str) -> bool:
        parenthesis_map = {"(": ")", "{": "}", "[": "]"}
        stack = []
        
        for parenthesis in s:
            if parenthesis in parenthesis_map.keys():
                stack.append(parenthesis_map[parenthesis])
            elif parenthesis in parenthesis_map.values():
                if parenthesis != stack.pop():
                    return False
        return True
```

#おわりに
簡単な問題でも，普段使わないものを使うことができるので，様々な知見が増えて楽しいです．
変数名や，コミットメッセージなどの決定に少し時間を掛けてしまったので，ルールを決めて効率化を図りたいものです．余談ですが，自分はオンラインゲームなどで始める名前を決めるのに時間が掛かるタイプです．皆さんはいかがでしょうか？

今回書いたコードはGitHubにもあげておきます．

https://github.com/halpi17/LeetCodeStudy/blob/master/020/validParentheses.py

[前回](https://qiita.com/halpi/items/642c039cb339a5e4cf66)　[次回](https://qiita.com/halpi/items/5a25d5295e96608966d3)
【Bash】変数を用いてJSON文字列を作成する

## はじめに

Bashで変数を使用するには`"`を使う必要があるため、シンプルに書くと以下のようになります。
が、これだと見にくく、追加が面倒くさいです。
そこで良い方法が無いか調べてみました。

```sh
$ REPOSITORY="foo"
$ BRANCH="bar"
$ SCOPE="baz"

$ echo "{
  \"repository\":\"$REPOSITORY\",
  \"branch\":\"$BRANCH\",
  \"scope\":\"$SCOPE\"
}"

# {
#   "repository":"foo",
#   "branch":"bar",
#   "scope":"baz"
# }

```

## 環境

```sh
$ echo $BASH_VERSION
4.4.20(1)-release
```

## 方法

### 1. シングルクォートを使う

シングルクォートを使うと、JSON 中のダブルクォートをエスケープせずに済むため、上より見やすいです
ただし、そのままだと変数が展開されません。
そのため、変数の前後にシングルクォートを置き、文字列と変数を連結させることで、変数が展開できるようにします。
イメージ: `'~' + $BRANCH + '~'`

ただ、少し分かりにくいかもしれません。

```sh
# そのままだと変数が展開されない
$ echo '{
  "repository":"$REPOSITORY",
  "branch":"$BRANCH",
  "scope":"$SCOPE"
}'
# {
#   "repository":"$REPOSITORY",
#   "branch":"$BRANCH",
#   "scope":"$SCOPE"
# }

# 変数の前後にシングルクォートを置く
$ echo '{
  "repository":"'$REPOSITORY'",
  "branch":"'$BRANCH'",
  "scope":"'$SCOPE'"
}'

# {
#   "repository":"foo",
#   "branch":"bar",
#   "scope":"baz"
# }
```

### 2. jq コマンドを使う

[jq](https://stedolan.github.io/jq/)をインストールする必要があります。

`-n` オプションは入力値を無視する(null として扱う)オプションです。
通常、`jq`コマンドは入力値を必要としますが、`-n`を使うことで入力値無しに実行できます。詳細は[こちら](https://stedolan.github.io/jq/manual/)

また、jq コマンドを使用すると JSON が整形された状態で出力されるので、少し見やすいです。

またこちらの場合、変数に`"`や改行が組まれていた場合に自動にエスケープしてくれるので、JSON解析時のエラーになりづらいです。

```shell
$ jq -n \
 --arg repository "$REPOSITORY" \
 --arg branch "$BRANCH" \
 --arg scope "$SCOPE" \
  '{
    "repository":$repository,
    "branch":$branch,
    "scope":$scope,
  }'

# {
#   "repository":"foo",
#   "branch":"bar",
#   "scope":"baz"
# }

# 改行やダブルクォートを含めてみる
$ REPOSITORY='foo"
foo'

$ jq -n \
 --arg repository "$REPOSITORY" \
 --arg branch "$BRANCH" \
 --arg scope "$SCOPE" \
  '{
    "repository":$repository,
    "branch":$branch,
    "scope":$scope,
  }'

# {
#   "repository": "foo\"\nfoo",
#   "branch": "bar",
#   "scope": "baz"
# }
```

### 3. printf コマンドを使う

組み込みコマンドの[printf](https://www.atmarkit.co.jp/ait/articles/1907/05/news012.html)でも変数が埋め込み可能です。

```shell
$ printf '{
  "repository":"%s",
  "branch":"%s",
  "scope":"%s"
}
' $REPOSITORY $BRANCH $SCOPE

# {
#   "repository":"foo",
#   "branch":"bar",
#   "scope":"baz"
# }
```

## 参考

- [Build a JSON string with Bash variables - Stack Overflow](https://stackoverflow.com/questions/48470049/build-a-json-string-with-bash-variables)
- [shell - Expansion of variables inside single quotes in a command in Bash - Stack Overflow](https://stackoverflow.com/questions/13799789/expansion-of-variables-inside-single-quotes-in-a-command-in-bash)
- [【 printf 】コマンド――データを整形して表示する：Linux基本コマンドTips（319） - ＠IT](https://www.atmarkit.co.jp/ait/articles/1907/05/news012.html)
- [jqマニュアル（開発版）](https://stedolan.github.io/jq/manual/)
『docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?』と出た時の対応。

■この記事を読む対象者
docker初学者向けの記事です。

■環境
Amazon Linux2 

■エラーが起きたあらまし
dockerのドキュメント（https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/linux-postinstall/）　　
を見つつdocker設定　→　起動しようとしたら『docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?』と出て、一向にdockerを起動できなくなってしまったので、その時の対応履歴を残します。


■原因
まず、今回どうしてこのエラーが発生してしまったか？　ですが、dockerのドキュメントに沿って、docker起動どうやってたっけ・・・と調べつつ進めていると、なぜか知らないうちにdockerのリモートアクセスの設定を行っていました。

今回のエラーの原因はdockerの外部アクセスを許可するための設定（リモートアクセス）で /etc/docker/の配下にdaemon.jsonを作成していました。
また、sudo systemctl edit docker.service　コマンドで、これまたリモートアクセスをしていました。
つまり、リモートアクセスしないのに、２重でリモートアクセスの設定を行っていました。

■対処方法

/etc/docker/の配下に作成していたdaemon.jsonファイルを削除。
sudo systemctl edit docker.service　コマンドをもう一度行い、ファイルの中身を綺麗に消しました。


あとは


sudo service docker stop して

sudo service docker start で再度dockerを起動

sudo docker run hello-world コンテナ作成

docker info でもdockerが起動できたことが確認できます。




■おわり
この記事がお役に立ったら幸いです。
どこか間違っている箇所ありましたらご指摘ください。
AWS BackupをCloudFromationで自動化

## 事前

* 大阪リージョンのAWS Backupに"Default"というバックアップボルトがある前提です。デフォルトであるのでだいじょぶだと思う

* デフォルトサービスロールを作っておく。"AWSBackupDefaultServiceRole"
  * これは、[この手順](https://docs.aws.amazon.com/ja_jp/aws-backup/latest/devguide/iam-service-roles.html)で作るか、[このブログ](https://dev.classmethod.jp/articles/backup-ec2-getbackup-001/) のようにAWS Backupで一度オンデマンドバックアップを行うと自動で作ることも可能。この方が楽です。

# サンプルテンプレート

* test-vault という名前のバックアップボールトを作成します。
* test-plan という名前のバックアッププランを作成します。
* ボールト test-vault に保存するバックアップを設定します。
* test-rule という名前のバックアップルールを作成し、毎日 1 回のバックアップを実行するようスケジュールします。これらのバックアップは、作成後 2 日で削除されるように設定します。
* 災害復旧の目的でバックアップを ap-norteast-3 AWS リージョンにコピーするように CopyAction を設定します。これらのバックアップは、作成後 2 日で削除されるように設定します。
* AWSBackupDefaultServiceRole という名前の IAM ロールを使用して、バックアップジョブを実行します。
キー backup2 と値 true でタグ付けされたすべてのリソースにバックアッププランを割り当てます。

```yml:
AWSTemplateFormatVersion: "2010-09-09"
Description: "Backup Plan template for thin backups"
Resources:
  testvault:
    Type: "AWS::Backup::BackupVault"
    Properties:
      BackupVaultName: "test-vault"

  testplan:
    Type: "AWS::Backup::BackupPlan"
    Properties:
      BackupPlan:
        BackupPlanName: "test-plan"
        AdvancedBackupSettings:
          -
            ResourceType: EC2
            BackupOptions:
              WindowsVSS: disabled
        BackupPlanRule:
          -
            RuleName: "test-rule"
            TargetBackupVault: !Ref testvault
            ScheduleExpression: "cron(25 11 ? * * *)"
            Lifecycle:
              DeleteAfterDays: 2
            CopyActions:
              -
                  DestinationBackupVaultArn: arn:aws:backup:ap-northeast-3:xxxxxxxxxxxx:backup-vault:Default
                  Lifecycle:
                   DeleteAfterDays: 2

    DependsOn: testvault

  testresource:
    Type: "AWS::Backup::BackupSelection"
    Properties:
      BackupSelection:
        SelectionName: "testresource"
        IamRoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/AWSBackupDefaultServiceRole"
        ListOfTags:
         -
           ConditionType: "STRINGEQUALS"
           ConditionKey: "backup2"
           ConditionValue: "true"
      BackupPlanId: !Ref testplan
    DependsOn: testplan

```

#### バックアッププラン

![スクリーンショット 0003-06-15 19.28.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/3b6fc8da-8c8c-773a-d848-12b5841ad7de.png)

#### バックアップルール

![スクリーンショット 0003-06-15 19.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/eb2a8549-4367-82a4-f893-a780570f0a47.png)

# 参考

https://aws.amazon.com/jp/premiumsupport/knowledge-center/aws-backup-cloudformation-template/
基本はこの通りやればできます。公式

AWS Backupの薄い教科書
https://qiita.com/pioho07/items/68ccbc7b974b1466e7a6
MySQL CLIでrootログインできなくなった時の話

MySQLでrootのパスワード忘れたという話は結構あると思いますが、自分の場合、パスワード忘れたわけでもないのにログインできなくなってハマったという話です。一言で結論を言うと、**認証のplugin欄がなぜかrootだけ空になってました**。なんでや。rootパスワード再設定してもログインできない人はpluginのカラムを見てみましょう。

それだけではなんなので。

rootパスワードがわからなくなった場合のよくある対処法は、セーフモードで起動してmysql.userテーブルのpassword(場合によってはauthentication_string)を手動でUPDATEするという感じです。うちはDebian(stretch)なので多少よそとコマンドが違うかもしれないから、手順を備忘録として書き記しておきます。

#具体的な手順

1.MySQLの停止

```
$ sudo service mysql stop
``` 

2.セーフモードでの起動

```
$ mysqld_safe --skip-grant-tables &
```
``&``はバックグラウンドでプロセスを走らせておくと言う意味。``--skip-grant-tables``で権限に関する動作を停止する。この間はMySQLで``SHOW GRANT``などの権限関係のコマンドは実行できない。

ここで``'/var/run/mysqld' for UNIX socket file don't exists.``というエラーが出るときは次の操作をしてから再度上を実行する。

```
$ sudo mkdir /var/run/mysqld
$ sudo chown mysql:mysql /var/run/mysqld
```

3.MySQLへログイン

```
$ mysql -u root
```

4.パスワードとpluginをUPDATE

```
USE mysql
UPDATE user SET authentication_string='パスワード' WHERE User='root';
UPDATE user SET plugin='mysql_native_password' WHERE User='root';
FLUSH PRIVILEGES;
```

2行目のauthentication_stringが古いバージョン（確かMySQL 5.7.5以前らしい）の場合はカラム名が違うので2行目はこちらを実行

```
UPDATE user SET password=password('パスワード') WHERE User='root';
```

5.確認してMySQLからログアウト

```
SELECT User, Host, plugin FROM user WHERE User='root';
```
これでplugin欄に``mysql_native_password``になっていることを確認する。なお、認証Pluginは最新のものに``caching_sha2_password``があるが、これに対応していないソフトがある様子。PhpMyAdminとか。

確認して問題無かったらMySQLから出る。

```
quit
```

6.セーフモードのバックグラウンドプロセスを停止させる

このままMySQLを停止〜再起動させる手順もあるようだが、自分の環境ではセーフモードのバックグラウンンドプロセスが走ったままだったので、これを停止させてからでないと再起動しなかった。

```
$ sudo pkill -f mysql
```

7.MySQLを起動し、rootでログインできるかどうか試す

```
$ sudo service mysql start
$ mysql -u root -p
パスワードを入力
```

これでログインできたらOK。いやしかしなんで認証pluginが空欄になったのか全くわからない。CMS用に作ったユーザーとかは消えてないのに。

**参考**
大変参考になりました。多謝。
[- Ubuntu 18.04 で MySQL 8 で root パスワードを忘れたときの再設定方法](https://obel.hatenablog.jp/entry/20191111/1573448206)
[- How To Reset Your MySQL or MariaDB Root Password] (https://www.digitalocean.com/community/tutorials/how-to-reset-your-mysql-or-mariadb-root-password)
*こちらはMariaDBの場合やバージョン違いの場合も丁寧に書いています。
【kotlin】forEach ラベル構文

#■forEachとは
配列やリストの要素を一つづつ取り出して処理を行うループ処理のためのものです。


例：
配列の数値全てに1を足したい。

例2:
配列の中に特定の文字列が存在するか

#■基本的な使い方

``` kotlin
fun main() {
 val nums = arrayOf(1,2,3,4,5)
 //ラムダ式で引数は単一なので省いている。
 nums.forEach{print(it)}
}

//結果：　　1、2、3、4、5
```

#■returnを使ってみる。
if文で数字が7になればreturnしてジャンプして8,9,10,
println("ラムダ式を終了しました。") が表示されて欲しい。
つまりこう言う結果が欲しい
//結果: 1,2,3,4,5,6,8,9,10,ラムダ式を終了しました。

しかしreturnを使えばforEachだけではなくmain()関数も抜けて関数全体が終了してしまう。

``` kotlin
fun main() {
 (1..10).forEach {
       if(it == 7) return
     println(it)
   }
 println("ラムダ式を終了しました。") 
}
//結果: 1,2,3,4,5,6
```

####■ラベル構文
kotlinのデフォルトの設定とは違う場所にジャンプするもの

ラムダ式だけをジャンプする。
forEachの横に loop@
returnの横に @loop
の様に書けば
ラムダ式のみをジャンプする事ができる。

``` kotlin
fun main() {
 (1..10).forEach loop@{
       if(it == 7) return@loop
     println(it)
   }
 println("ラムダ式を終了しました。") 
}

//結果: 1,2,3,4,5,6,8,9,10,ラムダ式を終了しました。
```

####■ラムダ式を引数に取る高階関数を名前をラベル構文に指定してもいい。

▼上記と違う書き方処理は同じ
returnの横に高階関数の@forEachを書く

``` kotlin
fun main() {
 (1..10).forEach{
       if(it == 7) return@forEach
     println(it)
   }
 println("ラムダ式を終了しました。") 
}

//結果: 1,2,3,4,5,6,8,9,10,ラムダ式を終了しました。
```
huskyでlint-stagedによるpre-commitがうまく動作しない時の対処法

huskyのバージョンを5系以降にupdateしたせいな可能性が高いです

huskyの[公式ドキュメント通り](https://typicode.github.io/husky/#/?id=automatic-recommended)に初期設定をし、以下のようにする。

```package.json
"husky": {
  "hooks": {
    "pre-commit": "yarn lint-staged"
  }
}
```

.husky/pre-commitファイルは以下の感じにする

```
#!/bin/bash
. "$(dirname "$0")/_/husky.bash"

yarn lint-staged
```
Google I/O 2021 フロントエンドまとめ（3/6）: 〜Webプラットフォーム最新情報（3/3）: その他〜

# Google I/O 2021 フロントエンドまとめ（3/6）: 〜Webプラットフォーム最新情報（3/3）: その他〜

この記事は、[Google I/O 2021](https://www.google.com/io)で発表されたフロントエンド関連情報の中で個人的に気になったものをまとめたもので、
全6記事中3本目。

## Webプラットフォームの話
[ウェブ プラットフォームの最新情報 @Google I/O 2021](https://events.google.com/io/session/97ea9417-2bba-4383-8eb4-22aee86af034?lng=ja)

### Google Mapの新機能`WebGLOverlayView`で3Dマップの操作が出来るようになったよ。というお話
`WebGLOverlayView`の継承クラスを作成して、その決められたイベントハンドラメソッド（`onAdd()`, `onContextRestored()`, `onDraw`）内でそれぞれ適切なセットアップ・描画処理を記述するとのこと。
デモではthree.jsを使ってグラフィックを設定／操作していた。

すげぇ楽しそう！！

### `WebGPU`の紹介
`WebGL`とは別の、より低レベルなグラフィックAPIである`WebGPU`の紹介。
低レベルAPIなのでハイパフォーマンスで、`Vulcan`, `Metal`, `Direct3D 12`などから発想を得ていて、3Dグラフィック界隈での今っぽい流れを汲んだものらしい。
いまのところ試験運用版とのこと。

### V8が`SIMD`をサポートしたからChromeの`WebAssembly`がもっと高速になったよ。というお話
まず、`SIMD`（読み: しむど、しむでぃー; Single Instruction, Multiple Dataの略）というのは、一回の命令で複数のデータを並列一括処理出来る仕組みで、いわゆるベクトル演算。ベクトル演算なのでグラフィック処理や暗号処理、物理演算、機械学習などの演算が得意と言われている。
今回ChromeやNode.jsのJavaSript実行エンジンであるV8で`SIMD`がサポートされたので、いくつかの処理でより高速化できる可能性が広がったよというお話。
その一例としてGoogle Meetで、ブラウザ内にメディア処理パイプラインに導入してパフォーマンスを200%向上したり、`TensorFlow`をつかった背景ぼかし機能を実現したりしたよ。という話もあった。

### V8のデバッグ体験向上としてDevToolsでWebAssemblyのブレークポイントと変数検査が出来るようになったよ。というお話
「これで、クライアントとサーバの両方で安全かつ快適に動作する`WebAssembly`が作れるね！」みたいなことを言ってました。

### [`content-visibility`CSSプロパティ](https://developer.mozilla.org/ja/docs/Web/CSS/content-visibility)によるレンダリングコスト削減手法の話
[`content-visibility`](https://developer.mozilla.org/ja/docs/Web/CSS/content-visibility)はCSSのプロパティの一つで、このプロパティが指定されたコンテンツのレンダリングを省略させたり出来る。
`content-visibility: auto;`を指定すると、要素がビューポート内にいないときはレンダリングが省略されパフォーマンスコストが削減できる。
今回は「これが使えるようになりましたよ」というお知らせ。

### [`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)のお話
[`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)自体の話や、
[`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)を改善したことによるページパフォーマンス改善・コンバージョン向上の話、
[`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)を計測可能なツールの広がり、
Google検索のページランクの考慮に[`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)が含まれるようになる
みたいな最近よく聞く[`Core Web Vitals`](https://qiita.com/toshi00ysm/items/29aa3c54e3e85247a1ef)の話。

[つづく](https://qiita.com/toshi00ysm/items/29e6409261da1d75fe07)
【Kintone】複数のユーザーフィールドの値を1つのユーザフィールドに重複なく当てはめる

# やりたいこと
Kintoneレコードで複数存在するユーザフィールドの値を別のユーザフィールドにすべて入れたい
ぱっとググって調べて出てこなかったので、ここに残します

KintoneのJavaScriptカスタマイズを使用します

# 例で使用するフィールド

* フィールドコードが"ユーザー1"のユーザー選択フィールド
* フィールドコードが"ユーザー2"のユーザー選択フィールド
* フィールドコードが"ユーザー3"のユーザー選択フィールド

##### ユーザー1とユーザー2の値を重複なくユーザー3に当てはめます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022607/079a5bf3-f1d0-f074-1237-c5b0bf721180.png)

# 実装例

レコード編集画面で一律にユーザ3の値をリセットし、レコード保存時に再度値を当てはめたうえで、保存される仕組みです
ユーザ3の値のリセットを保存前に実行するとうまく動作しなかったため、処理を分けています

```javascript
    kintone.events.on([
        'app.record.create.show',
        'app.record.edit.show',
    ], function(event){
        let record = event.record;

        // ユーザ3を空にする→レコードの保存直前に再度値を当てはめる
        record['ユーザー3'].value = [];

        return event;
    });

    kintone.events.on([
        'app.record.create.submit',
        'app.record.edit.submit',
    ], function(event){
        let record = event.record;

        // ユーザごとの値を変数にする
        let valueUser1 = record['ユーザー1'].value;
        let valueUser2 = record['ユーザー2'].value;
        let valueUser3 = record['ユーザー3'].value;

        // 処理のなかで使用する配列の変数を中身が空の状態で先に用意
        let usersArray = [];
        let usersUniqueArray = [];

        // ユーザフィールドの値をusersArrayの変数に入れる
        // (この時点ではユーザの重複が発生する)
        valueUser1.forEach(user => {
            // usersArray.push({'code': user['code']});
            usersArray.push(user);
        });
        valueUser2.forEach(user => {
            // usersArray.push({'code': user['code']});
            usersArray.push(user);
        });

        // usersArrayから重複のあるユーザを重複が無いようにして、
        // usersUniqueArrayの変数に入れる
        usersUniqueArray = usersArray.filter((user, index, self) =>
            index === self.findIndex((t) => (
                t['code'] === user['code'] && t['name'] === user['name']
            ))
        );

        // 重複の無いユーザデータを'ユーザー3'フィールドに当てはめる
        usersUniqueArray.forEach(user => {
            valueUser3.push(user);
        });        
        return event;
    });
```

# 注意事項
ユーザ選択をJavaScriptカスタマイズで登録するときは、ユーザーのcodeのみで登録が可能ですが、
私が試したときはユーザのnameも一緒に与えてあげないとうまくいきませんでした
ユーザのcodeのみで動作する場合は以下のコメントアウトされている部分を使用してください

```javascript  
  usersArray.push({'code': user['code']});
```
Pythonでクレカ発行してみた（Marqetaチュートリアル）

## データモデルの理解
### Card Products
https://www.marqeta.com/docs/core-api/card-products

こちらを読む感じだと、Card Productはクレカ商品を指します（なんとかカードってCMでやってるような感じのもの）。

物理カードやバーチャルのカードについて、動作や機能を定義することができます。Card Productで指定することが可能な属性は、カードがATMやオンラインで使用できるかどうか、また、現在有効であるかどうかを設定できます。物理カードの場合、Card Productは、カードの券面デザインを指定することができます。オプションとして、認証制御やベロシティ制御をCard Productに関連付けることで、関連するカードの使用場所や使用方法を制限することができます。

### Cards
https://www.marqeta.com/docs/core-api/cards

カードです。Card Productによって生成、管理できます。

## 作ってみる
https://www.marqeta.com/docs/developer-guides/core-api-quick-start

チュートリアルではCurlで叩いてますが、Python SDKを使ってみます。

### カードホルダであるユーザを作成（ダッシュボード）
ダッシュボードに記載があるHello Worldなcurlを実行してください。返却されたtokenをこの後使うのでメモしておいてください。

### SDKの準備
https://www.marqeta.com/docs/core-api/python-sdk

私はpipでインストールしました。

```sh
pip install marqeta
```

基本的な使い方は以下の通りです。

```py
from marqeta import Client

base_url = "ダッシュボードから取得"
application_token = "ダッシュボードから取得"
access_token = "ダッシュボードから取得"
timeout = 60 # seconds

client = Client(base_url, application_token, access_token, timeout)
```


### Card Productトークンの取得
サンドボックスではすでにいくつかCard Productが作られています。その中から"Reloadable Card"という名前のCard Productのトークンを取得します。

```py
card_products = client.card_products.list()  # 25個しか取得できないという制限がある模様。25を超える場合、streamメソッド等を利用すること。
card_product_token = [x for x in card_products if x.name == 'Reloadable Card'][0].token
```

### カードの作成
カードユーザ向けにカードを発行します。

先ほど作ったユーザに向けにカードを作成します。

```py
data = {
    "user_token": "a4e3decd-8540-4940-aebc-9b64b2e93e24",
    "card_product_token": card_product_token}
client.cards.create(data)
```

### カードの利用
商店のIDであるMID(merchant ID)を指定して、$10を擬似的に送ってみます。

シミュレータ実行はSDKでは用意されていないため、こちらからcurlを生成し呼び出します。
https://www.marqeta.com/docs/developer-guides/core-api-quick-start

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984649/0a8ff0c5-baf7-12dc-f393-31f63ffafcd6.png)

作ったカードのトークンは、Pythonコード内で```created_card.token```で取得できます。

ダッシュボードを確認するとtransactionが作成されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984649/59fb7479-b736-8b5a-eaac-0051ffb6f9ae.png)


Authorization Control、Velocity Controlを作成するとトランザクションが流れそうです。一旦カードが作れて使えそうなことがわかったのでこの記事は、ここまでとします。
Google I/O 2021 フロントエンドまとめ（2/6）: 〜Webプラットフォーム最新情報（2/3）: PWAによるWebとOSの連携強化関連〜

# Google I/O 2021 フロントエンドまとめ（2/6）: 〜Webプラットフォーム最新情報（2/3）: PWAによるWebとOSの連携強化関連〜

この記事は、[Google I/O 2021](https://www.google.com/io)で発表されたフロントエンド関連情報の中で個人的に気になったものをまとめたもので、
全6記事中2本目。

## Webプラットフォームの話
[ウェブ プラットフォームの最新情報 @Google I/O 2021](https://events.google.com/io/session/97ea9417-2bba-4383-8eb4-22aee86af034?lng=ja)

### PWA技術の拡充によるWebとOSの連携が強化されてくよ。みたいなお話
「最先端のエクスペリエンスを実現するための機能をWebですべて確保することを目指しています」って話からの、 
WebアプリとOS間での使い勝手のシームレスな統合の具体的な推進として
PWAアイコンからショートカットでクイックアクションを呼び出せる機能の紹介、
バッジAPIでランチャ上のPWAアイコンにバッジを表示させることでリエンゲージメントを図ることができますよという話、
PWAアプリのインストールUIが改善されたという話
などがあった。

### `Multi-Screen Window Placement API`（マルチスクリーンウィンドウ配置API）のお話
`Multi-Screen Window Placement API`は、Webアプリが接続されてるディスプレイを検出してそれらの配置する位置を制御できたりするAPIとのことで、リモートでのプレゼンとかビデオ会議とかで重宝されるよね。（そうだね。）というお話。

### `File System Access API`のお話
~~[これまでさんざん色々出てきたこれ系](https://caniuse.com/?search=file%20api)宜しく~~なんと！Webアプリケーションからローカルファイルが開ける！！すごい（棒読み）

そして`File System Access API`では、アプリケーションをファイルタイプのハンドラーとして登録できるとのこと。（ExcelインストールしてないPCの`.xlsx`ファイルのデフォルト起動先をGoogleスプレッドシートに出来る的な？すごい（本音））

#### ひとりごと
ところで、この、ファイルタイプのハンドラーとして登録出来る件、Macとかはともかく、Windowsのこの辺の設定ってレジストリいじる系だったと記憶してるんだが、大丈夫なんだろうか？
（このへんの設定ってWebブラウザとかの普通のアプリが修正できるとこだっけ？覚えてない。
それともWindows八分？でもそれだと標準にできなくない？）

### `WebHID`による周辺機器のWeb対応のお話
`WebHID`を使えば、キーボード、マウス・トラックパッド、ゲームパッドなどのHIDデバイスを、ソフトウェアのインストールやドライバーへの関与なしにWebで使用できるようになる。というお話。
一例として、
Nintendo SwitchのJoy-ConがHIDデバイスですよ、使えますよ。とか
Stadiaなどで妥協のない ~~（ん？）~~ ゲームプレイが可能ですよ ~~（では、[どれくらいのタイトル数](https://www.google.com/search?q=stadia+%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E6%95%B0)が"プレイ可能"ですか？）~~ 。とか 
Chromeでネットワークトラブルのときに表示される[恐竜ちゃんのゲーム](https://www.google.com/search?q=Chrome+Dino)がゲームパッドの操作に対応したよ
などが紹介された。

[つづく](https://qiita.com/toshi00ysm/items/b9822c6ab33cc55d62e9)
Golangサンプルコード: 構造体の情報を再帰的に読む

構造体を再帰的に読んでいく。
無限ループに陥らないようにチェックを入れた。

```golang
package main

import "fmt"

type Node struct {
	ID    int
	Child *Node
}

func (n *Node) PrintID() {
	check := map[int]bool{}
	var printID func(n *Node)
	printID = func(n *Node) {
		fmt.Printf("%d\n", n.ID)
		check[n.ID] = true
		if n.Child != nil {
			if _, done := check[n.Child.ID]; !done {
				printID(n.Child)
			}
		}
	}
	printID(n)
}

func main() {

	n1 := Node{ID: 1}
	n2 := Node{ID: 2}
	n3 := Node{ID: 3}
	
	n1.Child = &n3
	n2.Child = &n1
	n3.Child = &n2

	n := Node{ID: 4, Child: &n1}
	n.PrintID()
}
```

https://play.golang.org/p/_Q5vZC8YNuc
【PHP】str_replace()とstrtr()の挙動の違い

# はじめに
PHPで複数の文字列を一度に置換したい場合に利用する`str_replace()`と`strtr()`ですが、挙動が少し違ったので書き残しておきます。


## 要件

「東京都新宿区新宿3丁目」という文字列があって、新宿区は`<span>新宿区</span>`に、新宿は`<b>新宿</b>`に置換したいとします。


> `「東京都<span>新宿区</span><b>新宿</b>3丁目」`


## 1. str_replace()

最初に思いついた方法が以下になります。

```php:str_replace
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿区' => '<span>新宿区</span>',
    '新宿' => '<b>新宿</b>',
];

echo str_replace(array_keys($array), array_values($array), $str);
// '東京都<span><b>新宿</b>区</span><b>新宿</b>3丁目'
```

`str_replace()`では、配列の先頭から順番に文字列を置換します。

まず「東京都<font color="red">新宿区</font>新宿3丁目」の<font color="red">新宿区</font>という文字列を置換して
`「東京都<span>新宿区</span>新宿3丁目」`になります。

次に「東京都\<span><font color="red">新宿</font>区\</span><font color="red">新宿</font>3丁目」から<font color="red">新宿</font>を探してもう一度置換を行うので
`「東京都<span><b>新宿</b>区</span><b>新宿</b>3丁目」`となります。



## 2. str_replace()

配列の順番を変えてみます。

```php:str_replace
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿' => '<b>新宿</b>',
    '新宿区' => '<span>新宿区</span>',
];

echo str_replace(array_keys($array), array_values($array), $str);
// '東京都<b>新宿</b>区<b>新宿</b>3丁目'
```

念のためもう一度。`str_replace()`では、配列の先頭から順番に文字列を置換します。

この場合、「東京都<font color="red">新宿</font>区<font color="red">新宿</font>3丁目」の<font color="red">新宿</font>という文字列を置換して
`「東京都<b>新宿</b>区<b>新宿</b>3丁目」`になります。

置換後の文字列には’<font color="red">新宿区</font>’という文字列は無いので、そのまま出力されます。



## 3. strtr()

```php:strtr
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿' => '<b>新宿</b>',
    '新宿区' => '<span>新宿区</span>',
];

echo strtr($str, $array);
// '東京都<span>新宿区</span><b>新宿</b>3丁目'
```

これで欲しい結果が取得できました。

strtr()`の場合、配列の順番は関係がなく、キーの文字列の長いものから順に調べて置換をし、一度置換された部分の文字列は置換対象から外れるようです。

新宿と新宿区では、もちろん「新宿区」の方が文字列としては長いので、先に「新宿区」が「\<span>新宿区\</span>」に置換されます。

その後、置換された新宿区は対象外になるので、「東京都~~\<span>新宿区\</span>~~<font color="red">新宿</font>3丁目」が置換されて
`東京都<span>新宿区</span><b>新宿</b>3丁目`となります。



## おわりに

今回のは記事はどちらの関数の方が良いかという話ではなく、要件によって使い分けが必要だと思います。

複数の文字列の置換をしたい時にこの記事を思い出してもらえればと思います。



## 参考

https://qiita.com/ryoo_ss/items/8ca05de64d7c583df0dc

https://norm-nois.com/blog/archives/4088

https://www.php.net/manual/ja/function.strtr.php
Golangサンプルコード：自己参照構造体のデータを再帰関数を使用してプリントする

今日書いたサンプルコード

自己参照構造体のデータを再帰関数を使用してプリントします。
マップを使って無限ループを回避。

```go
package main

import "fmt"

type Node struct {
	ID    int
	Child *Node
}

func (n *Node) PrintID() {
	check := map[int]bool{}
	var printID func(n *Node)
	printID = func(n *Node) {
		fmt.Printf("%d\n", n.ID)
		check[n.ID] = true
		if n.Child != nil {
			if _, done := check[n.Child.ID]; !done {
				printID(n.Child)
			}
		}
	}
	printID(n)
}

func main() {

	n1 := Node{ID: 1}
	n2 := Node{ID: 2}
	n3 := Node{ID: 3}
	
	n1.Child = &n3
	n2.Child = &n1
	n3.Child = &n2

	n := Node{ID: 4, Child: &n1}
	n.PrintID()
}

```

https://play.golang.org/p/_Q5vZC8YNuc


3000文字Tips - 知ると便利なTipsをみんなへ届けよう
https://qiita.com/official-events/d523df99d6479293ffa7
DynamoDBのscanでPaginatorを使用し、filterExpressionとprojectionExpressionを使う方法(bot3編)

# はじめに
* boto3を利用したdynamoDBのscanでPaginatorを使用した場合に、filterExpressionを使用した際に、詰まったので、記事に残しておきます。

# filterExpression
* FilterExpressionとは、条件を満たした項目だけが返されるような条件を指定します。他のすべての項目は破棄されます。

# projectionExpression
* projectionExpressionとは、スキャン結果に必要な属性を指定します。

# 発見したバグ
* [issue](https://github.com/boto/boto3/issues/2300)としても上がっているのですが、boto3.dynamodb.conditions を利用した方法でfilterExpressionを使用すると、うまく使えない問題が発生します。

下記がその時のサンプル

```sample.py
import boto3
from boto3.dynamodb.conditions import Key, Attr

    page_iterator = paginator.paginate(
        TableName=TABLE_NAME,
        IndexName=INDEX_NAME,
        FilterExpression=Key('X').eq(x) & Key('Y').lte(y)
    )
```

# PaginatorでFilterExpressionを利用したい場合の書き方

* 簡単に書くと、ExpressionAttributeValuesを利用して、文字列で渡してあげるやり方にするとFilterExpressionを使用することができます。

```sample2.py
def scan_dynamo():

    dynamoDBName = 'testdb'
    dateStr = 'xxx-xx-xx'
    filterExpression = 'time_stamp <= :searchDate'
    projectionExpression = 'id'

    try:
        cnt = 0
        for page in dynamoPaginator.paginate(
            TableName=dynamoDBName,
            PaginationConfig=paginationConfig,
            ProjectionExpression=projectionExpression,
            FilterExpression=filterExpression,
            ExpressionAttributeValues={
                ":searchDate": { "S": dateStr },
            }
            ): 
            print('Scan件数：{}'.format(cnt))
 
    except Exception as e:
        print('DynamoDBのScanに失敗しました。TableName={0}, Error={1}'.format(dynamoDBName, e))
```

# 参考
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStarted.Python.04.html

https://github.com/boto/boto3/issues/2300
クラス継承　オブエジェクト指向設計実践ガイドより

#はじめに
本題は[ここクラス継承](#クラス継承)からです
##読者対象
読者対象はプログラミング初学者です。
といっても全くの初学者ではなく、Railsチュートリアルを終えたレベルと定義します。
##オブジェクト指向設計実践ガイド
**オブエジェクト指向設計実践ガイド**の記事は、他の方も書いてありますが、
一度に全部まとめたものが多かったです。
この記事は、オブエジェクト指向らしく、各章ごとに、単一責任に、シンプルさを意識して書きました。
余談ですが、とある弁護士が弁護士は六法全書を丸暗記してないが、各条文を見ただけで、関係ある条文、知識を思い出すそうです。
この記事は、**オブジェクト指向設計実践ガイド**ってこんなこと書いてあったなーと思いだすための記事でもあります。
また、**オブエジェクト指向設計実践ガイド**を読んだことがなくても、こういうことが書いてあるとのかー、とさわりだけでも理解して頂けたら幸いです。
##オブジェクト指向設計実践ガイドで得た3つのポイント
**リファクタリング前のコードを読み、コードの危うさを察知できる。**
**リファクタリングするために、より抽象的なコードの書き方を学べる。**
**gemなどの抽象的なコードを読解できる。**
##一問一答
一問一答風の構成にしています。
リファクタリング前のコードを読み、コードの危うさ、嗅覚を養っていきましょう。
その後、リファクタリング前のコードの危うさを説明し、自分なりにリファクタリングしたコードを書いてみましょう。
最後に、もう一度、リファクタリング前のコードと、リファクタリング後のコードを読み比べ、
抽象的な思考、抽象的な書き方を共に学んでいきましょう。
#クラス継承
今回は**第6章クラスによる継承**について説明します。
下記コードを読んで、このコードの危うさを考え説明して見て下さい。
そして、自分なりにリファクタリングしたコードを書いてみましょう。
この記事を理解したなら、オブエジェクト指向設計実践ガイドの第6章　「継承によって振る舞いを獲得する」、
この章を半分理解していると言えるでしょう。（残りは後日書きます）
##リファクタリング前
```ruby
class Bicycle
  attr_reader :style,:size,:tape_color,:front_shock,:rear_shock

  def initialize(args)
    @style = args[:style]
    @size = args[:size]
    @tape_color = args[:tape_color]
    @front_shock = args[:front_shock]
    @rear_shock = args[:rear_shock]
  end

  def spares
    if style == :road
      {
        chain: "10-speed",
        tire_size: "23",
        tape_color: tape_color
      }
    else
      {
        chain: "10-speed",
        tire_size: "2.1",
        rear_shock: rear_shock
      }
    end
  end
end
bike = Bicycle.new(
  style: :mountain,
  size: "s",
  front_shock: "Manitou",
  rear_shock: "Fox"
)
bike.spares
```
###コードの危険性
Bicycleクラスが肥大している。
特に、機能が拡張するたびに、sparesメソッド内のif文を修正しないといけない。**←バグのもと**
##リファクタリング後
```ruby
class Bicycle
  attr_reader :size
  def initialize(args = {})
    @size = args[:size]
  end
end
class RoadBike < Bicycle
  attr_reader :tape_color

  def initialize(args)
    @tape_color = args[:tape_color]
    super(args)
  end

  def spares
    {
      chain: "10-speed",
      tire_size: "23",
      tape_color: tape_color
    }
  end
end
class MountainBike < Bicycle
  attr_reader :front_shock,:rear_shock

  def initialize(args)
    @front_shock = args[:front_shock]
    @rear_shock = args[:rear_shock]
    super(args)
  end

  def spares
    super.merge(rear_shock: rear_shock)
  end
end
road_bike = RoadBike.new(
  size: "M",
  tape_color: "red"
)
road_bike.spares
mountain_bike = MountainBike.new(
  size: "s",
  front_shock: "Manitou",
  rear_shock: "Fox"
)
mountain_bike.size
```
##クラスの継承
Bicycleクラスの下に、新たにサブクラスを設置することによって、
Bicycleクラスがすっきりしました！
##注意点
このリファクタリング後のコードがベストではありません。
より改善できます。サブクラスを設置しない方法もあります。
あくまでリファクタリング前よりかはよくなったと捉えて下さい。
#後記
コードの危険性の説明を加筆しようか検討中
#参考文献
[オブエジェクト指向設計実践ガイド　～Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方](https://gihyo.jp/book/2016/978-4-7741-8361-9)
KGraphQLでaccessRuleを使う

# KGraphQLでaccessRuleを使う

https://kgraphql.io
備忘録です。

## Gradle

``` build.gradle.kts
dependencies {
  implementation("com.apurebase:kgraphql:$kgraphqlVersion")
  implementation("com.apurebase:kgraphql-ktor:$kgraphqlVersion")
}

```

## 使う

``` Application.kt

data class AuthSession(val id: UUID) : Principal

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused")
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
    install(Authentication) {
        session<AuthSession>()
    }

    wrap {
        authenticate(optional = true, build = it)
    }

    context { call ->
        call.authentication.principal<AuthSession>()?.let {
            +it
        }
    }
}

```

``` Utils.kt
fun checkAuth(context: Context): Exception? =
    if (context.get<AuthSession>() == null) Exception("権限がありません。") else null
```

``` Sample.kt
query("sample") {
    resolver { context: Context -> }
    accessRule(::checkAuth)
}
```
【LeetCode】就活に向けたコーディングテスト対策 #05

#はじめに
こんばんは．
M1就活生が[LeetCode](https://leetcode.com/)から，easy問題を中心に**Python**を用いて解いていきます．

https://leetcode.com/

↓では，解いた問題のまとめを随時更新しています．
[まとめ記事](https://qiita.com/halpi/items/43761b89a1873dcc9a5c)

https://qiita.com/halpi/items/43761b89a1873dcc9a5c

#問題
今回解いたのは，難易度easyから [問題14のLongest Common Prefix](https://leetcode.com/problems/longest-common-prefix/) です．
問題としては，入力として与えられる文字列の配列の中から，最長の共通の接頭辞を持つ文字列を見つけるというもの．

入力例と出力例は以下の通りです．

Example 1:

```python
Input: strs = ["flower","flow","flight"]
Output: "fl"
```

Example 2:

```python
Input: strs = ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
```

なお，この問題は文字列のペア間ではなく，配列中の全ての文字列が対象とのことです．
例えば，入力配列が ["a", "a", "b"] なら "" を返します（"a" ではない）．

#書いたコード
とりあえず，思いついたままに書いてみました．

```python
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        prefix = ""
        flag = True
        for i in range(len(strs)):
            prefix_candidate = strs[0][i]
            for str_element in strs[1:]:
                if str_element[i] != prefix_candidate:
                    flag = False
                    break
            if flag:
                prefix += prefix_candidate
        return prefix
```

入力配列`strs`の先頭文字列の要素を順に接頭辞候補とします．接頭辞候補を，残りの文字列の同じ位置の要素と同じかどうか走査していくことで，接頭辞を見つけます．

しかし，このままではリストの範囲外を参照してしまうのと，接頭辞が異なる判定となった場合も，文字列の最後の要素まで走査してしまいます．そのため，入力配列`strs`中に含まれる文字列の最低文字数を繰り返しの範囲とし，`flag`が`False`であれば，走査を終了する判定を追加しました．

```python
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        prefix = ""
        flag = True
        for i in range(len(min(strs))):
            prefix_candidate = strs[0][i]
            for str_element in strs[1:]:
                if str_element[i] != prefix_candidate:
                    flag = False
                    break
            if flag:
                prefix += prefix_candidate
            else:
                break
        return prefix
```

内側の繰り返しでも，明示的に繰り返し回数を指定してあげたほうがリーダブルかつ効率的かも...？

#おわりに
LeetCodeでは，Testcaseがいくつか用意されているようですが，今回のようにたまたまうまく動いた場合もあるみたいです（上側のコード）．例外的なケースにも対応できるコーディングを意識していきたいと思いました．

今回書いたコードはGitHubにもあげておきます．

https://github.com/halpi17/LeetCodeStudy/blob/master/014/longestCommonPrefix.py

[前回](https://qiita.com/halpi/items/f889b47cace3031dd54c)　[次回](https://qiita.com/halpi/items/84f93e57d6742678dff4)
自己紹介

# 自己紹介

### はじめに
初めまして！しんしんです！

今回は以下について伝えていきたいと思います。

[1.想い](#1-想い)
[2.プログラミングを始めた経緯](#2-プログラミングを始めた経緯)
[3.記事を投稿していこうと思った理由](#3-記事を投稿していこうと思った理由)
[4.ポートフォリオについて](#4-ポートフォリオについて)
[5.最後に](#5-最後に)

### 1. 想い
僕は世の中の為になる、人々の役に立つサービスを多くの人に届けたくてプログラミングを学んでいます。

そして将来はプログラミングの知識・スキルをわかりやすく教えるだけでなく、プログラミングの本質だったり、プログラミングを通じて人格を磨き、「知性」、「感性」、「生き様」も学べる**『プログラミング道』**を教えていきたいと思っています。

僕はプログラミングを分かりやすく教えてくれる人になかなか出会えなくて大学ではプログラミングがつまらなすぎて挫折してしまいました。しかし、大学を休学してプログラミングスクールに通った時は分かりやすく教えてくれる人に出会えてプログラミングが楽しくなりイメージが180度変わりました。

僕はこういう経験を学校の授業やスポーツなど様々なことで繰り返し経験してきました。

何事もできるようになれば楽しいのにちゃんと教えてくれる人がいなくて諦めてしまうのはすごくもったいないです。
そんな人達を少しでも減らしたいと思い日々活動しています。

### 2. プログラミングを始めた経緯
最初は純粋にアプリとかWebサービスを作れたらかっこいいなと思ったのが理由です。
そして僕はその理由で情報学部に入りましたが、実際入ってみるとアプリとか作ることは一切なく、プログラミングも文法ばかりで最終的になにができるようになるのかイメージが全く湧かず、やる気もなくなり、レベルの高い授業にもついていけず挫折をしてしまいました。

それで大学を休学することになり、休学期間で起業をして物販、せどり、投資、イベント運営など色々手を出し、最終的には借金まで背負い失敗してしまいました。

そこで自分にはスキルも知識も人脈も何もないと気づき、もう一度スキルを身につけるためにプログラミングをやろうと思いました。

失敗して自分を見つめ直し学んだことは、自分の欲望のために生きるのではなく、世のため人のために尽くす利他の心が何よりも大切だということです。
そんな世のため人のためになるサービスを作りたいと思いプログラミングを始めました。

### 3. 記事を投稿していこうと思った理由
僕は、最初はパソコンの電源の付け方しかわからない状態で、さらには大学の情報学で挫折をした経験があるので、初学者の気持ちがわかるし、そんな僕だからこそ他の人には伝えられないことを伝えていけると思ったのと**自分が乗り越えたことは次の人を救うコンテンツ**となり、自分と同じ悩みを抱えた人の助けになれると思ったからです。

さらに、Qiitaに投稿することで学んだことをアウトプットできて頭の中が整理されるし、読み手の気持ちも考えて作成したり、同じ壁にぶち当たった時などに振り返ることができたり、記事が記録として残るので、自分の成長の軌跡にもなると思ったからです。

### 4. ポートフォリオについて
イクスバリュー（スキル交換サービス）
[https://ex-value.com](https://ex-value.com)

↑興味がある方は是非リンクから飛んでみてください！

####4-1. サービス説明
このサービスはあなたが持っているスキル(好き・価値)とあなたが得たいスキル(好き・価値)と交換できる、スキル交換サービスです。

教えることでサービス内通貨(教えてもらえる権利)を貰うことができ、サービス内通貨を払うことで教えてもらうことができます。

スキルをシェアするにあたって、お金、資格などは一切不要です。

あなたのスキル(好き・価値)をいつでもどこでも気軽にシェアし、その対価に新しい知識・スキルを得ることができます。

####4-2. イクスバリューを作った背景
みんなそれぞれ違った個性、強みを持っていたり、好きなことがあったりして、それを生かせる場所がなかなかないと思っていて、
そのみんなの持っている個性、強みを生かせて、みんなで価値を提供しあって一緒に成長していける、
そんなサービスがあれば多くの人の助けになり、一緒に世の中を良くしていけるんじゃないかと思ったので作ることにしました。

####4-3. イクスバリューの今後
いずれは、ただのスキル交換サービスではなく、イクスバリューが就活・転職などでアピールしてもらえるような、就活生や転職する方などの助けになれるようなクオリティーのサービスにしていきたいと思っています。

そして、就活・転職で終わらすだけでなく、みんなで強みを分かち合って一緒にいい世の中を作っていきたいと思っています。

### 5. 最後に
これから少しずつ投稿していこうと思うのでよろしくお願いいたします！

最後まで読んでいただきありがとうございました。
Ruby 文字列の順番を変える

Rubyで勉強したことをアウトプットします。

# やりたいこと
- 任意の文字列の最初の2文字を取得する
- 取得した2文字を最後尾に移動させた状態で、その文字列を出力する

# 最初に作成したコード
```ruby
def change_str(str)
  first_str = str[0]  
  second_str = str[1]
  len = str.length
  arr = []
  (2..len).each do |num|
    arr << str[num]
  end
  puts "#{arr.join}#{first_str}#{second_str}"
end

change_str("Hello")
# >> "lloHe"

```

# joinメソッド
joinメソッドを使用することで、配列内の要素を文字列として連結することができます。

```ruby
# 配列を宣言
arr = ['a', 'b', 'c']

# 配列の要素を連結して文字列として返却します  
p arr.join
# >> 'abc'
```

引数を指定すると、要素ごとに引数の文字列を結合することができます。

```ruby
# 配列を宣言
arr = ['a', 'b', 'c']

# 配列の要素を連結して文字列として返却します  
p arr.join(":")
# >> 'a:b:c'
```

# 改善後のコード
```ruby
def change_str(str)
  puts str[2..-1] + str[0..1]  
end

left2("Hello") 
# >> "lloHe"
```
今回の勉強で、配列の操作方法について学びました。
【論文紹介】Enchanting Your Noodles: GAN-based Real-time Food-to-Food   Translation and Its Impact on Vision-induced Gustatory Manipulation

#論文紹介
論文：Enchanting Your Noodles: GAN-based Real-time Food-to-Food   Translation and Its Impact on Vision-induced Gustatory Manipulation
著者：Kizashi Nakano; Daichi Horita; Nobuchika Sakata; Kiyoshi Kiyokawa; Keiji Yanai;
https://ieeexplore.ieee.org/abstract/document/8798336

#どんなもの
　StatGANを用いて動的に食べ物の見た目を別の食べ物に変えるARシステムを開発した。素麺がラーメンや焼きそばのような味になるのか、蒸したご飯がカレーライスやチャーハンのような味になるのか調査した。実験の結果、被験者は見ている食べ物の味を強く感じた。また、この実験の結果は被験者の食体験に依存することがわかった。

#先行研究と比較してすごいところ
　食品の外観を別のものに変える研究はなく、そのシステムが味覚に与える影響についても研究されていない。この論文ではGANベースのリアルタイム画像間変換を用いて、食べ物の見た目を別の食べ物に変えるより柔軟なARシステムを開発した。

#技術や手法のキモ
　StarGANベースのリアルタイム食品間翻訳システムを開発した。<font color="gray">被験者の手やお箸が料理にさえぎられない、食品の外観は元の食品の変形に応じて動的に変化するなどといったメリットがある。</font>
　クライアントモジュールは、HMDのフロントカメラからRGB画像を取得して、サーバーモジュールに送る。サーバーモジュールはRGB画像を受け取って、中心部を切り取り別の食べ物の画像に変換してクライアントモジュールに送る。クライアントモジュールは処理された画像をステレオテレビの背景に重ね合わせてHMDを介して被験者に提示する。
　<font color="gray">ラーメン、焼きそば、炊き込みご飯、カレーライス、チャーハンの5つの食品の149,370枚の食品画像を用いている。</font>

#検証方法
　素麺がラーメンや焼きそばのような味になるのか、蒸したご飯がカレーライスやチャーハンのような味になるのかを調査した。HMDを装着していない元の食べ物を見てHMDを装着した後に変化した食べ物を見る。食べる前にどのような食べ物に見えるか答えてもらい、正しい答えを教える。そのあと食べ物を食べてもらう。そして何の味がしたか評価してもらう。
→被験者は見ている食べ物の味を強く感じ、実際に食べている食べ物の味を弱く感じていた



#議論
　視覚による味覚操作は画質に大きく依存するので、高画質な映像を提示した実験が気になった
　→素麺はスープありだったのにもかかわらず、焼きそばを提示したときにはスープを感じていない人もいた。これを利用することで他の食べ物(汁なしと汁ありの食べ物など)でも実験できるのではないか。
　食べる前にどのような食べ物に見えているのか答えてもらう必要はあったのか。(答えを教えるならもとからそれでいいのではないか。)



#気になった論文
　DeepTaste: Augmented Reality Gustatory Manipulation with GAN-based Real-time Food-to-food Translation