OmniAICreator/Qiita-1.07M huggingface dataset:
FirebaseAuthentication + TwitterOAuth ログイン設定手順

これまでGoogle,Twitter,Facebook,GithubのOAuthAPIを使用したことがありますが、Twitterの手順が突出して複雑なので、手順を記録しておきます。

# Twitterの設定

1. Twitterアカウントを作成する。
1. [Twitter Developer Platform](https://developer.twitter.com/)にログインする。
1. Create an app」ボタンから使用用途等の情報を英語で記入し、開発者アカウント申請する。<br>
ここが一番の難所で、詳しく書かないとメールで細かく問い合わせを受けることになる。<br>
また、利用規約が厳しいので、規約を読んでから用途を書かないとＮＧを受けたりする。<br>
更には、何度か申請に失敗すると申請できなくなる。（らしい）
1. 承認後、再度[Twitter Developer Platform](https://developer.twitter.com/)にログインし、`Projects&Apps`タブからアプリを追加する。
1. 追加したアプリを選択後に、`Key and Tokens`を選択し、APIキーとシークレットキーを取得する。
1. `Authentication settings` で`3-legged OAuth`を有効に設定し、必要事項を記入する。<br>
最後の手順が抜けている場合、"Desktop applications only support the oauth_callback value 'oob'"エラーが発生する。



# Firebaseの設定
1. Authentication > Sign-in method > Twitter を開く。
1. `Twitterの設定`項目で取得したAPIキー、APIシークレットを登録し、同じ画面に表示されているコールバックURLをコピーしておく。

# Webサイトの実装

React + RealTimeDatabase 環境で設定する場合の例

```tsx:Login.tsx
import firebase, { auth } from "../firebase";
import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth";

...

  const UiConfig: any = {
    signInFlow: "popup",
    tosUrl: "利用規約URL",
    // signInSuccessUrl: 'リダイレクト先URL',
    privacyPolicyUrl: "プライバシーポリシーURL",
    signInOptions: [
      firebase.auth.GoogleAuthProvider.PROVIDER_ID,
      firebase.auth.FacebookAuthProvider.PROVIDER_ID,
      firebase.auth.TwitterAuthProvider.PROVIDER_ID,
      firebase.auth.GithubAuthProvider.PROVIDER_ID,
    ],
    callbacks: {
      // サインイン成功時のコールバック関数
      signInSuccessWithAuthResult: function () {
        // Twitterアカウント情報取得
        var authResoult: firebase.auth.Auth = firebase.auth();
        const userId = authResoult?.currentUser?.uid;
        const userName = authResoult?.currentUser?.displayName;
        const userEmail = authResoult?.currentUser?.email;
        const userPhotoUrl = authResoult?.currentUser?.photoURL;
        const existAccount = users.find((user) => user?.id === userId);
        if (!existAccount) {
          // 新規ログインの場合、DBのユーザー一覧にアカウントを登録する。
          var newUsersKey = DB.child("users/").push().key;
          DB.child("users/" + newUsersKey).set({
            id: userId,
            username: userName,
            email: userEmail,
            createdAt: new Date().getTime(),
            avatar: userPhotoUrl,
          });
        }
        dispatch("LOGIN", authResoult?.currentUser);
        history.goBack();
        return false;
      },
    },

...

<div>
  <h1>
    SNSアカウントでログイン
  </h1>
  <StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />
</div>


```
# その他TwitterAPIの使用方法

TwitterのDeveloper用リポジトリを参照のこと

https://github.com/twitterdev
カメラで10分おきに洗濯物干し場の写真を撮る(洗濯物が出ているか判別するための教師データの取得)

雨降りアラームを作成したものの(↓リンク)ハズレが多くて家族からの受けが悪かったので、雨が降っているのに洗濯物が出ているぞアラームを(最終的には)作ろうと思います。

その前段階として、洗濯物が出ているかどうかを機械学習で判断したいと思っています。
まずは、その教師データを収集から。

https://qiita.com/tosshie/items/43e141121cd5a83513ec

#### 前提

- raspberry piの初期設定が終わっていること
- raspberry piの標準カメラモジュールがあること


※ ケースは透明のプラスティックのやつを買いましたが、固定するツメが合わなくてツメを折って無理やり使っています。おすすめしません。

https://qiita.com/tosshie/items/d06c9f57ceb340f2d589

#### 事前準備
- 以下のサイトを参照して実施しています
https://www.pc-koubou.jp/magazine/17276

- カメラをラズベリーパイに接続する
- カメラモジュールの設定をGUI上で実施（ラズベリーパイにディスプレイとキーボード/マウスを接続して実施）
    - メニュー（ラズベリーパイマーク/windowsキー） → 設定 → Raspberry Piの設定
    - インターフェイス タブ → カメラを有効に変更
    - 再起動
    
- もう写真が撮れるはずです

`sudo raspistill -o image.jpg`

#### 定期実行のスクリプト

- 以下のサイトを参照して実施しています

https://www.pc-koubou.jp/magazine/25538

- 写真を保存するフォルダを作成

`mkdir <フォルダ名>`

- シェル作成

`vi shashin.sh`

```shashin.sh
#!/bin/sh
fn=$(date +%Y%m%d%H%M%S)
raspistill -o /<作ったフォルダのパス>/${fn}.jpg
```

- シェルを実行すると、写真が撮れていると思います。

`sudo sh shashin.sh`

- 定期実行するためにcronに設定(私はいつもrootで設定しています)

`crontab -e`
`1 (/bin/nanoを選択)`
`*/10 * * * *　sh /<シェルを作ったフォルダのパス>/shashin.sh` を最後の行に入力
`Ctrl + X`で抜ける
`Y` で保存

- 10分毎に写真が撮られていることを確認


#### 設置
- 洗濯物が映る場所に設置
- マスキングテープで窓ガラスに固定しました

#### データをローカルPCに持ってくる
* tar.gzに固める
    * tar -zcvf <ファイル名>.tar.gz <写真を保存しているフォルダ>
* ローカルにtar.gzファイルを持ってくる
    * 私はwindows端末でやっているのでteratermのssh scp機能でもってきています
* Raspberry piの写真とtar.gzファイルを削除しておく（1週間に1回ぐらいは削除した方がよいと思います）



----------
next actionはこちらです

https://qiita.com/tosshie/items/012dac7f6da60ba24f11

2021年3月から始めたスマートホーム化はこちらに一覧化しています（2021年7月時点）

https://qiita.com/tosshie/items/82dcc6405925b12d2fd1
PHP】名前空間の仕組みのサンプルソース

名前空間とは

すでに定義されているクラスと同じ名前のクラスを作成してしまった

問題を解決してくれる仕組み。

#public/object_sample/namespace_sample.php

```php
<?php
namespace A; // ここから名前空間A
 
class Fruit {
  public $name;
 
  public function __construct($name){
    $this->name = $name;
  }
 
  public function introduce(){
    print '僕は名前空間AのFruit:' . $this->name . 'です！';
  }
}
 
namespace B; // ここから名前空間B
 
class Fruit {
  public $name;
 
  public function __construct($name){
    $this->name = $name;
  }
 
  public function introduce(){
    print '僕は名前空間BのFruit:' . $this->name . 'です！';
  }
}
 
// 名前空間Bの中ではFruitは名前空間BのFruitsを指す
$b_fruit = new Fruit('banana');
$b_fruit->introduce();
 
// 名前空間Bの中で名前空間AのFruitを呼び出すには名前空間を付与したクラス名（完全修飾クラス名）を利用する
$a_fruit = new \A\Fruit('apple');
$a_fruit->introduce();
 
namespace C; // ここから名前空間C
 
// useで名前空間AのFruitの利用（インポート）を宣言している。
use \A\Fruit;
$fruit = new Fruit('meron');
$fruit->introduce(); // 名前空間AのFruit

```
みずほ銀行のシステム障害　調査報告書 のまとめと感想

# 調査報告書のリンク

https://www.mizuho-fg.co.jp/release/pdf/20210615release_2_jp.pdf
https://www.mizuho-fg.co.jp/release/pdf/20210615release_3_jp.pdf

# ３行でまとめろ
- 2021年2月にATMで通帳とカードが5000枚くらい取り出せない障害が起きた
- 外部の有識者・専門家による外部調査委員会を設置し，原因を追究した
- 結論：<font color="Red">**危機対応，ITシステム統率力，顧客目線，の3点の弱さからなる人為的側面と，企業風土に障害発生の要因があった**</font>

# もう少し詳しく

## 1. 何が問題だったのか

1. ATM内に通帳・カードが取り込まれて戻らなくなり，また，ATMの大半が停止するなど，**顧客に重大な影響を与えた**
1. 勘定系システム「MINORI」内の障害原因となった区画を認知し，区画の再立ち上げが完了するまでに8時間を要するなど，**システム復旧に遅延が生じた**

## 2. 原因は何だったのか

- 障害の直接の原因は，「取り消し情報管理テーブルのindex file のメモリ容量超過」
- 2018年にも1821件の通帳・カードの取込みが発生し，その影響範囲が非常に大きいことに気づく機会は何度もあったが，<font color="Red">**特段の検討もなされないまま当該仕様が継続され**</font>，その変更遅延が今回の重大な顧客被害をもたらした
- システム復旧遅延の原因は，①原因となった処理区画の確認が大幅に遅れたこと，②システムエラー時に自動的に作動する「取引サービス禁止機能」の作動条件を緩和したことでかえって重大エラーが多発したこと，③エラー原因となったシステムの切り離しが遅れたこと
    - 顧客対応部門はシステム復旧を待つという受動的な姿勢であり，**顧客が現に受けている不利益を迅速に解消する組織的な動きに欠けており**，通帳・カード取り込みを防ぐ措置が遅れ，影響が拡大した
    - 組織全体において，システム障害に係る情報を一元的に集約して対策する危機管理体制が機能しておらず，**状況を見守るような姿勢も見られた**

## 3. 原因の総括

- 人為的側面の原因は色々あるけど，以下のような体質・企業風土が根底にある
    - 他の部署からの情報を適切に把握する連携が機能していなかった
    - **リスク認識の不足**，**運用管理や障害復旧対応における情報収集態勢が不足**していた
    - 全体的にITガバナンス・ITマネジメントが機能しておらず，ITシステムの統率力に脆弱性があった
    - **顧客利益に極力配慮する姿勢**が足りていなかった（ATMを利用する顧客は銀行にとっては「顔の見えない顧客」であり，関心が薄いことも否定できない）
    - <font color="Red">**積極的に声を上げることで責任問題となるリスクをとるよりも，自らの持ち場でやれることはやったといえる行動をとる方が合理的な選択になるという企業風土**</font>
    - **間違いがあれば大きく評価を下げるような企業風土**
    - 前例がない提案を行うことが困難となり，根本的な改善提案やイノベーションが期待できない状況
    - **失点を恐れて積極的・自発的な行動をとらない傾向を促進する企業風土**が根底にある

## 4. 再発防止策について

- 現在，①システム関係，②顧客対応・危機管理関係，③組織・カルチャー関係の各観点から再発防止策が実施または実施が予定されている．
- 特に，**要所への「外部人材の登用」は企業風土を変える契機となるため高く評価できる**
- 継続的な努力の積み重ねと定期的なフォローアップによってはじめて，再発防止策の実効性を確保できる

# 感想

- かなり辛辣な指摘に満ちていたけど，我が身を振り返らされる指摘も多かった
- 特に，<font color="Red">**消極的・自分の庭だけ面倒を見る気質**</font> は大企業でよく見られるが，個人単位でも陥りやすいため，自分事として重々注意したい
- あとやはり**リスク管理と運用保守体制は大事**
【Webアクセシビリティ】ハンバーガーメニューをチーズバーガーくらいにしてみる

## はじめに
この記事がWebアクセシビリティ対応の足がかりになればいいなと思い書きました。
記事自体は5分程度で読める内容です。
ターゲットは

- Webアクセシビリティについて苦手意識がある。
- なんとなくアクセシビリティの単語など知ってはいるけど、aria属性とか指定したこと無い
- WAI-ARIAをワイエリアと読んじゃう（正しくはウェイ-アリア）

小難しいことはあまり考えず、
まずは`aria-expanded`、`aria-hidden`、`aria-controls`この3つの使い方を覚えます。

※JavaScriptでの属性の値を変更したり、フォーカス切り替えの説明については今回省きます
※CSS設計は考慮していません

## ハンバーガーメニューとドロワーにaria-expanded、aria-hidden、aria-controlsを使ってみる
まずは何もしてない状態（ハンバーガー）と完成形（チーズバーガー）を確認。
チーズバーガーはなんだかできる風に見えますね。

```html
■ ハンバーガー
<button class="hamburger" type="button">メニュー</button>
<div class="drawer">
  〜〜省略〜〜
</div>

■ チーズバーガー
<button class="cheeseburger" type="button" aria-controls="drawer" aria-expanded="false">メニュー</button>
<div id="drawer" class="drawer" aria-hidden="true">
  〜〜省略〜〜
</div>
```

各aria属性の説明と設置方法を見ていきましょう。


## aria-expanded
要素（またはグループ化された要素）が、現在展開されているか、折りたたまれているかどうかを示す状態を表します。

### aria-expandedを付与する要素は？
◯ ボタンなど、展開を制御する要素に付与
◯ ボタン、折りたたまれる要素をラップする親要素に付与
✕ 折りたたまれている要素には付与しない

```html
✕ NG
<button class="hamburger" type="button">メニューボタン</button>
<div class="drawer" aria-expanded="false">
  〜〜ドロワー省略〜〜
</div>

◯ OK
<button class="hamburger" type="button" aria-expanded="false">メニューボタン</button>
<div class="drawer">
  〜〜ドロワー省略〜〜
</div>

◯ OK
<nav aria-expanded="false">
  <button class="hamburger" type="button">メニューボタン</button>
  <div class="drawer">
    〜〜ドロワー省略〜〜
  </div>
</nav>
```

## aria-hidden
`aria-hidden="true"`と指定することで、その部分だけ読み上げをスキップする。
`aria-hidden="true"`を指定すると要素が非表示になるというわけではない。
非表示にしたい要素はCSSで非表示にする。

```html
◯ OK
<button class="hamburger" type="button" aria-expanded="false">メニューボタン</button>
<div class="drawer" aria-hidden="true">
  〜〜ドロワー省略〜〜
</div>
```

CSS記述例

```css
.drawer[aria-hidden=true] {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}
```

## aria-controls
展開を制御する要素に付与。
展開・折りたたむ要素にid属性を付与し、紐付ける

```html
✕ NG（折りたたまれた要素にidが付与されていない）
<button class="hamburger" type="button" aria-controls="drawer" aria-expanded="false">メニューボタン</button>
<div class="drawer" aria-hidden="true">
  〜〜ドロワー省略〜〜
</div>

◯ OK
<button class="hamburger" type="button" aria-controls="drawer" aria-expanded="false">メニューボタン</button>
<div id="drawer" class="drawer" aria-hidden="true">
  〜〜ドロワー省略〜〜
</div>
```

## まとめ
Webアクセシビリティはたくさん覚えることがあって大変なイメージがありますが、
`aria-expanded`、`aria-hidden`、`aria-controls`この3つを覚えてまずはチーズバーガーを意識しましょう。
これを覚えると、モーダルや開閉式のトグルメニューなども自然とアクセシビリティ対応をすることができます。

`aria-expanded`、`aria-hidden`のステートはJavaScriptで変更しますが、
trueとfalseを切り替えるだけなので難しくありません。

時間が無いから実装が難しいと言ってしまいがちですが、普段マークアップしていることと工数は変わらなかったりするので、
今回のように少しインプットするだけで次回からできることも増えていきます。
みんなで少しずつ知識をつけて、共有しあえるといいですね。
AtCoderで緑色になるまでにやったこと


2021/6/13のABC205で入緑しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083618/3df58d08-9813-15cc-c3f7-4a5442a8dba6.png)
簡単にですが緑になるまでにやったことを書きます。基本的に入緑を目指す茶コーダーに向けての記事となっております。
完全に個人の主観且つ、中学生の書く駄文ですので、悪しからず。


＜学んだ典型アルゴリズム＞（←学んだ順番に書いてます）

・bit全探索
　基礎はけんちょんさんのブログでやって、演習はAtCoder Tagsというサイトを使っていました。
　恐らく僕が参加したコンテストでは1回しか出てこなかった気がするので、緑になるだけなら必須では無いと思います。

・BFS、DFS
　これも基礎はけんちょんさんのブログでやって、演習はAtCoder Tagsを使っていました。
　ライブラリを貼るだけの問題がABC-Cに出てきてたので軽くさらっておくと良いと思います。

・二分探索
　アルゴリズムロジックというサイトで基礎を勉強した後、これも演習はAtCoder Tagsを使っていました。
　応用も含めて何回かコンテストに出てきたので、勉強した方が良いと思います。

・DP
　これもけんちょんさんの記事で勉強した後、そのブログに載っていた演習問題を解きました。ナップサックDPくらいまでは勉強しておいた方が良いと思います。


＜その他の精進＞

・くじかつ
　毎夜9:00～にAtCoder Problems上で開かれているバーチャルコンテストです。最低でも茶diffまでは解いた方が良いと思います。（最近は忙しくて殆ど参加できていません...）

・Boot camp for Beginners の Medium
　AtCoder ProblemsのTrainingからできます。
　不足していた知識を補うことが出来、総合的な力も結構付いたと思います。（難易度も茶～緑下位diffで丁度良いですね）
　僕は100問中98問埋めました。（この2問は解説が理解できなかったのを放置しているやつです。良くないですね）
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083618/b833e34a-8106-5a17-db77-4a4ea6fc1da5.png)

