OmniAICreator/Qiita-1.07M huggingface dataset:
Pages RouterからApp Router移行で詰まったところ

移行時に意図しないところで手間取ったので備忘録です。

# Next.js本体の移行作業
小規模なアプリということもあり、基本的には公式のマイグレーションガイドで概ね解決。
https://nextjs.org/docs/pages/building-your-application/upgrading/app-router-migration

# トラブルと対応
#### ヘッダがMetadetaになったのでcdnのリンクを差し込めない
fontawesomeのcdnリンクなど。
layout内にheadタグ書いてその中に入れればよしなに合成してくれる。
Issueはあったけどclose。
https://github.com/vercel/next.js/issues/46785

#### next devでは動くけどnext buildでエラー
API RoutesでresponseLimitの設定ができない
https://github.com/vercel/next.js/issues/55589
https://github.com/vercel/next.js/discussions/53986
公式ドキュメントには記載があるものの、この通りに記載してもdeprecatedでエラーとなってしまう。
https://nextjs.org/docs/messages/api-routes-response-size-limit
解決できず、部分的にPages Routerに戻して回避。

#### next devでは動くけどnext build->startでエラー
```
RangeError: Maximum call stack size exceeded
```
原因はUIコンポーネント(material-tailwind)のAppRouter非対応。
特定バージョンでのNext.jsなら動くとのことでv13.5.3に固定して解決。
v13.5.7のcanaryでも行けるらしいですが少し様子見。
[Material TailwindのNext.jsバージョン問題Issue](https://github.com/creativetimofficial/material-tailwind/issues/468)

#### google cloud storageへのファイルアップロードエラー
原因はNext.jsのバージョンをv13.4からv13.5に上げたためにserverMinificationのデフォルトがtrueになり、node-fechがエラーになっていたため。
next.config.jsでserverMinification: falseを明示的に指定して解決。
[Next.jsのserverMinificationの変更起因トラブルIssue](https://github.com/vercel/next.js/issues/55682)

#### その他
nodeもついでにv16->v20に上げたのですが、github actionsのself-hosted runnerが対応しておらず、
そちらの設定更新なども必要でした。

# 最後に
Next.jsがrecommendしているし、登場から半年以上経っているのでもう大丈夫だろうと移行に踏み切りましたが、本体こそスムーズに移行できたもののライブラリ周りでは思ったより手間取りました。
誰かのお役に立てば幸いです。

# 参考
[Next.jsの公式App Router説明ページ](https://nextjs.org/docs/app)
[ざっくりApp Router入門【Next.js】](https://zenn.dev/yamadadayo123/articles/6cb4f586de0183)
[Next.jsのPages RouterからApp Routerへの移行に挑戦してみた](https://tech.every.tv/entry/2023/10/04/110528)
私がRDBで対応に苦労したクエリ


この記事は、[株式会社うるる（ULURU） Advent Calendar 2023](https://qiita.com/advent-calendar/2023/uluru) の19日目の記事です。

私は長年にわたり検索システムの開発に携わっており、ここ１０年近くの開発では全文検索システム(SolrやElasticsearchなど)を利用したシステムに携わっています。全文検索システムを利用してからは検索の性能で苦労する機会はほとんどないのですが、全文検索システムを利用する前、RDBで検索をおこなっていたときにはとても苦労することがありました。今回はその苦労したクエリについて記事にしたいと思います。

## 対応に苦労したクエリ
RDBで検索を行う際は、主にBツリーインデックスが利用されます。このBツリーインデックスは検索する際、大抵は１テーブルにつき一つしか使用されません。そのため該当する件数が多い条件を復数指定するような検索をした際は性能がよくありません。

株式会社うるるでは[NJSS](https://www2.njss.info/)という入札情報の検索サービスを提供しています。この入札情報の検索を例にしますと、落札情報を検索する場合、データは1,700万件以上あり、検索条件には業種や履行場所といった条件を指定することができます。例えば業種が「土木工事か舗装工事」、履行場所が「東京都か神奈川県」といった具体で検索を行う事ができるのですが、このとき各条件に該当する件数はそれぞれ数百万件あります。

RDBでインデックスを作成して対応しようとする場合、業種と履行場所の複合インデックスを作成して、なるべくインデックスのスキャンだけにする方法があるかと思います。しかし、検索する条件が１項目に対して復数あったり、検索する項目が復数あったりすると、Bツリーインデックスでは効率よくデータを選択できず、該当する件数分に応じたデータ量を捜査せざるを得ない状況にすぐ陥ります。それでもテーブルのデータを読むよりデータ量が少ない分遥かに早いのですが、捜査する件数が多くなるとリニアに遅くなりますし、数百万件のデータとなってくるとやはり時間がかかります。また実際のところ履行場所は1案件に対して復数ありえるのですがそうした1:Nのデータには更にjoinのコストがかかります。また業種や履行場所以外にも、様々な検索条件やソート条件があるのですが、そうした多くの条件を複合インデックスで対応するには限界があります。

実際、当時行われた対応策（NJSSとは全く別のシステムです）としては、主に複合インデクスを作成することで対応していたのですが、その他には非正規化した検索用のテーブルを利用すること、また仕様として選択性の高い条件を検索時の必須項目にすることなどがありました。どうしても捜査するデータ量が問題で性能が十分でなかった部分は、物理的に読み込むブロックが減るようにするために物理的な配置の工夫も行いました。
結果的にそれで対応はできたのですが、条件によってはどうしても遅くなるものがあったり、条件追加などのメンテナンスがしづらかったりとの苦労や制約のあるものでした。

## 全文検索システムではどうだったか？
全文検索システムではこうした選択性の低い条件を復数指定する検索でも素早くレスポンスが返ってきます。そのためこうした通常の検索の性能では幸い苦労したことはありません。全文検索システムは全文検索機能を行える様になること以外にも、そうした検索も難なく早い性能で実現できるという強みがあります。
なぜ全文検索システムだと高速に処理できるのかについては、随所にビットマップによる索引の活用が見受けられるため、それによるものではないかと考えています。ビットマップによる索引や演算はRDBでも利用できるものがあり、仕組みの詳細はそちら（後述の[Oracleのビットマップ索引のドキュメント](https://docs.oracle.com/cd/F19136_01/cncpt/indexes-and-index-organized-tables.html#GUID-B15C4817-7748-456D-9740-8B9628AF9F47)など）が参考になります。

## RDBでの対応策
私は実際に試したことはないのですが、今回紹介したような私の苦労したクエリにも対応できるRDBもあるようです。（ただし実際の効果や性能については未確認です）

Oracleでは[ビットマップ索引](https://docs.oracle.com/cd/F19136_01/cncpt/indexes-and-index-organized-tables.html#GUID-B15C4817-7748-456D-9740-8B9628AF9F47)が解決策になりそうでした。ただし、ビットマップ索引はエンタープライズエディションでしか使用できません。

PostegreSQLの場合は[復数のインデックスを組み合わせて使用できる](https://www.postgresql.jp/document/15/html/indexes-bitmap-scans.html)ようです。これは今回この記事を書くために調べて初めて知ったのですがすごい利点だと思います。もし使う機会があればぜひ試してみたいと思いました。

## 最後に
今回の記事は以上になります。１０年以上前に苦労した時の話で、今はそもそもそうした苦労される人は少なかったり、別のよりよい解決策があったりするかもしれませんが、なんらかの参考になれば幸いです。
【EC2】WebサイトをGitHubを使って公開まで ～備忘録～

## GitHubからEC2にクローン
https://qiita.com/kn_program/items/c41c62f465368f0b0152

## Apacheのインストール
https://zenn.dev/grazie/articles/20c05aa22738b5

## フォルダのコピー
クローンしたファイルを「/var/www/html/」に移動させる
```
sudo cp -r フォルダ名/* /var/www/html/
```
https://envader.plus/course/1/scenario/1003https://qiita.com/kn_program/items/c41c62f465368f0b0152

## 追記
強引な方法になっていると思います。
他に良い方法があれば、教えてください。
機械学習で株価分析 04.機械学習の基礎

# はじめに
本記事では、**株価予測に機械学習手法を利用する上での基礎知識**を紹介します。ただし、初学者を対象にあくまで利用するためだけの基礎中の基礎の説明にとどめます。機械学習を株価予測に利用するにあたっての、勘所の把握の一助となることを目的としています。そのため、不正確・大雑把な表現が多分に含まれますがご容赦ください。誤り等についてのご指摘はコメントいただければ幸いです。


# 機械学習について
機械学習の特徴のひとつに、人間にはルールを見つけることが難しい複雑な条件設定から、ルールを導き出し結果を算出する、という点があります。株価予測に機械学習を用いる理由もそこにあります。様々な経済指標・株価等の膨大なデータから、株価等の予測したい結果を導くことが可能となります。

では、機械学習の正体は何なのでしょうか。答えは、言ってしまえば単に最適化問題を解いているだけです。より単純に言えば、$y = f(x)$ の関数$f$に当たる部分を自動的に設定するのが機械学習です。ここでは、アウトプットの$y$が予測したい株価等の情報、インプットの$x$が経済指標・株価等のデータに当たります。

したがって、株価予測に機械学習を用いるにあたって、重要なのは以下の3点です。
1. 機械学習手法と機械学習パラメータの選定（どんなルールで関数を定めるか）
1. 説明変数の設計（インプットの$x$をどう設定するか）
1. 目的変数の設計（アウトプットの$y$をどう設定するか）

機械学習手法の選定とパラメータの設定については、説明が膨大になるため本記事では割愛します。ぜひご自身で調査してみてください。以下では引き続き説明変数・目的変数の設計について説明します。


# 説明変数について
株価予測における説明変数は、一例としては以下などが考えられます。
* 始値・終値・高値・安値・出来高などの株価データ
* 営業利益・総資産などの財務データ
* 日経平均株価などの経済指標データ

説明変数の設計には、株式市場に関する基礎知識やテクニカル分析の知識が役立ちます。また、数理統計の知識も非常に有用です。

なお、説明変数の設計では、主に以下の点に留意する必要があります。
* 説明変数が少なすぎると機械学習モデルが単純になりすぎ、予測がうまく行かない。
* 説明変数が多すぎると機械学習モデルが複雑になりすぎ、予測がうまく行かない。
* 相関の高い説明変数を複数採用すると、予測精度が低下しやすい。

それぞれの理由は割愛しますので、興味のある方はご自身で調べてみてください。

# 目的変数について
株価予測における目的変数は、一例としては以下などが考えられます。
* 翌日の株価そのもの
* 翌日に株価が上がるか下がるかのTrue or False
* 翌日の株価上昇率ランキング

目的変数の設計は、資産運用における基礎知識・機械学習における基礎知識を踏まえ、自身で試行錯誤する必要があります。

なお、目的変数の設計では、主に以下の点に留意する必要があります。
* 目的変数はなるべくシンプルにしたほうが予測精度が上がりやすい。
* 複数の目的変数を設定したい場合は、ひとつの変数に統合する・機械学習を複数回試行する、という手段が有効である。

それぞれの理由は割愛しますので、興味のある方はご自身で調べてみてください。

# おわりに
本記事では、株価予測に機械学習を用いる際に、機械学習手法の選定・説明変数の設計・目的変数の設計、が重要と説明しました。

以下ご要望ありましたら、ぜひコメントをお待ちしております。
* こんな機械学習手法・パラメータ設定を試してほしい
* こんな説明変数を利用してみてはどうか
* こんな目的変数を設定してみてはどうか

コメント頂けましたら筆者の構築手法に反映し、結果を記事にてお伝えしようと思います。

# 目次へのリンク

https://qiita.com/ryo2_9393/items/2b1ada62c2537c901b6b
nlplotで自然言語の可視化

ライブラリ作成者の方のブログを参照しました。
https://www.takapy.work/entry/2020/05/17/192947
<br>
インストール
```python
pip install nlplot
```

ライブラリのインポート
```python
import nlplot
import pandas as pd
import plotly
from plotly.subplots import make_subplots
from plotly.offline import iplot
import matplotlib.pyplot as plt
```

```python
npt = nlplot.NLPlot(df_split, target_col='words')

stopwords = npt.get_stopword(top_n=0, min_freq=0)

npt.bar_ngram(
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    stopwords=stopwords,
)
```
```python
npt.treemap(
    title='Tree of Most Common Words',
    ngram=1,
    top_n=30,
    stopwords=stopwords,
)
```
```python
f =npt.wordcloud(
    max_words=100,
    max_font_size=100,
    colormap='tab20_r',
    stopwords=stopwords,
)
plt.imshow(f)
plt.axis("off")
plt.show()
```
```python
# ビルド（データ件数によっては処理に時間を要します）
npt.build_graph(stopwords=stopwords, min_edge_frequency=5)
```

ビルド後にノードとエッジの数が表示される。ノードの数が100前後になるようにするとネットワークが綺麗に描画できる
例：node_size:63, edge_size:63
```python
fig_co_network = npt.co_network(
    title='Co-occurrence network',
    sizing=100,
    node_size='adjacency_frequency',
    color_palette='hls',
    width=1100,
    height=700,
    save=False
)
iplot(fig_co_network)
```
MinecraftサーバーとGithubリポジトリの同期(CI/CD)

**Minecraft Command Advent Calendar 2023 シリーズ3 19日目の記事です。**

https://qiita.com/advent-calendar/2023/mccmd

# はじめに

データパックを複数人で開発している際、開発用のサーバーのデータパックを手動で更新した経験はありませんか？

それ、自動化できます。

:::note warn
サーバーはLinuxを想定しています。
Windowsでの動作保証はありません。
:::

# できること
- サーバーのデータパックを常に最新に保つ
- データパックの構文チェック
- サーバー内への更新通知

# 仕組み
Githubには様々なイベントをトリガーとして`Webhook`を送信する機能があります。

リポジトリにPush
↓
サーバーにWebhook送信
↓
サーバーでgit pullを実行

# 利用するコード / ライブラリ
Webhookを受け取るサーバー
以前作って実際に使っているものです ※必須

https://github.com/0kq-github/MCDatapack-CICD


Github Actionsでデータパックの検証を行う場合に使います ※オプション

https://github.com/ChenCMD/datapack-linter


サーバーでデータパックの検証を行う場合に使います ※オプション

https://github.com/mcbeet/mecha

# 手順

 1\. Python3.10以上をインストール
 2\. 以下のリポジトリをクローン

 https://github.com/0kq-github/MCDatapack-CICD
 
 3\. `pip install -r requirements.txt`で必要なパッケージのインストール
 4\. `config.py`の編集
 5\. `config.py`で設定したポートを開放
 6\. GitHubで対象のリポジトリを開き  
    Settings > Webhooks > Add webhookでwebhookを追加し  
    Payload URLに`http://サーバーアドレス/`  
    Content typeを`application/json`  
    イベントを`Just the push event.`  
    に設定する
 7\. `python main.py`でサーバーを起動

# Webhookを受け取るポートについて
ポート開放が必要ですが、できない環境の場合は以下のツールがおススメです。
難易度は★の数が多いほど高くなります。

## ngrok
難易度 ★
安定性 ★★★
対応プロトコル HTTP HTTPS TCP

一番簡単です。
起動のたびにポート番号が変わるのが難点です。

https://qiita.com/kujira_engineer/items/ce8f0f7e025324afc6b6


## cloudflared
難易度 ★★★
安定性 ★★★★
対応プロトコル HTTP HTTPS

ドメインを持っていると使いやすいです。

https://qiita.com/youtoy/items/3d312552f08a729bb5bb


## frp
難易度 ★★★★
安定性 ★★ ~ ★★★★★
対応プロトコル HTTP HTTPS TCP UDP 

VPSやポート開放できるマシンが別途必要です。
安いVPSとの組み合わせが最強です。

https://blog.tumf.dev/posts/diary/2021/1/2021-1-12/

# まとめ
チーム開発をする上でめちゃくちゃ便利なので皆さんも使ってみてください。
管理者としてsetupへの移行方法を間違えている


+ [Problemas para completar el Reto](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T6ANp)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2ca42678-4b5c-94d3-a21f-ef9f3e86e5af.png)

:::note
Please operate as below

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b6dd00df-4e91-7782-dc68-90d42c74171e.png)
:::
compileSdkVersionとtargetSdkVersionの違い

# はじめに
いつも忘れてしまう。SDKの違いについてメモとして残しておきます。


# targetSdkVersion
以下に影響する

* UIの見た目
* UIの動作のアニメーション

# compileSdkVersion
以下に影響する

* 指定したバージョンまでの機能が使える

## 注意！！
compileSdkVersionで指定したバージョンの機能が使えるけど下位互換を意識する必要がある
以下の表記のやつ

```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
  // ここはLollipop（Android 5.0）以降で実行される。
} else {
  // こっちはKitKat（Android 4.4）以前。
}
```

# まとめ
本当によく忘れるので覚えておいて損はないと思う。
バーコードとQRコードの生成プログラム

## バーコード生成プログラム
* 使用パッケージ：[barcode](https://python-barcode.readthedocs.io/en/stable/)

まだ詳しい事はわかっておりませんが、ひとまずバーコードを生成するところまで感覚でやってみました。

```zsh
pip3 install python-barcode
```

```zsh
pip3 install "python-barcode[images]"
```

```python
from io import BytesIO
from barcode import Code128
from barcode.writer import ImageWriter

# Write to a file-like object:
rv = BytesIO()
Code128(str(100000902922), writer=ImageWriter()).write(rv)

data = "AbCd-123456"
fileName = data + ".jpeg"

# Or to an actual file:
with open(fileName, "wb") as f:
    Code128(data, writer=ImageWriter()).write(f)
```

### 生成バーコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476751/0183efbf-e1fa-c3d7-5d51-8b82c7db4e60.png)

* [サポートフォーマット](https://python-barcode.readthedocs.io/en/stable/supported-formats.html?highlight=CODE128#barcode.codex.Code128)


## QRコード生成プログラム

```zsh
pip install PyQRCode
pip install pypng
```

```python
import qrcode
import pyqrcode

FILE_PNG_A = 'qrcode_A.png'

# QRコード作成
code = pyqrcode.create('https://qiita.com', error='L', version=3, mode='binary')
code.png("qiita.png", scale=5, module_color=[0, 0, 0, 128], background=[255, 255, 255])
```
### 生成QRコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476751/c6de6c9e-9105-ce9a-a697-08379f2dec51.png)



## 参考サイト

https://github.com/WhyNotHugo/python-barcode

https://www.keyence.co.jp/ss/products/autoid/codereader/basic-types.jsp
コミュニケーションで気を付けていることをちょっとだけ

この記事は [MicroAd (マイクロアド) Advent Calendar 2023](https://qiita.com/advent-calendar/2023/microad) 19日目の記事です。
今回は開発に必要なコミュニケーションを取る際に僕自身が気を付けていること、心掛けていることをまとめようと思います。

# 要約
以下記事の要約は、**相手のことを思いやってコミュニケーションを取ろう**です。  
相手のことを思いやるというのは単に相手をいたわるのみならず、相手の立場に立ったときどんな情報が欲しいか、どうコミュニケーションを取ってくれると動きやすいかを考慮するといったニュアンスを含みます。  
そんなの当たり前じゃん知ってるよ、という方はこの記事を読まなくても大丈夫そうです。一方で相手のことを思いやるって具体的にどうやるの？と思った方向けに記事を書こうと思います。　　

全般的に何をそんな当たり前のことを言ってるんだと思うかもしれませんが、新卒の頃の僕は全然できていなかったので自戒の意味を込めて記事にします。

# 気を付けるポイント

以下、コミュニケーションを取るときに気を付けている内容を項目ごとにまとめます。

## 相手の職能を意識する

一口にエンジニアと言っても担当は多岐に渡ります。  
僕はETL/ELT処理のバッチ開発チームに所属していますが、周りには広告配信システム開発チーム、画面開発チーム、機械学習チーム、インフラチーム...と多くのチームが存在します。  
所属するチームが異なれば背景知識が大きく異なるのは当たり前です。そのことを意識せず自チーム内の前提知識を元にコミュニケーションを取ろうとするとすれ違いが発生し、往々にして失敗します。  
相手のことを思いやった場合、「相手の立場だったら○○は知っているはず、××が気になるはず」という思考が発生します。  

具体例を挙げたほうが分かりやすいかもしれません。例えばインフラチームに相談するときにはアプリの用語よりミドルウェアやハードウェアの用語を用いたほうがスムーズに話が進みます。言語仕様に基づく実装方針を質問するよりネットワーク的な観点での懸念を質問した方が有益な情報がもらえます。ここを意識するのとしないのとでは話の進み方が段違いです。

## 優先度や内容に応じて口頭とチャットを使い分ける

開発を進めていると周りに相談・共有したい事項が多数出てきます。優先度・内容もバラバラで、どれをどうやって伝えようか悩みがちです。そんなとき、基本的に以下の口頭・チャットの二軸に従ってコミュニケーションを取ります。

- 以下に該当するものは口頭で相談・共有する
  - 緊急性の高いもの
  - 優先度の高いもの
  - 複雑な相談を含むもの
- 以下に該当するものはチャットで相談・共有する
  - 軽く共有しておきたいレベルのもの
  - 非常に多くのメンバーに告知しておく必要があるもの
  - AかBかといったシンプルな回答が想定されるもの

この軸が絶対というわけではありませんが、常にここを意識することに変わりありません。場合によっては併用することもあります。  
例えば障害対応のとき一次報告はチャットで、詳細報告は口頭で行うケースがあります。大規模開発の開始時には一番最初に口頭で全体感を共有した上で、詳細検討はチャットに移行するケースもあります。
ここでも重要なのは相手のことを思いやる意識です。相手の認知負荷を下げ、できる限り円滑に物事が進むように配慮します。

## 話の要点を絞る

相談・共有時には自分自身が得た情報を全て公開する必要はありません。得た情報の中から要点をピックアップして整理し、端的に報告します。情報量が多ければ多いほど相手は疲弊し、本来必要な理解や判断にたどり着けなくなってしまいます。  

要点を絞る重要性についてはこの世に数多ある書籍や文章で書きつくされていると思いますが、僕自身が強調したいのは「特に意思決定者に対して判断に必要な情報をまとめる意識を持つ」という点です。
意思決定者は職責が重く日々重要な判断を迫られています。そんな立場の方に一から十まで情報を開示するのはコストが高く、業務の無駄になりかねません。どのような経緯で何を決めるのか、決めるにあたって必要な情報は何か、といった観点からまとめられた報告が期待されます。

# 終わりに

過去の失敗経験を踏まえ、特に重要だと思ったポイントに絞って記事を書きました。　　
まだまだ書きたい内容はありますが、今回はここまで。  
今年も残りわずかですが、良い年の瀬をお過ごしください。
分析チームで振り返りの振り返りを実施して、アップデートした話


こんにちは！[shun](https://twitter.com/shun_xxx_1350)です。私はタイミーのデータ統括部 BIグループでデータ分析やLooker開発を担当しています。この記事は ["Timee Advent Calendar 2023"](https://qiita.com/advent-calendar/2023/timee) の19日目の記事です。

今回は、BIグループで振り返りの振り返りを実施して、アップデートした話を紹介したいと思います！

# 実施してきた振り返り

Good/Bad/NextやPNPT3(KPTとYWTのいいとこ取りをしたフレームワーク。[こちらの記事](https://qiita.com/newta/items/4a68a90ba7ca924e3397)を参考)のフレームワークを使って2週間ごとに振り返りを行なってきました。チームの状態を検査し、改善策を導き出すための重要なプロセスでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277089/c2a17e35-e9c6-eb9b-dba7-4cac7ae06368.png)

# 振り返りの見直しを行ったきっかけ

### BIグループ全体での振り返りのスコープが曖昧になっていた

BIグループが成長する中で、各ユニットやPJチームが組成されました。それぞれの単位で業務が進行するので、全体での振り返りの意義が曖昧になってきました。グループ全体での課題を抽出し解決に繋げるのが難しくなり、振り返りの生産性が低下していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277089/6964fe46-9396-3c3f-3731-072b7138d602.png)

# 実際に取り組んだこと

### 振り返りの意義/目的とスコープを考える会の実施

振り返りの場自体をなくすのも選択肢に入れつつ、改めてメンバーの認識や振り返りの場に期待していることを出し合い、議論しました。

その結果、下記のテーマを扱う場として存続する方針がまとまりました

- グループの目指す方向性やあり方を考える
- 分析環境やリソース配分の業務の効率性改善を考える
- 会議体やSlackチャンネル、BIグループへの依頼の受け方の運用フローの改善を考える
- 個人の興味やモヤモヤをラフに共有するコミュニケーションの場とする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277089/7d013ba5-218e-4e2c-d258-a57a933ffd85.png)



# 結果

### 運用方法の変更

振り返りたいテーマのネタDBを作成し、振り返りの日の前日にチームメンバーの投票により、扱うテーマを決める運用に変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277089/9097d960-7fb2-1ad1-36e5-ec819b620a91.png)


### テーマを決めた振り返りの実施

現在まで、「**BIグループの目指す姿/目標を考える回**」と「**BIグループに来る依頼や問い合わせを見直す回**」の二つのテーマを新しい運用方法に変えて実施しました。

振り返り時に関心が高いテーマに対してまとまった時間で深い議論ができるのがよい点だと感じています。

# まとめ

1. **振り返りのスコープの見直し:**
    
    BIグループ全体での振り返りのスコープが曖昧だった課題を克服するために、振り返りの目的やスコープを再検討しました。
    
2. **テーマに焦点を当てた振り返りの導入:**
    
    以前の振り返りでは一般的なフレームワークを使って全体で行っていましたが、特定のテーマに焦点を当て、そのテーマに基づいた振り返りを行っています。これにより、より具体的で深い議論が可能になりました。
    
3. **運用方法の変更とテーマの投票:**
    
    テーマを前日にメンバーが投票で選ぶ仕組みを導入したので、メンバー自身が重要視する課題やテーマにフォーカスできるようになりました。振り返り時点での最も重要なテーマに効果的に対処できるようになりました。また、事前にテーマに関する考えを整理し、有益な意見や提案を出しやすくなりました。
    

振り返りはチーム状況の検査と適応をするための手段であるため、チームの成長や変化に応じて振り返り自体のあり方を絶え間なくアップデートすることが大切だと感じました。

より自律的で強い組織に育っていくために、引き続き取り組んでいきたいと思っています。

# We’re Hiring!

タイミーのデータ統括部では、私たちとともに働くメンバーを募集しています。

現在募集中のポジションは[こちら](https://hrmos.co/pages/timee/jobs?category=1814216944314011650)です。

[カジュアル面談](https://devenable.timee.co.jp/casual)も行っていますので、興味を持っていただけた方は、ぜひお話しさせてください！
ISUCON的なパフォーマンスチューニングをリアルな現場で体験した記録

この記事はBBSakuraNetworksアドベントカレンダー2023の17日目の記事です
https://adventar.org/calendars/8572

# はじめに

発端はある時点からAPIのレスポンスが計測データ上で悪化する事象が起ったことでした。
その問題を解決するためにデータベースへのアクセスと、アプリケーションロジックの切り分けを行いました。
ISUCONをするというパフォーマンスチューニングの大会が存在しますが、これはISUCONをリアルな現場で行なった参戦記録になります。

## 事象について

まずどんな事件が起きたかを説明していきます。

* 特定の API のレスポンスタイムが普段の5倍ほどになっていた
* 計測データからはデータベースへアクセスしてデータ取得する処理の周辺で負荷が増えているように見える
* データベースの負荷は特に上がっていない

これらの情報から切り分けを行なっていきます。

## 切り分け1ステップ目: データベース処理遅延の疑い
直接目に見えるデータはデータベースへのアクセス時間が増加していることを示しています。
このため、データベースへ直接アクセスして処理遅延が発生しているか確認しますが、特に遅延が発生していません。
一旦データベース自体の処理遅延については考慮しないようにします。

## 切り分け2ステップ目: 計測データについて
1ステップ目でデータベースが直接遅延している訳ではないことが分かりました。
データベース内で処理遅延していない場合、計測データに問題がある可能性があります。
そのため、どの時点が計測対象になっているかを確認する必要がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/3d2426f8-c309-fbf5-ce96-dc3a5d40b2c0.png)
こちらの図で[データ取得<=>DB間]の処理には問題がないので、[処理<=>データ取得]間で時間のかかる処理が存在しないか確認していきます。

## 切り分け3ステップ目: 全 API に影響を与える処理の特定
[処理]は実際は多くの処理を含んでおり、特定の処理ではないので、問題のある処理の特定が必要です。この観点でソースコードにデバッグログを差し込んで確認するなど、遅延した処理の特定を行いました。
そこからAPIリクエストの最初に行う暗号化データの処理の負荷が高まっていることを特定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/be1fb2e5-4ff8-ec75-6b79-0938588815d3.png)
上記の例で言うと[デバッグログ1]の計測データに悪化が見られたことが分かりました。

## 暗号データの処理の内容を確認
被疑箇所の特定がで来ました。次に暗号データの処理で時間に影響する内容を特定していきます。暗号データで最も時間のかかる処理は暗号のデコード、エンコード処理です。このデコード、エンコード処理を行う被疑箇所に注目して、アプリケーションロジックを確認するとデータベースから取得して来たデータに対してデコード、エンコード処理をデータベースのレコード分行なっている処理が確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/2016a3cf-ac8e-7c0b-2932-4d529ccee0c6.png)
図は、全件データを取得して暗号データの処理を取得したデータ分行なっている当時の状況を表しています。

## 全件データの処理から必要なデータを絞り込む検討
全データから必要な処理を絞りこみ、必要なデータのみ処理の対象とすることがこのような問題の解決方法になります。
なので、全データを取得している処理からから必要なデータを絞りこみます。
このため、特定の識別子をデータベースのクエリに指定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/c67dfbd8-3442-4674-088c-88fd7d818cbe.png)

## 結果
以上の対応でAPIのパフォーマンスは劇的に改善されました。

## データベースとアプリケーショロジックのアンチパターンappendix
ここで、今までに遭遇したデータベースとアプリケーションロジックのアンチパターンをまとめておきます。

### N+1問題
有名なN+1問題です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/8250901f-e45f-8b43-5329-c26ddb3b7589.png)

解決方法はクエリを分けないで一回で取得すること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/e8b71bc3-f5b8-1154-68c8-cd4a3bf4d489.png)

### データベースからの複数件取得から、ロジック側で負荷の高い処理を高頻度で行う
今回APIの処理劣化で遭遇した問題です。

### データベースから大量の情報を取得する
いや、そんな大量のデータを気軽にSELECTするなよ問題です。
アプリケーションサーバのメモリかデータベースサーバのIOが死にます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/84fee280-bb7a-9de1-bf3c-86da253e907a.png)

### アプリケーションロジックのデータアクセス順序に関して
アプリケーションロジックから複数回にわたるデータアクセスがある場合、少ないデータに絞り込んでから次の処理でデータを渡す方が負荷が少ないが、最初にデータを絞り込まないで多いデータを次の処理に渡す問題です。
改善前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/bbab01e6-0290-3953-2de7-ec4b8927dfaa.png)

改善後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54281/48c1714d-11a7-33e7-4359-344f4c494471.png)


## 終わりに

ISUCONはリアルな業務でも役に立つコンテストであり、日々の業務に積極的に生かせる良いコンテストだと思います。
日々、システムパフォーマンスを上げるべくリアルな現場でISUCONをされている皆様と現場でのリアルISUCON話をまた共有したいです。
変数の入れ替え (paizaランク D 相当)

https://paiza.jp/works/mondai/array_utilization_primer/array_utilization_primer__excange

以前、コメントで教えてもらった方法でやってみる。

```py
X,Y=map(int,input().split())
X,Y = Y,X
print(X,Y)
```

一発OKでした
これすっごく便利ですね。

次に行ってみる

https://paiza.jp/works/mondai/array_utilization_primer/array_utilization_primer__swap

これもさっきので解けます
```py
N = int(input())
A = [int(input()) for _ in range(N)]
X,Y = map(int, input().split())
A[X-1],A[Y-1] = A[Y-1],A[X-1]
print(*A,sep="\n")
```
配列の順序の反転 Python3編

https://paiza.jp/works/mondai/array_utilization_primer/array_utilization_primer__reverse

私の答えは
```py
N = int(input())
A = [int(input()) for _ in range(N)]
print(*reversed(A),sep="\n")
```

まあ、これは前にもやったことなので難しくはない。
仮に、reversed関数がなかったとすると、どうするか。
まずはA配列を作るところまでは同じで
逆順のB配列を作るにはどうするか。
とりあえず前勉強した通り空の配列を作る

```py
B = [None] * N　#0でも同じ結果が出る
```

たとえば、５つの要素があるとして
B[0]＝A[4]
B[1]＝A[3]
B[2]＝A[2]
.
.
.
という順番になる。
これをルール化すればいいわけで、
i = 0なら、NからN（＝ここでは５）-０（＝i)-１
とすればいいのではと考えて、


```py
N = int(input())
A = [int(input()) for _ in range(N)]
B = [None] * N
for i in range(len(A)):
    B[i] = A[N-i-1]

print(*B,sep='\n')
```

OKでした
行指向JSONと列指向JSONのサイズ比較

WebAPIなどで送受信するJSONのサイズを限界まで小さくしたいと思った時に、列指向のJSONにした方が圧縮後も含めて小さくなりそうでいいかもと思ったので簡単に実験してみたメモです。

行指向JSONの例

```json
[{"d1":100, "d2":"aaa"}, {"d1": 101, "d2": "bbb"}]
```

列行指向JSONの例

```json
{"d1": [100, 101], "d2": ["aaa", "bbb"]}
```

## ダミーデータ生成プログラム

5000行分(1行2プロパティ)のデータを持つJSONを生成します。

```js
import fs from 'fs'

// generate random number arrays
function gen(n, min_value, max_value) {
    var arr = [];
    for (var i = 0; i < n; i++) {
        arr.push(Math.floor(Math.random() * (max_value - min_value)) + min_value);
    }
    return arr
}

function genAlphabets(n, size) {
    var arr = [];
    for (var i = 0; i < n; i++) {
        var str = "";
        for (var j = 0; j < size; j++) {
            str += String.fromCharCode(97 + Math.floor(Math.random() * 5));
        }
        arr.push(str);
    }
    return arr
}

const d1 = gen(5000, 0, 1000)
const d2 = genAlphabets(5000, 5)

const json1 = JSON.stringify({
    d1,
    d2
})
fs.writeFileSync('column_based.json', json1)


// column based json
const json2 = JSON.stringify(d1.map((x, i) => {
    return {
        d1: x,
        d2: d2[i]
    }
}))
fs.writeFileSync('row_based.json', json2)
```

| ファイル名 | サイズ | gzip(レベル6)圧縮後サイズ |
| ---- | ---- | ---- |
| 列指向データ | 59480| 21345 |
| 行指向データ | 119466 | 24127 |


この例では圧縮前で `50.2%`、圧縮後で `11.5%` 列指向JSONの方が小さくなりました。
WebAPIに送信するJSONの場合は圧縮されないことも多いので50%はかなり大きいですね。
意図しない視線誘導を避けるための素材のNG構図と画像補正のコツ

## はじめに
写真やイラストなど、素材選びや補正の際に意図せず不安感がある素材を選んだり、違和感のある画像補正をおこなってしまっている場合があります。
意図しない箇所への視線誘導を避けて本来注目させたい箇所がしっかりと目立つように、写真や素材を選ぶ際に避けたい構図・画像補正の際に気を付けたい基本のポイントをまとめました。

## :warning:人を不安にさせる避けたい構図
### 首切り構図・串刺し構図
窓枠や植物、背景の切り替わりなどが被写体の首の水平・垂直にあると首が分断されたり、頭に刺さっているような印象で不安感を煽ります。
画像を選ぶ際には被写体の背景も確認しておきましょう。
どうしても使いたい場合には、背景に強めにぼかしを入れたりして線の印象を薄めると印象はやわらぐかもしれません。

![2023_1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/f7a58267-30d9-6748-18e5-a4db7b1aa9d8.png)
![2023_1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/cd21e481-c631-8f6c-5eb6-ba8b1b2332cd.png)
***
### 目刺し構図 
被写体の目の付近に尖ったモチーフ・背景の切りかわりがあると目に刺さりそうな印象で不安感を煽ります。
目の付近に意図していないものが写ったり、配置していないか確認しておきましょう。

![2023_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/64fa7d9d-80b7-9ae8-1344-d74c33ff990a.png)
***
### 関節切り構図
前例の首切り構図・串刺し構図と同様に、手首・指・足首など関節で切る構図にすると不安感や違和感を与えます。
関節で切り取ると、その先にどのようなポーズをしているんだろうという意識が働いてしまうので、できればフルショット・ニーショット・ウエストショット・バストショット・アップショット(※1)のいずれかで切り取ると違和感を減らせます。

:::note warn
※1 なるべく首切り構図にならないようにバストアップよりも寄ったくらい・首よりやや下まで入れるように補正すると良いです。
:::

![2023_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/063c0a9b-2c42-3a58-239a-3943f436146d.png)

## :warning:画像補正の際に気を付けたいポイント
### 傾いた水平と垂直
あえて傾けて躍動感を出したいのならば問題はないですが、意図的でなければ傾きを補正して水平・垂直に見えるように調整しましょう。
水平・垂直にすることで、わずかな違和感をとり安定した印象になります。

![2023_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/fb928c55-6129-0afd-cb48-f436eb111cf6.png)
***
### 画像の端に被写体の端がピッタリと重なる
画面の端に被写体の端がピッタリと重なると、接点の付近に目がいきやすくなり窮屈な印象を与えます。
緊張感のある印象を与えたかったり、注目させたい箇所ならば問題はないですが、意図的でなければ大きく切り取るか・余白を持たせましょう。

![2023_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/c3488289-ad4e-2fb5-9f9f-93d881e6672e.png)
***
### 画像の端に、ちょっとだけ残す
画面の端に目立った色を少しだけ残して切り取るのは避けましょう。
前例で挙げた画像端と被写体の端がピッタリと重なると目立つように、画像の端に目立つ色が少しだけ残っていると目がいきやすくなります。
意図的でなければ、切り取ってしまうか・見えている面積を大きくさせ何が写っているか分かりやすくしましょう。

![2023_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/3200f330-3058-c82c-9b8f-10787bed0de5.png)
***
### 被写体の顔や目線が画像端に向いている
顔の向きや目線が画像端に向いていると注目させたい部分が画面の外に散乱してしまいます。
意図的に画像の外側に広がりを持たせたい場合は問題ないですが、意図的でなければ被写体の目線の先や顔の前(※2)にコンテンツや文字などをもってきましょう。

:::note warn
※2 顔とコンテンツが近すぎると窮屈な印象を与えるため、ある程度余白をあけて配置すると良いです。
:::

![2023_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301853/42d63152-94eb-152a-7c80-0271d2ff3a9b.png)
AI-102試験対策のまとめ「Azure AI Video Indexerのショット/シーン/キーフレーム検出」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
### Azure AI Video Indexerのショット/シーン/キーフレーム検出
* Azure AI Video Indexerは下記に基づいて一時的な単位にビデオをセグメント化する
    - 構造プロパティ
    - セマンティックプロパティ
* この機能により、下記の検出が可能となる
    - ショット：同じ動画カメラから撮影された連続するフレーム
    - シーン：単一のイベントを表し、意味的に関連する連続したショットで構成
    - キーフレーム：各ショットを最適に表すフレーム

#### **ショット検出**
* 下記の両方を追跡することで、ビデオのショットがいつ変化するのかを決定
    - 隣接するフレームの配色における突然の遷移
    - 隣接するフレームの配色における段階的な遷移
* ショットのメタデータには下記が含まれる
    - 開始時間
    - 終了時間
    - そのショットに含まれるキーフレームIDのリスト

#### **シーン検出**
* 連続するショット間の色の一貫性に基づいてビデオをシーンにセグメント化  
    ⇒各シーンの開始時刻と終了時刻を取得
* シーンのサムネイルは、その基になるショットの最初のキーフレーム

#### **キーフレーム検出**
* キーフレームは、審美的プロパティ(コントラストや安定性など)に基づいてビデオ全体から選択される
* ショットのメタデータの一部として、キーフレームIDのリストを取得  
    ⇒このリストに基づき、キーフレームを高解像度画像として抽出可能
* キーフレームを抽出するには、下記のいずれかの方法でビデオをアップロードしてインデックスを作成する
    - Azure AI Video Indexer Webサイトを使用
        1. ビデオをアップロードしてインデックスを作成
        1. Artifacts(ZIP)をダウンロード
        1. ZIPファイルを解凍することで抽出されたキーフレームを確認可能
    - Azure AI Video Indexer APIを使用
        1. `Upload Video`呼び出しを使用してビデオをアップロードしインデックスを作成
        1. `Get Video Indexer`を呼び出し、キーフレームIDのリストを表示
        1. `Get Thumbnails`呼び出しでキーフレームIDをそれぞれ実行
        1. 各キーフレームのイメージがダウンロードされる

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/azure-video-indexer/scenes-shots-keyframes


## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「Azure AI Video Indexerにおける多言語識別」**

https://qiita.com/fsd-jume/items/cf2264682a3d8a004bae

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d
Kiara Game Studio Prototype 随時更新

サイエンスの楽しさをマスマーケットに伝えたい
量子力学を幼稚園の必須科目にしたい
単純で笑いがある音ゲーにしよう！
いまの物理学のプレゼンはちょっとイキっているかも
場の量子論が難しい？
味方を変えるとホモサピエンスの能力が低いだけかもですよね
自然をありのままに、本質の論理のみを純粋数学で抜き出したら
割と単純なはず、という仮説を立てます

また、X = A x B x C x D

という状況で、一見複雑に見えるイシューを独立変数で分解すると
単純にそれぞれを数理最適化できます


企画書

https://docs.google.com/presentation/d/18OqZX_yHcl33vsg_pTlQmyWVAnGOpSouiQdHv8OJTik/edit?usp=sharing

以前のまとめ
https://zenn.dev/taka2_kiara/articles/d095a45d62cea9#car-driving-/-#games-#all-remix
ジンズが描くグローバルネットワーク

### この投稿は、2023年JINSのアドベントカレンダー19日目の記事です。

初日、11日目に続き、19日目の記事を岡田(@knt-okada)が担当致します。

今回はジンズが描くグローバルネットワークについての記事となります。

## 海外展開の状況
2022年8月時点での店舗数は以下のようになっております。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621633/b0bd7c13-bfa0-53a2-8337-875aaa84e6f9.png)

引用元：[JINS HOLDINGS](https://jinsholdings.com/jp/ja/)

以下はこれまでの店舗数の推移となりますが、2011年に海外第一号店となる中国に出店しそこから12年で海外店舗数は247店舗まで拡大致しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621633/dd76942f-08e2-c95b-b289-7fb1404f5f20.png)

## グローバルネットワーク運用の課題
グローバル規模でのシステム連携が必要となり、さらなる会社の成長・事業展開を支えるには以下を実現する必要がありました。

- 柔軟性・伸縮性を持たせたい
- 耐障害性を強くしたい
- 楽に管理したい

## ソリューション検討
以下をソリューション選定の軸に据えて検討を実施しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621633/3d9bd971-de4d-8167-dd39-03ea25fc0277.png)

SD-WAN、ZTNA、SASE等で検討を進めていきましたが、最終的にはSASEを導入することになりました。選定時の検討内容は以下となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621633/e9fe6b60-4140-3789-8f49-4c54c423862c.png)

