OmniAICreator/Qiita-1.07M huggingface dataset:
CSSで三角形をサクッと作れるジェネレーターまとめ

0から書き出すとそれなりに時間が取られる三角形。主に吹き出しなどに使う機会が多いと思います。そんな時にパッと使える三角形ジェネレーターまとめです。
## 吹き出しジェネレーター

border付きの吹き出しジェネレーターです。
beforeとafterを重ねて表現しているベーシックな形です。


<img width="1004" alt="スクリーンショット 2020-07-31 17.35.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457046/4f433c41-70fe-b87d-654d-bdef74dbdc30.png">
http://www.cssarrowplease.com/

## CSS三角形作成ツール

とてもシンプルで、とりあえず三角形を作ってから調整したい場合はコレです。


<img width="1078" alt="スクリーンショット 2020-07-31 17.33.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457046/a095ea81-5b30-fd23-cb21-14be0ea72748.png">

http://apps.eky.hk/css-triangle-generator/ja


## CSS Triangle Generator

CSS三角形作成ツールと記述方法は変わらず、ちょっとお洒落な雰囲気なので使いやすいです。

<img width="1470" alt="スクリーンショット 2020-07-31 17.32.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457046/e938cace-6728-14b6-3038-66278f0ea80b.png">


https://triangle.designyourcode.io/
平均値と中央値と最頻値と代表値の違い

# 平均値
平均値と言った時は大体算術平均のこと。
英語だとMEANと書かれていることが多い。
(でもExcelはaverageよね…)

### 式
MEAN=ΣXi/n

### 例

|X1  |X2  |X3  |X4  |
|---|---|---|---|
|1  |3  |5  |7  |

MEAN
=(X1+X2+X3+X4)/4
=(1+3+5+7)/4
=4


# 中央値
小さい順に並べた時に真ん中の値。
英語だとMEDIANと書かれていることが多い。

### 式

- データが奇数個

(n+1)/2番目の値

- データが偶数個

(n/2番目の値+(n+1)/2番目の値)/2

### 例

- データが奇数個

|X1 |X2 |X3 |X4 |X5 |
|---|---|---|---|---|
|1  |3  |5  |7  |9  |

MEDIAN
=X3
=5

- データが偶数個

|X1  |X2  |X3  |X4  |
|---|---|---|---|
|1  |3  |5  |7  |

MEDIAN
=(X2+X3)/2
=(3+5)/2
=4


# 最頻値
最も頻繁に出現する値。
英語だとMODEと書かれていることが多い。

### 例

|X1 |X2 |X3 |X4 |X5 |
|---|---|---|---|---|
|1  |2  |3  |1  |1  |

MODE=1

※分布にしないとあんまり意味わからないかも。

# 代表値
分布の中心についての特性値。
上述の最頻値・中央値・平均値から選択する。

最頻値・中央値・平均値についてはデータが決まれば人の手が入る余地はないが、代表値は選び方によって変わる。
(年収分布の平均値と中央値の話が有名)

相手に伝えたい内容に合わせて選ぶと良いかも。

## 参考
http://pref.shimane-toukei.jp/index.php?view=15564
LightGBMの主要なパラメータについてのまとめ



出典：[Parameters－－LightGBM2.3.2](https://lightgbm.readthedocs.io/en/latest/Parameters.html)


|パラメータ         |  既定値         |説明                 |アライアス（別名でも指定可） |
|:---------------|:--------------:|:-------------------|:-----|
|num_leaves      |        31      |1本の木の葉の最大数を制限する．       |num_leaf, max_leaves, max_leaf|
|max_depth       |        -1      |決定木の最大深度を制限する．0以下なら制限なしを意味する． |
|min_data_in_leaf|        20      |1つのリーフ内のデータの最小数．過剰適合に対処するために使用する．大きな値ほど決定木が深くなりすぎるのを回避できる．|min_data_per_leaf, min_data, min_child_samples|
|learning_rate   |       0.1      |学習率．        |shrinkage_rate, eta |
|num_iterations  |       100      |ブースティング反復回数． |num_iteration, n_iter, num_tree|
|early_stopping_round|    0       |指定されたラウンド数の間で評価が改善しなければトレーニングを停止する．0以下で無効になる．|early_stopping_rounds, early_stopping|
Docker for MacのLaravelが遅いから速くしたい

# 要約

- Docker for Macのファイルマウントが遅すぎるので、ファイルマウント量を減らす
- ファイルマウントに:delegatedや:cachedを使う
- php.iniの設定でOPcacheを有効化する
- composerも遅いのでリポジトリの変更し、プライグイン導入

## ファイルマウント量を減らす、かつマウントする時は:delegatedや:cachedを使う

- .gitはマウントする意味がないので、除外する
- マウントがどうしても必要な時は:delegatedや:cachedを使う

例

```docker-compose.yml
version: '3'
services:
  web:
    image: nginx:${Version}
    ports:
      - "8000:80"
    depends_on: # 追加
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html:delegated #:delegatedを追加
      - exclude:/var/www/html/laravel-dir/.git #追加
    container_name: web

  app:
    build: ./docker/php
    volumes:
     - .:/var/www/html:delegated #:delegatedを追加
     - exclude:/var/www/html/laravel-dir/.git #追加
    depends_on:
      - mysql

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: hoge
      MYSQL_USER: hoge
      MYSQL_PASSWORD: hoge
      MYSQL_ROOT_PASSWORD: hoge
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql:cached #:cachedを追加

volumes:
  exclude: #空のVolumeを追加
  mysql-data:
```

## php.iniの設定でOPcacheを有効化する

```php.ini
~~省略~~
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1
```

## composerも遅いのでリポジトリの変更し、プライグイン導入

```Dockerfile
FROM php:7.4-fpm

~~省略~~

# composerの高速化
RUN composer config -g repos.packagist composer https://packagist.jp && composer global require hirak/prestissimo

WORKDIR /var/www/html
```

## 参考

[光遅い問題に対応して Composer を100倍速くする](https://qiita.com/bezeklik/items/f9bc7afc229b5476e822)
[Macのdockerが遅いストレスから解放されよう](https://qiita.com/ysKey2/items/346c429ac8dfa0aed892)
[Laravel で 最適化 高速化 手法一覧](https://qiita.com/ntm718/items/196bd6a84a93edc24ae7)
[Flutter] google_sing_inを使ったサインイン時にキャンセルを押すとcatchできないErrorが出る問題

# 環境
* VSCode ← たぶん重要
* iOS 13.6 シミュレータ
* google_sign_in 4.5.1

※ 試していませんが、Android Studioでデバッグしている場合は起こらないかもしれません

# 問題
Googleアカウントでのサインインを行うためのパッケージ[google_sign_in](https://pub.dev/packages/google_sign_in)を使って、サインイン画面を表示させた際に、左上に表示されるキャンセルボタンを押して、サインインせずにサインイン画面を閉じると、下記のようなエラーが出る。しかもcatchできない。
`signIn()`関数は失敗時に`null`を返すと関数の説明に書いてありますが、なぜ。。。？

```
PlatformException (PlatformException(sign_in_canceled, com.google.GIDSignIn, The user canceled the sign-in flow.))
```

```dart
Future<void> _handleSignIn() async {
  try {
    await _googleSignIn.signIn();
  } catch (error) {
    // サインインをキャンセルした時にここが実行されない。
    // _googleSignIn.signIn().catchError(onError)としても同様
    print(error);
  }
}
```

# 対処方法
先に対処方法から。
デバッグを開始する際、コマンド`flutter run`で実行する。

？？？
そんなんでほんとに変わるの？
と思いましたが、ちゃんと動きました。（自分の場合は）

```dart
Future<void> _handleSignIn() async {
  try {
    // キャンセルした時は、nullが返ってくる
    final GoogleSignInAccount googleSignInAccount await _googleSignIn.signIn();

    if (googleSignInAccount != null) {
      // ~~~
    } 
  } catch (error) {
    print(error);
  }
}
```

ちなみに、以下ではダメでした。
VSCodeのデバッグ機能を使うと起きる問題？

* VSCodeのメニュー「実行」→「デバッグの開始」
* F5

以下のQAを参考にしました。
https://github.com/flutter/flutter/issues/44431#issuecomment-657431886

> なんとなく不便なので、他に対処方法をご存知の方がいらっしゃいましたら、教えていただけると大変助かります。
LabelImgをMacにインストール

# labelImgとは

無料のアノテーション（画像ラベリング）ツールで、物体検出の教師データ作成に使用する。VoTTと比較して、UIが初心者向けなので、採用しました。

今回はインストール手順を記載。

labelImgのGithub
https://github.com/tzutalin/labelImg

# インストール準備

ターミナルを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144410/96db68ce-ed9b-9963-2476-1f05b660a3a0.png)

brew更新（念のため）

```
brew update
```

gitの更新

```
brew install git
```

作業場所を作成

```
mkdir ~/Work
cd ~/Work
```

# labelImgのダウンロード

```
git clone git@github.com:tzutalin/labelImg.git
```

## gitの設定エラーがでた場合

E-mailと名前の設定

```
git config --global user.email example@example.com
git config --global user.name hogehoge
```

# インストール

```
cd ./labelImg
brew install python3
pip3 install pipenv
pipenv --three 
pipenv shell
 pip install pyqt5 lxml 
make qt5py3
 rm -rf build dist 
python setup.py py2app 
cp -rf dist/labelImg.app /Applications 
exit
```

参考

【labelImg：物体検出】公式READMEが当てにならない件
https://qiita.com/mdo4nt6n/items/46d53e19ed65c44c0eb7

# インストール完了

こんな画面が表示されたらOK

※画像の部分は何も表示されなくてOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144410/b449eb7d-ce8e-cb0c-84e2-68498c5a7fdc.png)

# 次回以降の起動方法

デスクトップにアイコンができるらしい。
MySQL でJSON型のnull/空配列のデータをフィルターする

環境は MySQL 5.7

# 値が null のレコードを検索する

```sql
SELECT data FROM test WHERE JSON_EXTRACT(data, "$.value") = CAST('null' AS JSON);

+-----------------+
| data            |
+-----------------+
| {"value": null} |
+-----------------+
```

# 値が 空配列 のレコードを検索する

```sql
SELECT data FROM test WHERE JSON_EXTRACT(data, "$.value") = JSON_ARRAY();

+---------------+
| data          |
+---------------+
| {"value": []} |
+---------------+
```

# 参考
* https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object
* https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract
* https://dev.mysql.com/doc/refman/5.7/en/json.html
ActiveHashについて

DB設計をしてる時に便利なgemを見つけたのでまとめてみたいと思います。

##ActiveHashとは

都道府県一覧やカテゴリーなど「基本的に変更されないデータ」（区分情報等）があったとします。基本的に変更されないデータであるため、データベースに保存する必要性がありません。

ですがビューファイルなどに都道府県のオプションを書くと見るに耐えないコードになってしまいます。


そういう悩みを解決するのに便利なのがactive_hash。
ハッシュデータをモデルとして定義することで、ActiveRecordと同じように使えることができます。

それでは定義の仕方を見ていきましょう。

まずGemfileにactive_hashを記載して、bundle installします。

```ruby

gem 'active_hash'
```

###モデル作成

今回はArticleモデルとgenreモデルを作りたいと思います。

```
rails g model article
```

```
rails g model genre --skip-migration
```

genreモデルには情報をデータベースに持たせないのでマイグレーションファイルを作成する必要はありません。

###ハッシュの作成

次にデータをハッシュの形で定義します。

```ruby:app/models/genre.rb

class Genre < ActiveHash::Base
 self.data = [
   { id: 1, name: '--' },
   { id: 2, name: '経済' },
   { id: 3, name: '政治' },
   { id: 4, name: '地域' },
   { id: 5, name: '国際' },
   { id: 6, name: 'IT' },
   { id: 7, name: 'エンタメ' },
   { id: 8, name: 'スポーツ' },
   { id: 9, name: 'グルメ' },
   { id: 10, name: 'その他' }
 ]
end
```

ここで気をつけるのは**ActiveHash::Base**をGenreモデルに継承することで
ActiveRecordのメソッド(allなど)が使えるようになります。

###使用するクラスにアソシエーションを定義する。

ActiveHash::Associations::ActiveRecordExtensionsモジュールをArticleクラスにextendする事で
このモジュールに定義してある**belongs_to_active_hashメソッド**をArticleのクラスメソッドとして
使用する事が出来ています。

```ruby:app/models/article.rb

class Article < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :genre

  end
end
```

コンソールで試してみましょう


```
irb(main):001:0> Article.create(genre_id:1)
=> #<Article id: nil, title: nil, genre_id: 1, created_at: nil, updated_at: nil>

```


無事Articleモデルでgenreモデルで定義したデータを取得することができました。
AWS Honeycodeでガソリン管理アプリを10分で作ってみた

いつも忘れないように、コンセプトから。

###コンセプト
・お金かけてまでやりたくないのでほぼ無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

前回と前々回に簡単にHoneycodeを調べてみました。
https://qiita.com/auf/items/08cde2ce3f88e0f3ed44
https://qiita.com/auf/items/b3a239adda19f7d8079f

今回はちょっとアプリでも作ってみようというトライです。何にしようかなと考えていたんですが、私は興味もあって、ガソリンの給油量を管理しているんですが、いつもはGmailの下書きにメモしておいて、あとでExcel集計していました。特段不便でもなかったのですが、そもそもガソリンスタンドで直接データを入れたら便利じゃね？という発想です。

ちなみに、勘ででやってみようということで、上記の2回調べた以上の前提知識はありません。実際に触るという意味では初見でした。が、想像以上に簡単にアプリが作れてしまい、ローコードって凄いな、と思いました。　
　
　
###まずはデータを準備する
今回はスクラッチ開発を選びました。データは元々Excelで持っているのでCSV化します。テキストで見るとこんな感じ。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/540564c5-12df-21ef-d9e6-f124f164e9ad.png)

次にHoneyCodeにデータを取り込みます。CSVインポートがあるので簡単です。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/f94b401b-662c-2b20-9770-6bbc51b69a59.png)

無事にインポートされたので1行目のヘッダーだけ書き換えました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/b57fc7ec-1c55-8346-3c58-bd162f5d95d9.png)

