OmniAICreator/Qiita-1.07M huggingface dataset:
Goで構造体をシリアライズしてURLパラメーターに付与する

## お詫び
AdventCalendarの21日目の記事なのですが、筆者がコロナになってしまって書ききれなかったので途中ですが公開だけいたします………。
残りは動けるようになってから仕上げます。

## この記事について
こちらの記事は[CyberAgent AI tech studio | Go Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ca-ai-go)の21日目の記事です。


## 筆者について
筆者は業務で書くGo歴は2ヶ月くらいで割とペーペーな部類です。
前職ではPHPを主に書いていたのですが、転職を機にGoを使い始めそのタイミングで社内のAdvent Calendarが開始されたので思い切って参加してみました。
記事内容に対する意見、提案、改善等大歓迎です！


## 概要
業務中にURLパラメーターを用いて多めの値を受け渡しするという要件に遭遇しました。
単純に`https://example.com?a=a&b=b&c=c&d=d....`とすべての値を羅列する方法も当初は考えました。
ただ、**エンドユーザーには渡されている値がわからないようにする**という要件もあったため、URLパラメーターは1つにまとめ、そこに構造体をシリアライズ&暗号化することにしました。
今回はそのシリアライズ部分について記事にしたいと思います。

## 仕様
- URLパラメーターに受け渡す値のフィールドを持った構造体をシリアライズしたものを入れて、値の受け渡しを行う
    - 例)`https://example.com?values=${seriarized_struct}`
- 受け渡された値はエンドユーザーにわからないようにする
    - 暗号化で対応(記事のスコープには含めません)
- シリアライズされた構造体はBase64でエンコードされている
- 各値は渡されないこともあり、渡されなかったこととGoのゼロ値の値で渡されたことを区別する
    - 渡されなかった場合はゼロ値で初期化せずに`nil`とする
    - 値は0で渡された場合に0となるが、渡されなかった場合は0ではなくnilとする

## シリアライズ方法の候補
### Protobuf
まず一番最初に考えたのはProtobufでした。
Protobufを考えたのは単純に使ったことなかったから使ってみたいとか単純な理由で導入を考えていました。
ただ、Protobufは要件に対して少しオーバースペック気味でした。
やりたいことはただ**構造体をシリアライズして文字列でやり取りすること**だったので、「渡す側も受け取り側もGoなのにプログラム言語から独立した.protoファイルを書いたりするくらいならGoに組み込まれているgobやjsonのほうが良いのでは？」となりProtobufは見送りました。

### encoding/gob
coming soon

### encoding/json
coming soon
パラメータの変更

# はじめに
にゃーん。趣味でポスグレをやっている者だ。

この記事はPostgreSQL 16 全部ぬこ Advent Calendar 2022 24日目の記事です。

今回はCommitfest個々の項目ではなく、PostgreSQLパラメータ全般の変更状態を調べてみました。
なお、あくまでも開発途中のものなので、beta版リリースのときには、これよりも大きく変わっている可能性は高いです。

# 比較対象

今回の記事は、以下のバージョン間のシステムカタログ・ビューの変更状態を調査しました。

* PostgreSQL 15.1
* PostgreSQL-devel
  * 12/20朝時点の版
  * commit eb60eb08a95eb531f3f2a459c1b623c5ac37ecd3
  * CATALOG_VERSION_NO 202212191

# パラメータの追加/変更/削除

現時点だとパラメータの変更はそれほど多くないようです。
実質的な変更は削除パラメータが1つ、追加パラメータが2つです。

|パラメータ名|種別|変更内容|
|:--|:--|:--|
|client_connection_check_interval|変更|categoryがConnection SettingsからTCP Settingsに変更|
|promote_trigger_file|削除|リカバリの完了を示すトリガファイルの名前|
|send_abort_for_crash|追加|Developer Options|
|send_abort_for_kill|追加|Developer Options|
|tcp_keepalives_count|変更|categoryがConnection SettingsからTCP Settingsに変更|
|tcp_keepalives_idle|変更|categoryがConnection SettingsからTCP Settingsに変更|
|tcp_keepalives_interval|変更|categoryがConnection SettingsからTCP Settingsに変更|
|tcp_user_timeout|変更|categoryがConnection SettingsからTCP Settingsに変更|

## promote_trigger_file
このパラメータは、PostgreSQL 12でレプリケーションの手順が変更されたことに伴い追加されたパラメータです。
このパラメータで指定されたトリガファイルを配置してPostgreSQLを起動することでpromoteモードで起動します。しかし、このパラメータを使うことなく、``pg_ctl promote``あるいは``pg_promote``を使ってスタンバイサーバを昇格することが可能でした。