初日の記事の中でお伝えした以下のSASEのネットワーク構成に社員、新オフィスだけでなく現在は一部店舗も組み込まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621633/bffa1674-00c3-ef7d-dab8-4ef6ba1216ae.png)

今後は日本国内だけでなく、海外の社員および店舗を含めてSASEに収容予定であり、会社のさらなる成長・事業展開を支えるグローバルネットワークを構築していきます。

#### 明日は@Akihiro_Yoshidaさんの『社内セキュリティエンジニアのおしごと』の記事です。
Androidスマホを使ったイーサネットテザリングによるWi-Fi環境構築例

:::note
1人暮らしの賃貸等で回線工事をするのが面倒な人向けに、イーサネットテザリングを使用したWi-Fi環境の構築方法についてまとめてみました。
:::

# イーサネットテザリングとは

スマートフォンに有線LANアダプターを取り付け、Wi-Fiルーター等に直接LANケーブルをつないでテザリングする方法をイーサネットテザリングと言います。

::: note warn
現時点※2023/12/19時点でイーサネットテザリングを使用できるスマートフォンは、Android11以上が搭載されたスマートフォンのみとなっています。
:::

# 必要なもの

- Android11以上のスマートフォン
    - 長時間使用するなら、大容量バッテリー搭載機種がおすすめです。
    - Rakuten Mobile等のデータ無制限プランで契約できるt通信キャリアで契約すると費用を抑えられます。（この記事で紹介する例では、Rakuten Mobileを使用しています）
    - 自宅で使用しているスマホ：**Galaxy S20 Ultra 5G**