###アプリを作ってみる
今回はウィザードを選んでみました。これが超便利だったんですよ！！
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/ff3a87b1-a472-0ec1-2442-df86870167e7.png)

はじめにソースとなるテーブルを選択します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/84de43e1-92df-2571-fdca-c598a06165db.png)

そうするともう表示アプリができました。完全自動で何もやってません。ここまで1分。。。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/6fbbe36b-a5ac-7602-5a87-b0f3d7f34142.png)

次に詳細表示アプリが作られます。これはいらない機能だなと思ったので後から消しました。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/2aad59a8-c945-76b4-14cf-4b4075f0bcf5.png)

次に行追加のアプリです。テーブルにInsertされます。表示アプリのAddを押すとこれが呼ばれます。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/91f05740-d59d-d4b6-1c4b-6c051ead278a.png)

はい、完成です。ここまで2分。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/4096ccb7-c4d1-0e24-5238-e55507358a75.png)

###平均燃費を確認するアプリも作る
あまりにも簡単すぎて拍子抜けしたので、平均燃費を表示するアプリも作ってみました。同じように作るには、要はTableがあればいいわけなので、平均燃費の値が取れるTableを作ります。ソースデータは別Tableなので、MaxとSum関数を使いながら拾ってきました。ここら辺はExcelと同じように勝手に候補が表示されますし、テーブルやカラム候補も勝手に出てくるので簡単です。関数を調べて作るのに5分くらいという感じです。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/08061754-cbb3-f93a-40cd-f5114e35aa95.png)


###作ったアプリをスマホから確認する
実際にここまでで10分もかかっていません。スマホからログインするともうアプリはできています。一番左がこれまでの履歴表示の画面で、真ん中が平均燃費の表示です。一番右側は、左画面の「＋Add」を押すと遷移する画面で、走行距離、入れたガソリン、場所を入力できます。試しに入れてみましたが、Tableの一番下の行に入ってきました。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/0a70a444-56cd-a8a5-824a-9242469c23b4.png)
　
　
　
個人的にはかなり実用的なアプリが超簡単に作れてしまったので大満足です。現状ではβ版なので機能は限定されていますが、スマホで撮影したデータとかも簡単に送れるようになると思いますし、夢が広がりますね。GSPとかセンサーも拾ってこれないかなぁ。マジでいろいろ妄想が膨らみますww
K-平均法(k-means法)についてふわっと理解する

# 想定読者
機械学習の知識が何もない方向けに作成しています。少し理解のある方は、必要な知識の節は飛ばしてもらって構いません。
# 必要な知識
必要な知識をなるべく難しい言葉を使わずに解説します。いや読むのだるいなという方は読み飛ばしてください。
## 教師有り学習、教師なし学習
教師有り学習とは、正解ラベルが与えられているデータから学習を行うもの、教師なし学習は、正解ラベルが無いものです。え？わかりにくい？
すごく分かりやすく言うと、私たち（使う側）が、正解を与える、与えないで分類します。
###教師有り学習の例
明日の天気を予想したいがために、今までの天気のデータを使用したいとします。当然、今までの天気はもう正解が分かります。そしてこれは、昨日の天気は雨。おとといの天気は晴れ、と私たちがコンピュータに正解を与えているため、教師有り学習に含まれます。
###教師なし学習の例
迷惑メールの分別をしたいとします。この時、そのメールが本当に迷惑メールかどうかということは、教えないこととします。コンピュータは、メールの中身を見て、それらををふたつのグループに分けます。これが教師なし学習です。この例では、最後人間が見てどちらがより迷惑メールか？を考えなければいけません。
##クラスタリングアルゴリズム
クラスタリングアルゴリズムアルゴリズムとは、ある規則に基づいて、与えられた要素を似た者同士でグループ分けするものです。
##階層的クラスタリング
　階層的クラスタリングとは、その名の通り階層的にクラスタリングを行うものです。初めはそれぞれが一つのグループに属しています。その後、段々似たもの同士のグループをくっつけていき、最終的には全員が属するひとつのグループになります。トーナメント表を思い浮かべてください。
最初は4人だったものが、2人と減っていき、最後は1人になりますね。階層的クラスタリングでは。最初は1グループに1人しか属していません。つまり、4グループになります。試合をすると、昨日の敵は今日の友ということで、グループが合併されると思ってください。
<img width="887" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513355/b110ba3a-91a0-8a80-9d0e-b8d91faf2ac8.png">
試合が進行していくにつれ、グループ数が減っていきます（1グループに属する人数は増える）。最終的には、1つのグループになる事、任意の場所でトーナメント戦をを中止にすれば、好きなグループ数で止めれることも重要な強みです。非階層的クラスタリングが、そうなっていないものです（ひどい）。おそらく階層的クラスタリングのほうが理解が難しいため、今回はこちらを解説しました。