緑になるまでにやったことは大まかにこんな感じです。
少しでもお役に立てたら幸いです。
次の目標は当然入水ですが、まずは逆色変を決めないように頑張ります。
wslのターミナルのパスを改行する

# 現状
```
AAA@BBB:aaaa/bbb/ccc/ddd$
```

パスが長くていやだ

# 解決

$の直前で改行をさせた。

``` ~/.bashrc
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\n\$ '               
```

# 結果
```
AAA@BBB:aaaa/bbb/ccc/ddd
$
```

見やすくなった。

# 参考
https://sakurawi.hateblo.jp/entry/bash-prompt
【LeetCode】就活に向けたコーディングテスト対策 #09

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

https://leetcode.com/

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

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

#問題
今回解いたのは，難易度easyから [問題27のRemove Element](https://leetcode.com/problems/remove-element/) です．
問題としては，リスト`nums`から，整数`val`を全て削除し，最終的なリスト`nums`の個数を返すというもの．

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

Example 1:

```python
Input: nums = [3,2,2,3], val = 3
Output: 2, nums = [2,2,_,_]
Explanation: Your function should return k = 2, with the first two elements of nums being 2.
It does not matter what you leave beyond the returned k (hence they are underscores).
```

Example 2:

```python
Input: nums = [0,1,2,2,3,0,4,2], val = 2
Output: 5, nums = [0,1,4,0,3,_,_,_]
Explanation: Your function should return k = 5, with the first five elements of nums containing 0, 0, 1, 3, and 4.
Note that the five elements can be returned in any order.
It does not matter what you leave beyond the returned k (hence they are underscores).
```

#書いたコード
今回の問題は，[前回](https://qiita.com/halpi/items/62fed7603931695f9574)とほとんど変わらない問題でした．リストの指定した要素を削除するものとして`remove()`があります．しかし，`remove()`では，指定した最初の要素のみを削除するため，`val`以外の値をリストとして返す，リスト内包表記を使いました．なお，リスト内包表記においても，新しいlistオブジェクトを生成するため，リストのスライスを用いることで，元のリストの中身を書き換えています．

```python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        nums[:] = [num for num in nums if num != val]
        return len(nums)
```

#おわりに
リスト内包表記を使うと，可読性が欠けてしまう場合があります．時と場合を考えてうまく使いこなしていきたいものです．

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

https://github.com/halpi17/LeetCodeStudy/blob/master/027/removeElement.py

[前回](https://qiita.com/halpi/items/62fed7603931695f9574)　[次回](https://qiita.com/halpi/items/7336ad1df98ec7a6890d)
【アルゴリズム】JavaScriptでソート問題を解く

#はじめに
Qiitaの競技プログラミング研究月間ということで、アルゴリズムの記事を書いています。
今回はソート問題(バブルソート、選択ソート、マージソート)をまとめました。

JavaScriptでアルゴリズムの勉強をされている方の参考になれば幸いです。
記事を順次まとめていきますので、その他の記事についてはマイページからご覧ください。

https://qiita.com/suzuki0430

https://qiita.com/official-events/5a0502a2d94ed6a00c30

#バブルソート
配列をバブルソートでソートしてください。
＊バブルソートは、隣り合うふたつの要素の値を比較して条件に応じた交換を行う整列アルゴリズムです。 

##解答
配列の先頭から末尾に向かって隣り合う要素を比較し、前の要素が後ろの要素よりも大きければ交換するような処理を考えます。
これを実現するために二重ループを用います。
要素の交換のために、`arr[j+1]`の値を一度`lesser`という変数に格納しています。

```js:index.js
function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        const lesser = arr[j + 1];
        arr[j + 1] = arr[j];
        arr[j] = lesser;
      }
    }
  }

  return arr;
}
```

#選択ソート
配列を選択ソートでソートしてください。
＊選択ソートは、線形探索で取得した最小値と左端の値との交換(ソート)を繰り返す整列アルゴリズムです。

##解答
バブルソートと同様に二重ループを用います。
最小値のインデックスを`indexOfMin`として、線形探索で更新していきます。
その後に得られた最小値`arr[indexOfMin]`を`arr[i]`に設定します。
これらの処理を配列の末尾まで繰り返します。

```js:index.js
function selectionSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    let indexOfMin = i;
    
    // 最小値のインデックス(indexOfMin)を更新
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[indexOfMin]) {
        indexOfMin = j;
      }
    }

    // 最小値をarr[i]に設定
    if (indexOfMin !== i) {
      let lesser = arr[indexOfMin];
      arr[indexOfMin] = arr[i];
      arr[i] = lesser;
    }
  }

  return arr;
}
```

#マージソート
配列をマージソートでソートしてください。
＊マージソートは配列を半分ずつ分割していき、小さい順に並べ替えてマージしていく整列アルゴリズムです。

##解答
配列を分割するまでの処理を`mergeSort()`、並び替えてマージする処理を`merge()`に分けます。

>The Coding Interview Bootcamp
![スクリーンショット 2021-06-18 21.40.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/fed1b3f8-39e8-6e5d-f3d6-ee41d7d91808.png)

`mergeSort()`では配列の中心`center`を算出して`left`と`right`に分割します。
`merge(mergeSort(left), mergeSort(right))`を返し、`arr.length === 1`になるまで再帰呼び出しを行います。

`merge()`では分割した配列`left` `right`を引数にとり、それぞれの配列の先頭から順番に比較していきます。
比較して小さい方の値から`results`に格納していき、これを`left` `right`のどちらかが空になるまで繰り返していきます。
最終的にソートされた結果を`[...results, ...left, ...right]`として返します。

このように、`mergeSort()`と`merge()`を使うことでマージソートを行うことができます。

```js:index.js
function mergeSort(arr) {
  if (arr.length === 1) {
    return arr;
  }

  const center = Math.floor(arr.length / 2);
  const left = arr.slice(0, center);
  const right = arr.slice(center);

  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
  const results = [];

  while (left.length && right.length) {
    if (left[0] < right[0]) {
      results.push(left.shift());
    } else {
      results.push(right.shift());
    }
  }

  return [...results, ...left, ...right];
}
```

#参考資料
https://www.udemy.com/share/101WNkCEEZd11VRno=/

https://qiita.com/iwamot/items/8b884dbcd9eda358503e
AWS EC2 Linuxインスタンス 2要素認証の設定方法

root ユーザーに切り替える。

```
$ sudo -i
```

ec2-user のパスワードを設定する。

```
# passwd ec2-user
New password:
BAD PASSWORD: The password fails the dictionary check - it is too simplistic/systematic
Retype new password:
passwd: all authentication tokens updated successfully.
```

/etc/ssh/sshd_config を編集する

編集前

```
    61  #PasswordAuthentication yes
    62  #PermitEmptyPasswords no
    63  PasswordAuthentication no
```


編集後（142行目は新規追加行）

```
    61  PasswordAuthentication yes
    62  PermitEmptyPasswords no
    63  #PasswordAuthentication no

   142  AuthenticationMethods publickey,password publickey,keyboard-interactive
```

ssh デーモン再起動

```
systemctl restart sshd
```

2 要素認証でログインに成功したところ

```
PS C:\WINDOWS\system32> ssh -i C:\Users\user\Downloads\private.pem ec2-user@52.123.123.123
The authenticity of host '52.123.123.123 (52.123.123.123)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxx
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '52.123.123.123' (ECDSA) to the list of known hosts.
ec2-user@52.123.123.123's password:
Last login: Fri Jun 18 13:17:46 2021 from example.net

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-123-123-123 ~]$
```

秘密鍵のみでログインしようとして失敗したところ

```
PS C:\WINDOWS\system32> ssh -i C:\Users\user\Downloads\private.pem ec2-user@52.123.123.123
ec2-user@52.123.123.123's password:
Permission denied, please try again.
ec2-user@52.123.123.123's password:
Permission denied, please try again.
ec2-user@52.123.123.123's password:
ec2-user@52.123.123.123: Permission denied (password).
```

普段使っている TeraTerm は2要素認証に対応していない様子。

https://ja.osdn.net/projects/ttssh2/ticket/31493

# 参考記事

https://qiita.com/jinnai73/items/f41fa6df6998d47d1f33

https://teratail.com/questions/130187

https://teratail.com/questions/95749
HerokuへのPush時にFailed to install gems via Bundler.エラーが出た時の対処法

##開発環境
MacOS Big Sur version11.2.3
Ruby 3.0.0
Rails 6.0.4
##エラーが出た経緯
アプリ作成中、よし!あとはHerokuへのデプロイだけだ！！！と、
`$git push heroku master`と打ったところ、`Failed to install gems via Bundler`のエラーに遭遇。

```Ruby:ターミナル
$git push heroku master
# ...(省略)...
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.2.16
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-3.0.0
remote: -----> Installing dependencies using bundler 2.2.16
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote:        Bundler Output: Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote: 
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
```

##解決策
`Failed to install gems via Bundler`を大ざっぱに訳してみると、bundlerを経由してgemのインストールに失敗した、とのこと。

エラー文をよく読むと、下記のように書いてある。

```ruby:ターミナル
Bundler Output: Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
```

現在ローカルで使用しているのはMacOS（Darwin）だけど、HerokuのプラットフォームはLinuxだから異なるよ〜ってことかな。

エラー文に書いてある下記コマンドを実行。

``` Ruby:ターミナル
$bundle lock --add-platform x86_64-linux

Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Writing lockfile to /Users/macbook/Desktop/BrainTraining/Gemfile.lock
#できたぽい。

#変更したので再度add,commit
$git add -A
$git commit -m "fix Gemfile.lock"

$git push heroku master
# ...(省略)...
remote: Verifying deploy... done.
To https://git.heroku.com/******.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'heroku'.
# Herokuへのデプロイができた！！
```


答えはエラー文の中に…！！！
いい勉強になりました:blush:
【論文紹介】Towards Understanding the Design of Playful Gustosonic Experiences with Ice Cream

#論文紹介
論文：Towards Understanding the Design of Playful Gustosonic Experiences with Ice Cream
著者：Yan Wang, Zhuying Li, Robert S. Jarvis, Angelina Russo, Rohit Ashok Khot, Florian 'Floyd' Mueller
https://dl.acm.org/doi/pdf/10.1145/3311350.3347194

#どんなもの
　新しい静電容量式アイスクリームコーン”iScream!”の研究を行った。アイスクリームを食べるときに4種類の音を再生する。
　被験者は食べる前に普通のアイスクリームを見て、ソフトでクリーミーなものと対応させる。食べ始めると、多感覚体験(味、触覚体験、時間経過によって溶けるなど)とアイスクリームへの期待の一致が確認される。しかし、アイスクリームから期待とは異なる不協和な音を知覚すると、被験者は驚きを体験し、結果的に遊び心のある食体験を体験する。
　音を選択することで、食べ物にまつわる幻想的な要素を助長し、それが不調和を助長して、遊び心のある体験につながることがわかった。(例：iScream!で轟音を選択すると、被験者は冷たい風の音と考え、寒いという感覚になった)

#先行研究と比較してすごいところ
　先行研究では、音が食事の動作を変化している様子を示すことや、食べる動作と音の生成の間の相互作用は食べることを遊びとして経験することを促進する可能性があると示した。この研究では、iScream!によって音を出すことで遊び心のあるGustosonic[^1]体験を促進する方法、食べることに関するインタラクティブな音の開発、食べることとインタラクティブな音の相互関係について初めて概念的なデザイン理解に貢献した。

[^1]: 食べることと聞くことが複合的な多感覚体験の中で結びついていること。

#技術や手法のキモ
　iScream!は、被験者がアイスクリームを食べると静的にデジタルサウンドを生成するシステム。ハードウェアを搭載したプラスチック製のアイスクリームコーンを3Dプリントした。
　iScream!はアイスクリームを食べる前、舐めたとき、一部を食べたときという段階でデータを検知する。
　4つのカテゴリー(刺激、実用的、主観的、否定的)に基づいて4つの異なる音(轟音、歯ごたえのある音、笑う音、ゲップ音)を再生する。


#検証方法
　一般的なバニラアイスを使って、4つの音をランダムに体験してもらう。被験者には普段通りにアイスクリームを食べてもらう。1人1位個のアイスクリームを食べてもらい、被験者はおかわりを自由にすることができ、自由に食べるのをやめることができる。その後、音の効果やiScream!の経験などアンケートをとった。

　アンケートは音声で録音されて、Excelを使って書き込まれた。主題分析などを使って分析した。

→被験者はiScream!を非常に魅力的なものを感じ、自分の笑い声と共にシステムが遊び心のある体験を促進することがわかった。
　iScream!を使う食べ方は、食べる動作によって次にどんな音がするのか好奇心を刺激し、通常よりも「楽しい」と感じた。アイスクリームを食べる楽しさだけでなく、音で遊ぶことの両方を楽しむことができた。アイスクリームを食べるときの音と対称的なシャリシャリ音は、遊び心があって面白い体験になった。歯ごたえのある音は、被験者はより多くのアイスクリームを食べたいと感じたが、ゲップ音は食べるときに嫌悪感を抱いた。
 　カリカリ音で空腹感が増したと答える被験者もいた。これは、カリカリ音は一般的に食べ物のサクサク感を連想させるため、音の刺激としてのサクサク感が食べ物の快楽に影響を与えた可能性があると示した 

→まず、食べ物を摂取するためにアイスクリームを口に入れる。次に、食べる行為を通して遊び心のある音を感じ取る。その後、被験者は食べる動作の中で音を探り、音をコントロールするために食べる動作に意識を移す。このように食べる行為と音の相互作用を促進することは、食べることを遊びとして体験することができる可能性を示した。



#議論
　バニラアイス以外の味でも実験した方がいいのではないか。
　音のカテゴリーを増やしてみてはどうか。
　BGMとしての音楽を追加したらいいのではないか。


#気になった論文
　Towards Experiencing Eating as Play(未来の論文)
【初心者でもわかる】〇〇禁止できるCSSたち

# どうも7noteです。ユーザー操作を禁止するCSSを紹介

クリックやスクロール、テキスト入力など、web上のユーザーの操作を制限できるCSSを紹介。

## ・HTML要素の選択禁止

```style.css
div {
  user-select: none;
}
```

全てのHTML要素の選択をできないようにします。クリック、画像のコピーまで。

テキストのコピペ対策として入れる事もあります。もちろんCSSを無効化されたらコピーできてしまいますので、100%完璧な対策にはなりませんが、webに強い人でない限りは基本防ぐ事ができます。


## ・左右クリック、タップ禁止(画像のコピー禁止も)

```style.css
div{
  pointer-events: none; /* 初期値に戻す時はauto */
}
```

画像のコピー禁止だけしたい場合は以下のようにimgにだけ書くことで対策できます。

```style.css
img {
  pointer-events: none;
}
```

## ・右クリック禁止

右クリックだけを禁止させるにはbodyタグに以下のような記述をします。
これで右クリック禁止ができるので、上同様に画像のコピーなどを防ぐ事ができます。

```index.html
<body oncontextmenu="return false;">
```


## ・スクロール禁止

これで画面スクロールする事はできなくなります。
本来はスクロール禁止というよりも、ウィンドウからはみ出た部分の処理をどう扱うかという指定をしているだけです。
何も指定しなければスクロールできますが、hiddenにすることではみ出た部分は非表示扱いになり、スクロールがされないという結果になっています。

```style.css
html,body {
  overflow: hidden;
}
```

## ・文字の折り返し禁止

```style.css
div {
  white-space: nowrap;
}
```

テキストの折り返しを禁止できます。
逆にURLなど英数字を強制的に折り返したい場合はいかのように指定します。

```style.css
div {
  word-break: break-all;  /* 強制折り返し */
}
```

## ・inputテキスト入力禁止

inputのテキスト入力などを無効化する方法です。
inputタグは使いたいけど、値を書き換えられたくない場合などに使います。
明示的に変更不可だという事が伝わりやすいですね。

```index.html
  <input name="hoge" type="text" value="hoge" disabled="disabled" />
```

## まとめ

ユーザーの操作を制限することで、対策を行ったり、また時には制限することによってユーザーの行動を制御し使いやすいwebサイトを作ることもできます。

なんでもかんでも意味なく禁止したり無効化するのはオススメしませんが、目的に合わせて禁止する制御を入れてみてもいいかなと思います。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【LeetCode】就活に向けたコーディングテスト対策 #08

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

https://leetcode.com/

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

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

#問題
今回解いたのは，難易度easyから [問題26のRemove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) です．
問題としては，ソートされたリスト`nums`から，重複した要素を削除し，最終的なリスト`nums`の個数を返すというもの．このとき`nums`は直接返さずに重複した要素を削除して元のリストから変更します．

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

Example 1:

```python
Input: nums = [1,1,2]
Output: 2, nums = [1,2,_]
Explanation: Your function should return k = 2, with the first two elements of nums being 1 and 2 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).
```

Example 2:

```python
Input: nums = [0,0,1,1,1,2,2,3,3,4]
Output: 5, nums = [0,1,2,3,4,_,_,_,_,_]
Explanation: Your function should return k = 5, with the first five elements of nums being 0, 1, 2, 3, and 4 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).
```

#書いたコード
今回の問題は，リスト`nums`の重複要素をなくすため，`set`を使い，それをまた`list`を使ってリスト型に戻しています．このとき，`set`を使うと元の順序を保持してくれないため，`sorted`でリストの中身を整列させました．

```python
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        nums[:] = sorted(list(set(nums)))
        return len(nums)
```

## ここで詰まった...

今回の問題では，元のリストを変更するために`nums = ...`ではなく，`nums[:] = ...`とスライスを用いています．
Pythonでは，関数にリストを引数として取ると値渡しではなく，参照渡しとなります（変数などは値渡し）．これは，`id`で確認することができます．そのため，今回のような問題では，関数内でリストを変更すれば，そのリストを返さずとも，リストの中身が書き換えられることとなります．

しかし，次のようなコードではどうでしょうか．同じリストでも，別々のidとなっています．このように，同じリストでも，別々のidとなるのは，`list()`や`sorted()`が，新しいlistオブジェクトを生成するためです（元のリストをソートする`sort()`などもあります）．

```python
def tmp(l):
    print(id(l))     # 4551362632 ... (1)
    l = list(set(l))
    print(id(l))     # 4551378696 ... (2)
    l = sorted(l)
    print(id(l))     # 4551378376 ... (3)
    l.sort()
    print(id(l))     # 4551378376 ... (3)

nums = [1, 2, 3]
print(id(nums))      # 4551362632 ... (1)
tmp(nums)
print(id(nums))      # 4551362632 ... (1)
```

元のリストの中身を書き換える場合は，スライスを用います．

```python
def tmp(l):
    print(id(l))     # 4564949064 ... (1)
    l[:] = list(set(l))
    print(id(l))     # 4564949064 ... (1)
    l[:] = sorted(l)
    print(id(l))     # 4564949064 ... (1)
    l[:].sort()
    print(id(l))     # 4564949064 ... (1)

nums = [1, 2, 3]
print(id(nums))      # 4564949064 ... (1)
tmp(nums)
print(id(nums))      # 4564949064 ... (1)
```

このように，スライスを用いると，新しいlistオブジェクトを生成する場合でも元のリストの中身を書き換えることが可能になります．

#おわりに
今回の問題は一見簡単そうに見えましたが，実際に解いてみるとなかなかハマってしまう事態になりました．調べながらアウトプットすることで，より知識として身についた気がします．

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

https://github.com/halpi17/LeetCodeStudy/blob/master/026/removeDuplicatesFromSortedArray.py

[前回](https://qiita.com/halpi/items/5a25d5295e96608966d3)　[次回](https://qiita.com/halpi/items/387dce16bca5ce7a99ad)
Tips: Terraformのマルチリージョン構成で複数のリソースに対するprovider指定を1箇所で行う

# 問題: マルチリージョン構成で、複数のリソースの provider を変更するには、それらを個別に変更しなくてはいけない。

Terraformでは、aliasを使用してマルチリージョンに対するリソースなどの指定が可能。

https://www.terraform.io/docs/language/providers/configuration.html#alias-multiple-provider-configurations


リソースなどで参照する際には、provider = \<PROVIDER NAME>.\<ALIAS> として指定する。


```
resource "aws_instance" "foo" {
  provider = aws.west

  # ...
}
```


ここで、この \<PROVIDER NAME>.\<ALIAS> が曲者。

> These references are special expressions. Like references to other named entities (for example, var.image_id), they aren't strings and don't need to be quoted. But they are only valid in specific meta-arguments of resource, data, and module blocks, and can't be used in arbitrary expressions.

これは文字列ではなく、${local.aliasname} などterratermの変数として渡すことができない。
**そのため、そのままでは、複数のリソースの provider を変更するには、それらを個別に変更しなくてはいけない。**

# 対応: YAMLで管理し、YAMLのアンカー、エイリアスを使用する

tfファイルをYAMLで管理し、使用前に.tf.json形式に変更して使用する運用とする。

```
rm *.tf.json
ls *.tf.yml | awk '{TO=$1; sub(/.tf.yml$/,".tf.json",TO); print "yq . "$1" > "TO}' | sh -x
```

その上で、YAMLのアンカー、エイリアスが使用可能。

## 例

```:region-tok.yf.yml
provider:
  ibm:
    region: tok
    alias: tok
```

```:region-osa.yf.yml
provider:
  ibm:
    region: osa
    alias: osa
```

上の内容は同じキーでことなる値のdictionaryとなっているので、単一のYAMLファイルとできない。
別ファイルとして、変換後の.tf.jsonファイルを同一ディレクトリーにおいておくことで、terraformが対応してくれる。
aliasの値はユーザーが決めて良いので、ここではregionと同じ値を使用。

```:site1.tf.yml
locals:
  provider-site1: &provider-site1 ibm.tok  # YAMLアンカー

resource:
  ibm_pi_instance:
    ins-node4a:
      provider: *provider-site1            # YAMLエイリアス
      ...
    ins-node4b:
      provider: *provider-site1            # YAMLエイリアス
      ...

```


yq .などによりJSONに変換すると、YAMLエイリアスによる指定箇所はYAMLアンカーで指定した値に変換される。
これにより、YAMLアンカーの行による指定のみで複数リソースに対するprovider指定を変換可能。

残念ながら、JSONにアンカー、エイリアスの様な機能はない様です。
tfファイルにはどうでしょう。
吉里吉里Zを使い倒す

吉里吉里Zを使い倒してSLGやRPGを作れるように環境整備していく事を目的としています。
まずはタイピングゲームを作れるようにしました。

Avalanches
https://github.com/Halo1234/Avalanches/releases/tag/Release2.1.4.1

とりあえず実行したいなら
\src\goki2\run.bat
を実行してください。

タグはKAG3とほぼ同じものが使えます。

詳しくは徐々に書いていきたいと思います。
xdebugでリモートデバッグ出来ない時に確認すべき内容

# はじめに

xdebugでデバッグ出来ない時に確認すべき内容について。
VM上にプロジェクトを作り、デバッグしようとして、詰まりました。確認を行ったことをメモ書きします。


直接的には関係無い箇所も含まれていますが、
不明点の事象を切り分ける意図で、
書いてあります。

# 最終更新日
2021年8月23日

# 環境の情報

ubuntu 20.04
VirtualBox
Vagrant 
phpstorm
apache2
php
xdebug

# 公式はこちら
https://xdebug.org/
xdebug


# 注意

設定ファイルの書き方など、バージョンにより異なりますので、最新の公式を確認して下さい。


# 関連記事

https://qiita.com/berukokoko/items/949e857a9551e5029fee


# 私が詰まった原因

己のとりあたまでは、誠に難解でした。
詰まった原因ですが、大体こんな感じになります。

```
・リモートデバッグの仕組みを理解できていなかった。
・ネットワークの知識が足らなかった。
・設定する箇所がいくつかあったため、混乱した。
・やり方が色々あったため、正しいやり方が分からなかった。故に、原因の特定が難しかった。
・公式のドキュメントに、たどり着けなかった。
・個人のブログには、出来ない、さまざまな理由が書いてあり、混乱した。
・設定ファイルの設定をどれを付けるべきか分からなかった。
```


# 前提

いまいち仕組みが理解が出来ていませんでしたが、xdebugは、どうやらこの図の仕組みになっているようです。
（ポート番号やipは環境により異なります。）
![D47794D6-192E-4CCD-90C5-EBF741B3451F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/6751adb4-73ec-2651-819a-a28f3f60254f.png)

公式のここにありました。
https://2.xdebug.org/docs/remote


# 確認するべき大まかな観点
・ネットワークの回線そのものに問題は無いのか。
・vagrant、apache2、IDE、php、xdebugは問題無く動いているのか。
・IDEの設定に問題は無いのか。
・デバッグの設定ファイルに問題は無いのか。
・ホスト←→ゲスト間の通信間に問題は無いのか。



# ネットワーク &  サーバー（Apacheなど）
・ホストのネットワークに問題は無いか。
・ゲストのネットワークに問題は無いか。
（ifconfigしてipが表示されるか。）
・サイトは問題無く表示されるのか。
・httpsを使用しているのか。
・httpsを使用しているなら、証明書はあるのか。
・Apacheのページが問題無く表示出来るか。
・Apacheは、問題無く起動出来るか。
・Apacheのプロセスが起動しているか。
・Apacheの設定ファイルに問題は無いか。
・Apacheのドキュメントルートに問題は無いか。
・Apacheが使っているポートを確認する。
・ファイルを表示しているのは何番ポートなのか。
・9000ポートは使用できるか。
・ファイヤーウォールが、どうなっているか。
・vhostの設定に問題無いか。
・ポートが開いてるか。


# VM（vagrantなど）
・VMが問題無く起動しているか。
・VMにホストのファイルが、問題無く同期が出来ているか。
・ファイルを、どこのipアドレスで表示させているのか。
・Vagrantfileファイルの記載は問題ないか。
・vagrant reloadを忘れていないか。
（Vagrantfileファイルを操作した後）

# php
・phpinfoにて、デバッグの設定が表示されるか。
![2AF34167-CF07-4CB3-8682-18429354D8F6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/f8950522-22cf-b72f-4b51-d411c7c0b9f7.png)


# 統合開発環境 （phpstormなど）
・設定に問題は無いのか。
・エラーログは何か出ているのか。

# その他
・他のアプリではどうなるのか。
・各バージョンに問題は無いか。




# 表示
このように表示されましたら問題ありません。

![B09D9377-D7E2-4021-BFBA-5A38326644B5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/e8c60323-2e61-9fa2-1dc4-bf44572ddec6.png)




# こんな時は

### Cannot load Xdebug - it was already loaded、が表示される。

xdebugの設定ファイルがエラーで読み込めていません。
設定ファイルを確認して下さい。
書く場所は、どちらでも問題ありませんが、2つとも書くと2つとも、読み込んでしまうようです。
また、コピーしたものも読み込んでしまうようです。
インストールしたバージョンによって、
書き方が、違うため、バージョンと合っているかも確認してみて下さい。
（apacheの設定ファイルなどとは、違うよう。）
（2021年08月25日現在時点）


### phpinfoにて、xdebugの情報が出てこない。

xdebugがあるか、xdebugが有効になっているか、
確認してみて下さい。
JavaScript(TypeScript)で特定の時間内であるかどうか判定する処理を作ってみた

開始時刻と終了時刻を定義し、現在時刻がその間に存在するかどうか確かめるプログラムを思いつきで書いてみたので参考になればと思い載せます。
日付を跨ぐ場合も考慮しました。

```ts
const confirmInTime = ({
  startHours,
  startMinutes,
  endHours,
  endMinutes,
  h,
  m,
}: {
  startHours: number;
  startMinutes: number;
  endHours: number;
  endMinutes: number;
  h: number; // 今の時間
  m: number; // 今の分数
}) => {
  if (startHours < endHours) {
    if (startHours === h) {
      return startMinutes <= m;
    }
    if (endHours === h) {
      return m <= endMinutes;
    }
    return startHours < h && h < endHours;
  } else if (startHours === endHours) {
    if (startMinutes === endMinutes) {
      return startHours === h && startMinutes === m;
    } else {
      return startHours === h && startMinutes <= m && m <= endMinutes;
    }
  } else {
    if (startHours === h) {
      return startMinutes <= m;
    }
    if (endHours === h) {
      return m <= endMinutes;
    }

    return h > startHours || h < endHours;
  }
};

```
docker-compose 下で Java + Spring Boot + PostgreSQL (Mybatis)を動かす

#内容
Docker docker-compose下でSpringBootを動かすことに挑戦した。
システムインテグレーターの現場でもDockerを使うことが議題に上がるようになっているのは
実際に見聞きするようになっている。


#リソース
https://github.com/noikedan/springmybatis

#前提
Dockerが入っていること
docker-compose が入っていること
imageやコンテナはできる限り整理していることが望ましいかと思われる。
実行確認はマッキントッシュで行なっている。
都度　cd pwd ls などのコマンドを使用している。
参考
https://suin.io/537
https://github.com/IBMDeveloperTokyo/DojoBasicLab/tree/master/Lab1_ShellCommand/Lab1-1_CommandLineBasic

#イントロダクション
Dockerが動いているのを確認し、余計なコンテナがあれば削除する。
リソースをターミナルから取得し、springmybatis内に移動する。

```
docker info
docker ps

docker rm -f postgres ← 削除系なので注意すること


git clone https://github.com/noikedan/springmybatis.git
cd springmybatis
```
注意点：gitが入ってない場合はダウンロードで今回のタスクは完了できます。
#手順
基本これでいけるはずあとは
Google検索などで・・・

０.
application.ymlを
はじめてコミットを参考にapplication.properties に変更する。

内容は
mybatis.configuration.map-underscore-to-camel-case=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.url=jdbc:postgresql://postgres:5432/testdb
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username= postgres
spring.datasource.password=admin
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none 

1.
jarを作成する。

```
./mvnw clean package -DskipTests
```

確認方法
・BUILD SUCCESS
・springmybatis/targetフォルダ内でjarができていることを確認する。
注意点
springmybatis内で行うこと。以下断りがない限り同様に行う。

2.
docker imageをビルドしてRUNを行う。

```
docker build ./ -t springbootapp
```
参考
Dockerfile
確認方法
springbootapp imageができていることを確認する。

```
docker image ls -a
```

3.
コンテナ同士をデプロイする。

```
docker-compose up
```
参考：docker-compose.yml
確認方法
エラーが出てないことを確認する。

4.
別ターミナルを立ち上げてデータベースが立ち上がっていることを確認する。
データベースの中に入る。

```
docker info
docker -ps
docker exec -it postgres bash
psql -h localhost -p 5432 -U postgres -d postgres
\c testdb
```
注意点
springmybatis内でなくてもオペレーション可能のはず。

5.
SQL文を流す。

```
CREATE TABLE IF NOT EXISTS staff ( id SERIAL, name VARCHAR(60), email VARCHAR(254) NOT NULL, status BOOLEAN NOT NULL, registration DATE NOT NULL );

INSERT INTO staff(name, email, status, registration) VALUES('中池', 'nakaike@example.com', 't', CURRENT_DATE); INSERT INTO staff(name, email, status, registration) VALUES('田中', 'tanaka@example.com', 't', CURRENT_DATE);
```
6.
下記アドレスにアクセルする。
http://localhost:8080/
確認方法
一覧画面表示
無料でSlackを使い続ける方法

## はじめに

これは不法を教える文章ではございません。

そして無料でSlackを使い続けるように説得する文章でもございません。

Slackの有料版を使うのにいちアカウントあたり毎月最低850円の費用がかかるので、それぐらいのお金が稼げないプロジェクトや団体向けに、無料でSlackを使い続ける方法に関してまとめた文章です。

## 知っておくべき無料版Slackの制限

無料で使い続けるんですが、Slackには下記のような制限があります。

- １万件のメッセージしか表示できない。
- ワークスペース毎の容量が５Gに限定

メッセージが１万件を超える場合、削除はされないですが、検索したり、見たりすることはできなくなります。

そしてファイルのアップロード容量も上限が設定されているので、それ以上はアップできないようになっています。

## 無料で使い続ける為のルール

上記の無料で使用する場合の上限をわかれば、ずっと無料で使い続ける為のルールがわかってくるでしょう。

ルール１：重要な情報はスラック以外のところで保管して置く。

ようはSlackはリアルタイムで情報共有やコミュニケーションとして活用はするが、重要な情報は必ず別の永久的な場所に保存して置くことで、１万件の会話を超えた時点で重要な情報が見れなくなることを避ける為です。

重要な情報を管理・保管する場所を別で用意することで、Slackでは情報のロースの心配なく気軽に使うことができます。

ルール２：ファイルをアップロードしたら、ダウンロード後必ず削除する。

これは容量制限を避ける為のルールになります。削除するとその分アップロードできる空間が増えるので、これを繰り返せば何回もアップロード機能を使い続けることができます。

もう一つ方法として、GoogleDriveなどを利用し、ファイルのシェアリンクを貼っとくことで、容量制限を受けないこともできます。

## 可能であれば有料版を使いましょう

Slackはとても有用でコミュニケーションに大きく役に立ちますね。もしプロジェクトの予算が十分であれば、できるだけ有料版のSlackを使いましょう。Slackが長く生きて儲けることで、無料でSlackを利用するみんなもずっと無料で使い続けることになりますから。
【Microsoft 365】Microsoft 365 グループを PowerShell で作成する

# 準備

## Exchange Online PowerShell V2 モジュール をインストールする

以下のコマンドでモジュールをインストール、または更新してください。

```powershell
if((Get-Module ExchangeOnlineManagement -ListAvailable | measure).Count -eq 0) {
    Install-Module ExchangeOnlineManagement -Force
} else {
    Update-Module ExchangeOnlineManagement
}
```

# グループの新規作成

## Exchange Online に接続する

```powershell
$Credential = Get-Credential
Connect-ExchangeOnline -Credential $Credential
```

## グループを作成する

CSV ファイルのデータを元にグループを作成します。以下のようなデータのファイルを用意します。
※他に追加したい[パラメーター][newgrp]があれば増やしてください。

###### GroupList.csv

| DisplayName | Alias   | AccessType | ManagedBy | Language |
| ----------- | ------- | ---------- | --------- | -------- |
| グループ1   | Group01 | Public     | admin     | ja-JP    |
| グループ2   | Group02 | Public     | admin     | ja-JP    |
| グループ3   | Group03 | Public     | admin     | ja-JP    |

以下のコマンドを実行します。

```powershell
ipcsv 'GroupList.csv' | % {
    New-UnifiedGroup -DisplayName $_.DisplayName -Alias $_.Alias -AccessType $_.AccessType -ManagedBy $_.ManagedBy -Language $_.Language
}
```

# グループの情報を CSV ファイルに出力する

```powershell
Get-UnifiedGroup | select Name, DisplayName, Alias, PrimarySmtpAddress, AccessType, ManagedBy, Language | epcsv -NoTypeInformation -Encoding UTF8 -Path 'GroupList.csv'
```

# 参考サイト

- [Exchange Online PowerShell V2 モジュールのバージョン情報 | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-and-maintain-the-exo-v2-module)
- [Exchange Online PowerShell に接続する | Microsoft Docs](https://docs.microsoft.com/powershell/exchange/connect-to-exchange-online-powershell)
- [New-UnifiedGroup (ExchangePowerShell) | Microsoft Docs][newgrp]
- [基本認証 - Exchange Online PowerShell に接続します | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/exchange/basic-auth-connect-to-exo-powershell?view=exchange-ps)
- [【Office 365】PowerShellでOffice365へ接続する［Import-PSSession］ | BIZLOG](https://bizlog.tech/powershell-connect-office365/)
- [【Office 365】Office 365グループを一括で作成する | BIZLOG](https://bizlog.tech/add-unified-group/)

[newgrp]: <https://docs.microsoft.com/powershell/module/exchange/new-unifiedgroup>
Webページの読み込み速度改善

#■Webページの読み込み速度改善
今回はWEBページの読み込み速度が遅かったので、速度改善を行いました。
その方法を紹介します。


##■WEBサイト解析ツール
今回のWEBページ速度改善に向けてPageSpeed Insightsを使用しました。
こちらのツールは読み込みたいWEBサイトのURLを入力し、解析することでスコア評価を色で分かりやすく分別することが可能です。
また、PC版とスマホ版の評価を確認することもできます。
例
90～100（緑）	速い
50～89（オレンジ）	平均
0～49（赤）	 遅い
https://developers.google.com/speed/pagespeed/insights/?hl=ja

##■改善したいWEBサイトの解析
WEBページの解析を行いました。結果は下記の通りで、PC版は平均速度でしたが、スマホ版はレッドゾーンでした。
ページ速度が遅いとSEOにも影響が及ぶため、改善していきます。
ページ速度が遅い原因としては、画像が多いためだと考えられますので、画像関連の最適化を行います。

PC版
![スクリーンショット 2021-06-13 19.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/5aed9ccf-f9d0-4a6c-15a6-8de634bb47db.png)

Mobile版
![スクリーンショット 2021-06-13 19.39.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/b7f28f70-eae5-4393-4dd1-94a4b5b29949.png)

##■改善①画像のoptimize化
optimize化するために下記、ツールを使用しました。
https://imagecompressor.com/ja/
optimizeツールを使用することで、全画像11MBから2MBに抑えることができました。

##■改善②拡張子最適化
拡張子などの最適化も行いました。
- JPG/JPEG
写真など高画質かつ画像容量を下げて保存可能。
- Png
ロゴやイラストをサイズを下げて保存可能。

##■改善(その他)img要素にwidthとheight属性指定
こちらは、速度改善というよりSEO対策になります。

Googleが新しいアルゴリズム要素を発表したことで、
imgタグにはwidthとheightを直接設定する事はSEO上重要となりました。
下記の現象を持つWEBページは、改善をしなければ検索順位に影響する事になりました。

・画像レンダリングによる「文章コンテンツの移動」が発生する。

なので、下記のように設定することが望ましいです。

```

<img src="img/image.jpg" width="200" height="300" alt="画像の説明">

```

widthとheightを設定しない場合、
画像が読み込まれた後に、下のテキストなどの要素が大幅に変動します。

下記の記事をご参照ください。
https://parashuto.com/rriver/development/img-size-attributes-are-back



##結果
以上の改善を行い再度、ページ速度の評価を行いました。
評価がご覧の通り改善することができました。
■PC版
73→92
■SP版
49→67

PC版
![スクリーンショット 2021-06-13 21.04.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/8f860564-74be-9d0d-cf89-f23306b00089.png)


SP版
![スクリーンショット 2021-06-13 21.05.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/de40e072-82f6-2d48-2ea3-e7cf14142b70.png)



以上、
ご覧頂きありがとうございました。


■参考記事
https://parashuto.com/rriver/development/img-size-attributes-are-back

https://lpeg.info/seo/img_width_height.html
[2020/06] Google Play Console での新規リリース時にわからなかったこと

Google Play Consoleで新規アプリをリリースする際に、公式ドキュメントを読んでも不明確な箇所があったので問い合わせました。
ポイントだけまとめておきます。

※2020/06時点の情報なので、今後変更される可能性があります。

## 1. テスト版で審査通過した場合、製品版で審査をスキップできるのか

-> スキップはされないが、一部の審査項目は短縮されるようです。

古い情報だと「審査がスキップされる」といった記事もありましたが、現時点だと再度審査が入るようです。

## 2. 初回リリース時に手動で公開することができるのか

-> 一定の手順を踏めば利用可能なようです。

要は「管理対象の公開機能」が初回リリース時に利用できるのかという話になりますが、
以下の公式のドキュメントには、初めてアプリを公開する場合には利用不可能といった記載があります。
> 管理対象の公開機能を使用するには、アプリを先に公開しておく必要があります。初めてアプリを公開するときには使用できません。

https://support.google.com/googleplay/android-developer/answer/9859654?hl=ja

ただ、ネット上にはクローズドテスト版として一度アプリを公開すれば製品版でも利用可能との情報がありました。

試したところ、クローズドテスト版として審査提出（Rollout）をしたタイミングで「管理対象の公開機能」の設定オンオフが切り替えられるようになりました。
この状態になっていれば、製品版でも手動リリースが可能なようです。

（恐らくですが、公式ドキュメントの「公開」という言葉には、製品版以外での「公開」も含んでいるということかと思います。）

## (余談) 審査提出時のボタン表記

管理対象の公開がオンになっていても、審査提出の最終確認ダイアログには以下のように表示されます。

>「このリリースは（中略）全てのユーザーに公開されます。」

本当に押して良いのか迷いますが、管理対象の公開がオンになっていれば押してしまって大丈夫です。
審査中の状態になった後、管理対象の公開メニューの一番下に「審査中」の状態として製品版のアプリが記載されます。

押す前に勇気づけられた記事
https://qiita.com/taketakekaho/items/8afba6c7846668cf8dfa
https://pepecam.com/it/googleplayconsole/

以上です。
ストアまわりの仕様は変更が入ることも多く、かつGoogle Play Consoleはわかりにくい点も多々あったため、最新情報を求めている人向けに書き留めました。
【kotlin】配列 使い方

#■配列の作成
大きく分けて2つある。

###■arrayOf関数で配列を作成
arrayOf関数を使っているので最初は小文字です。

``` kotlin
val ary = arrayOf("あ","い","う","え")
```
▼arrayOfは何の型でも入る。

``` kotlin
val ary = arrayOf(1,2,3,4)
//いろんな型でも入る。何でも入るから
val ary = arrayOf("あ",1,2.5,"え")
```
###■型の指定パフォーマンスの向上処理速度が速くなる。
型を指定するだけではarrayOf()メソッドの型にArray<型>で指定はできますが

下記のintArrayOf等を使えば型を指定できる上、処理速度が上がります。

ソース
https://qiita.com/KenjiOtsuka/items/e3d42f34ee731747220d

``` kotlin
//整数しか入らんでー
val ary: IntArray = intArrayOf(1,2,3,4)
//型推論もできる。
val ary = intArrayOf(1,2,3,4)

Int型      型名:IntArray     intArrayOf()
Short型	型名:ShotArray    shortArrayOf()
Long型	    型名:LongArray    longArrayOf()
Byte型	    型名:ByteArray     byteArrayOf()
Boolean型	型名:BooleanArray  booleanArrayOf()
Float型	型名:FloatArray    floatArrayOf()
Double型	型名:DoubleArray   doubleArrayOf()
```
string型だけ arrayOf()を使う

###■arrayOfNullsメソッドでnullの配列を作る。

値は後から入れる予定、要素数だけを指定

■要素の型を必ず指定しその横に?を書く
Array<型?>

■引数に要素数を入れる。
arrayOfNulls(要素数)

``` kotlin
val ary: Array<Int?> = arrayOfNulls(3)

//結果: [null,null,null]
```


###■Arrayクラスのコンストラクタで作成
要素数とラムダ式で作成する。

``` kotlin
//itには0からの整数5つ分が入る。
val ary = Array(5){it}
//結果: [0,1,2,3,4]
```

#■配列の型パラメータ　arrayOf()メソッドの型
arrayOf()メソッドの型指定をしたい！！

■arrayOf()メソッドの型名の書き方
Array<型>です。
<>内を型パラメータと呼びます。

``` kotlin
//String型で固定されています。
val a: Array<String> = arrayOf("あ","い","う")
//Int型で固定されています。
val b: Array<Int> = arrayOf(1,2,3,4)
//Any型で何でも入るようになっています。
val c: Array<Any> = arrayOf(1,2.4,"あ")
```

#■配列の操作

``` kotlin
val a = arrayOf("うどん","からあげ","焼肉")

//インデックス番号で指定
println(a[2])
//結果:焼肉

//インデックス番号0番目のうどんを寿司に変更
a[0] = "寿司"

//配列の最後にデザートを追加
a += "デザート"

//配列の中身全部を表示
println(a.forEach{println(it)})
//結果: 寿司、からあげ、焼肉、デザート
```

▼for文かforEach文で配列の中身全部を指定


``` kotlin
val a = arrayOf("うどん","からあげ","焼肉")
//itはfor文のiが入る。
for(i in a){println(it)}
//結果: うどん、からあげ、焼肉

//結果は上と同じ
a.forEach{println(it)}
//結果: うどん、からあげ、焼肉
```
rails sを実行時、ターミナル上で"A server is already running." と表示される対処法

# はじめに
タイトル通りです。自身の備忘録としてQiitaへ初投稿させていただきます。
ターミナル上で以下のエラー文が表示され、起動できなくなりました。

```terminal
itoshin@mbp "ファイル名" % rails s
=> Booting Puma
=> Rails 6.0.3.7 application starting in development 
=> Run `rails server --help` for more startup options
A server is already running. Check /Users/itoshin/"ファイル名"/tmp/pids/server.pid.
```

`A server is already running.`
直訳すると、「すでにサーバーが起動しています。」とのこと。
しかし、製作中のサイトをローカル上で読み込もうとしても動作せず、確認することができません。
 
# 原因について
`Ctrl + C`でローカルサーバを実行して終了したつもりが、`Ctrl + Z`を押してしまったからです。
ターミナルに打ち込んだ`^Z`の表示を見て、気がつきました。

 
```terminal
itoshin@mbp "ファイル名" %
```
実行後、上記のように見慣れたプロンプトのみの表示になりました。
一見、ローカルサーバが起動していないように見えるのですが、実はバックグラウンド上で起動した状態になっております。
 
# 対処方法
ローカル上で動いているプロセスを見つけ出し、`kill`を実行します。
　
まず、以下のコマンドを実行します。
 
```terminal
itoshin@mbp "ファイル名" % lsof -i:3000
```
この`lsof -i:3000`という`lsofコマンド`の詳細を明記します。
 
|コマンド名     |説明                         |
|:----------:|:---------------------------:|
|lsof        |オープンしているファイルを一覧表示する|
|-i:3000     |ローカル（3000番）のネットワークソケットファイルを指定する　|
 

実行後、下記のようなものがターミナル上に表示されます。

```terminal
COMMAND     PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby      29088 itoshin   13u  IPv4 0x57e8cc5b4f41b215      0t0  TCP localhost:hbci (LISTEN)
ruby      29088 itoshin   14u  IPv6 0x57e8cc5b5416fe15      0t0  TCP localhost:hbci (LISTEN)
ruby      29088 itoshin   19u  IPv6 0x57e8cc5b52360475      0t0  TCP localhost:hbci->localhost:58355 (CLOSE_WAIT) ​
```
PID番号が「29088」と表示されています。（PID番号は都度変わります）
こちらの番号を指定して`kill -9 "PID番号"`を実行します。
すると下記（２行目以降）のような表示が出力されます。

```terminal
itoshin@mbp "ファイル名" % kill -9 29088
itoshin@mbp "ファイル名" % 
[1]  + killed     rails s
```

再度下記のコマンドを実行し、まだバックグラウンド上で起動していないか確認します。
 
```terminal
itoshin@mbp "ファイル名" % lsof -i:3000
```
 
実行後、プロンプトのみの表示が出ればOKです。
再度`rails s`を実行し、サーバーを起動させます。
 

```terminal
itoshin@mbp "ファイル名" % rails s
=> Booting Puma
=> Rails 6.0.3.7 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.6 (ruby 2.6.5-p114), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
```
無事、ローカルサーバが起動しました。

# おわりに
丁寧に記載したつもりですが、プログラミング初学者のため至らない部分があるかもしれません。
間違いなどございましたら、お手数ですがコメントいただけると幸いです。
よろしくお願いします。

# 参考記事
 
https://qiita.com/Tatsu88/items/f908dd445fb114b9e172
【React/Next.js】自作コンポーネントをLinkで囲めない件

## 結論
`div`で囲んでしまえば、とりあえず解決

## 環境
* React 16.12.0
* Next.js 10.0.4


## 事象
こうすると

```react
import Link from "next/link";

<Link href={`/sample`}>
  <MyComponent/>
</Link>
```

怒られる。

```console
Warning: Function components cannot be given refs.
Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
```


## 再度 結論
`React.forwardRef`を使えというので、色々なサイトを元に試行錯誤しましたがうまくいきませんでした。  

なので仕方なくこう

```react
<Link href={`/sample`}>
  <div>
    <MyComponent/>
  </div>
</Link>
```
[Vue warn]: Property or method "XXX" is not defined on the instance but referenced during render. とか言われたが、XXXは確実に存在する件

## 事象

Vueでとあるコンポーネントを表示させようとするとコンソールに下記のエラーが出力される。

```
[Vue warn]: Property or method "XXX" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
```


## 原因

何とscriptタグが閉じられていない。

```Hoge.vue
<template>
　～略～
</template>

<script>
export default {
　～略～
}
```

という状態。
オンラインデートを向上させたソフトウェアソリューションとは

タイトルにも記載の通り、「オンラインデートサービスを向上させたソフトウェアソリューション」についてご紹介します。記事を読めば、オンラインデートサービスの現状や今後の課題なんかも見えてくるかも知れません。ぜび参考にしてみてください。

**ユーザーインターフェースの技術**
近年のオンラインデートサービスのアプリやソフトウェアは新たな機能・ユーザーインターフェースが多数生み出されています。理由として挙げられるのは、新型コロナウイルスの流行。
失業や、外出禁止令などで外出できる場所と時間が極端に制限され、普段の移動時間やその他の時間が自宅でゆっくりとスマホを使用する時間に変わってきたのです。結果的に、オンラインコミュニケーションアプリの利用者が増えました。利用者の増加に伴い、アプリやソフトウェアが進化していったわけです。
出会い系サイト[igetnaughty.com](https://www.igetnaughty.com/)では、ストレートなカップルやゲイやレズビアン、さまざまなカップリングが可能です。更には、サイト独自の検索ツールも搭載されており、ユーザーインターフェイスの面に関してもしっかり対策。具体的には、人気マッチングアプリでも「オンラインデート」機能が搭載され始めてきています。

**ジオフェンシング技術**
出会い系アプリやオンラインデートサービスでの特に秀でている技術の1つが[ジオフェンシング技術](https://k-tai.watch.impress.co.jp/docs/column/keyword/716576.html)です。もともとユーザーたちをマッチングさせる関係で、相性度の高いユーザーをおすすめしてくれる機能はありました。しかし、最近のオンラインデートサービスもジオフェンシング技術の進化がめざましいです。
例えば、現在のオンラインデートアプリのはTwitterのような投稿機能からマッチングをしたりなどユーザーへのマッチングなどの特別な機能もあり、ユーザーの欲求を刺激するような進化を遂げています。

**他のサービスとの統合**

以前からフェイスブックなど、他SNSとの連携が盛んでした。おそらくSNSを連携されることで身分証明のような役割を担っているのかも知れません。しかし今のオンラインデートサービスは、SNSの連携の他にもさまざまな連携サービスが生まれています。

興味深い機能がオンラインデートアプリを介してテーブルを予約するために導入されています。 これはとても便利で便利な機能だと思います。 ユーザーは多くの時間を節約できます。今までのデートサービスでは、マッチング後でレストランの予約を行わなければならず、やり取りの過程でデートがキャンセルになってしまっている事もありました。
しかし、自動予約サービスの「ペコッター」はマッチング後にレストランの予約を代行してくれて最適なレストランを自動で探すことも可能です。今後も「Dine」と「ペコッター」のような連結型のサービスが増えていくことが予想されます。将来的には、出会い系アプリには地元のレストランがたくさんあると予想されており、とても便利です。 これはあなたにどんな料理を選ぶ機会も与えるでしょう。

**デートサービスにおけるAIの可能性**
デートサービスにおける[AI](https://qiita.com/savaniased/items/7e66a0b76b1e20327868)の可能性は相当高いと思います。実際にAIを用いたデートサービスはすでに存在するのです。恋活アプリではデートをした相手や希望条件などを吟味して次のデートへのアドバイスが可能。
自分と相性のいい恋人は誰なのかをAIの力を借りて、探すことができるサービスが出来上がっているのです。中には、どんな考えでマッチングアプリを作るか気になる人もいるかも知れません。これらの関数を作成するプロセスは非常に長いです。 100人以上の開発者が彼らと協力しています。
【Java】ObjectからCSV形式の文字列を生成する

# 概要

普段システム間のやりとりはjsonを使用しているが、
システムの運用をしているとjson形式のデータだと扱いづらい…

→CSVならエクセルでいろいろできて便利そう！
と思ったのでObjectからCSV形式の文字列を生成する方法をまとめてみました。

# ライブラリ

[jackson-dataformat-csv](https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-csv)を使用します。

```groovy:build.gradle
implementation 'com.fasterxml.jackson.dataformat: jackson-dataformat-csv:2.12.3'
```

# 実装

ここではは以下のObjectを扱います。

```java
@Data
public class SampleEntity {
    private int id;
    private String name;
}
```

早速実装です。

```java
// インスタンスの生成
var entity = new SampleEntity();
entity.setId(1);
entity.setName("rhirabay");

// mapperを生成
var csvMapper = new CsvMapper();
// csvを生成
var csv = csvMapper.writerFor(SampleEntity.class)
        .with(csvMapper.schemaFor(SampleEntity.class))
        .writeValueAsString(entity);

System.out.println(csv);  // 1,rhirabay
```

これだけ！

細かい設定や機能はいろいろあるのだろうが、
POJOを扱うぶんにはこれで良さそう。