https://www.samsung.com/jp/explore/hint/review-s20ultra/
        
- スマホ用の有線LANアダプター
    - 充電対応のものがおすすめです。充電対応のものであれば、充電用アダプターとケーブルも用意してください。
    - 自宅で使用しているアダプター：**Lemorele Usb c lan 変換 アダプタ**

https://amzn.asia/d/eCOEhLR

- LANケーブル
    - 100均に売ってるもので十分だと思います。
- Wi-Fiルーター
    - こだわりがなければ何でもいいです。
    - 自宅で使用しているルーター：**AirMac Express 802.11n (第2世代)**

https://support.apple.com/kb/SP651?locale=ja_JP
        

# 接続方法の手順

1. スマホに有線LANアダプターを取り付け、ケーブルを使ってWi-FiルーターのWANポートに接続する
2. スマホのテザリング画面でイーサネットテザリングをONにする
    ![Screenshot_20231218_133005_Settings.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1995005/c0ed03cd-34ba-c928-aeb4-f39863dafdbf.jpeg)
    
3. ルーター側でWi-Fiの接続がアクティブになれば、Wi-Fi環境構築は完了です。

# 通信速度

## 通常のテザリングの速度
![download.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1995005/ec950c27-7773-5a56-c890-c2aaabd2e49e.jpeg)