# K-平均法について
k-means法は、教師なし学習、非階層的クラスタリングの部類に属するクラスタリングアルゴリズムです。
アルゴリズムを解説していきます。色々なパターンに対応できるよう、抽象度を上げて解説します。
## 初めのセントロイドを決める
おい、まーた知らない単語出てきたよという声が聞こえます。大丈夫です。セントロイドとは、そのグループのリーダーだと思ってください。K-平均法の「K」は、最終的にK個のグループに分けるという意味のKなので、たくさんいるデータの中から、K人リーダーを決めてあげましょう。
## データをK個のクラスタに分割する
セントロイドをきめたら、すべてのデータがどのグループに属するか決めます。ここでの指標は様々あるため、必要に応じて使い分けなければいけませんが、K個あるセントロイドの中で、自分が一番似ているセントロイドが属するグループに属します。わかりにくければ、リーダーの中で自分と一番似ているのが太郎君だった場合、太郎君と同じグループに入ると読み替えてください。
## 重心を決める
全てのデータをどこかのグループに割り振ったら、もう一回似たようなことをします。具体的には、同じグループ内で重心を求め、それをセントロイドとして、一個前の作業に戻ります。重心を求めるのがいまいちピンとこない方は、同じグループ内で話し合いをして、それぞれの意見をまとめます。そのあとでほかのグループの意見を聞き、もう一度、自分が一番賛同できる意見のグループに属し...を繰り返すというイメージです。
## 終了条件
一個前のグループと、今回のグループ構成が全く変わらなかったら終了です。それ以降、グループ構成が変わることは無いです。
#まとめ
実際に実装するときは、もう少し難しくなります。何をもって「似ている」とするか？初めのセントロイドの決め方はランダムでいいのか？などの問題があります。一番簡単な例から実装するのであれば、二次元座標上に表現できるデータが好ましいかと思います。実装すると理解が深まるので、ぜひ一回実装してみてください。誤字脱字、内容の修正があればぜひ教えてくださると助かります。
Trace Labs Global OSINT Search Party CTF V writeup

今回はseemaとkanau、blaclearの3人で[Trace Lab](https://www.tracelabs.org/
)が主催するOSINTのCTFに参加してみました。結果としては,、残念ながら127/190位でした。実際に行方不明になった人たちを探すというCTFの性質上、詳細なwriteupを載せることはできませんが(CTF終了後scoreboardへアクセスできなくなったし)、その形式や内容について簡単にwriteupしたいと思います。