ところが、PostgreSQL 16からトリガファイル自体が削除されたことに伴い、このパラメータも削除されたようです。
このパラメータの削除に関するpgsql-commiters MLのメールはこれみたいですね。
[pgsql: Remove promote_trigger_file.](https://www.postgresql.org/message-id/E1oznIt-001DZ5-Dp%40gemulon.postgresql.org)
PostgreSQL 15までpromoteの運用をトリガファイルを使っていたユーザは、この変更による運用方法の変更が必須になります。

## send_abort_for_crash/send_abort_for_kill
これらのパラメータはcategoryが``Developer Options``（開発者向けのオプション）なので、通常のユーザが使うパラメータではありません。
これらのパラメータはたぶん、以下のCommitfest項目が関連していそうです。（深追いはしてないですが）
[Commitfest 2023-01](https://commitfest.postgresql.org/41/):[Sending SIGABRT to child processes](https://commitfest.postgresql.org/41/4016/)

``send_abort_for_crash``はバックエンドのクラッシュ後に、子プロセスに SIGQUIT ではなく SIGABRT を送信するかどうかを制御するパラメータのようです。

``send_abort_for_kill``はスタックした子プロセスに SIGKILL ではなく SIGABRT を送信するかどうかを制御するパラメータのようです。


# おわりに
今回は、PostgreSQL 15とPostgreSQL 16とのパラメータ差分を調べてみました。
現時点ではそれほど大きなパラメータの差分はないようですが、トリガファイルに関連するパラメータの削除など、運用に影響するパラメータの変更もあるのでチェックはしておいたほうが良さそうですね。
爆速インデックス検索

# はじめに
こんにちは！[AI開発事業部](https://www.ambl.co.jp/ "AMBL")の須藤です。
この記事は、[Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ambl-rd "AMBL2")の21日目の記事になります。
主に画像系のアプリ開発に携わっておりますが、分析業務なども経験してきました。
この記事はpandasのテーブル検索における３つの手法とそれぞれの処理速度を比較していきたいと思います。

# 検証環境
- MacBook Pro (13-inch, M1, 2020)
- Python 3.8.12
- pandas 1.4.0
- numpy 1.22.2

# データを用意する
今回は日本郵便株式会社さんが公開している郵便番号のCSVデータを使わせていただきます。
以下のリンクからデータを取得できます。
https://www.post.japanpost.jp/zipcode/dl/roman-zip.html

# 検証開始
データを読み込みます。
```python
import pandas as pd

names = [
    "郵便番号", "都道府県名", "市区町村名", "町域名",
    "都道府県名(ローマ字)", "市区町村名(ローマ字)", "町域名(ローマ字)"
]
tbl = pd.read_csv(
    "./KEN_ALL_ROME.csv", encoding="cp932", header=None, names=names, dtype={"郵便番号": str})
```
テーブルの中身は以下のようになっていて、全部で124,541レコードありました。
![スクリーンショット 2022-12-21 20.48.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2802936/0b6bbdf4-07cf-7108-e449-9e5bb77c1cbe.png)

それではこちらのテーブルを使って、都道府県別にデータを抽出した場合の速度比較をしていきます。
検索方法は３つ用意しました
1. 比較演算子を使うノーマルな検索
例 ``` tbl[tbl["都道府県名"]=="北海道"] ```
2. queryメソッドを使った検索
例 ``` tbl.query("都道府県名=='北海道'") ```
3. indexを使った検索
例 ``` tbl2 = tbl.set_index("都道府県名").sort_index() ```
　 ``` tbl2.loc["北海道"] ```

検証コードです。
```python
import timeit

areas = tbl["都道府県名"].unique()

def func():
    """ 比較演算子を使うノーマルな検索 """
    for area in areas:
        sub = tbl[tbl["都道府県名"]==area]

def func_query():
    """ queryメソッドを使った検索 """
    for area in areas:
        sub = tbl.query("都道府県名==@area")

tbl2 = tbl.set_index("都道府県名").sort_index()
def func_index():
    """ indexを使った検索 """
    for area in areas:
        sub = tbl2.loc[area]

run_time = timeit.timeit("func()", number=10, setup='from __main__ import func')
print(f"func       = {run_time} sec")
run_time = timeit.timeit("func_query()", number=10, setup='from __main__ import func_query')
print(f"func_query = {run_time} sec")
run_time = timeit.timeit("func_index()", number=10, setup='from __main__ import func_index')
print(f"func_index = {run_time} sec")
```
３つの手法に対し、timeitモジュールで、それぞれ10回ずつ実行した合計時間を表示します。
結果はこのようになりました。
```
func       = 1.9060642909999927 sec
func_query = 0.7746682920000012 sec
func_index = 0.021593332999998438 sec
```
indexを使った検索が一番速く、ノーマルな手法に対しおよそ88倍という結果になりました。
indexを使った手法は事前に都道府県名をindexにセットしソートしておりますが、それを差し引いても十分すぎるほど速いです。

# おわりに
いかがでしたでしょうか？
本編で触れませんでしたが、個人的にはqueryがノーマルの3倍近い検索速度だったのが驚きでした。
今回はシンプルな検索条件で検証しましたが、ケースバイケースで色んな手法を使い分けていただければと思います。
本記事が少しでも参考になれば幸いです。
最後まで呼んでいただき、ありがとうございました！
【SwiftUI】キーボードツールバーを実装する

# はじめに
DeepL翻訳アプリを使用していたらキーボードの上にツールバーが表示されていたので同じように実装してみました。
![IMG_1843.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ed482a32-e094-5276-767c-3889ae3f85f9.png)

# サンプルアプリ
![Simulator Screen Recording - iPhone 14 - 2022-12-21 at 21 30 53](https://user-images.githubusercontent.com/84154073/208905758-a6a78e3b-5c8c-48ce-8a76-2a21ec8d48da.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State var text: String = ""
    var body: some View {
        TextField(text: $text) {
            Text("テキストフィールド")
        }
        .textFieldStyle(.roundedBorder)
        .padding()
        .toolbar {
            toolbarItem
        }
    }

    var toolbarItem: ToolbarItem<(), HStack<TupleView<(Button<Text>, Spacer, Button<Text>)>>> {
        ToolbarItem(placement: .keyboard) {
            HStack {
                Button {
                    text = UIPasteboard.general.string ?? ""
                } label: {
                    Text("ペースト")
                }

                Spacer()

                Button {
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                } label: {
                    Text(Image(systemName: "keyboard.chevron.compact.down"))
                        .font(.system(size: 15))
                }
            }
        }
    }
}
```

# おわり
キーボードツールバーを実装することができました
意外とキーボードが閉じられないアプリが多いのでこれは忘れないようにしたいです。
Babelの変換、多すぎ…？→bugfixes: trueで解決できるかも

必要以上にBabelの変換が入ると思ったら、Babelの裏機能とそれを制御する新機能を知ってしまいました。

## 起きていた状況

ブラウザJavaScriptをBabelで変換していたのですが、`.browseslistrc`でIE11を除外した最新設定にしているのも関わらず、Optional Chaining（`?.`）や、デフォルト引数、引数内でのスプレッドといったものが変換されてしまう状態が続いていました。

`@babel/preset-env`に`exclude`を明示すると止まるので、`@babel/preset-env`が挿入しているとわかったところでさらに調査を進めていました。

## 裏機能…ブラウザごとのバグの吸収

今回調べてみるまで知らなかったのですが、`@babel/preset-env`による変換は、ブラウザネイティブでサポートしないもの…だけではなく、ブラウザごとの**バグ回避**も含んで処理を行っていました。

ところが、`@babel/preset-env`が処理を選択できるのは、`@babel/plugin-transform-function-parameters`といったプラグイン単位であるため、ごくわずかなパターンでバグが起きる場合にもプラグインを全部入れる、ということとなってしまい、バグを踏まないコードまで変換されて冗長となる事態となっていました。

## 新機能…`bugfixes`

このような状態を解決するため、「不具合の出るところだけ変換する」ための`@babel/preset-modules`というパッケージが作られ、Babel 7.9になって`@babel/preset-env`へ組み込まれ、`bugfixes: true`という設定を行うことで利用可能となっています。

実際に設定をかけてみたところ、`?.`の変換で余計な`var`が現れたり、引数の変換で`arguments`と`function`になってしまったり、と言った箇所がきれいに解消しました。

## 参考

* [@babel/preset-envは必要なプラグインをどう判定しているのか調査した](https://qiita.com/kyntk/items/2e7432c0bb01d8d99c2a)
* [Babel 7.9のリリースノート](https://babeljs.io/blog/2020/03/16/7.9.0#babelpreset-envs-bugfixes-option-11083httpsgithubcombabelbabelpull11083)
【ルール説明・shared】meta-incorrect

こちらの記事は[Ansible lint Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ansible-lint) 21日目の記事になります。

今回はルール [meta-incorrect](https://ansible-lint.readthedocs.io/rules/meta-incorrect/) について説明します。

### meta-incorrect

[meta-incorrect](https://ansible-lint.readthedocs.io/rules/meta-incorrect/) は metadata が初期の値ではないか、もしくは値が設定されているかを検証します。metadata に関しては [12日目の記事](https://qiita.com/mamono210/items/a52e16bee771772a7b5f) に概要を載せてあります。

[meta-incorrect](https://ansible-lint.readthedocs.io/rules/meta-incorrect/) は現在のところは Ansible galaxy role の metadata のみを検証するようです。

#### Roleの作成

以下のコマンドでRoleを作成します。

```bash
ansible-galaxy init <role-name>
```

初期化に成功すると以下のようなファイル群が生成されます。

```bash
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml
```

[meta-incorrect](https://ansible-lint.readthedocs.io/rules/meta-incorrect/) はこのファイルのうち`meta/main.yml`の検証を行います。

以下は初期状態の`meta/main.yml`です。

```yaml:meta/main.yml
galaxy_info:
  author: your name
  description: your role description
  company: your company (optional)

  # If the issue tracker for your role is not on github, uncomment the
  # next line and provide a value
  # issue_tracker_url: http://example.com/issue/tracker

  # Choose a valid license ID from https://spdx.org - some suggested licenses:
  # - BSD-3-Clause (default)
  # - MIT
  # - GPL-2.0-or-later
  # - GPL-3.0-only
  # - Apache-2.0
  # - CC-BY-4.0
  license: license (GPL-2.0-or-later, MIT, etc)

  min_ansible_version: 2.1

  # If this a Container Enabled role, provide the minimum Ansible Container version.
  # min_ansible_container_version:

  #
  # Provide a list of supported platforms, and for each platform a list of versions.
  # If you don't wish to enumerate all versions for a particular platform, use 'all'.
  # To view available platforms and versions (or releases), visit:
  # https://galaxy.ansible.com/api/v1/platforms/
  #
  # platforms:
  # - name: Fedora
  #   versions:
  #   - all
  #   - 25
  # - name: SomePlatform
  #   versions:
  #   - all
  #   - 1.0
  #   - 7
  #   - 99.99

  galaxy_tags: []
    # List tags for your role here, one per line. A tag is a keyword that describes
    # and categorizes the role. Users find roles by searching for tags. Be sure to
    # remove the '[]' above, if you add tags to this list.
    #
    # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
    #       Maximum 20 tags per role.

dependencies: []
  # List your role dependencies here, one per line. Be sure to remove the '[]' above,
```

#### 問題のあるコード

```yaml:meta/main.yml
---
# 値が初期値のまま
galaxy_info:
  author: your name
  description: your role description
  company: your company (optional)
  license: license (GPL-2.0-or-later, MIT, etc)
```

#### 修正されたコード

```yaml:meta/main.yml
---
galaxy_info:
  author: Leroy Jenkins
  description: This role will set you free.
  company: Red Hat
  license: Apache
```

### 参考サイト

* [meta-incorrect — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/meta-incorrect/)
エントロピー増大の理由にまだ悩んでるの？人類？

#
**エントロピー増大が何故かに悩む物理学者はなんなんだ🤔**

# エントロピーは時間方向を決める

ちょっと時間が無いので詳細書けないけど、この世界の物理で一番重要でしかもまだなんかみんなでよく分からないと言ってるのがエントロピー増大の法則であり、これによって時間が不可逆になる。自分も最初大学で習った時かなり悩んだけど。

そしてこの点もすごく現代の物理学者が混乱してるけど、自分的にはあまりにも明確な話だと思ってるので書いておく。

# ゲームとか

Unutyとかで開発してたら、時間は普通は巻き戻せる。物理法則は「ランダムが入らない限り」普通は完全に逆戻りでき、時間の矢は本当はない。

でも、それでもエントロピーが増大して元に戻らなくなるのは、「系の誤差」は影響する。floatでもdoubleでも、計算のベースはたった数バイトであり、そこで表せる数値は分解能が限られている。ここに計算が「影響されて」誤差で元に戻れなくなる。レイトレーシングなんかやってたらすぐに分かる。

これはつまり、正確に数学的に言うなら、「系の最小単位の揺れがエントロピー増大を生む」と言い換えられる。

しかしこれも正確じゃない。いちばん簡単に時間軸を元に戻るためには、系の進行を全て「メモリーしておけばいい」。これはつまり、元に戻る所が「明確になっていれば」良いのだよ。とても面白いのはエントロピーの問題はゲーム世界でもあるって事だ。

で、実際のところそれが出来ないのはこの世界に「経路のメモリーがないから」とも言えるけど、誤差だけでなくても本当は戻れなくもなる。もう少し考えてみよう。

# この世界は？

この世界の最小単位は、当然わかってないけど、いわゆるプランク定数と、そこから来る、不確定性原理はその候補だろう。

でもそれでもまだモヤモヤしてるので、さっきのデジタル系も含めて考えてみよう。
実は、この「元に戻れない」本質は、一番の原因は、数学だ。

それは言ってしまえば誰でも高校ぐらいで教わる、関数の射影の話だと思ってる。以下にそれを書くよ。

時間が戻る時に、もとに戻れないのは、いちばん簡単なのは、「戻り道か2つある」事だ。複数あっても同じだけど。最低でも2つあると、選択が正しくできないなら元に戻ることは保証されない。

実はunityで戻るのにメモリーが必要なのはまさにこのせいだ。1つの物体の位置が、複数の戻り位置がある時だけ、それが起こる。要は

「弾が直進してる時には完全に元に戻れる」が、
「弾が跳ね返った時が、戻れない」んだよ。レイトレーシングの光でもおなじ。

それは、「複数の経路から同じ経路に来てしまう」ことがあるからだ。

それによって、戻り道はメモリがない限りどれだか分からなくなるんだよ。

戻り経路が複数ある、のが問題。で、じゃあどうしてそうなるのか。それは最初に原因がある。誤差のために最初のフォーワードな計算時に、本来の場所でない所に必ず行ってしまう。それは最小の誤差なんだけど、確実に正確な場所からはズレている。

そしてその事は、行先の数値も「同じfloatで計算している限り」ズレた複数の最初の位置が重なる、事がある。2つの光線が反射で重なる、事がある。多対1の時間発展になる。まさのこの瞬間に「戻り道は2つになり、戻れなくなる」。それだけでなくて、ある時には複数の状態が次の瞬間にひとつに重なる。この瞬間にエントロピーは、減少が出来なくなるのですよ！

で、実世界だけど。

ここで「不確定性原理」出てくるんだけど。自分は先からの色んな話でわかるように実は「量子世界は曖昧だからぼやけてる」立場はとってない。アインシュタインと同じで、「神はサイコロは振らない」。高次元物理は存在するが、それは本来的にカオス力学であり、その射影の量子力学が本質では無いのでは？と言う考えになって来てる。

だから、不確定性原理に頼らない。ここではそうではなくて、より本質的なと思う自発的対称性の破れからそれを解釈してみよう。

自発的対称性の破れは非線形な結合振動子系には一般的に生じる。これは系の非線形性がもたらす完全に数学的なものであって、曖昧なものでは無い。この世が数学に従う限り、これは避けられない。

そして、自発的な対称性の破れは、「系の対称性を失わせる」。これは、計算から来るもので系の「次元が減る」。正確には対称性なんだけど、実際には系の畳み込みが起こる。だから広い意味での次元減少と捉えられる。これにより数学的には群の直積の空間が減少する。要は出先は必ず小さくなるので「どこから来たのかが重なってしまう」これは完全に数学的な話。そしてそれはあの最近のHQFT理論が正しければ物理的にも完全に正しいと見える、だろう。

そしてそれがために、系は「戻り道を失う」。時間逆方向への対称性が戻った世界に帰る時には、次元の高いエリアに戻らなければらず、経路多数で戻れなくなる。それどころか本来的には実数空間なら系の戻り道は「無限個」になる。この空間が実数空間かどうかは分からないけど、それでも無限に近い数あるのはあまりに確実。ああ、エントロピーが少ない状態への戻り道もう永遠に分からなくなった。これは実はゲーム世界でも成り立つ。誤差だけでなくて、非線形性と対称性の破れによる畳み込みが戻り道を見失わせる。

# 今回の結論？

物理学者がこれが分からないのは何故なんだろう。次元と対称性の破れから、必然的にエントロピー増大はもたらされる。対称性が常に破れ、次元が減少している系だからこそ逆に戻れなくなり、エントロピーは増大する。これはここで書いたように、数式のほとんど要らない、かなり定性的にわかる話だ。

**物理世界の継続的な自発的対称性の破れがエントロピー増大則をもたらす**

これが結論。とうかな？自分的には破綻が見えないんだけど、誰か反論あるのかな？少なくても物理学者が言ってるように、エントロピー増大は人間の認識のせいだ、とか変なこと言わないで済む論理と数学からの話なんだよな。

ただし、この話は自発的対称性の破れのための時空カオスを必要とする。要は「動かない系はエントロピーは増大しない(当たり前)」。激しく動き、空間が畳み込まれて初めて時空カオスが作られ自発的対称性の破れが発生して、系の至る所で空間が次元減少と不可逆な拡大を繰り返すからこそエントロピーが増大するって事だ。

そして、そして時間は時空カオスの進展とともにもりもり流れて行く。

またそれによって撹拌された時空全体の情報量は系全体を表したものになる。つまり意識の情報空間、のような風体を取るだろうという予測はできると思ってる。怪しい話にもなってくる。これはまた別の機会に。
DB Browser for SQLiteでテーブル作成

DB Browser for SQLiteでテーブルを作成しました。

### 01.要件に登場する情報を整理する

ユーザーログイン画面を作るための登録情報は以下。
（※今回作るログイン画面で使用するのは上の2つのみだが、練習で登録。）

テーブル名：ACCOUNT
| 列名  |型（桁） | 制約 | 備考  |
|:-:|:-:|:-:|:-:|
| USER_ID  | CHAR(10)  | PRIMARY KEY  | ユーザID  |
| PASS  | VARCHAR(10)  | NOT NULL  |  パスワード |
| MAIL  | VARCHAR(100)  | NOT NULL  | メールアドレス  |
| NAME  | VARCHAR(40)  | NOT NULL  | 名前  |
| AGE  | INTEGER  | NOT NULL  |  年齢 |

### 02. DB Browser for SQLiteでテーブル作成

データベースファイルの作成→新しいデータベース→ファイル名入力→「SQL実行」タブで以下入力→SQLを実行

```sql:ACCOUNT TABLE
CREATE TABLE ACCOUNT(
USER_ID CHAR(10) PRIMARY KEY,
PASS VARCHAR(10) NOT NULL,
MAIL VARCHAR(100) NOT NULL,
NAME VARCHAR(40) NOT NULL,
AGE, INTEGER, NOT NULL
);
```
「データ閲覧」タブで、作成したテーブル名を選択→登録された内容を確認できる。

:::note info
気を付ける
最後のデータ末=「 ); 」の前に、「 , 」を入れない。
:::
SOLID JS part1

# SOLID JSってなんだ
リアクティブJabascriptライブラリです。

https://www.solidjs.com/

`React` `Vue`が日本だと有名だと思います。`Vue`はフレームワークだぞという突っ込みが飛んでくるかも知れませんが、細かいことは置いといてフロントエンドでモダンなものといえば、この二つもしくは派生された`Next` `Nuxt`と答える人が大半なのではないでしょうか？`Solid`もそれの一部だということです。

`React` `Vue`で開発体験最強！これ以上非の打ち所がないと思っている人も中にはいるかも知れませんが、2021年の世界のトレンドのJSを知る上で参考になる資料として有名な`state of js`において使ってみた上でもう一度使いたいと答えた人が90%も超える結果となりました（2022年版は12月21日現在だと発表されていませんでした、ぜひ皆さんの目で確かめてみてください)

![front_end_frameworks_experience_ranking.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980538/2a7ee771-777f-f0da-0287-0dc377b9c8d4.png)

なぜこんなにもう一度使いたいと思う人がいるのでしょうか？必ず`React` `Vue`との違いがあるはずです。


# 高いパフォーマンス
![スクリーンショット 2022-12-21 19.11.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980538/a3336108-1ea4-6a6d-ccd9-2316f9030228.png)

公式によるとなんだが、早いようです。ただ、これは今年、viteよりturbopackは10倍早いのか問題があったように公式サイトに載っているからいって我々は簡単に信じていいはずはないはずです(正直どっちも早いから個人的にはどうでもいい気がしますが...)

https://qiita.com/tsrnk/items/6b184564aadecf8fc405

JavascriptのPerformanceをまとめた表がありました!（このサイトの信憑性について疑う人は目を瞑ってください...)

https://krausest.github.io/js-framework-benchmark/current.html


絞り込みしないとLibrary盛り沢山なので、とりあえず私が知っていたり聞いたことあるやつのみの最新のもので絞り込みました

![スクリーンショット 2022-12-21 19.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980538/5c647083-96f8-3e1e-fa78-1da61ad60224.png)

### solid js　優勝!!!!
 (あれ思ってたよりVueもすごくね？..(笑))


![K10013926701_2212190432_1219043759_01_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980538/93dfcc6f-8729-8e3d-9736-250d66200795.jpeg)

> パフォーマンスを重視しない場合でも、複雑な DX のコストは必要ありません。Solid のパフォーマンス向上は、タダで手に入るものと考えてください。頑張らなくても速くなるということです。

しかも公式には頑張らなくても早いよって書いてました笑

### なぜ早いのか？

### 1. 仮想DOMではない
`React`や `Vue`では仮想DOMが用いられています。仮想DOMを操作しリアルDOM と同期させ、その差分のみ反映させる仕組みです。

![ebb2611212e7-20220225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980538/be4974e3-df6a-3c9a-1feb-a8380d3cb033.png)

> 仮想DOMは、ブラウザが持っていたDOMツリーを、JavaScriptのオブジェクト（仮想DOMツリー）として表現します。そして、メモリ上の仮想DOMツリーを用いて差分検知を行い、必要最低限の差分のみをリアルDOMに反映するため、一般的にパフォーマンスが向上すると言われています。

しかし、solid JSは別の方法でそのようなリアルDOMが遅い現実を変える方法を見つけ出しました。テンプレートを実際のDOMノードにコンパイルし、更新をきめ細かい反応でラップすることです。
> きめ細かいリアクティビティにより、少ない労力でより多くのことを実現します。
> Solid は、ユーザーランドのコードから JSX ビューへの効率的なリアクティブプリミティブで構築されています。

> これにより、DOM バインディングレベルでも、何をいつ更新するかを完全に制御できます。コストのかかる仮想 DOM を超えて、Solid は必要以上の作業を行いません。
> このように、状態が更新されると、それに依存するコードのみが実行されます。

Solid のリアクティビティについての全体的なアプローチは、リアクティビティの計算をすべて関数でラップし、依存関係が更新されたときにその関数を再実行することです。

https://www.solidjs.com/docs/latest/api#%E5%9F%BA%E6%9C%AC%E3%81%AE%E3%83%AA%E3%82%A2%E3%82%AF%E3%83%86%E3%82%A3%E3%83%93%E3%83%86%E3%82%A3

また、仮想DOMにはdiffを計算するアルゴリズムがある以上DOMツリーの構造が大きくなればなるほど、差分検知の計算量が増え、結果的に遅くなってしまうこともあります。また、ほんのわずかなdiffであっても、全てのNodeを見比べるのはスマートではない気がします。加えて、仮想DOMをランタイムでレンダリングするプロセスもブラウザに負担をかけているのではないでしょうか？

### 2. コンポーネントが一度しか呼ばれない

Reactのようにコンポーネントが再レンダリングしません。Reactとは異なり、コンポーネントは1回だけレンダリングされ、コンポーネントで使用されているJSX式とプリミティブのみが更新されます。しかし、コンポーネント内部で発生する変更を必ず追跡します。

> Solid の JSX コンパイラーは、ほとんどの JSX 式（中括弧内のコード）を関数でラップし、依存関係が変更されたときに自動的に更新 (および対応する DOM 更新のトリガー) します。



# 続く

今回は少し調査して疲れたので、次回以降にsolid.jsの素晴らしい点を述べていきたいと思います。それではpart2で
自称コミュ障が考える、プロジェクトチーム内のコミュニケーション方法

# はじめに
はじめまして、
普段あまりゲームをしないわたしが未経験からスタートして、気づいたらゲームQA歴が6年程になっていたr_sbyです。
テスト実行や設計を経て、現在はチームのまとめ役をやることが多くなってきました。
そんな中、自称コミュ障の私が日頃から大事にしているコミュニケーション方法について
某携帯ショップの店員などで培った接客スタイルをベースに記載させていただこうと思います。
少しでもご参考になれば幸いです。
## 某携帯キャリアショップでの経験則
ショップ店員時代は顧客満足度エリアNo.1をとるなどで表彰いただいたりした経験がありますが、
冒頭でも軽くお伝えした通りコミュ障ですし、接客するのは嫌いです（笑）
特に知らない人とお話することがとても苦手で怖いのですが、
以下を行っていくことで評価がよくなっていったので参考にしてみてください。

　__①相手の目を見すぎない__
　　　　小学校などで聞いたことあるかもしれませんが、あまり良くないです。
　　　　現代では7割程度の方が視線に対して耐性がありません。
　　　　わたしも目をまっすぐ見て話されると恐怖を感じるタイプ（※
　　　　なので、なるべく相手を見すぎないように心がけています。
　　　 __※過去受けたことがあるホスピタリティ研修でも注意点として挙げられていました。__

　__②否定をしない__
　　　　「できません」よりも「こうしたらできるかも！」と建設的に返答しましょう。
　　　　事実だとしても否定の言葉を使うことはいいことがありません。

　__③自分で選ぶ感覚を持っていてもらう__
　　　　ただひたすら押してもなかなか響きません。
　　　　「いいですね～こっちも好きですが、、、悩みますよね～(ﾆｯｺﾘ)」
　　　　と店員としてではなく自分自身の気持ちを出しつつ共感をすることで
　　　　95％は買ってほしい方を選んでくれてました。
　　　　※商品だけでなくプランなども一緒

　__④説明している内容が相手に正しく伝わったか逐一確認する__
　　　　携帯ショップならではかもですが、間違って伝わってしまった場合に
　　　　直接わたしに被害はなくても説明不足により相手(この場合はお客さま)に迷惑をかけてしまう可能性があります。
　　　　※携帯のプランはわかりづらいので

　__⑤マニュアル通りにやってることも「わたしがやりました！」__
　　　　ショップ店員をやっているとクレーム対応を行うこともあります。
　　　　具体例ですと、携帯を契約した際に余計なオプションを付けられてしまい
　　　　想定外の料金が発生していた、などがあります。
　　　　こういった対応に対して、対処方法が用意されているのですが
　　　　嫌々対応されるよりも「わたしが助けてあげましょう！」の意気で対応すると
　　　　やってることは一緒なのにお客さんは減らないのでWinWinになります。

　__⑥相手の話を勝手に判断しない__
　　　　ここに関してはわたしの察し能力の低さでもありますが、
　　　　勘違いをしてしまうのは相手のせいではなく自分のせい
　　　　聞いた話が自分の考えと一致しているかは都度確認していくと話がスムーズに進みます。

　__⑦相手と同じことばを使用する__
　　　　⑥に通じるところがありますが、
　　　　言い換えたり別のことばにしてしまったときは齟齬が発生しやすいです。
　　　　こちらもホスピタリティ研修で教えていただきました。

上記7点を是非活用してみていただけると嬉しいです。
続いては上記に加えてプロジェクトチーム内で気づいた点を記載します。

## 相手からの好意や善意に感謝することは当たり前
+ なにかをお願いしたいとき
+ なにかをお願いされたとき
+ 普通に会話をしているとき　等々

当たり前のように思いやりなく業務依頼をしている人を見て、
「あああ！もったいない！かわいそう！」と思うことがかなり多いです。
もちろん業務範囲だったりすれば当たり前かもしれないですが、
相手の __”行為/行動”そのものにまず感謝（リスペクト）__ していきましょう。

__～業務範囲ではあるが、相手が抜け漏れしていて気づいていない時～__
+ 良くない例
「業務内容に入ってるんだからここまでやってほしい」
+ 良い例
「ここまでやってもらえると、とても助かります」

伝えた内容は同じものですが、受け取り手のモチベーションは全く異なります。
なにかをしてもらったあとの「ありがとう」や「うれしい」などは率先して伝えていくと
相手は「この業務をやってよかった」「今回できた！次もできるかも！」と思うことができて
チーム内の雰囲気もよくなり業務効率もUPしていきます。

プロジェクトチームの仲間はお客さまではないですが、
ここまで記載した内容と真逆のことを続けていくと
+ 齟齬が発生して抜け漏れが発生する
+ ミスが続くとやりがいがなくなっていく
+ チーム内の雰囲気が悪くなる　等々

上記が積み重なった結果、
チームメンバーが離脱していき、チーム自体が瓦解してしまう恐れも出てきます。

### 1番大事にしたいこと
仕事は楽しくないもの、という前提を持っている人は多いでしょう。
楽しさを求めるのは違うという意見も耳にしますが、楽しくできるに越したことはないと思います。
たまには無駄な話も混ぜつつ、会話相手が笑顔になってくれるように心がけていきましょう。
そして、相手に求めるのではなく、 __自分から一歩ずつ進めていく__ ことで周りに伝染していけると思います。
## さいごに
記載した内容ですべてがうまくいく！という物ではないと思いますが、

現時点でプロジェクトチームがとても良好である方も
プロジェクトチーム内の雰囲気が芳しくない方も

記載させていただいた経験則を参考に、自分から少しずつでも実践していっていただけると嬉しいです。
また、実践例などコメントいただけると幸いです🐰
Lens Protocolという新しいインフラ


Web3番SNSにはいろいろなところで色々な議論が展開されています。1つ間違いないのはWeb３の登場でSNSは大きくその姿を変えることになるということです。そんなSNSですが、開発にかなりのコストがかかります。これからしばらくたくさんのSNSが乱立する時期が訪れることを読んで、その競争の激化を促すサービスこそが今回紹介するlens Protocolです。

### # Lens Protocol とは

---

Polygonの上に作られたこのLensの目的は、Web3.0版ソーシャルメディア構築を補助する〔ソーシャルグラフ提供〕ことである。
【Why Polygon?】 エコフレンドリーでガス代を抑えつつ、カーボンフットプリントの減少に力を入れてるからのようです。

**備えている機能**
基本機能は下記の通りです。
プロフィール作成・コンテンツ投稿・コメント・リツイート・コンテンツ収集・フォロー・ガバナンス・コミュニティ

❓じゃあ既存と何が違うのか❓
→全ての機能のNFT化＆IPFSによるコンテンツ管理することです。

- **Profile NFT**
    
    複数所持可能で、個々のWalletアドレスに紐づきます。
    さらに、投稿や共有・コメントなどの活動履歴はこのProfile NFTに紐付きます。
    ※使用可能Walletは、Metamask・Argent・Gnosis Safeとなっています。
    
- **Follow NFT**
    
    フォローことに関するNFT。Followする→Follow NFT mintという流れです。
    ミソなのは、このFollow NFTにはtoken IDがついている。順に1から2,3,4と順に大きくなっていきます。
    すなわち、フォローした/してくれた順番までも記録されます。
    また、このFollow NFTのMintには、Followされる側があらかじめtokenのBurnを設けることもできます（→Followerの制限）
    
- **Publication**
    
    主には、投稿・コメント・リツイートの3種類が存在します。
    作成した、全てのコンテンツはProfile NFTに紐付きます。
    
- **Collect（NFT）**
    
    要は、コンテンツNFT購入機能。値段・ビジュアル・期間限定などのカスタマイズ可能です。
    唯一の制限は、Followしている人のみに買ってもらえます。
    
- **Mirror**
    
    Twitterのリツイート機能のようなものです。
    自分がMirrorした大元のコンテンツを誰かが、Collect（購入）すれば、Mirrorした自分に収益の一部が分配されます（今のアフィリエイト）。
    
- 

### # Lens Protocol の本質

---

一言で言えば分権的なプロトコルです。では、分権的なプロトコルとは何か…

①中央集権的なデータの保存を廃止

 これは、Web3の根本的価値です。データの分散はもちろんここにも反映されています。Web３の根本なので、そべてのサービスはここを内包していることになるので、詳しくは書きません。

②デジタル主権

そろそろ世界的にデータのプライバシーが騒がれてきています。このLensProtocolの活用で、既存の中央集権的な protocolの好き勝手なやり方から解放され、個人が主体となって、データを所有・管理できるようになります。だから、真の意味でデジタル主権が実現されます。

**Lens Protocolが解いている課題**

① イノベーションを推進

 大手がデータを独占的に所有するようになると、たとえそのサービスがイケてない状態になっても、新興サービスがそれを倒すのは困難です。でも、個人がデータを所有することによって、イノベーションが推進され、いけてないサービスはすぐに取って代わる環境になります。

②インターネット活動の価値上昇

今のインターネットでの活動が価値を持っているのは、「それに価値を見出している人」と「活動しているプラットホームが生き残っている」からです。万が一そのプラットホームがなくなれば、それまでの活動は水の泡となります。でも、分散化によって、半永久的に自身の活動は価値を持ち続けます。インターネットでの活動がより鮮明な意味を持つようになります。

最後に
---
![Frame 9 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3077219/b363e741-c7ba-641f-233a-3aecd76ee4fa.png)

Verooは、Blockchain技術を活用した「想いの巡るグルメSNSアプリ」です。食に対する熱量、例えばラーメンがめちゃくちゃ好きで年間400杯食べているとか、変態的に具材にこだわった中華料理を作っているなどのような、今まで直接お金にはならなかった食に対する情熱や熱量、その裏側にある想いがトークンを使うことで巡る世界。自分のラーメンに費やす熱量がコミュニティに承認される。自分がほんとにいいと思って作った食べ物がコミュニティで広まる。Verooは単なるSNSアプリではなく、クリエイターたちの想いが紡がれるソーシャルグルメアプリです。

Homepage: https://veroo.xyz/
Discord URL：https://t.co/VoT0gpsflA
[python] Django Paginatorを用いたページ選択画面


# Code
```python:views.py
from .models import Venue
from django.core.paginator import Paginator

def list_venues(request):

    p = Paginator(Venue.objects.all().order_by('name'), 2)
    # 表示するオブジェクトの個数を指定する ここでは2個分を指定

    page = request.GET.get('page')
    # urlからページの情報を読み取る

    venues = p.get_page(page)
    # ページの情報に相応するデータ

    nums = "a" * venues.paginator.num_pages
    # 総ページ数をaの数で渡す（htmlでint型でrootができないため）

    return render(request, 'list_venues.html',
                  {
                      "venues": venues,
                      "nums": nums
                  })
```

```html:list_venues.html
{% for venue in venues %}
     {{venue}}
{% endfor %}
<!--指定した数だけ表示される-->

{{venues}}  <!--<Page 1 of 2>-->
{{venues.has_previous}}  <!--False -->
{{venues.has_next}}  <!--True -->
{{venues.number}}  <!--1-->
{{venues.paginator.num_pages}}  <!--2-->
```

# Bootstrap(4.x)を用いたページ選択ボタン
```html:list_venues.html
{% if venues.has_previous %}

<li class="page-item"><a href="?page=1" class="page-link">&laquo First</a></li>
<li class="page-item"><a href="?page={{venues.previous_page_number}}" class="page-link">previous</a></li>

{% else %}

<li class="page-item disabled"><a class="page-link">&laquo First</a></li>
<li class="page-item disabled"><a class="page-link">previous</a></li>

{% endif %}


{% for i in nums %}

<li class="page-item"><a class="page-link " href="?page={{forloop.counter}}">{{forloop.counter}}
    </a></li>

{% endfor %}

{% if venues.has_next %}
<li class="page-item"><a href="?page={{venues.next_page_number}}" class="page-link">next</a></li>
<li class="page-item"><a href="?page={{venues.paginator.num_pages}}" class="page-link">Last &raquo </a></li>


{% else %}

<li class="page-item disabled"><a class="page-link">next</a></li>
<li class="page-item disabled"><a class="page-link">Last &raquo </a></li>

{% endif %}
```
## ページ１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/e0a695d8-fc77-2f15-d7f2-b18e6f25ba50.png)

## ページ２
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/f2ae83f3-6fc3-9295-9fe1-2c2ae4de967c.png)


# 参考

https://docs.djangoproject.com/en/4.1/topics/pagination/

https://www.youtube.com/watch?v=N-PB-HMFmdo
初めてPCのフタを開けたエンジニアが残すカスタマイズの記録

# はじめに
1から自作PC…というわけではないのですが、
メモリを増設したりSSDに換装したりしているので、その軌跡を記録として残そうと思います。
# カスタマイズしている端末
Lenovo ThinkCenter M70s Smallです。
Core-i5のものを購入しました。

https://www.lenovo.com/jp/ja/p/desktops/thinkcentre/m-series-small/thinkcentre-m70s/wmd00000406?orgRef=https%253A%252F%252Fwww.google.com%252F

# やったこと


## SSDの容量UP
もともとついていた128GBのSSDから1TBのものに変えました。

https://www.amazon.co.jp/gp/product/B0BBQNZPXW/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1

## メモリの増設
8GB→64GBに増設しました。
どうせならMAXの128GBまで増設してみたいです。

https://www.amazon.co.jp/gp/product/B07ZLD6Q1G/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&th=1

# 苦労した、していること

## カバー外すのはいいけどつかない
なんか毎回うまくつけられないです。
外すときはすっと行くんですけどね…
動画とか見てる限りでもすっといってるし、そんなに難しい話ではないはずなんですが…
原因がわかったら追記していきます。

## メモリの留め具かっっったい
想像の1000000倍硬かった…
これ本当にあってるんだよね？大丈夫だよね？と思いながら留めてました。

結果、タスクマネージャーで無事に認識されていたので、大丈夫だと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/fa533c2b-9683-1b25-c57e-bc5921536217.png)

# 感想
できなかったことが調べたりして少しずつできるようになって楽しいです。
今までお金や時間を言い訳にしてやらないでいたけれど、ずっとやりたかったことが少しずつできるようなっていって、個人的に成長を感じています。

# 参考文献

https://download.lenovo.com/pccbbs/thinkcentre_pdf/m70s_m80s_ug_ja.pdf

ユーザーマニュアルの内容もわかりやすかったです。

https://support.lenovo.com/jp/ja/solutions/ht511358-removal-and-replacement-videos-thinkcentre-m70s-11db-11dc-11ew-11ex-thinkcentre-m80s-11cu-11cv-11em-11en-thinkcentre-m90s-11d1-11d2-11d6-11d7

公式で取り外し、取り付け動画を掲載してくれていたので助かりました。

# おわりに
追加でカスタマイズしたら都度追記していきます。
少しずつでもいいので、自分でできることを増やしていきたいです。
CSSの擬似クラス:has()を使ってみる

[ひとりCSS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/css-becolomochi) 22日目です。

:has() 使ってみます

## :has() とは

https://developer.mozilla.org/ja/docs/Web/CSS/:has

()の中のセレクターを持っている要素にスタイルを当てられる。

## サンプル

### サンプル1

p 要素がすぐ下にある h2 はオレンジ色にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/bc3a7165-9100-5e8f-0a00-ff6b99ed0d3d.png)

```html
<section>
  <h2>Headline</h2>
  <p>Paragraph</p>
</section>
<section>
  <h2>Headline</h2>
  <div><p>div > Paragraph</p></div>
</section>
```

```css
:root {
  --color1: #edb658;
}

h2:has(+ p) {
  color: var(--color1);
}
```

https://codepen.io/becolomochi/pen/LYBEdNM

### サンプル2

p 要素を持たない section 要素は中央揃えにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/b4ed34b9-4c61-f635-4b46-5c0ee0d64f40.png)

```html
<section>
  <h2>Headline</h2>
</section>
<section>
  <h2>Headline</h2>
  <p>Paragraph<br>Paragraph<br>Paragraph<br>Paragraph</p>
</section>
```

```css
section:not(:has(p)) {
  text-align: center;
}
```

https://codepen.io/becolomochi/pen/bGjNvKW

## 感想

- 〇〇を持っている要素や、〇〇の上にある要素に対して指定できるようになったのとてもありがたい…

## 参考

https://developer.mozilla.org/ja/docs/Web/CSS/:has
ruby 練習問題１（アウトプット用）

```ruby
puts hash.keys
puts hash.values
````
上記のメソッドを実行した時に
```ruby
one
two
three
1
2
3
```
とターミナルに表示されるような変数hashを作成するためのコードをシンボルを使って記述する問題。

以下、模範解答
```
hash = { one: 1, two: 2, three: 3 }
```
以下、解説

まずシンボルの理解。
シンボルを使うことで数値として扱うので処理速度が速くなる。よってハッシュはシンボルを使用することが多い。
シンボルを使ってキーを記述する方法はキーの後に:をつける。
```
hash = {キー: 値}
```
keysメソッド、valuesメソッド
両方ともHashクラスで使用できるメソッド。
オブジェクト.keysでハッシュに含まれるキーを取得
```
hash = { one: 1, two: 2, three: 3 }

puts hash.keys
one
two
three
```
オブジェクト.valuesでハッシュに含まれる値を取得
```
hash = { one: 1, two: 2, three: 3 }

puts hash.values
1
2
3
```
Sudachiでカスタマイズした辞書を使いたい


形態素解析ツールSudachiで、
カスタマイズしたシステム辞書とユーザー辞書のbuild方法について紹介します.

##  なぜ辞書をbuildしたいのか?
Sudachiにおけるシステム辞書は[build済みのもの](https://github.com/WorksApplications/Sudachi#%E8%BE%9E%E6%9B%B8%E3%81%AE%E5%8F%96%E5%BE%97)が配布されており、それを使うのが一般的です。
しかし、独自に辞書をカスタマイズしたい場合、自分でbuildする必要があります。

## 辞書のbuild方法(.csv→.dic)
「必要なファイル」
 - build前のシステム辞書(small_lex.csv,  notcore_lex.csv,  core_lex.csv)
自由にカスタマイズ可能なCSVファイルとして以下で提供されています.
[こちらからインストール可能](https://github.com/WorksApplications/SudachiDict/tree/develop/src/main/text)
 - javaコマンド実行に必要な各ファイル
ZIPファイルとして提供されています. zip内に必要なファイルが含まれているため, それらをbuildしたい辞書と同じディレクトリに配置してください. 
[こちらからインストール可能](https://github.com/WorksApplications/elasticsearch-sudachi/releases/download/v2.1.0-es7.0-7.3/analysis-sudachi-7.3.2-2.1.0.zip)
 - matrix.def
matrix.def.zip内の格納されています.
[こちらからインストール可能](https://github.com/WorksApplications/SudachiDict/tree/develop/src/main/text)

「buildコマンド」
 ```
# システム辞書
java -Dfile.encoding=UTF-8 -cp sudachi-0.5.1.jar com.worksap.nlp.sudachi.dictionary.DictionaryBuilder -o [任意の出力ファイル名].dic -m matrix.def small_lex.csv core_lex.csv notcore_lex.csv  
```
```
# ユーザー辞書
java -Dfile.encoding=UTF-8 -cp sudachi-0.5.1.jar com.worksap.nlp.sudachi.dictionary.UserDictionaryBuilder -o [任意の出力ファイル名].dic -s [システム辞書].dic [ユーザー辞書].csv
```

## その他　
ユーザー辞書の形式やbuildの詳細に関しては以下のサイトなどに詳しく載っています.
[https://github.com/WorksApplications/Sudachi/blob/develop/docs/user_dict.md](https://github.com/WorksApplications/Sudachi/blob/develop/docs/user_dict.md)
[https://qiita.com/po3rin/items/d9a0cc9d8202ff16ed3f](https://qiita.com/po3rin/items/d9a0cc9d8202ff16ed3f)

システム辞書のbuild方法はWEB上であまり紹介されていません(2022/12/21時点)
もし開発などで行き止まった場合には, [slack上のコミュニティ](https://sudachi-dev.slack.com/)などに助けを求める必要があるかもしれません.
【Firestore】【Python】Firestoreでselect()を使って特定のフィールドのみ取得する

# FirestoreでSelect()を使って特定のフィールドのみを取得する
Firestoreのデータを取得する際に特定のドキュメントのみを取得したいというケースがあるかと思います。

今回はそういったケースのpythonを用いた解決方法を紹介します。

## 参考例 1 特定のフィールドのみを取得
"customers" コレクションのドキュメント内の"user"フィールドのみを取得したい
### データ例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/f4c5e43b-a0c3-0f70-3f0d-228ca38fc6ed.png)
### コード例
下記のget_user()関数は、customerid として、ドキュメントIDを付与して、userのフィールドを結合させた辞書型のユーザデータを配列にしてリストで返却しています。
```python:sample.py
FB_DB = firestore.client()

def get_user():
    doc_ref = FB_DB.collection("customers").select(field_paths=["user"])
    doc = doc_ref.stream()

    response = [{"customerid": el.id, **el.to_dict()["user"]} for el in doc]

    if len(response) <= 0:
        raise FileNotFoundError("Customer Data Not Found")

    return response

```

## 参考例 2 ネストした特定のフィールドのみを取得
"customers" コレクションのドキュメント内の"user">"username"フィールドのみを取得したい
### コード例
下記のget_user()関数は、ドキュメントIDをKeyとして、usernameの値を代入した辞書型の値を返却しています。
```python:sample.py
FB_DB = firestore.client()

def get_user_name():
    doc_ref = FB_DB.collection("customers").order_by("user").select(field_paths=["user.username"])
    doc = doc_ref.stream()

    response = {el.id: el.to_dict()["user"]["username"] for el in doc}

    if len(response) <= 0:
        raise FileNotFoundError("Customer Data Not Found")

    return response

```


# 参考記事
https://vexus2.hatenablog.jp/entry/2019/12/18/101256

↓公式リファレンス

https://googleapis.dev/python/firestore/latest/query.html?highlight=select#google.cloud.firestore_v1.base_query.BaseQuery.select
Vagrant で VirtualBox 用 Rocky Linux 8 が起動しなくなった

WSL2 で Vagrant を使っていますが、VirtualBox 用 Rocky Linux 8 をアップデートしたら、起動できなくなりました。

```shell-session
$ vagrant up
Bringing machine 'node-1' up with 'virtualbox' provider...
==> node-1: Importing base box 'rockylinux/8'...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["import", "-n", "\\\\?\\c:\\Users\\tom-sato\\.vagrant.d\\boxes\\rockylinux-VAGRANTSLASH-8\\7.0.0\\virtualbox\\box.ovf"]

Stderr: 0%...VBOX_E_OBJECT_NOT_FOUND
VBoxManage.exe: error: Appliance read failed
VBoxManage.exe: error: Failed to open OVF file '\\?\c:\Users\tom-sato\.vagrant.d\boxes\rockylinux-VAGRANTSLASH-8\7.0.0\virtualbox\box.ovf' (VERR_FILE_NOT_FOUND)
VBoxManage.exe: error: Details: code VBOX_E_OBJECT_NOT_FOUND (0x80bb0001), component ApplianceWrap, interface IAppliance
VBoxManage.exe: error: Context: "enum RTEXITCODE __cdecl handleImportAppliance(struct HandlerArg *)" at line 510 of file VBoxManageAppliance.cpp
```

Rocky Linux のフォーラムに同じ問題が報告されていて、[Vagrant Cloud](https://app.vagrantup.com/) で配布のボックス [rockylinux/8](https://app.vagrantup.com/rockylinux/boxes/8) v7.0.0 に不備があるようです。

https://forums.rockylinux.org/t/vagrant-box-rockylinux-8-fails-for-virtualbox-provider-with-error-vbox-e-object-not-found/8228

解決策は `Vagrantfile` でバージョンを指定して古いボックス v5.0.0 を使うか、

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "rockylinux/8"
  config.vm.box_version = "5.0.0"
end
```

Rocky Linux で配布の最新のイメージを使ってボックスを追加します。

それには、まず、以下の内容でボックスのメタデータを作成し、

```json:box-metadata.json
{
  "name" : "rockylinux/8",
  "description" : "Rocky Linux 8 7.0.0 Bugfix",
  "versions" : [
    {
      "version" : "7.0.1-20221213.0",
      "providers" : [
        {
          "name" : "virtualbox",
          "url" : "http://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-Vagrant-Vbox-8.7-20221213.0.x86_64.box"
        }
      ]
    }
  ]
}
```

そのメタデータを使ってボックスを追加します。

```shell-session
$ vagrant box add box-metadata.json
==> box: Loading metadata for box 'box-metadata.json'
    box: URL: file:///home/tom-sato/vagrant/box-metadata.json
==> box: Adding box 'rockylinux/8' (v7.0.1-20221213.0) for provider: virtualbox
    box: Downloading: http://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-Vagrant-Vbox-8.7-20221213.0.x86_64.box
==> box: Successfully added box 'rockylinux/8' (v7.0.1-20221213.0) for 'virtualbox'!
```

なお、最新のイメージでは UEFI が有効になっているので、`Vagrantfile` で VirtualBox の設定が必要です。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "rockylinux/8"
  config.vm.box_version = "7.0.0"
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--firmware", "efi"]
  end
end
```

これで、最新のバージョンで Rocky Linux 8 を起動できます。
カスタマーサポートと協働するためにエンジニアチームがやってよかったこと4選

この記事は[モチベーションクラウドシリーズ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mcs) 22日目の投稿です。

# はじめに
私はモチベーションクラウド開発で顧客からの問い合わせを技術的に解決したりする部署に所属しています。
日々様々な問い合わせや技術的な相談が来るのですが、以前はカスタマーサポートとの距離が遠く、内容の詳細把握にも時間がかかっていました。
機能的に実現できないかの相談を受けても「できる/できない」の返事しかできず、顧客理解も進まないという状態が続いていました。
ちなみに以下画像が弊社の顧客問い合わせ対応体制です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545192/6649aad5-920a-731e-8eec-d1583c7d67ba.png)

そんな中で、よりカスタマーサポートと協働しようと色々やってきました。
やって良かったこと４つを紹介します！

# やったこと
以下を実践しました。
1. 依頼ルートの統一
1. 背景のヒアリング
1. 判断軸の言語化
1. エンジニア⇔CSのコミュニケーション


一つずつ何をやったのか書いていきます。

## 1. 依頼ルートの統一
### なぜ必要なのか？
依頼内容の把握を個人ではなくチームでできるようにするためです。
DMで依頼が来たり対応者に電話が来たりすることがありました。
個人で請け負う判断をしなければいけない状態は健全ではないですよね。
どんなタスクを何個受けて実行しているのか、全タスクに対して見える化できることで、優先度判断や重要性の受信につながります。

### 実施策
依頼の経路を絞り、全てのやりとりの情報を残すようにしました。
弊社ではJIRAを使っています（導入のお話は[弊社のアドベントカレンダー8日目の記事](https://qiita.com/hirotaka-awata/items/023bc06472bea06bb1c5)にも書いてます）
今でもCSの方から電話で質問が来ることもありますが、基本的に電話できた内容は全てCSの方にJIRAに転記してもらうようにしています。情報集約！
人の目を入れようと思えば入れれる環境を作ることで、変な握りをしそうになったら口を挟めるし、連携内容に誤りがあったら指摘をしてあげられるようになります。
慣れるまでは多少めんどくさいですが、すべての情報が探せばJIRAにあるという環境は安心にもつながるのでおすすめです。

## 2. 背景のヒアリング
### なぜ必要なのか？
顧客・カスタマーサポート・カスタマーサクセス ・開発全員にとっての最適解を出すためです。
依頼はやって欲しいことベースで来るのですが、
依頼されたことをそのまま実施するのでは、プロダクトのルールや工数の問題でできないことも多々あります。
そんな時に別の対応策を提案するためには背景のヒアリングが必須です。
本当に顧客が満たしたい要望を最低限の工数で最適に叶えるために背景のヒアリングを必ずしました。

### 実施策
これは簡単、JIRAの依頼フォームに「背景」記入欄を加え、記入必須にしました。
ただ、「顧客が分析に使うため」みたいな表面的な理由を記載される場合もあるので、
そういう時は追いヒアリングをかけます。

### つまずきポイント
これは結構驚きだったんですが、カスタマーサポートなども顧客の依頼の背景を理解していないことがまあまあ多かったです。
つまり、顧客とカスタマーサポートも仕事の受け渡しのみしていることがあったんです。
そんな関係を止めてあげるのも私たちの仕事だと自己定義をし、めちゃくちゃ根気よく背景を聞いていました。
これは一人でやるとなかなか諦めそうになるので、対応するエンジニアチーム全員の朝会で話し、「深ぼったほうがいいよね」となったものを諦めずにみんなで聞くというアクションをとっていました。
その時「なんでやるの？」と聞いたら角が立つので、
「〇〇さんがお客さんのことを思っているのと同じように、我々もお客さんの要望を可能な限り実現してあげたいので詳しく聞いてきてください！」的に聞くといいですね（目的の共通化ですね）。

## 3. 判断軸の言語化
### なぜ必要なのか
属人性やその時の感情にできるだけ影響されない判断をするためです。
正直私たちも、目の前の人が困ってるんだからできるだけやってあげたいです。
エンジニアは特に、1日とか数時間とかで解決できるものは解決してあげたいと思います。
が、それを続けるとエンジニアチームの仕事は無限に増えていき、仕事を減らすための仕事もできなくなってしまいます…

### 実施策
判断軸をまとめました。
ここで大事なのはミッションです。
私たちは 全ての お客様に価値を届ける必要があるため、できるだけ特定のお客様だけの価値に注力しないようにしようと話しておりました。
本当に価値のある対応であれば、プロダクトに実装するのが一番ですからね。

そこで有意義だった問いは「イレギュラーの場合、改善策を講じられるか」というものでした。
2回以上依頼が来るならエンジニアの対応工数も大変だし、実装する？みたいな思考回路ができたと思います。

## 4. エンジニア⇔CSのコミュニケーション
### なぜ必要か
解決策の幅が広がるためです。
当時はなぜかエンジニアはカスタマーサポートと連絡をしないという暗黙のルールがありました。
エンジニアが自分のタスクに集中できるようにと作られたルールだったのですが、現状の組織にあっていませんでした。
タスクを実行するのはエンジニアなことが多いので、カスタマーサポートと一緒に解決策を考えたほうが絶対にいいです。
一次情報に触れられなくてもいいが、いつでも触れられるという状態を作ることで、方針に悩んだ時にスムーズに解決に向かうと思っています。

### 実施策
まず問い合わせ対応のカスタマーサポートへの返事をやってみるなどしていました。
これもJIRA導入の功績ですが、チャット形式になったことで「お疲れ様です、〇〇と申します」とか書かなくてよくなったため、ハードルがグッと下がりました。
エンジニア側の心理ハードルを下げるために、「連絡を取ったことがある人」という前提を作りました。
あとはランチとかいろいろやって、最終的にカスタマーサポートと課題解決定例を始めるまで漕ぎ着けました。
定例で顔を合わせるようになったらだいぶコミュニケーションはしやすくなり、議論できる信頼関係の土壌を築けたかと思います。


# 最後に
このようなことをして、「顧客のことをよく知っているエンジニア」という立ち位置を作っていきました。
ただただ顧客問い合わせ対応をしているのではなく、
それをプロダクトやプロセスのアップデートに繋げられたらなと思います。
ここまで読んでくださりありがとうございました！
NuGetでパッケージを更新できないを解決する

## 前提
- ソリューションに複数のプロジェクトがある。
- プロジェクトの依存関係は、複雑である。
- インストールしている複数のパッケージも複雑に依存している。（私の環境では、グレープシティのComponentOne WPF）

この状況で、パッケージのバージョンが上がったときに、NuGetで更新すると、失敗することが多いです。

## 簡単な解決策
次で解決できます。他にもっと良い方法があるかもしれませんが。

1. 依存関係で、他のプロジェクトを依存している数が多いプロジェクトの、依存関係を、一時的にはずす。どのプロジェクトに依存しているか、スクリーンショットを撮るなどして、メモする。
2. そのプロジェクトで、NuGetでパッケージを更新する。
3. チェックをし直す。
4. 他のプロジェクトでも、NuGetでパッケージを更新する（できないなら、同様に依存関係を一時的にはずして更新する）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/fe44b43e-0e51-0674-ccf9-5c5c773d74f8.png)

#### プロジェクト単位で、NuGetで、パッケージを更新
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/aa842852-2522-eef7-22b7-174acbedce18.png)

#### バージョン
- Microsoft Visual Studio Community 2022 (64 ビット)
Java面接問題

問題１、GETとPOSTの区別
GETメソッドでは、送信内容がURLパラメータに含まれていますので、
同じURLに再度アクセスすると同じ内容が再現できます

GETは指定したリソースの表現を転送するようにリクエストするメソッドです。
つまり、何か情報を検索したり取得するために使うためのメソッドになります。


POSTメソッドでは送信内容がURLからはわからずリクエストボディに含まれていますので、URLだけでは同じ内容が再現できません。

POSTは指定したリソースを実装した機能に従って処理をする機能になります。
主に登録処理や更新処理などの、書き込みがありリソースが更新される可能性のある処理に対して使うメソッドになります。


問題２、重複な文字を除外する

string  str = "abcdde";
List<string> data = new ArrayList<string>;
for (int i=0; i<str.length(); i++){
 string s = str.substring(i,i+1)
  if(!data.contains(s)){
    data.add(s);
  }
}

string result = ""
for (string s:data){
    resut +=s;
}
system.out.println(result)

問題３、
if文よりコード量が多くなってますが、拡張性・可読性が上がっていると思います。
https://deecode.net/?p=938

enumの場合
　既存の要素を少し修正して新たに要素を追加するのみです。



問題４、Cookieとセッション
HTTPにおけるWebサーバとWebブラウザ間で状態を管理するプロトコルです。
また、そこで用いられるWebブラウザに保存された情報のことをCookieと言います


Cookieの場合はクライアント側に保存されるという性質上、ユーザーがデータを改ざんすることもできるため、セッションのほうがよりセキュリティ的に安全だと言われています。
https://amg-solution.jp/blog/7061

問題５、Ajaxとは
JavaScriptでサーバーと非同期通信をする技術のことです。

一部の情報だけサーバーにリクエストし、画面の一部だけ反映させる仕組みのことです。
https://nanayaku.com/interview-measures-1/
【Playdate】加速度センサーを使ってSpriteを動かす

![sample_1211.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100912/ba133fdc-f417-b425-8051-28cb61a3e39c.gif)
Playdateには加速度センサーもついています。
今回は加速度センサーを使ったサンプルを作成してみました。
ベースとなるプロジェクトは[こちら](https://qiita.com/sada_lp1/items/1751040555361bae33b7)。

```main.lua
import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"

local gfx <const> = playdate.graphics

local playerSprite = nil
local status = "ACCELEROMETER\nOFF"

function myGameSetUp()

	local playerImage = gfx.image.new("Images/playerImage")
	assert( playerImage )

	playerSprite = gfx.sprite.new( playerImage )
	playerSprite:moveTo( 200, 120 )
	playerSprite:add()

	local backgroundImage = gfx.image.new( "Images/background" )
	assert( backgroundImage )

	gfx.sprite.setBackgroundDrawingCallback(
		function( x, y, width, height )
			backgroundImage:draw( 0, 0 )
			
			gfx.setImageDrawMode(gfx.kDrawModeFillWhite)
			gfx.drawText(status, 20, 20)
			gfx.setImageDrawMode(gfx.kDrawModeCopy)
		end
	)

end

myGameSetUp()

function playdate.update()
    -- Aボタン: 加速度センサーをON/OFF
	if playdate.buttonJustReleased( playdate.kButtonA ) then
		if playdate.accelerometerIsRunning() ~= true then
			playdate.startAccelerometer()
			status = "ACCELEROMETER\nON"
			gfx.sprite.redrawBackground()
		else
			playdate.stopAccelerometer()
			status = "ACCELEROMETER\nOFF"
			gfx.sprite.redrawBackground()
		end
	end
	
    -- 加速度センサー
	if playdate.accelerometerIsRunning() == true then
		local x, y, z = playdate.readAccelerometer()
		playerSprite:moveBy( x, y )
	end

	gfx.sprite.update()
	playdate.timer.updateTimers()

end
```

加速度センサーはバッテリー節約のため、最初はオフにされています。
加速度センサーを開始するには`playdate.startAccelerometer()`で明示的にオンにする必要があります。
`playdate.accelerometerIsRunning()`で加速度センサーの有効無効状態をbooleanで取得します。
加速度センサーを終了するには`playdate.stopAccelerometer()`でオフできます。

加速度センサーによって傾きを取得するには`playdate.readAccelerometer()`を使います。
返り値は`x``y``z`となり、`0〜1`の範囲で取得することができます。
端末の背中(スクリーンの裏側)を床に置くと(x,y,z)は(0,0,1)となり、端末を立てる(ロックボタンを上側にする)と(x,y,z)は(0,1,0)と値が返されます。
今回は`x`と`y`をそのまま代入して、スプライトを動かしています。
CP4DaaSのWatson Studioのプロジェクトでのファイルダウンロード、アップロードのログ

Activity TrackerというIBM Cloudのサービスを使うとCP4DaaSのWatson Studioの様々な操作のログを確認できます。

その構成方法については以下の@makaishi2さんの記事で紹介されています。

IBM Cloud Activity Tracker with LogDNAで、Watson Studioの監査をしよう - Qiita 

https://qiita.com/makaishi2/items/ff1c3eefa7c9e5246723

この記事ではWatson Studioのプロジェクトからファイルをダウンロード、アップロードした場合にどんなログが記録されるのかを確認します。

* 環境
    * CP4DaaS
    * Activity Tracker

# 1. ファイル・ダウンロードのログ
ATTestというプロジェクトから「anova1.csv」をダウンロードしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/fdbe2fa4-d223-bc70-ae87-2209aa2f316a.png)

Active Trackerを確認すると、「Watson Studio: project signed url create」というイベントが記録されています。詳細を見ると「action:data-science-experience.project-download.create」というactionでした。
また、いつ、誰が(initiator.name)、どのファイル(requestData.filename)をダウンロードしたのかも記録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/958a8eab-6b42-9b7e-ced3-478448d38747.png)

また、プロジェクト名の項目はありませんがrequestData.projectIdがありますので、Watson Studioの「管理」＿「一般」のタブでプロジェクトIDと照合できますし、APIを使えばプロジェクト名は確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/99f7f922-c5c0-10f8-9f01-e1ed51ab8810.png)

なお、
「action:data-science-experience.project-download.create」をクリックして「＋」をクリックすると条件指定の入力ボックスに入ります。Enterを押せば、「action:data-science-experience.project-download.create」のイベントのみに絞りこむことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5727f2e4-a054-19e7-53e3-b0460cc13ec2.png)

また、「Unsaved View」をクリックして「Save as new view」を行なえば、ダウンロードが発生したログのみを確認できるViewを保存したり、Alertに結び付けることも可能です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b1868d1c-e1c5-621a-6e90-eece6c015656.png)



# 2.ファイル・アップロードのログ
ATTestというプロジェクトに「cars.csv」というファイルをアップロードしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/133d83e5-e792-724f-9a30-cbb356088dbc.png)

Active Trackerを確認すると、「Watson Studio: project create data asset」というイベントが記録されています。詳細を見ると「action:data-science-experience.project-asset.create」というactionでした。
また、いつ、誰が(initiator.name)、どのファイル(requestData.assetName)をアップロードしたのかも記録されています。そして、やはりrequestData.projectIdがあります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d6505ec2-3bdd-90ea-e520-a817cfb0b3c4.png)

#### 参考：Activity Tracker イベント - IBM Cloud Pak for Data as a Service 

https://dataplatform.cloud.ibm.com/docs/content/wsj/admin/at-events.html?context=analytics&audience=wdp

#### 参考：CP4DaaSのWatson Studioのプロジェクト作成を検知しメール通知する - Qiita 

https://qiita.com/kawada2017/items/0d31e5b1261dc2e3faa6
NewRelic Infrastructure Agentで収集するログにカスタム属性を追加する

## 前提
NewRelic　Infrastructureエージェントがインストールされている
（`newrelic-infra`コマンドが利用可能である）

## **/etc/newrelic-infra/logging.d/logging.ymlを編集**

```yaml
  - name: newrelic-cli.log
    file: /root/.newrelic/newrelic-cli.log
    attributes:
      newrelic-cli: true
      logtype: newrelic-cli
      tag: test
```
`file`にはNewRelicへ転送するログファイルのパスを記述する。

`attribute`に`key: value`といった形式で任意のカスタム属性を追加する。
（今回は"tag"というkeyに対して、"test"というvalueを設定した）

ファイルの変更内容を保存すれば、**即時反映**される。

## NewRelicで確認
Logsから確認

`key: "value"`のような形式で対象のログを検索する
![スクリーンショット 2022-12-21 20.04.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/e1e14e23-279e-7133-39ee-188ad5927d7d.png)

適当にログの詳細を確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/7b6850c0-0300-ba33-0e8b-4b7d19197969.png)

カスタム属性の`tag: test`が反映されている。


***

ログに対してカスタム属性を付けることによって、担当チームごとに分けてログの調査を行うなどといった使い方ができそう。

## 参考
https://docs.newrelic.com/jp/docs/logs/forward-logs/forward-your-logs-using-infrastructure-agent/
Elasticsearch："_id" でソートする方法

Elasticsearchのクエリ検索結果を「`_id`でソートする方法」についてまとめました。

## 環境
Elasticsearch：7.3.2

## 検索結果のソート
Elasticsearchでは、検索結果をソートした形で受け取ることができます。
例えば、カラム`number`で昇順ソートしたい場合は以下のようになります。
```
GET /{index_name}/_search
{
    "query": {
        "match_all": {}
    },
     "sort" : [{"number":"asc"}]
}
```

## `id`でソートするのにハマった
Elasticsearchでは特に指定がない場合、各ドキュメントへ`_id`が自動生成されます。
以下のように`_id`でソートしてみた...
```
GET /{index_name}/_search
{
    "query": {
        "match_all": {}
    },
     "sort" : [{"_id":"asc"}]
}
```
結果、全然うまくソートされていない...
どうやら、自動生成された`_id`はstring型らしい。

MySQLのcastみたいな方法はないのか。
全然ドキュメント見つからない。


## 解決方法
[中国語で書かれたサイト](http://www.philpy.top/articles/141)で解決策を見つけました。
`_id`に基づくソートは以下のように書けるらしい。
```
GET /{index_name}/_search
{
  query: {
    match_all: {}
   },
  sort: {
    _script: {
      type: 'number',
      script: "Integer.parseInt(doc['_id'].value)",
      order: 'desc'
    }
   }
 }
```
この方法は、テキスト数字のソートへ汎用的に使えそうですね!
Engrossについての初歩的な知識

# ジャンル
スケジュール、タイマーアプリ

# プラットホーム
1. モバイル版
    1. Android
    1. iOS

# 価格
1. Free
1. Premium (800円)


# 概要
　このアプリは、インドのHusain Haideryが開発し、Engross Applicationsとして公開を行っている、Todoと時間管理のためのアプリです。

  2020年1月17日にリリースされ、広告が表示されないタイマーアプリとして高い評価を得ています。

# 機能
　Engross は タイマーとTo-doリストを組み合わせたもので、仕事や勉強に集中し、物事をより早く終わらせるのに役立ちます。表示は英語ですが、難しい機能はないので、使っていけばわかると思います。このデモは、プレミアムにアップグレードしたものです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/ZUlN5UGiCV8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

　一番の目玉は、完全にカスタマイズ可能なポモドーロタイマーです。ポモドーロタイマーとは、[ポモドーロテクニック](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%A2%E3%83%89%E3%83%BC%E3%83%AD%E3%83%BB%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF)のためのタイマーで、基本的には25分の作業セッションと5分の休憩を交互に繰り返します。Engrossでは、、最大180分の作業セッションの長さと最大240分の長い休憩が設定可能です。無料版でここまで使えるのは、とても素晴らしいです。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/4dbc3cab-f9ed-bff2-715b-09d7a8390274.png"/>

　無料でも広告がなく、とても気持ちよく使えます。

1. To-Doリスト
    - リマインダーを設定し、時間になると通知を受け取ります。
    - ラベルを添付して、タスクをより適切に整理します。
1. ラベル/タグ
    - タイマーセッションとタスクにラベルを付けて、作業をより整理し、ラベルごとの統計で時間を分析します。
1. タイマー
    - 一時停止機能
    - 時間延長機能

　有料にすると以下のような機能が使えます。

1. To-Doリストとタイマーの統合（プレミアム）
    - タスクにフォーカスタイマーをアタッチし、To-doリストからセッションを開始します。
1. 分析（プレミアム）
    - 6つの異なるグラフによる作業統計とフォーカス分析。
    - 迅速な評価のための作業と焦点の要約。
1. 作業目標（プレミアム）
    - 毎日の作業目標を設定し、毎日の労働時間を追跡します。
1. ホワイトノイズ (プレミアム)
    - なだめるような音で、作業中に集中できるようになります。

　800円とモバイルアプリとしてはちょっとお高いですが、ついつい買っちゃいました。