- 仕事ができない速度ではないですが、この状態だと時々接続が瞬断することがあります。

## イーサネットテザリングの速度

![download 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1995005/2d3a6274-24ee-c639-780b-3e5fe8a752ed.jpeg)


- 通常のテザリングに比べて約10Mbps程度早くなります。
- 仕事中に接続が切れたりすることもなく、安定して使用できる実感です。

## PCに有線LANアダプターをつけ、イーサネットテザリング状態のWi-Fiルーターと有線接続した場合の速度

![download 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1995005/277ea34c-a78a-187d-5834-da85b624e18f.jpeg)

- 大体60~80Mbpsくらいの速度になります。
- おそらくイーサネットテザリングをする場合に、一番早くて安定した接続するならこの手段が一番だと思います。
- Wi-Fiルーターを介さずにスマホとPCを直接有線ケーブルで接続する方法もあるみたいですが、私の場合はそれだとスマホ側でイーサネットテザリングがアクティブになりませんでした。
【キーボード】キーボードって200種類以上あんねん【沼】

私は常日頃から作業環境はよくしろと啓蒙活動を行っているのですが、その一環にキーボードがあります。今回は私が12年間かけて触ってきたキーボードの紹介と結論をお伝えしたいと思います。

まず、キーボードには沼というものがあり、好きなキーボードを見つけるまでキーボードを買い続けることになります。そして好きなキーボードに出会ってもより良いキーボードに出会うこともあります。気にせずに**散財**していきましょう。