↓CTF全体の結果
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We were so proud to see our community come together for our Global <a href="https://twitter.com/hashtag/OSINTSearchParty?src=hash&amp;ref_src=twsrc%5Etfw">#OSINTSearchParty</a> <a href="https://twitter.com/hashtag/CTF?src=hash&amp;ref_src=twsrc%5Etfw">#CTF</a> and use the power of <a href="https://twitter.com/hashtag/OSINTForGood?src=hash&amp;ref_src=twsrc%5Etfw">#OSINTForGood</a> to generate all of these important leads! Our team is now compiling valuable intelligence reports for Law Enforcement with these <a href="https://twitter.com/hashtag/OSINT?src=hash&amp;ref_src=twsrc%5Etfw">#OSINT</a> findings! <a href="https://t.co/1SPdqvYY8z">pic.twitter.com/1SPdqvYY8z</a></p>&mdash; Trace Labs (@TraceLabs) <a href="https://twitter.com/TraceLabs/status/1282506791574745090?ref_src=twsrc%5Etfw">July 13, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# OSINT Search Party CTFの特徴
Trace LabsはOSINTを用いて実際に行方不明になっている人々を探すNPOです。過去には[Defconにブースを出したり](https://www.security.land/tracking-missing-people-through-public-information/)、[Youtube](https://www.youtube.com/watch?v=2puBmXfi9Z0&feature=emb_logo)等のメディアで紹介されたりしています。今回のCTFの特徴としては

- 参加費：$24([Trace Labsオリジナル動画教材](https://academy.osintcombine.com/p/tracelabstraining)付き)
- 制限時間：6h
- [flagがキーワードではなく、捜索している人物の行方の特定につながる情報な点](http://download.tracelabs.org/Trace-Labs-OSINT-Search-Party-CTF-Contestant-Guide_v1.pdf)

などが挙げられるかなと思います。
 
# 反省点
今回の悲惨な結果について、参加者からのコメントです。
seema「表面的な情報しか得られなかった気がするので、様々な検索機能をもっと使いこせるようになりたいと思いました。」
kanau「明確なflagがあるわけではなかったし、よく分からなかったよ。」
blaclear「FacebookやInstagramといった本名と紐付けされやすいSNSを芋づる式に辿っていくことしかできなかった。家族や友人を特定することはできたが、それ以上flagを見つけることができなかった。あとリアルな人物をネトストするのは思ってたより心がしんどかった。」
[Swift]ContainerView周りの値渡し

意外とContainerViewでの値渡しに関する記事が少なかったので、書いておきます...

## 親ビュー -> 子ビュー

```ParentViewController.swift

//値を渡したい処理で以下を実行
let child = self.children[0] as! ChildController

child.textValue = "Hoge"
```

```ChildController.swift
var textValue: String = "Huga"

//実行後
print(textValue)    //->Hoge
```

##子ビュー -> 親ビュー
```ParentViewController.swift
var textValue: String = "huga"

//実行後
print(textValue)    //->hoge
```

```ChildViewController.swift
//値を渡したい処理で以下を実行
let parent = self.parent as! ParentViewController

parent.textValue = "hoge"
```

##子ビュー -> 子ビュー
```FirstViewController.swift
//値を渡したい処理で以下を実行
//一度親を通す
let parent = self.parent as! ParentViewController

let second = parent.children[0] as! SecondViewController

second.textValue = "Hoge!"
```

```SecondViewController.swift
var textValue = "Huga?"

//実行後
print(textValue)    //-> Hoge!
```

##最後に
子ビューを制定する、

```parent.swift
let child = self.children[0] as! ChildViewController
```
のようなコードの数字(上のは0)はなんでもいいと思います。もしエラーが出たらその都度変えてみてください。(競合するとエラーが出る)

間違えているところがあったら教えてください。
WINE で lessmsi で msi ファイルを展開する

## 背景

Linux + WINE で `.msi` ファイルを展開したい.

Linux native で動く msiextract(msitools) がありますが, 

https://github.com/GNOME/msitools

バグがあり, たまに展開できなかったり, 展開したファイルが壊れている `msi` ファイルがあったりします.
あとビルドがめんどい.
(apt とかにあるのはバージョン古くてうまく展開できないファイルがより多い)

msitools の Ubuntu 18.04 でのビルドメモ
https://qiita.com/syoyo/items/64ce9eea9176ce0a9d41

## lessmsi

Windows native の msi 展開やファイルブラウザ lessmsi がありました.

https://lessmsi.activescott.com/

ソースコードもあります. IE 拡張もあるので, Windows で使いたいときも便利です.
(issue でいくつか展開できない `msi` があるようですが, 少なくとも `msiextract` よりはうまくいく感じです)

GUI 版は, WINE 環境だと UI が真っ黒になり使い物になりませんでした.

展開先ディレクトリを指定の場合は, パス名の最後にバックスラッシュ(`\`)が必要です.

Unix shell だと, `\` は複数行入力のエスケープ文字と扱われてしまうため, 以下のようにエスケープする必要があります.

```
$ lessmsi.exe x file.msi "dist\\"
```

binfmt + wine で Windows バイナリを Linux で ./a.exe のようにして実行するメモ
https://qiita.com/syoyo/items/9fd8758ea3878c36e807

で `.exe` を直接実行できるようにしているとより便利に使えるでしょう.
ずんだの波打つ進捗問題 Ruby 編

任意の文字列を任意の幅で波打たせてください。

## ルール
1. 対象の文字列を1文字1行ずつ出力する
1. 1行進むごとに左に全角スペースを1文字増やし、文字の表示位置をずらしてください
1. 文字の位置が指定の幅まで到達したら、今度は1行進むごとに全角スペースを1文字減らしてください
1. 全角スペースがなくなったら2の手順に戻ってください
1. 対象の文字列をすべて出力し終わるまで 2-4 を繰り返してください

ちょっとわかりにくいかと思うので、サンプルをみてください。

## サンプル
### 文字列「進捗どうですか？」、幅「3」
```
進
　捗
　　ど
　う
で
　す
　　か
　？
```

### 文字列「進捗どうですか？」、幅「4」
```
進
　捗
　　ど
　　　う
　　で
　す
か
　？
```

### 文字列「完全に理解した」、幅「4」
```
完
　全
　　に
　　　理
　　解
　し
た
```

## プログラム
```ruby
def get_spaces(range)
  pre = *(0..(range - 1))
  reversed = pre.reverse[1..-2]
  (pre + reversed).cycle
end

def wave_text(text, range)
  spaces = get_spaces(range).take(text.length)
  text.each_char.with_index(0) do |char, i|
    print "#{'　'*spaces[i]}#{char}\n"
  end
end

wave_text("進捗どうですか？", 3)
wave_text("進捗どうですか？", 4)
wave_text("進捗どうですか？", 5)
wave_text("進捗どうですか？", 6)
wave_text("完全に理解した", 4)
```

### 出力
```
進
　捗
　　ど
　う
で
　す
　　か
　？
進
　捗
　　ど
　　　う
　　で
　す
か
　？
進
　捗
　　ど
　　　う
　　　　で
　　　す
　　か
　？
進
　捗
　　ど
　　　う
　　　　で
　　　　　す
　　　　か
　　　？
完
　全
　　に
　　　理
　　解
　し
た
```


## プログラムを利用して出力した文字列によるツイート
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">進<br>　捗<br>　　ど<br>　う<br>で<br>　す<br>　　か<br>　？<br>進<br>　捗<br>　　ど<br>　　　う<br>　　で<br>　す<br>か<br>　？<br>進<br>　捗<br>　　ど<br>　　　う<br>　　　　で<br>　　　す<br>　　か<br>　？<br>進<br>　捗<br>　　ど<br>　　　う<br>　　　　で<br>　　　　　す<br>　　　　か<br>　　　？</p>&mdash; てぃーびー - Learning Designer (@tbpgr) <a href="https://twitter.com/tbpgr/status/1289185496095047680?ref_src=twsrc%5Etfw">July 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 関連情報
* [ずんだ問題まとめ - Qiita](https://qiita.com/tbpgr/items/3a4169b370f1a317ece0)
【GameMaker Studio2】リズムゲームの作り方

# はじめに
今回はGameMaker Studio2での、リズムゲームのざっくりとした作り方を紹介します。

## サウンドデータの用意
まずリズムゲームに必要なサウンドデータですが、"*.wav*" で用意します。
というのも、"*.mp3*" といった圧縮されたサウンドファイルの場合、GameMaker Studioでは、再生開始時やループ時にラグで発生します。
そのため、通常は "*.wav*" ファイルで用意したほうがよいです。

"*.wav*" の場合、ファイルサイズが大きくなりますが、
サウンドエディタで Attribute を "Compressed" (圧縮有効)の設定にすると、最終的なファイルサイズを小さくすることができます。

<img width="452" alt="gms2_poker2_-_GameMaker_Studio_2-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/ba37537a-1845-8dfe-4e67-e52ad83ec7ca.png">

## 拍の計算方法
ゲームで使用する譜面は "拍" を基準に作ることになります。
というのも、"拍" がリズムの基本的な単位となるためです。

リズムゲームはタイミングに合わせてボタンを押す（またはタッチする）
というのが基本のゲーム性となるので、現在の曲の再生位置が何拍目であるかという情報が必要となります。

そして再生中の曲の現在の拍(位置)は曲のBPMから求めるのが良いです。

BPMとは1分間あたりの拍数(4分音符の数)です。
そして、以下の計算式で1秒あたりの拍数を求めます。

> BPM ÷ 60秒 = 1秒あたりの拍数

例えば BPM が 120 の場合、1秒あたりの拍数は、
> 120 ÷ 60 = 2

となり、現在の経過秒数が "4秒" であれば、
> 2 x 4秒 = 8
で "8拍目" となります。

<img width="743" alt="名称未設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/63ac49da-8e8e-889e-ec61-030505434ff7.png">

## 譜面データの単位
さきほど拍を基準とする……と書きましたが、
譜面の単位は「`小節`」を基準にすると扱いやすいかもしれません。

というのも拍を基準にした譜面データだと DAW の表記から連想しにくいためです。

<img width="484" alt="スクリーンショット_2020_07_30_23_54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/bfb54f75-9f9d-b427-52fd-eb770cff8d9d.png">

例えば、DAW はこのように `小節数` で表示され、小節単位で演奏データの区切りがされています。
そして多くのリズムゲームでも、小節単位で区切り線が引かれています。

<img width="472" alt="Made_in_GameMaker_Studio_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/9b7ea02e-05d3-9e50-eeb8-9bd20850f368.png">

そのため、例えば、"0, 1, 2, 3, 4, 5, 6, 7, 8, ……" という拍を、4拍子であれば、
"1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, ……" という数値で扱ったほうが、
整数値の部分がちょうど小節数と一致するので、譜面データが作りやすいような気がします。

<img width="645" alt="名称未設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/535455a3-b4eb-42dc-3808-b59a44052399.png">

## GMLの制御
では、GMLで再生中のBGMの再生位置を取る方法です。
例えば Createイベントで `audio_play_sound()` を使って BGM を再生し、サウンド再生番号を変数 "bgm" に保持します。

```js:Createイベント
// BGMをループ再生
bgm = audio_play_sound(snd_Bgm, 10, true);
```

次に、再生番号から `audio_sound_get_track_position()` で再生位置を取り、BPMから現在の拍数(小節数)を計算して判定を行います。
以下は BPMが `132` の場合の例です。

```js:Stepイベント
// 現在の再生位置を取得する
var pos = audio_sound_get_track_position(bgm);

var bpm = 132; // BPMは132とする
// 現在の再生位置を拍に変換
var note_pos = pos * bpm / 60;
// 拍から小節数に変換
note_pos /= 4;
```

これにより、`note_pos` が現在の再生位置（判定ライン）となるので、そこから譜面データの位置と差分を取って、譜面データ（ノーツ）を描画します。

<img width="529" alt="Made_in_GameMaker_Studio_2-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/13829f9c-ac53-aeec-15de-22bfe2b8ca09.png">

ボタンを押したときの判定は、現在位置からどれだけ離れているかで計算できます。

```js
// 譜面の位置との差分の絶対値を計算
var diff = abs(notes - note_pos);
if(diff < 0.05) {
  // GREAT判定
}
else if(diff < 0.15) {
  // GOOD判定
}
else if(diff < 0.25) {
  // 1拍近く離れていたらBAD判定
}
else if(diff < 0.5) {
  // 1拍以上離れていたらPOOR判定
}
else {
  // 2拍ぶん離れているので判定なし
}
```

あと、判定するノーツは "一番近いノーツのみ" 行うようにします。

これでリズムゲームの基本的な部分を作ることができます。

![rhythm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/3baf70ef-c072-e607-7911-a9a1b2e37491.gif)
プログラミングスクール行って良かったなっていう話。

※この記事、若干前置き長いです。

こんにちは、Shotaです!


僕がプログミングを勉強してからついに7カ月が経ちました。時が過ぎるのはあっという間ですね。。。
ちなみに、Ruby歴は４カ月程度です

7月にプログラミングスクールを卒業して、今ではRubyで簡単なアプリを作れるようになった僕ですが、はじめはなかなかうまくいきませんでした。


最初の挫折は、**Progateの道場**です。

プログラミングをやろう！と思って、
まず最初に安定のProgateから始めてみました。

しかし、大学生ということで勉強・2つの部活・バイト・遊び　など、
やることも少なくなかったため、ずいぶんスローペースで進めてました。

確か2カ月くらいでHTML,CSS,JS,jQueryを１～2周ずつくらいしたと思います。

一通りProgateやった僕は、腕試しにと、初めてHTMLの道場編をやりました。
そして、絶望しました。(笑)

プログラミングで初めて、
「めちゃめちゃ難しくね？？？」
と感じた瞬間です。

これを機に、僕がパソコンの前に座る回数は減っていきました。

典型的な挫折パターンです。


しかし僕は、プログラミングに対する思いを捨てきれず、挫折の4カ月後に
またProgateを再開しました。

今度は冬休みということもあり、結構時間もあったので、1～2カ月独学でほぼ毎日プログラミングの勉強をしました。

でも、やっていくうちに気づいたんです。
「独学じゃプログラミングスクール行ってる人に勝てないんじゃないか。」
ということに。

Twitterなんか見ると、
「独学でも案件取れる」とか「独学でもエンジニアになれる」
というのは、結構言われてる気はします。

そういったものを見ると、
「独学でも案外行けんじゃね」
って簡単に思ってしまいます。

たしかに、それは可能だとは思います。
でも個人的な意見としては、スクールに行った方が、成長できるし、得られるものが多いと思います。
また、案件を取れる確率やエンジニアになれる確率も、間違いなくスクールに行った方が上がるはずです。


スポーツを例にすると分かりやすいですね。

例えば、テニススクールに通っている子と、テニススクールには通ってないけどテニスをしている子がいたとします。

テニススクールに行っている子は、
毎日、監督・コーチに教えてもらいながら、仲間と一緒に良い環境で練習や試合をやります。
フォームがおかしかったり、新しいプレーにチャレンジしたりするときは、基本からしっかり教えてもらえます。

一方、テニススクールに行っていない子は、
毎日テニスの上手い人の動画や、解説動画を見ながら、壁当てをやり続けます。
自分だけでは、おかしいフォームになっても気づきづらいです。

では、この2人が試合するとします。
皆さんもお分かりだと思いますが、スクールに行っていない子が
勝つ確率は、非常に低いでしょう。

そりゃそうです。
スクールの方が練習環境がいいし、指導してもらえるから。
さらに言うと、スクールに行ってない子が見たテニスの動画は、スクールに行ってる子も見て参考にできます。

これと同じことがプログラミングスクールの世界にも言えると、僕は思います。

だから、プログラミングスクールは行く価値があるのです。

***

***「多くの人に影響を与え、前向きにさせるようなサービス開発をする」***

というのが僕の目標です。
そのためには、スキルのある立派なエンジニアになる必要があります。

そしてそれを実現するためには、

**よりエンジニアになりやすい、プログラミングスクールに行った方が良い**

ということになります。


これに気づいた僕は、すぐにプログラミングスクールに申し込みました。

プログラミングスクールの感想としましては、

**「とにかく行って良かった」**

この一言に尽きます。

一体なにが良かったのか。
ポイントは主に２つです。

1つ目、**分からないことをすぐに聞けること**
2つ目、**継続できること**

1つ目、分からないことがあればすぐに聞ける

独学だと、いくら調べてもなかなかエラーから抜け出せない
ということがあると思います。

でも、分からないところを聞ける環境があれば、そこで多くの時間足止めをされる心配がなくなります。
メンターさんに質問した時、返ってくるのは**答え**ではなく、**ヒント**でした。
だから無駄に時間をかけることなく、思考停止もせず、エラーを解決することができました。
運よく、僕の専属のメンターさんは非常にお優しい方で
とてもやりやすかったです。


2つ目、継続できる

プログラミングは継続が大事といいますが、本当にそうだと思います。
独学だと挫折しやすいです。ほんとに。
まぁ現に僕も挫折しましたし、笑
プログラミングの独学で挫折する確率は90%と言われています。
プログラミングスクールって結構お金かかりますよね？
でもスクールに行くと、損したくない気持ちが出てくるおかげで、より継続しやすいと思います。
スクールには、受講生を継続させるシステムも整ってますし。

とまぁ、こんな感じで、
すぐ聞ける、継続できる

という点が非常に良かったかなと、僕は思います。

結論、
***プログラミングスクール行って良かった。***

なるべく早く結果を出したい人や、プログラミングで何か高い目標がある人は、
プログラミングスクールに行くことを僕はオススメします！

ちなみに、僕は
「テックアカデミーのWebアプリケーションコース」
で、12週間のプランでした。

一応リンク貼っておきますね！
テックアカデミーのリンクはこちら　☞　https://techacademy.jp/

長くなりましたが、最後まで読んでくださりありがとうございました！
RustでAtcoderを解くときに使う処理を書いていく

# 初めに
PythonでAtcoderを解いていた私が、Rustの習得のためA,B問題を取り組んだ時にググったりほかの人のコードで参考にした処理をまとめる。

# 制御系
## if~else if~else
```
if a < 10 {
    // 処理a;
} else if a > 10 {
    // 処理b;
} else {
    // 処理c;
}
```

## while
```
while a > 0 {
    a -= 1;
}
```

# 配列操作
## 空Vecの宣言
```
let mut ans = Vec::new();
```

## Vecを0で初期化する
```
let mut rec =  vec![0; n+1];
```

## Vecの長さを取得(sum)
```
println!("{}", ans.len());
```

## Vecの合計をとる（sum）
```
let ans:i64 = a.iter().sum();
println!("{}", ans);
```

## Vecの最大値・最小値をとる（i64, max,min）
iter().max()の帰り値はOptions型で、unwrapで値を取り出す

```
println!("{}", k-x.iter().max().unwrap());
println!("{}", k-x.iter().min().unwrap());
```

### 参考
https://qiita.com/tatsuya6502/items/cd41599291e2e5f38a4a

## 数値計算
### float(f64)型
#### 数値を丸める(roud)
```
    let mut n:f64 = 100.0;
    let interest:f64 = 1.001;
    while n < x {
        n = (n*interest).round()/1.0;
    }

```

### 累乗
```
let b: i64 = 2;
println!("{}", b.pow(2));
```

# 文字列操作

## 入力
input!マクロを使う
```
input!{
    s: String,
}
```

## スライス
```
let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6..11];
```

### 参考
https://doc.rust-jp.rs/book/second-edition/ch04-03-slices.html


## n文字目を取り出す

```

```


### 参考
https://qiita.com/7ma7X/items/7fb68395984958987a54


# 型変換
ここが参考になる
https://qiita.com/smicle/items/29a4d5d1d14ad7f77f60
"0x80131500"エラーが出てMicrosoftStoreが開けない場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576356/736685d4-db66-0799-4d2b-f5a898e8d737.png)

1. Win + Rキーを押してinetcpl.cplを入力して[OK]。
2. [詳細設定]タブをクリックして、[TLS 1.2を使用]オプションにチェックマークを付ける。
DynamoDBのデータをnode.jsのReadableStreamに流す

DynamoDBテーブルのデータをざーっと `ReadableStream` に流し込みたかったが、どうやってバックプレッシャーに対応すればいいのか分からなかったので対応させてみた。

# やりたいこと

- DynamoDBからデータを読み込む(基本は内部バッファサイズ分)
- `ReadableStream` にpush
- ひたすら読み込んではpush
- 詰まったら一時停止
- 次回開始位置をpushしきれなかったアイテムに設定
- またpushできるようになったら続きから読み込み再開
- 以下繰り返し
- 全て読み込んでpushし終わったら処理終了

# DynamoDBのQuery/ScanとLimit

DynamoDBのQuery/Scan操作では `Limit` を指定することで取得件数を制限することができる。
ただ `Limit` は検索結果の件数制限でなので、`QueryFilter` や `ScanFilter` を掛けると検索結果がさらにフィルタリングされ指定した件数より少ない件数が返ってくる場合がある。

クエリーで検索し、指定件数分の結果が揃ったら、クエリーフィルターでさらに絞る、というのはDynamoDBに限らずよくあるのでおそらく同じ動作なんだと思う。

まぁこれは `Limit` を指定してもフィルターを指定すると思ったとおりの件数は返ってこないですよ、という注意事項。

# DynamoDBのページネーション

DynamoDBのQuery/Scanは読み込みサイズが1MBを超えるとそこで帰ってくる。`Limit` を指定した場合も途中で帰ってくる。
まだ全てのデータを読み込み終えてない場合、次ページを取得するための開始地点がレスポンスに含まれる。
レスポンスに含まれる `LastEvaluatedKey` を次回Query/Scan時のリクエストに `ExclusiveStartKey` として含めれば次ページを取得できる仕組みになっている。

`LastEvaluatedKey` は実際にはプライマリーキー(パーティションキーあるいはパーティションキーとソートキーの組み合わせ)のオブジェクトである。
なので `LastEvaluatedKey` でなく、レスポンスに含まれるアイテムの何番目かをぶち込めば次回の読み込み開始位置はその項目の次からになる。なった。

これを利用して、`ReadableStream` にpushしている途中で `ReadableStream` の内部バッファが一杯になった場合は、入り切らなかった次のアイテムを読み込み開始位置として `ExclusiveStartKey` に設定することにした。

# ReadableStreamのハイウォーターマーク

`ReadableStream` は内部バッファを持っていて、そのサイズ＝閾値をハイウォーターマーク(HWM)という。
オブジェクトモードの場合はデフォルトで `16` に設定されている。
データを `push` し続けてHWMに達すると、

- `push` が `false` を返す
- `_read` が呼ばれなくなる

それで内部バッファに空きがでると再び `_read` が呼ばれるらしい。
また `push` が `false` を返しても内部バッファには詰め込まれてた気がする。たしか。HWMが上がるんだったかな・・・

ということで、Query/Scanで取得したデータをpushしてる最中に `false` を返した場合はそこで処理を中断し、次のアイテム以降は残念ながら次回のQuery/Scan時に再取得することにした。

# 諸々踏まえて

最終的にこんな感じの実装になった。
切り貼りしてたのでこのままでは動かないかも。雰囲気を感じ取って欲しい。

```js
class DynamoDBStream extends stream.Readable {
    :
  _read(size) {
    // 何度も呼ばれるので
    if (!this.#querying) {
      this.#querying = true;
      this.#params.Limit = size || this.hwm;
      this._query(this.#params);
    }
  }
  // HWMに達するまで再帰的にQueryを実行する
  _query(params) {
    const recursiveQuery = (params) => {
      // AWS.DynamoDB.DocumentClient.query()
      this.#ddb.query(params, (err, data) => {
          :
        let abort = false;
        for (const item of queryResult.Items) {
          // HWMに達したらそのitemまで処理済みとし次回の開始位置を指定して中断
          if (!this.push(item)) {
            params.ExclusiveStartKey = item;
            abort = true;
            break;
          }
        }
        // 中断したら次の読み込み要求を待つ
        if (abort) {
          this.#querying = false;
        // 次ページがなかったら処理終了
        } else if (typeof queryResult.LastEvaluatedKey === "undefined") {
          this.push(null);
          this.#querying = false;
        // 中断せず、次ページがあれば続けて次ページを取得
        } else {
          params.ExclusiveStartKey = queryResult.LastEvaluatedKey;
          recursiveQuery(params);
        }
      });
    }
    recursiveQuery(params);
  }
    :
}
```

# 余談: DynamoDBのコスト

リクエスト単位で課金される。また、結果整合性のある読み込みが一番安い。
`Limit` を小さく指定しすぎるとリクエスト数が増えてしまい、ちゃりんちゃりん課金されてしまう。

かと言って、あんまり `Limit` を大きくしてしまうと、詰め込みきれなかったデータが無駄になってしまうのでうまく調整しないといけない。

頻繁にリクエストが細分化してしまう場合は、いっそのことStreamとは別にバッファを持ったほうがいいかもしれない。
【Git】PortableGit→GitBucket(Gitlab等)にpushする際に「Authentication failed」が表示された場合の対応

# はじめに
職場のPC(Windows10)のPortableGit→GitBucketにpushしようとしたところ、「Authentication failed」が表示されpushできませんでした。
こちらの原因と解決方法についてアウトプットしていきたいと思います。

# 環境

|  項目  |  内容  |
| ---- | ---- |
|  PC  |  Windows10  |
|  ローカルリポジトリ  |  PortableGit  |
|  リモートリポジトリ  |  GitBucket  |

# 状況

- PortableGit→GitBucketにコードをpushしようとしたところ、認証エラーが表示されpushできず。


```bash
fatal: Authentication failed for 'http://192.168.0.150:8080/git/satton-test/test-code.git'
```
※そもそもユーザー名とパスワードが聞かれない。

- GitBucket→PortableGitへはコードのpull/clone可能

- 初期設定に間違いがないことは確認済み

```bash
git config --global user.name "satton-test"
git config --global user.email "<email address>"
```

# 原因

資格情報マネージャーの資格情報のユーザー名/パスワードに誤りがあった。
(コントロールパネル→ユーザーアカウント→資格情報マネージャー)

![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/29be91a9-e939-f2f8-76b7-8f0261cd6e86.jpeg)


# 対策

正しいユーザー名とパスワードに修正する。

![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/8fad338f-388c-5494-59f4-e20698128393.jpeg)


# 所感

インターネット上を探しても、ほぼ情報が落ちていなかったために苦労しました。。。

# 参考リンク
[GitLabからクローンしようとして認証失敗する場合の対応例](https://www.backyrd.net/entry/20190110/1547101414)
TextViewの編集箇所がキーボードで隠れないようにする

このコードをコピーするだけで実装できます。

```Swift
override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let notificationCenter = NotificationCenter.default
            notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
            notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}

@objc func adjustForKeyboard(notification: Notification) {
        guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
        let keyboardScreenEndFrame = keyboardValue.cgRectValue
        let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
        
        if notification.name == UIResponder.keyboardWillHideNotification {
            textView.contentInset = .zero
        } else {
            //textViewの下にキーボードの高さ分の余白を作る
            textView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)
        }
        //スクロールインジゲーターが表示される長さ
        textView.scrollIndicatorInsets = textView.contentInset
        //編集箇所の高さ
        let selectedRange = textView.selectedRange
        //編集箇所が見えるようにする
        textView.scrollRangeToVisible(selectedRange)
    }
```

コメントで説明を書いていますが、Swiftの経験が浅いため、間違いがあるかもしれません。
[英語の記事](https://www.hackingwithswift.com/example-code/uikit/how-to-adjust-a-uiscrollview-to-fit-the-keyboard)
4DからTelnet端末を制御したい

# 4DからTelnet端末を制御したい

## 背景

WiFiブリッジホストの古いヤツ、ヤマハルーターの古いヤツ、ネットワークカメラの古いヤツ、PoEハブの古いヤツ。これらをモニタリングして状況に応じて再起動をかけたいので昔はPerl Net::Telnetモジュールを使ったりしていた。そちらを使えばイイのだが端末の設定しまくって → 破損 → リプレイス → 設定手順忘れた・・・とか泣けてくる。大体コレが起こるのが数年後の忘れた頃w


## 4D Serverなら

4D Serverならアプリを別端末に移動して起動すると、まるっと環境は元通り。4D Serverに監視と再起動を任せるためTelnetコンポーネントを作ってみた。ログインしてコンフィグやログを取ったり再起動かけたりする単純なコマンドなら動くようになったみたい。

ちなみに・・・CUIなどうしても使いたいコマンドなどは、4D ServerのストラクチャーのResourcesに放り込んでおくとクライアントが接続した時に自動的に配信される仕組みがあって便利。ffmpegとかImageMagickとか自前で作ったexeとかdllとか放り込んでおくと、クライアントへのインストールが不要で決まったパスでアクセスできる。

## 内容

4D標準コマンドと、InternetCommands PluginのTCPローレベルコマンドで処理構成されています。
BLOBデータを送受信してエンコーディングはShift_JISのみ想定だったかな。

## 使い方

ヤマハのルーターに接続してコンフィグ取ってきたりリスタートしたり、使い方はこんな感じ。

### コンフィグ取得

```Pascal

C_OBJECT($obj)
ARRAY TEXT($arrLines;0)

OB SET($obj;"HOST";"192.168.0.1";"PORT";23)  //ホストアドレスとポートの設定
OB SET($obj;"USER";"";"USER_PROMPT";"")  //ユーザー名なし、明示的にユーザー名とプロンプトを無しにするとスキップ
OB SET($obj;"PASS";"hogehoge";"PASS_PROMPT";"Password:")  //パスワードとパスワードプロンプト
OB SET($obj;"PROMPT";">";"MORE_PROMPT";"---")  //通常のコマンド待ちプロンプトと、ページングプロンプト
If (True)
	$err:=Telnet_clinet (->$obj;"connect")  //オブジェクトの内容で接続、自動ログインまで実施www
	If ($err=0)
		$err:=Telnet_clinet (->$obj;"command";"show config")  //コマンドとして、show configを実行
		OB GET ARRAY($obj;"LINES";$arrLines)  //コマンドの戻り値がLINESとして文字列配列になっている。
		$err:=Telnet_clinet (->$obj;"disconnect")  //切断、デフォルトのexitコマンドが実行されTCP_Closeされる。
		ALERT(Array_join (->$arrLines;Char(13)))
	Else 
		ALERT("接続できません。\n"+JSON Stringify($obj;*))
	End if 
End if 
```

### リスタートする場合

```Pascal

If (True)
	$err:=Telnet_clinet (->$obj;"connect")  //オブジェクトの内容で接続、自動ログインまで実施www
		$prompt:=""  //プロンプト待ちは明示的に無し（こうしておかないとコマンド実行後の待ち受け状態になってしまう）
		$err:=Telnet_clinet (->$obj;"command";"restart";$prompt)
		OB SET($obj;"LOGGED_IN";False)  //リスタートなのでログイン状態は強制解除（こうしておかないとdisconnect時にexitしようとして固まる）
		$err:=Telnet_clinet (->$obj;"disconnect")  //TCP_Close実行しなきゃね。
	Else 
		ALERT("接続できません。\n"+JSON Stringify($obj;*))
	End if 
End if 
```

オブジェクトは参照渡しできるのでポインタ渡しする必要は無いけど、先に設定配列渡しとかでコード作ってた残骸かな。

### ダウンロード

[こちらから](https://www.dropbox.com/sh/k0q1aczkcbby0qc/AAD3-ChUbWuE0f5s1PtCwJxaa?dl=0)ダウンロードできます。v16〜v18の適宜バージョンの合ったものをダウンロードしてください。
[4Dのダウンロードはこちら](https://jp.4d.com/4d-free-trial)より。

## 問題点

特に認識していませんが、おそらく複雑なコマンドを処理させようとすると問題が出ます(*^ｰ^)。テストしてマトモに動いているのは先のコンフィグ取得と再起動くらいですw トラブルが発生しても責任は負いかねます。自前で拡張／改修／解決をご希望の場合はご連絡ください。
React Contextのメモ

親コンポーネントのstateの値を、孫コンポーネントのpropsの値として使う場合はこのような書き方になる。

```index.js
import React from "react";
import ReactDOM from "react-dom";

/*　親 -> 子 -> 孫 -> .. の順に値を渡すことをバケツリレーと呼ぶ(親のstateの値を孫やひ孫のpropsにする) */
class Grandchild extends React.Component {

    render() {
        return(
            <div>{this.props.text}</div>
        )
    }

}

class Child extends React.Component {

    render() {
        return(
            <Grandchild text={this.props.text} />
        )
    }

}

class Parent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {"text": "まんち"};
    }

    render() {
        return(
            <div><Child text={this.state.text} /></div>
        )
    }

}