Happy Hacking Keyboard（以下、HHKB）を使っている方なら聞いたことあると思いますが私もこの言葉を知ったときにそうだなってなったので引用させていただきます。

> アメリカ⻄部のカウボーイたちは、
> 馬が死ぬと馬はそこに残していくが、
> どんなに砂漠を歩こうとも、鞍は自分で担いで往く。
> 
> 馬は消耗品であり、
> 鞍は自分の体に馴染んだインタフェースだからだ。
> 
> いまやパソコンは消耗品であり、キーボードは大切な、
> 生涯使えるインタフェースであることを忘れてはいけない。

ただ、先程も述べましたが良い鞍が一つとは限らないのです、RPGをやっている方なら分かると思いますが新しい街に行き新しい武器を買う、そんな気持ちです。

さて前置きが長くなりましたが、私のキーボード遍歴とおすすめポイントを伝えていきます。

# ノートパソコンのキーボード（パンタグラフ）
現場で渡されたノートパソコンをそのまま使うパターンですね、Webシステムを作成する現場ではデスクトップパソコンの性能が不要なため、持ち歩けるノートパソコンが支給されるケースがあります。そして大抵のノートパソコンはパンタグラフと言われる機構になっています。正直最初はこれでなれてたのでキーボードって何でも大丈夫じゃんって思っていた時期でもあります。