ReactDOM.render(<Parent />, document.getElementById("app"));
```

バケツリレーをせずに、親コンポーネントから直接孫やひ孫のコンポーネントに値を渡すのがContext(子コンポーネントにも渡せる)
関数コンポーネントの場合はpropsが存在しないのでこの書き方一択になる？


```index.js
import React, {useState, createContext, useContext} from "react";
import ReactDOM from "react-dom";

var Context = createContext(); 

var GrandChild = function() {

    //受け取った値が文字列ならその文字列が、配列ならその配列がそのまま渡される
    var arr = useContext(Context);　
    return(
        <div>
            <p>{arr[0]}</p>
            <p>{arr[1]}</p>
        </div>
    )

}

var Parent = function() {

    var [cnt, addCnt] = useState(0);
    var [numState, switchNumState] = useState("偶数");

    function onClick(num) {
        num += 1;
        addCnt(num);
        if (num % 2 === 0) {
            numState = "偶数";
        } else {
            numState = "奇数";
        }
        switchNumState(numState);
    }

    return(
        <>
          <div>
            {/* providerコンポーネントの作成 value=渡す値 渡す値は文字数字などの単体の値やオブジェクトでも良い */}
            <Context.Provider value={[numState, cnt]}>
                <GrandChild />
            </Context.Provider>
            <input type="button" value="連打しろ!!" onClick={() => onClick(cnt)} />
          </div>
        </>
    )

}

ReactDOM.render(<Parent />, document.getElementById("app"));
```
【Python】numpyでの計算方法

##numpyでの計算

numpyを使用して0~10の配列を作ります。

```
import numpy as np

arr = np.arange(11)

arr
```

```実行結果.
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
```

sqrtメソッドを使用することで各数字の平方根の計算できます。

```
np.sqrt(arr)
```

```実行結果.
array([ 0.48273727, -1.28739284,  1.52422575, -1.73666091, -0.25126809,
       -0.41952278, -0.75042054, -0.64585434, -0.86014472, -0.44542315])
```

random.randn()で正規分布(平均=0,分散=1)の乱数を計算することができます。

```
A = np.random.randn(10)
```

```実行結果.
array([-0.94897439, -0.43075947,  0.088691  ,  0.37859721, -0.2141078 ,
        1.30327378,  0.41654781, -0.42907224, -1.61139916, -0.651694  ])
```

addメソッドを使用することで足し算をすることができます。

```
B = np.random.randn(10)

B

array([ 0.05623043,  1.97843447, -0.02581691,  0.70663108,  0.51213852,
       -0.70386143,  1.50729471, -0.00577632, -1.08456477, -0.38103167])

np.add(A,B)
```

```実行結果.
array([ 0.5389677 ,  0.69104164,  1.49840884, -1.03002983,  0.26087043,
       -1.1233842 ,  0.75687417, -0.65163066, -1.94470949, -0.82645482])