# HHKB
そして出会ったのが、HHKB。キーボードを叩くとまじで幸せになれる謎成分が分泌されます。私が買ったのはHHKB Professional JP。これは長年使いました、スコスコという気持ちの良い打鍵音と長時間打っていても疲れない感覚。セブンイレブンのATM（テンキー）にも使われている無接点静電容量方式と呼ばれる。HHKBの他にもREALFORCEというキーボードも同じ方式を採用しているリッチなやつだ。
HHKBの場合、フルキーボードからテンキーとファンクションキーを除いた、65%キーボードと言われるものになるが慣れはそんなに必要ない気がする。
カッコいいからと言って、英語配列にした場合方向キーも無い60%となるので注意が必要です。
私は英語配列のカッコよさ、利便性のある配列なことを理解しながらも永遠に日本語配列を使っております。

# MINILA Air
次に紹介するのは、なんとなく遊びで買った、Majestouch MINILA Air JP68キー 赤軸。
スペースの両脇にFnキーがついてる、ちょっと特殊なキーボード。
ただ、そこまでFnによる変更にメリットを感じず、カスタマイズできるような機構があれば良かったのですがそんなことも無かったので、結構早めに使うのを辞めてしまった。

# ErgoDox EZ
その後、分割キーボードやキーマップのリマッピングが流行ってきて、ErgoDox EZを購入した。はんだごては使いたくなかったので、出来合いを輸入しました。

マッピングに関してはめっちゃ楽しかったな、白軸にしてしまったのでタッチがかるすぎたのはちょっと失敗でしたが、現場で使うと私のパソコンは触れないって言われるので良かったな。キー数が多いので問題にはならなかったが、私はBだけ右手で押す癖があるのでNの左にあるキーにマッピングしてたな。なのでキー数が少なかったりリマップできない分割キーボードは使えないんだろうなぁってこのとき実感しました。
あとはこのときに親指でエンターを押す快感を覚えてしまいました。
バックスペースとエンターってどの配列でも右側にあると思うのですが、こんなに押す機会があるものが端っこにある理由がよく分からんのですよね、スペースは真ん中にあるでしょ？

https://qiita.com/ysm_slj/items/b94215d3b946d3ded0fe

# その後
複数の現場を行ったり来たりすることが多くなり、キーボードを持ち運ぶ（鞍を担ぐ）のが面倒になりMacBookキーボードを使ってました（ぉぃぉぃ）。
でも弘法筆を選ばずという言葉もあるし、結構慣れたらまぁ打ちやすいキーボードだと思いました。私はTouch Bar搭載のキーボードが好きでした、カスタマイズするのが楽しいからね！！

コロナ禍でリモートワークが増えてきて、在宅勤務のため、またHHKBを使っておりましたが、2023年10月25日革新が生まれます。
HHKB Studioが発表されました。
私はこの日、HHKBユーザミートアップ Vol.7に参加したのですが現地で販売していた為、触って数秒で買いに走ってしまいました。

発表時はメカニカルキーボードと聞いて、HHKBがメカニカル？無接点静電容量方式なら即買いなのにな、触れたらいいな。って気持ちだったのですが、触ってみてびっくり、言われなければ無接点静電容量方式に感じます、つまりHHKBが出したものはHHKBなのでした（当たり前体操）。

このキーボードにはマウスポインティングとジェスチャーパッドという変態機能が備わっているのですが、使い込んで思ったこととしてこの2つを有効に活用できてません。  [^1] 

それでも買ってよかったと思えるのはキーのマッピングが可能なこと、これは最近のBT対応HHKBであればある程度リマッピングはできるものの、Fn押しながらキーを押すことで別キーにするレイヤー機能が2面しかないこと、このStudioは4面あるのでとても色々な事ができます。
基本的にはErgoDoxで組んでいたマッピングを参照して、HJKLで矢印を置いたり、そのあたりにテンキーを置いたり、左手ハーフキーボードにしたりです。

ポインティングデバイス用に配置されている、左クリック、中クリック(Fn)、右クリックを全部置換して、スペース、バックスペース、エンターにすることで小指を疲れにくくすることができます。人を選びますが私はこれが最強だと思っています。
従来のスペースにはFnを割り当てしているので、MINILA Airを思い出す感じになります（伏線回収）。
カスタマイズは無限大なので、今後もよりよい使い方があればQiitaの記事にしたいと思います！！！

でも、HHKB Studioではまだまだできない機能（マクロやワンショットモディファイア）があるので早くファームウェア公開もしくはアップデートしてほしいです。

# 結論
## まだキーボード初心者のあなたへ
まずは秋葉原とか行ってキーボードを触ってみて違いを理解すべし！

## キーボード中級者のあなたへ
高級なキーボードを買うのをためらうな！

## キーボード上級者のあなたへ
一緒に変態になろう！

以上です。素晴らしいキーボードライフを…。

[^1]: 参考 https://hirama1406.com/pointing-stick
GPT-4に将棋解説してもらうアプリを作ってみた

# はじめに
初めて記事投稿します、yamashitaと申します。  
私は現在プログラミングスクールRUNTEQでRuby on Railsを中心にプログラミング学習中の初学者です。

今回は、私の趣味である将棋をOpenAIのAPIに解説してもらうアプリを作ったので、開発日誌も兼ねて投稿してみます。更新などあれば追記したいと思います。  
アプリは現在公開中で、URLはこちらです：[https://shogikaisetukun.com/](https://shogikaisetukun.com/)

# 経緯
調べてみたところ、ChatGPTと将棋を指す試みをされている方はいましたが、解説させてる方は見受けられなかったので作ってみました。既にいたらごめんなさい。

# 結果
現行で出てるモデルでは、精度の高い解説は生成できませんでした。  
将棋を知らない方からはそれっぽく見え、知っている方からは間違った解説を面白がってもらうジョークアプリみたいになりました。

採用したモデルは「gpt-4-1106-preview」です。現行のChat Completions APIの最新版です。  
「gpt-3.5-turbo-1106」ではオリジナルの戦型や囲いの名前を連発しました。  
もっと下位のモデルだとそもそも日本語が怪しくボツとしました。  
また新しいモデルが出たら随時試してみたいと思います。  

画像は「gpt-4-1106-preview」で生成した解説です。それっぽいけど殆ど合ってません。
ちなみに形勢は後手の典型的な大やらかしにより先手勝勢です。

![shogi-board-1702924872.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656491/f424985c-6b18-5647-7f57-91c1fdc02694.png)

# 技術面
フロントエンドはReact、バックエンドはRuby on RailsをAPIで使用しています。  
将棋UIの作成については、shogi-player-wc（[https://shogi-player.netlify.app/](https://shogi-player.netlify.app/)）を使用させていただきました。  
詳細はGitHubをご確認ください。：[https://github.com/yamashita-takahiro-44/shogi-kaisetukun](https://github.com/yamashita-takahiro-44/shogi-kaisetukun)

# 機能
シンプルに使ってもらえるようSPAで認証などは何も要らない作りにしました。  
KIFあるいはSFEN形式の棋譜を読み込む、あるいは手動で一手ずつ盤面を動かして、解説ボタンを押すことで解説が生成されます。  
今後の機能追加は検討中です。

# まとめ
やっぱり将棋は専門的な知識なのでトレーニングデータを準備してしっかり学習させないと厳しいのかなと思いました。  
現行のGPT-4による解説を可愛がってくれる人が少しでもいれば幸いです。
そもそも将棋用のAIじゃないので、個人的にはそれっぽい解説が出てくるだけで凄い技術だと感動してます。
今後も面白そうと思えるアプリを作っていきたいと思います。  
ご意見・ご感想はコメント欄あるいはtwitterまでお願いします。[https://twitter.com/yamashita_44](https://twitter.com/yamashita_44)

# 追記
12/21　アップグレード第一弾
将棋を知らない方でもなんとなく遊んでもらえるよう、棋譜プリセット、
GPTのバージョン、プロンプトをいくつか選べるようにしました。

12/26 アップグレード第二弾
・見た目をなんかいい感じに。 
・トップページ、画像投稿機能、ランキング機能追加 
・画像へのコメント機能追加 
・URLベタ打ちやリロードしても動くようになった 
本筋と関係ないんですが、最後の機能実装に他の機能の10倍ぐらい時間かかりました。
react-router-domでルーティングしたのですがそのままだとリロードとかURLベタ打ちすると動きませんでした。
そこでNginx導入を検討しましたがうまく動きませんでした（Rails-apiへのPOSTリクエストが弾かれ続けた。）。
結局フロントエンドだけVercelでデプロイし、vercel.jsonでリクエストをindex.htmlにリライトしてもらう手法で思った通りURLベタ打ちやリロードしても問題無い実装ができました。
vercel.jsonはこんな感じです。

```
{
  "version": 2,
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/static-build",
      "config": { "distDir": "build" }
    }
  ],
  "rewrites": [
    { "source": "/(.*)", "destination": "/index.html" }
  ]
}

```
SwiftUIのページビューにおけるライフサイクルを観察する

SwiftUIでは `TabView` を使ってページビューを作成できますが、多量のページを表示したい場合に負荷的な問題がないのか、ライフサイクルを観察してみました。

以下のコードを動かしてみます。

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            ForEach((1..<100)) { id in
                Page(id: id)
            }
        }
        .tabViewStyle(.page)
    }
    
    private struct Page: View {
        let id: Int
        
        init(id: Int) {
            self.id = id
            print("Instantiate: \(id)")
        }
        
        var body: some View {
            print("Render: \(id)")
            return Text("Page\(id)")
                .onAppear { print("Appear: \(id)") }
                .onDisappear { print("Disappear: \(id)") }
        }
    }
}
```

アプリ起動後、以下のログが出力されました。

```
Instantiate: 1
Instantiate: 2
Instantiate: 3
...
Instantiate: 99
Instantiate: 1
Render: 1
Appear: 1
```

この後次のページへの切り替えを行なっていくと、

```
Instantiate: 2
Render: 2
Appear: 2
Instantiate: 3
Render: 3
Appear: 3
Disappear: 1
Disappear: 2
...
```

と出力されました。

推察するに、

1. `TabView` の ViewBuilder でページ数分の `Page` がインスタンス化される
(ページ数計上のため？そしてレンダリングは行わない)
2. 実際に表示するページごとに `Page` をインスタンス化、表示のためレンダリング

という挙動になっているようです。

SwiftUIのViewは何度もインスタンス化されるものなので、 `init` に高負荷な処理を入れない限りは問題なさそうです！
OSSJでのOSPOのパネルディスカッションを終えて

# はじめに
12/6に続いて、再び投稿させていただく大和田です。本日は、Open Source Summit Japan 2023の2日目に行われたパネルディスカッション ["The OSPO Panel of JAPAN 2023: How to Accelerate OSPO?"](https://sched.co/1TyrU)について簡単に報告します。

# 概要
Open Source Summitは[The Linux Foundation](https://www.linuxfoundation.org/)が開催するLinuxをはじめとするOSSに関わる人々が集まるイベントで、世界各地で行われています。12/5-6に日本の有明セントラルタワーホール＆カンファレンスで開催されました。12/19の投稿にその概要が紹介されています。

ご紹介するパネルディスカッション ["The OSPO Panel of JAPAN 2023: How to Accelerate OSPO?"](https://sched.co/1TyrU)は、[TODO Group](https://todogroup.org/ja/)のAnaさんにモデレーターをしていただき、[Open Chain Japan Work Group](https://openchain-project.github.io/OpenChain-JWG/)のOSPO SWGのメンバーで行いました。

日本でもOSPOを設置する企業が増えてきていますが、OSPOについてよくご存じない方も多く、OSSコミュニティ活動の重要性やOSPO設置の有益性についてお伝えしたいと行ったものです。
日本でのOSPOの理解を広める活動例として、OSPOを紹介する漫画[^1]や、OpenChain Japan Work GroupのOSPO SubWGの活動[^2]を紹介したのち、ディスカッションを行っています。
ディスカッションやその後のQ＆Aの内容については、[Open Source Summit Japan 2023のスケジュールサイト](https://sched.co/1TyrU)にリンクのあるビデオをご覧いただくと良いと思います。


![53381004123_6e18cf929e_c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/c5295331-8d2f-d14b-d289-a92a00be3f24.jpeg)
The Linux Foundation / CC BY-NC 2.0 DEED
https://www.flickr.com/photos/linuxfoundation/53381004123/in/album-72177720312540604/


# なぜ、このパネルディスカッションを行ったのか
それぞれの企業内の取り組みであるはずのOSPOについて、なぜ、このようなOpenな場で話をしているのかと思われるかもしれません。

実は、これもOSPOの活動の一つだからです。

OSPOにはいろいろな側面があり、OSPOが何かを端的に表現するのはむずかしいのですが、一つの説明として「OSPOはOSSコミュニティ活動を企業活動で有効活用する状態を目指すもの」ということができると思います。

今日、OSSは企業活動に必須となっています。そのOSSの開発、発展を支えているのはOSSコミュニティです。そのOSSコミュニティは、多くの企業からの貢献によって成り立っています。つまり、多くの企業の貢献が個々の企業活動に必須という状態になっているのです。
Openな場で、話をすることで、OSS、および、OSSコミュニティについて理解が広がり、OSSコミュニティ活動と企業活動の効果的な連携が他社に広がれば、自社にもその恩恵がもたらされる、と考えています。

一方で、OSSコミュニティとの効果的な連携とはどんなものかは、それぞれの企業の状況によって様々です。また、OSSコミュニティの状態は常に変化するので、絶対的な正解はありません。
常に、よりよい関係を追い続けるものだと思います。
そのために、自分の取り組みをOpenにして、周囲に働きかけるとともに、フィードバックを得て自身も変化することを繰り返して、正解に近づくという活動が最適な戦略なのだと考えています。

# おわりに

パネルディスカッションの報告のつもりが、自身のOSPOについての考えを書かせていただきました。これもOSPOの活動の一つになっていると思います。フィードバックをいただけると大変うれしいです。


[^1]:OSPO紹介漫画
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/b0d2568b-a038-020c-5d7c-cf37652c1beb.png)
by みらくるちゃん(@miraclelinux) CC BY-SA 4.0
https://www.miraclelinux.com/miracle110/miracle-chan/miracle-chan#------------
[^2]:参考：[OSPO SWG(第2週)の紹介](https://qiita.com/hiromotai7/items/68f5f8f64e0e01b9b60f), [OSPO SWG(第4週)の紹介](https://qiita.com/owada-k/items/017d1b98d0e437766bd0)
Appium Capabilities memo

# background

appiumを使ってテスト自動化をするときに、必ずcapabilisitesの設定が発生する。
そして、毎回ググって必須項目等を調べていたw
それが面倒なのでよく使うCapability Nameをまとめた

appium inspectorでデバイスに接続するときの、設定項目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/be690f07-b6ac-8c13-d641-a3e8ba9f8556.png)

capabilities detail
https://appium.io/docs/en/2.1/guides/caps/


# iOS編

| Capability Name | mean | example |
|:-----------|:------------|:------------|
| platformName       | The type of platform        | ios         |
| platformVersion       | The version of a platform        | 16         |
| deviceName       | The name of a particular device        | iPhone15         |
| automationName       | The name of the Appium driver        | XCUITest         |
| udid       | device id         | XXXXX-XXXXXX         |
| bundleId       | The name of the Application         | jp.co.xxxx.xxx         |
| app       | ipa path to install          | ~/app/xxxx.ipa         |
| wdaStartupRetries       | Number of times to try to build and launch WebDriverAgent          | 4         |
| wdaStartupRetryInterval       | Time, in ms, to wait between tries to build and launch WebDriverAgent          | 20000         |
| iosInstallPause       | Time in milliseconds to pause between installing the application and starting WebDriverAgent          | 8000         |
| nativeWebTap       | Enable native, non-javascript-based taps being in web context mode          | true         |
| autoAcceptAlerts       | Accept all iOS alerts automatically if they pop up          | false         |
| noReset       | Prevents the device to be reset before the session startup if set to true          | true         |
| autoGrantPermissions       | Accept all  Grant Permissions         | true         |

udidはFinderで調べることができる
bundleIdはcfgutil（Apple Configurator2 に付属）で調べることができる

# Android編

| Capability Name | mean | example |
|:-----------|:------------|:------------|
| platformName       | The type of platform        | android         |
| platformVersion       | The version of a platform        | 12         |
| deviceName       | The name of a particular device        | XPERIA5         |
| automationName       | The name of the Appium driver        | UiAutomator2         |
| udid       | device id         | XXXXX-XXXXXX         |
| bundleId       | The name of the Application         | jp.co.xxxx.xxx         |
| noReset       | Prevents the device to be reset before the session startup if set to true          | true         |
| autoGrantPermissions       | Accept all  Grant Permissions         | true         |



udidはadbで調べることができる
bundleIdはadbで調べることができる

```
adb shell pm list packages
```
自衛官からエンジニアへ Elixirから始める Web開発 Part21

この記事は「Elixir Advent Calendar 2023」21日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

普段は 合同会社TheWaggle で教材開発・システム開発・研修講師などマルチに活動してます。

このシリーズでは、文系ですらない、体育会系でも始められるプログラミング学習　というテーマで元自衛官だった僕が
自衛官からエンジニアになってもらいたいという気持ちを込めて、普段は大人しいですが、このコラムシリーズでは、あえて、体育会系のノリで、貴様ら理屈で覚えるなら体で覚えろ！というノリで書いてみたいと思います。

なので、初学者向けですが、理論は後回し、まずは動かして体感しろってノリの第21回目です。

それでは、いくぞ！

## リファクタリング



```elixir
defmodule TNT do
    def create_c4({"RDX", rdx},{"ポリイソブチレン", polyisobutylene},{"モーターオイル", motorOil},{"セバシン酸ジオクチル", dioctylSebacate},{"ガソリン", gasoline}) do
        { g , ml } =
        [ rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline ]
        |> Enum.split(-1)

        g_results = 
        Enum.map(g, &(String.codepoints(&1) |> List.delete_at(-1) |> List.to_string() |> String.to_float()))

        ml_result = "25ml" |> String.codepoints() |> List.delete_at(-1) |> List.delete_at(-1) |> List.to_string() |> String.to_integer()
        
        g_results ++ [ml_result]
    end
end
```
貴様らが作ったものを改良して前回、以下のように修正した。しかし、まだまだ改良する余地がある。

```elixir
defmodule TNT do
  def create_c4({"RDX", rdx}, {"ポリイソブチレン", polyisobutylene}, {"モーターオイル", motorOil}, {"セバシン酸ジオクチル", dioctylSebacate}, {"ガソリン", gasoline}) do
    materials = [rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline]

    Enum.map(materials, fn material ->
      # 単位を取り除く
      numeric_part = material
                      |> String.trim_trailing("g")
                      |> String.trim_trailing("ml")

      # 小数点の有無に基づいて数値に変換
      if String.contains?(numeric_part, ".") do
        String.to_float(numeric_part)
      else
        String.to_integer(numeric_part)
      end
    end)
  end
end
```

さらに改良したのが以下のコードだ。この改良にはいくつかのポイントがある。また、さらに貴様らが知らない技術が盛りだくさんだ。　また、今回から少しづつ教えてやるから、貴様らのそのnil頭によーく、詰め込んでおけ！

貴様らが書いたTNTモジュールはまるでクソコードだったが、それを改良したコードもまだまだ無駄が多い！　そう、まるで新兵のように未熟だ。今からこのひどいコード、いわば新兵から熟練の兵士に鍛えあげてやる！

### ダメなコード部分
単位の取り除き方が雑だ：String.trim_trailing/2を二回も使ってるだと？！貴様、それは無駄だ！もっと効率的な方法がある。

重複するロジック：String.contains?/2 で小数点の有無を確認し、それに基づいてString.to_float/1 か String.to_integer/1 を使ってる。このロジック、何度も使ってるなら別の関数に切り出せ！

### 改良点
単位を取り除く効率的な方法：正規表現を使って一度に単位を取り除け。String.replace/3 がお前の友だ。

数値変換のロジックを別関数に切り出せ：小数点の有無に基づく変換処理を繰り返し使うなら、それは別の関数にしろ。コードの重複は敵だ！

これらを踏まえて、改良したコードがこれだ。

```elixir
defmodule TNT do
  def create_c4({"RDX", rdx}, {"ポリイソブチレン", polyisobutylene}, {"モーターオイル", motorOil}, {"セバシン酸ジオクチル", dioctylSebacate}, {"ガソリン", gasoline}) do
    materials = [rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline]

    Enum.map(materials, &convert_material_to_numeric/1)
  end

  defp convert_material_to_numeric(material) do
    numeric_part = String.replace(material, ~r/[gml]/, "")
    
    convert_to_numeric(numeric_part)
  end

  defp convert_to_numeric(numeric_part) do
    if String.contains?(numeric_part, ".") do
      String.to_float(numeric_part)
    else
      String.to_integer(numeric_part)
    end
  end
end
```

このように新兵のようなコードをを鍛えることをリファクタリングという！ 
常に、貴様らは最初から熟練の兵士のようなコードは書けない！ だが、新米だろうが、熟練だろうが、まずは結果を出せれば良い！ 結果を出してから今回のようにリファクタリングをして行けばいいんだ！　わかったな！

* 教官！　何やら見たことないコード が沢山あります！

いいだろう！　次回以降で新たに出てきたコードを解説してやろう。 それでは 次回 Part22でまた会おう！
lubridateのメモ

# 初めに
lubridateパッケージを使っていると迷うことが多いので、調べたことをまとめている途中ですが、R言語 Advent Calendar 2023年（2nd）に空きが多いので投稿します。

まず初めにlubridateは遅いので（可読性は高いが）大規模データには使わない方がいいらしい。
https://qiita.com/okiyuki99/items/85ba75d232eb18717111

# 文字列から時刻型への変換
基本的にはあらゆる日付・時刻の文字列を変換する関数が用意されている。
変換したい文字列における年 (y), 月 (m), 日 (d), 時 (h), 分 (m) and 秒 (s) の要素の並び順を把握し、それに応じた関数を選ぶ。返り値の型別に整理する。
なお、以下の関数で変換するときにはタイムゾーンが

## Datetime型
ymd_hms(), ymd_hm(), ymd_h(). 
日本人にとってオーソドックスな`YYYYMMDD hh:mm:ss`の並び順で出てくるときに使う関数である。
下記のように日本語を含めた大体の表記はいけるが、元号は非対応である。
```R
> ymd_hms("2023/01/20 12:34:56")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("2023/01/20T12:34:56")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("2023-01-20 123456")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("20230120123456")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("2023年01月20日12時34分56秒")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("2023年1月20日12時34分56秒")
[1] "2023-01-20 12:34:56 UTC"
> ymd_hms("令和3年1月20日12時34分56秒")
[1] NA
```
ただし、この場合ではタイムゾーン付加されているが、（日本語の場合含めて）UTCになってしまっている。
タイムゾーンを以下の様に指定する必要がある。
```R
> ymd_hms("2023/01/20T12:34:56",tz="Japan")
[1] "2023-01-20 12:34:56 JST"
> ymd_hms("2023/01/20T12:34:56+09:00")
[1] "2023-01-20 03:34:56 UTC"
```
# Timezoneの変換

```R
> lubridate::now()
[1] "2023-01-17 12:49:24 JST"

> hoge <- lubridate::now()
> hoge
[1] "2023-01-17 12:50:38 JST"
> lubridate::force_tz(hoge,tz="GMT")
[1] "2023-01-17 12:50:38 GMT"
> lubridate::with_tz(hoge,tz="GMT")
[1] "2023-01-17 03:50:38 GMT"
```

with_tzではタイムゾーンの変更のみ（表示される時刻は変わるが時刻は変わらない）が、
force_tzではタイムゾーンを強制的に変えるので時刻が変わる（表示される時刻は変わらない）。

`OlsonNames()`を使えば、tzの指定に使えタイムゾーン一覧がでてくるが、"UTC"と"Japan"だけ覚えておけば日本人の使いたい業務の9割をカバーできるのではないかと思う。
（海外展開する予定ないのデータにtimezone付の時刻データで保存してわざわざUTCを付加するされていてはまってしまったせいでこの記事がかかれました。）
【Python】巡回セールスマンライブラリ

競技用にチューンした巡回セールスマン問題解法です。

# コード
```py
def TSPdp(n, d, inf):
  ln = 1 << n
  dp = [inf] * (ln * n)
  for k in range(n): dp[ln * k + (1 << k)] = 0
  for i in range(1, 1 << n):
    for x in range(n):
      t = i + x * ln
      j = 1
      for y in range(n):
        if i & j:
          j <<= 1
          continue
        tt = (i | j) + y * ln
        if dp[tt] > dp[t] + d[x * n + y]: dp[tt] = dp[t] + d[x * n + y]
        j <<= 1
  return dp
```

$n$ を頂点数、$d$ を距離行列、たどり着けない場所の値 (無限) を $inf$ とします。

$\mathcal{O}(2^nn^2)$ の時間計算量で計算する動的計画法を行います。
dp テーブルは二次元配列を flatten して一次元にすることで参照コストを減らしています。

最終的な dp 配列は、
$$dp_{i2^n+j} := 現在地が i であり、訪問した頂点集合がbit表現でjとして表されるときのこの時点での最適解$$

となります。

## 使い方
$n$, $d$, $inf$ を入力して、出力を解読してください。特に、
$$dp_{i2^n+2^n - 1} := 終了地点が i であり、全頂点訪問した際の最適解$$

となります。

これは多始点ですが 4 行目を変えれば単一始点になります。


# おわり
誰かに使わせるには不親切かも。。。
【Go言語】環境変数の活用

### 環境変数とは

* 実行時のオプションとしてではなく、プロセスが持つ変数として提供される
* オペレーティングシステムは、プログラムの実行時に環境変数のリストをプログラムに渡す
* デプロイ時に設定可能で、同一のバイナリを異なる環境（本番、テストなど）で使用する際に柔軟な設定を可能にする

### 環境変数の取得方法
2通り紹介する

#### `os`パッケージを使用する方法
一番プリミティブな方法

```go
package main

import (
	"fmt"
	"os"
)

func main() {
	gopath := os.Getenv("GOPATH")
	fmt.Println(gopath)
}

```


#### `envconfig`を使用する方法
環境変数をGoの構造体にマッピングすることができる

* 使い方
    * 構造体のフィールドに`envconfig`タグを付けることで、環境変数との対応付けを行う
    * `default`オプションを使用して、環境変数が設定されていない場合のデフォルト値を指定できる
    * `required`オプションは、環境変数が必須であることを指定できる。この環境変数が設定されていない場合、envconfig.Processはエラーを返す。

```go
package main

import (
	"fmt"

	"github.com/kelseyhightower/envconfig"
)

type Config struct {
	Port      uint16 `envconfig:"PORT" default:"3000"`
	Host      string `envconfig:"HOST" required:"true"`
	AdminPort uint16 `envconfig:"ADMIN_PORT" default:"3001"`
}

func main() {

	var c Config
	err := envconfig.Process("", &c)
	if err != nil {
		fmt.Println("Error processing environment variables:", err)
		return
	}
	fmt.Println(c)
}

```

## 参考
https://www.oreilly.co.jp/books/9784873119694/