```


subtractメソッドで引き算ができます。

```
np.subtract(A,B)
```

```実行結果.
array([ 0.42650684, -3.26582731,  1.55004266, -2.44329199, -0.76340661,
        0.28433865, -2.25771524, -0.64007803,  0.22442006, -0.06439147])
```

multiplyメソッドで掛け算ができます。

```
np.multiply(A,B)
```

```実行結果.
array([ 0.02714452, -2.54702237, -0.0393508 , -1.22717858, -0.12868407,
        0.2952859 , -1.1311049 ,  0.00373066,  0.93288266,  0.16972033])
```

divideメソッドで割り算ができます。

```
np.divide(A,A)
```

```実行結果.
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
```
競技プログラミング練習記 No.60【ABC103練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC103](https://atcoder.jp/contests/abc103)を解きました。
4完です！

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  3min |-| 8ms|
| B | 11min |-| 6ms|
| C | 12min |mod| 7ms|
| D | 27min |-| 41ms|

# まとめ
先にまとめを載せます。これ自体は最後に書いてます。

`std::max`関数と`std::min`関数は引数にタプルを指定すると3要素以上の比較ができます。



## A - Task Scheduling Problem
```c++
  int a1, a2, a3;
  cin >> a1 >> a2 >> a3;
  cout << max({a1, a2, a3}) - min({a1, a2, a3});
```
3つの入力値の中から最大のものと最小のものとの差が答えになります。
`std::max`関数と`std::min`関数は引数にタプルを指定すると3要素以上の比較ができます。

## B - String Rotation
``` c++
  string s, t;
  cin >> s >> t;

  for(int d = 0; d < s.length(); ++d)
  {
    if (s[0] != t[d]) continue;
    bool ok = true;
    for(int i = 0; i < s.length(); ++i)
    {
      ok &= (s[i] == t[(i + d) % s.length()]);
    }
    if (ok)
    {
      cout << "Yes";
      return;
    }
  }
  cout << "No";
```
スマートに解けそうなのですが、よくわからなかったので全探索しました。
文字列`t`を`d`文字ずらしたものが文字列`s`と一致していたら "Yes" を出力します。

## C - Modulo Summation

``` c++
  int n, a;
  cin >> n;
  ll ans = 0;
  for(int i = 0; i < n; ++i)
  {
    cin >> a;
    ans += a - 1;
  }
  cout << ans;
```
`m`を全入力の最小公倍数に設定すれば答えは最大化できます。

そして実は最小公倍数は求めなくてもいいです。
`m`が最小公倍数の時は $\ \ m\ \ mod\ \ a_i\ =\ a_i-1\ \ $ という決まった数値になります。
そのため、入力値から`1`を引いたものの和が答えになります。

その点に気付かずに最小公倍数を求めてオーバーフローし、1WAしました。


## D - Islands War
``` c++
  int n, m, ina, inb;
  cin >> n >> m;
  vector<vector<int>> a(n + 1, vector<int>());
  for(int i = 0; i < m; ++i)
  {
    cin >> ina >> inb;
    a[ina].emplace_back(inb);
  }

  const int INF = 1 << 30;

  int border = INF;
  int ans = 0;
  for(int i = 0; i < n; ++i)
  {
    if (border <= i)
    {
      ans++;
      border = INF;
    }
    if (a[i].size() == 0) continue;
    border = min(border, *min_element(a[i].begin(), a[i].end()) );
  }
  ans += (border != INF);
  cout << ans;
```
各入力は $a_i < b_i$ より、 $a_i$ を始点、$b_i$を終点とします。
始点が同じとき、終点が最小のものが条件を満たすように橋を落とせば、始点が同じ入力は全て条件を満たしますね。
つまり、始点が同じもの同士をまとめて、そのなかで終点が最小のものだけを見ればいいです。
落とすべき橋の最小位置を記録しながら始点を次々とみていって、みている始点が橋を落とす位置を超えた時に答えをカウントします。
このやり方だと$O(N + M)$ で解けます。

以上です。ありがとうございました。
Linuxでts-node-devを使うときに、エラー `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` が発生したときの対処法

## 発生したエラー

```
TypeError [ERR_FEATURE_UNAVAILABLE_ON_PLATFORM]: The feature watch recursively is unavailable on the current platform, which is being used to run Node.js
    at Object.watch (fs.js:1470:11)
    at add (/home/reoring/git/yyts/yychat-server/node_modules/filewatcher/index.js:74:34)
    at /home/reoring/git/yyts/yychat-server/node_modules/filewatcher/index.js:93:5
    at FSReqCallback.oncomplete (fs.js:177:5)
```

## 対処法

node-devの起動オプションに`--poll`を追加する。

```
  "scripts": {
    "start:dev": "ts-node-dev --poll src/index.ts",
  },
```

## 参考

[How to fix: The feature watch recursively is unavailable on the current platform, which is being used to run Node.js](https://stackoverflow.com/questions/61806341/how-to-fix-the-feature-watch-recursively-is-unavailable-on-the-current-platform)
Vue Apolloを@vue/apollo-composableに書き換える

[株式会社iCARE](https://www.icare.jpn.com/)のプロダクト[Carely](https://www.carely.jp/)のフロントエンド環境は、Vue.js + GraphQL([Vue Apollo](https://apollo.vuejs.org/guide/)を利用)で構成されています。

Carelyでは、今絶賛、Option APIから[Composition API](https://composition-api.vuejs.org/#code-organization)への移行中です。

その中でVue Apolloに関しても、Composition APIに合わせて、Vue Apollo v3から[@vue/apollo-composable](https://www.npmjs.com/package/@vue/apollo-composable)(Vue Apollo v4)に移行していますが、そこでどのように変わるのか、どんなメリットが生じるかについて書きたいと思います。

情報ソースは主に以下を利用しています。
https://apollo.vuejs.org/guide/
https://v4.apollo.vuejs.org/guide-composable/

これから移行を検討しているエンジニアの皆様の参考になれば幸いです。

# クエリの書き方

## v3の場合

```js
apollo: {
  users: gql`
    query getUsers {
      users {
        id
        name
      }
    }
  `,
},
```
のように「オプション」でクエリを定義すると、テンプレートでクエリの結果`users`を参照することができます。
この際、クエリの結果を`users`で参照するためには

```js
data () {
  return {
    users: [],
  },
},
```
のように`data`オプション内で`users`を初期化しておく必要があります。

## v4の場合

```vue
<script>
import { useQuery } from '@vue/apollo-composable'
import gql from 'graphql-tag'

export default {
  setup () {
    const { result } = useQuery(gql`
      query getUsers {
        users {
          id
          name
        }
      }
    `)

    return {
      result,
    }
  },
}
</script>
```

オプションではなく、`useQuery`関数を使ってクエリを実行します。
`setup()`の戻り値に`result`を含めることでテンプレートから`result`を参照できます。
v3と異なりクエリの結果を受け取る変数を事前に、`data`オプションで初期化する必要はありません。

```vuejs

<template>
  <ul>
    <li v-for="user of result.users" :key="user.id">
      {{ user.name }}
    </li>
  </ul>
</template>
```

# v3とv4で大きく異なる点（主観）

## マルチルートのクエリへの対応
```js

query getCatsAndDogs {
  cats {
    id
  }

  dogs {
    id
  }
}
```
といったクエリの結果を受け取る場合、v3の場合は、クエリの結果が自動的に`data`オプションで指定したオブジェクトのプロパティにマップされるため、デフォルトではこの結果をうまく受け取ることができません。

v4の場合は、マルチルートの結果は、`useQuery`の戻り値のプロパティとして受け取ることができるため、特段の迂回策を取らずに受け取ることができます。

## useResult

v4には`useQuery`と並んで`useResult`があり、クエリ結果に対して柔軟にアクセスすることができるようになっています。

```js
const { result } = useQuery(gql`
  query getMessages {
    currentUser {
      messages {
        id
        text
      }
    }
  }
`)

const messages = useResult(result, null, data => data.currentUser.messages)
```

上記のように`useResult`を使って結果を取得した場合、`result.values`が`undefined`だとしても、`useResult`の関数の中でエラーが出ないように実装されているので

```js
const messages = useResult(result, null, data => data && data.currentUser && data.currentUser.messages)
```

のように子要素の存在チェックをする必要はありません。

また、この様に簡単に処理を分けることもできます。

```js
import { useQuery } from '@vue/apollo-composable'
import gql from 'graphql-tag'

function useGetMessages() {
  const { result } = useQuery(gql`
    query getMessages {
      currentUser {
        messages {
          id
          text
        }
      }
    }
  `)

  return useResult(result, null, data => data.currentUser.messages)
}

export default {
  setup () {
    const messages = useGetMessages()
    return { messages }
  }
}
```

その他にも様々な点での仕様の変更があり、v3と比較してv4はいろいろな点で使いやすくなっている印象を受けました。


# 参考サイト
https://apollo.vuejs.org/guide/
https://v4.apollo.vuejs.org/guide-composable/
Railsでkaminariを使う

#プログラミングの勉強日記
2020年7月31日　Progate Lv.226

#概要
　[こちらの記事](https://qiita.com/mzmz__02/items/61423e7259c4624f3010)で扱ったgemのkaminariを説明する。kaminariは1つのページに掲載するコンテンツが増えたときに複数ページに分けて表示させる<font color=orange>ページネーション</font>を簡単に実装することができる。

<img width="482" alt="0731.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/e9994150-b92a-36f8-9944-cc32cb469a33.png">
　ページネーションを使うことで、情報量の多いサイトをまとめられるということだけではなく、表示される項目が一定数を超えると自動的に次のページへ内容を移行することもできるので便利である。


#使い方
　kaminariを使うためにGemfileを編集する。

```:Gemfile
gem 'kaminari'
```
　Gemfileを編集したら、kaminariをインストールする。

```:ターミナル
bundle install
```
　これでkaminariで定義されたメソッドや機能を使うことができるようになる。

#ページネーションの定義
　コントローラとビューでページネーションが表示されるようにする。

```ruby:controllerファイル
def index
  @users = User.page(params[:page]).per(10)
end
```

```erb:ビューファイル
<%# ページネーションの表示 %>
<%= paginate @users %>
```


#見た目の変更
　kaminariで表示されるページネーションはビューの中でCSSを適用させることはできない。なので、見た目を変えたい場合は`app/view/kaminari`フォルダを作り、その中にページネーションの部分のHTMLが記述されているようにターミナルで以下のコマンドを実行する。

```:ターミナル
$ rails g kaminari:views default
```

#Bootstapに合わせる
　bootstrap用にカスタマイズすることもできる。このためにはもう一度Gemfileを変更する。

```:Gemfile
gem 'kaminari-bootstrap', '~> 3.0.1'
```
　Gemfileを編集したら、インストールする。

```:ターミナル
bundle install
```

　そして、`config/config/locales/kaminari_ja.yml`を追加して編集する。

```yml:config/locales/kaminari_ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "..."
```
今日のメモ(パーセント記法、文字列演算、シンボル)

#パーセント記法
『'』や『"』で囲んできた文字列を、パーセント記法では囲む記号を指定できる。
文字列の中で『"』を使うときにエスケープしなくてもよくなる。
####例
```
#『"』無し
a = %*TEST*
p a  #=> "TEST"

#『"』あり
a = %*"TEST"*
p a  #=> "\"TEST\""
```

| 書式       |       生成される値 |
|:-----------------|------------------:|
| %             | ダブルクォート文字列 |
| %Q           | ダブルクォート文字列 |
| %q             | シングルクォート文字列 |
| %s               | シンボル |
| %x             | コマンド出力 |
| %r          | 正規表現 |

#文字列演算
文字列では『＋』と『＊』を適用して連結することができる。

```
a = "ru" + "by"
puts a    #=> ruby
```

他にも末尾に連結する場合は『<<』も使用することができる。

```
a = "ru"
puts a << "by"    #=> ruby
```
**※ですが、異なる文字コード(UTF-8とSJISなど)の連結はエラーが発生します。**

追記:文字列の比較はlengthやsizeメソッドで文字数を参照できます。

#シンボル
シンボルは主に文字列の前に『:』を置いて定義したもの。
ただし『"』で文字列を囲む必要は無い。

```
a = "ruby"
b = :study
 
p str.class    #=> String
p sym.class    #=> Symbol
```
パーセント記法を使ってもシンボルを生成することができる。

```
%s*test*    #=> :test
```

文字列からシンボルを生成する方法

```
a1 = "test"
a2 = a1.to_sym    # to_symメソッドを使用
p a2.class    #=> Symbol
```

作成したシンボルは、文字の並びが同じなら同一のオブジェクトIDを参照しますが、
文字列リテラルの場合は、文字の並びが同じでも、毎回新たにオブジェクトを生成するのでオブジェクトIDが変化します。
【Effective Javaを読む】　第３章　項目１２　『Comparableの実装を検討する』

#Comparableの実装を検討する

他のメソッドとは異なりcompareToメソッドはObjectでは宣言されていません。
正確に言えば、compareToメソッドはComparableインターフェースの唯一のメソッドです。
アルファベット順、数値順、年代順などの明らかに自然な順序を持つ値クラスを書くのであれば、ちょっとの努力で恩恵が受けられるのでComparableを実装しましょう。

##サンプルコード
```java
public int compareTo(PhoneNumber pn) {
    //市外局番を比較する
    if (areaCode < pn.areaCode)
        return -1;
    if (areaCode > pn.areaCode)
        return 1;

    //市外局番は等しく、市内局番の前半を比較する
    if (prefix < pn.prefix)
        return -1;
    if (prefix > pn.prefix)
        return 1;

    //市外局番と市内局番の前半は等しく、市内局番の後半を比較する
    if (lineNumber < pn.lineNumber)
        return -1;
    if (lineNumber > pn.lineNumber)
        return 1;
    
    return 0; //全てのフィールドが等しい
}
```
LGTMを集めやすい記事とは

Articles that reach everyone.
===

誰でも読める記事はLGTMが付きやすいです。
例えばGit関連の記事を眺めていると、尖った記事よりも、平易で誰でも読めるボトムな記事にLGTMが集まっている事に気づきます。

# The river never rises.

難しい記事は庶民には読めないので、LGTMが付き難いのです。
難しい記事にLGTMを付けている人は、優秀な人です。

# Get ahead of others
https://x.com/__muell__/status/1862500678008283495
![IMG_89D5392CCB6D-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67460/77a15eb9-6e72-3604-7332-9b7c9cfe3370.jpeg)