OmniAICreator/Qiita-1.07M huggingface dataset:
RDSを経由するaws glueの並列処理について

はじめに
-
aws glueは　データ分析のためにデータを用意する段階を自動化する、AWSの完全管理型ETLサービスです。

データソースとしてはRDS・DynamoDB・S3などの他、カスタムライブラリと JAR ファイルをインポートすることでネイティブにサポートされていないデータソースにアクセスすることもできます。

本記事では、RDSをデータソースにするglueの並列処理について、自分が分かったことをまとめます。


DBへの接続は基本１つ
-
基本的にsparkの`spark.read.jdbc()`は、1つのパーティションを持つRDDとして対象jdbc接続からデータを読み込みます。

「1つのパーティションでデータを読み込む」ことが重要です。
作業パーティションが1つ　→　読み込みタスクが1つ → 1つのCPUコアが割り当てる
→ 結局データの読み込みにただ1つexecutorしか使われ、DBへの接続も1つにしかならないことです。

従って、並列に読み込むノードの数を増やすには、読み込みデータのパーティションを分割する必要があります。

AWS公式ガイドの「JDBC テーブルからの並列読み取り」の内容が、まさにパーティションが分割されたRDDを作成することです。

https://docs.aws.amazon.com/ja_jp/glue/latest/dg/run-jdbc-parallel-read-job.html

一般的に、タスク数は全体CPUコア数と同じ場合最適です。
例えG1.Xワーカの１０個でglueを実行したら、36（9*4）パーティションが最適です。
ただ、対象DBの性能も考慮する必要がありますので、注意が必要ですね。

並列クエリをする時、出力ファイル数の注意点
-
ケースによって出力ファイル数を減らす必要もあります。

出力ファイル数は書き出す時のパーティション数と同じですので、書き出す前の`coalesce`又は`repartition`が有効です。
出力ファイルを増やす時は`repartition`しかないですが、減らす時は`coalesce`と`repartition`どっちが良いでしょか？

基本`repartition`はデータのシャッフルが伴いますので、性能的に`coalesce`が良いですかね？
ここで`coalesce`APIを再確認する必要があります。

`coalesce`はご存知の通りパーティションをパーティションの削減のみをサポートするAPです。
データの全体的なシャッフルが必要ないので、`repartition`より早いです。
しかし`coalesce`にはいくつかの問題があります。

1つ目は`coalesce`の処理タイミングです。
例え以下のようなSpark APPがあります。
```
load().map(…).filter(…).save()
```
`map()`からの並列処理が１０００個生まれると想定しましょう。
出力ファイル数として１０個を望むんだと、以下のことが考えられます。
```
load().map(…).filter(…).coalesce(10).save()
```
これで出力ファイル数が１０個になりました。
ただこれで1000の並列処理は失われます。

なぜでしょうか？
`coalesce`APIがデータのシャッフルを行われない理由は、この処理がnarrow dependencyの処理だからです。

Sparkはrddをlazy evaluation（遅延評価）で計算します。
`coalesce`APIは処理前のRDDと処理後のRDDと依存性が低いので、結局最終RDDは合体されたパーティションで行われます。

話を戻って、さっき私たちは、テーブルへの並列クエリが実現する為にはRDDのパーティションを分割する必要があることを確認しました。

データベースからデータを抽出して、データをファイルで吐き出す。
この一連の処理はglue上で1つのRDDとして行われます。
従って、「並列にデータを読んで、少ないファイルでデータを出力する」ことを為には、`coalesce`ではなく、`repartition`を使うしかなりません。

おわりに
-
ただし、`repartition`は確かに`coalesce`よりコストが高いです。
シャッフルによってむしろ処理時間が増える可能性も高いです。

1つの出力ファイルでデータを抽出するなら、並列クエリすら必要ないですね。
しかし、この場合クエリをもっと早くする為にはどうしたら良いでしょう？

データを活用する為には色々考えなければならないですね。

今回はRDSを経由するaws glueの並列処理について自分が調べたことをまとめました。


参考
-
https://spark.apache.org/docs/latest/rdd-programming-guide.html#rdd-operations

https://github.com/apache/spark/blob/branch-2.0/core/src/main/scala/org/apache/spark/rdd/RDD.scala#L417
一時ディスクがないWindows Server VMをデプロイしてみた

Azureでよく利用する仮想マシンサイズのDシリーズ、v3まではページングファイルを配置する用途の一時ディスクが必ずついてきていました。v4以降では一時ディスクのあり・なしで仮想マシンサイズが分かれています。一時ディスクの目的はページングファイル用というわけではなく、パフォーマンスが求められる一時領域用途に変更されており、ディスクサイズはVMのメモリサイズと比べると明らかに大きすぎるサイズが割り当てられています。一時ディスクありのタイプを選択すると$10以上月額が上がるので、不要であれば一時ディスクなしを選択することになります。
参考：[Windows Virtual Machines の料金](https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/windows/#ddv4-series)

というわけで、一時ディスクなしのタイプでWindows Serverをデプロイを試してみました。

# Windows Server 2019をD2s_v5でデプロイしてみる
一時ディスクがないタイプであるD2s_v5を選択してWindows Server 2019をデプロイしてみます。
デプロイ後、マシンにログインして確認すると想定通り一時ディスクがない状態になっていることがわかります。v3でデプロイした時にはなかったDVDドライブがなぜかついています。
![notemp01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/f2f17fef-ae02-b20c-ca30-950c8efe2fb7.png)
![notemp02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/afd7cc7f-b4a8-5e00-6ee2-a8844d3ae65e.png)

一時ディスクがなくなったので、仮想メモリの設定がどうなっているか確認します。
すると見た目上の設定は「ページングファイルなし」になっていますが、下部の割り当て済みのページングファイルサイズを見ると「1920MB」となっています。どういうこと？
![notemp03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/c408a9ac-fc64-e918-bd66-672ac41fd132.png)

「保護されたオペレーティングシステムファイルを表示しない」を無効化してCドライブ直下を確認してみたら、1.9GBほどのpagefile.sysがあります。

![notemp04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/486e8eae-55a0-46e2-83ce-21f083d0d6ec.png)

ページングファイルとして機能しているのかを念のため確認するため、[Testlimit](https://learn.microsoft.com/ja-jp/sysinternals/downloads/testlimit)を使って物理メモリ以上のサイズで負荷をかけてみます。

![notemp08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/682e86ef-f3f0-95ae-128f-ab9f8a1aff80.png)

負荷をかけた状態でページングファイルのサイズを再確認したら、サイズが拡張されていました。やはりページングファイルは有効になっています。

![notemp09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/3ace52dc-7c73-e26f-65c0-2f8032a94053.png)

試しに「No paging file」のチェックが入っている状態で「Set」を押し、再起動してみたところ、ちゃんとページングファイルは無効化された状態になりました。

# 検証結果
一時ディスクなしのタイプでデプロイすると、仮想メモリ設定が見た目は無効、実際は有効、という状態になっていることがわかりました。とても紛らわしい状態になるので、明示的に仮想メモリを有効にする設定に変更することが望ましいですね。
なお、仮想メモリを完全無効化するとメモリダンプが出力できなくなるので、完全無効化はおすすめできません。
Gitとは何か（初心者入門向け）

# Gitについて初心者向けの解説まとめ

## エンジニアを目指す場合Gitの学習は必須である

- gitとはバージョン管理システムの一種(現在はgitが主流）
- gitを使うには`CUI`もしくはSourceTreeという`GUI`での操作が必要

## バージョン管理システムとは何か？

- データの更新履歴（いつ、何を編集したか）を保存管理できる仕組み
- 複数人で同じプロジェクトを作成する際、バッティングを回避できる
- 過去の履歴のデータへアクセス、復元が可能
- 最新のデータをもつ所持者がわかる


## gitのリポジトリとは

- 和訳でgitとは貯蔵庫を意味し、データを保存しておく場所を指します
- リポジトリは2種類存在する（リモート/ローカル）
- リモートリポジトリとはサーバー上に保管しますという意味
- ローカルリポジトリとは自身のPC上に保管されます
- 複数人で管理する内、リモートリポジトリはサーバー上に1つだけ存在します
- ローカルリポジトリはプロジェクトに参加しているメンバーの数存在します
- 初めにローカルにデータを保存し、最終的にリモートへ保存する流れになります
- リモート側にトラブルがあった場合でもローカルに保存しておけば復旧できます

## GitHubとは

- gitを主軸に管理支援をする仕組みのツール
- リモートリポジトリを提供するさWEBアプリのこと
- 無料の会員登録でネットにファイルをアップロードできる
オリジナルアプリをIaC化＋データ移行

# はじめに
以前、以下のインフラ構成で[オリジナルアプリをデプロイしました](https://qiita.com/Unimaru/items/66a01ad5dab54e66ff47)が、いくつか改善などをしたく、今回別途インフラ構成をIaCで作成の上、移行をします。(Freenomで別の独自ドメインを取得)

【旧構成】
![スクリーンショット 2022-09-25 10.33.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/438fac02-196b-0b14-a50e-7b05fd973654.png)

【新構成】
![スクリーンショット 2022-09-25 14.14.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/a9e953a9-be23-8d41-7eff-de6b56293c10.png)


### 変更点
* スマホの買い替え/MFA関連により、AWSアカウントAのrootアカウントではマネジメントコンソールにログインできない状況になってしまったため、今後は別のAWSアカウントBを利用していきたいと思い、アカウントB側でインフラ構築/アプリデプロイをして、既存データなども移行していく。
* AWSリソースの構成管理を「CloudFormation」から「Terraform」へ変更
別のIaC技術も学習し、違いなどを知るために今回は「Terraform」を利用。また以前、CloudFormationで構築した際のコードはきちんと管理できていなかったので、今回はGithubで管理する。
* コスト削減のため、DBサーバはRDSではなくEC2で構築
* 以前はWeb/APサーバ内の設定は手動で行っていたが、今回WorkサーバをEC2で作成し、そこからAnsibleで設定するようにする

# Terraform
上記の【新構成】をTerraformで構築。
https://github.com/unimarist/memory_tank_terraform
「acm.tf」は以下が完了した状態で適用する。
「lb.tf」でALBとHTTP listenerを作成、「route53.tf」でゾーン,Aレコード作成
→Freenomのドメイン設定でAWS側のdns serverを指定するようにする

# Ansible
Workサーバ内でAnsibleを実行し、Web/APサーバ、DBサーバの設定を実施。
https://github.com/unimarist/ansible

# データ移行
* 旧環境で実施
Web/APサーバからmysqldumpでRDSのdumpファイルを取得
```
mysqldump -h [RDSのホスト名] -u [DBのusername] -p [DB名] > 出力先ファイルパス.sql
```
* 新環境で実施
上記で取得したdumpファイルをDBサーバ(EC2)に転送の上、インポートをする。
```
mysql -u root -p [DB名] < dumpファイル名.sql
```

# まとめ
今回、新構成への移行を優先し、Terraform/Ansibleのベストプラクティスなるものを十分にインプットしきれていないため、時間をとって整理したいと思います。
Hexabase Flutter SDKの使い方（インストールと認証）

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業向けのBaaS（Backend as a Service）を提供しています。認証やデータストア、ファイルストレージ、リアルタイム通知などの機能があり、企業向けのシステム開発に必要な機能をまるっと提供しています。

APIはREST APIとGraphQLを提供しています。そのAPIをラップしたSDKも開発を進めています。SDKは現在、TypeScriptとDart向けに開発しています。Dart向けのSDKは、もちろんFlutterでも利用できます。

この記事ではFlutter SDKについて、インストールとアプリケーションの作成・更新・削除の方法について解説します。

## パッケージとソースコード

パッケージはpub.devで公開しています。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)

ソースコードはGitHubにて公開しています。ライセンスはMIT Licenseです。

[hexabase/hexabase-dart: Hexabase SDK for Dart & Flutter](https://github.com/hexabase/hexabase-dart)

## インストール

インストールは `dart pub get` で行えます。

```
dart pub get hexabase
```

## インポート

SDKをインポートします。

```dart
import 'package:hexabase/hexabase.dart';
```

## 初期化

まずインスタンスを作成します。

```dart
var client = Hexabase();
```

別なファイルで再度インポートした場合には、以下でインスタンスを取得してください。

```dart
var client = Hexabase.instance;
```

## ワークスペースの設定とアプリケーションを取得

アプリケーションを検索する場合には、以下のようにワークスペースを設定して、 `applications` メソッドで取得します。

```dart
var workspace = client.workspace(id: keys['workspace']);
var applications = await workspace.applications();
```

またはアプリケーションIDを適用して、取得します。

```dart
var application = client.application(id: keys['application']);
```

## アプリケーションを作成する

新しくアプリケーションを作成する場合には、以下のように行います。現在、1つ目の引数である言語は `ja` （日本語）または `en` （英語）のみ対応しています。

```dart
var application = client.application();
application.name('ja', 'テストアプリ v2').name('en', 'Test App');
await application.save();
```

テンプレートを使う場合には、 `templateId` を使います。

```dart
application.templateId = 'TEMPLATE_ID';
await application.save();
```

## アプリケーションを更新する

アプリケーション名を更新する場合には、以下のように行います。

```dart
application.name('ja', 'テストアプリ v2');
await application.save();
```

## アプリケーションを削除する

アプリケーションを削除する際には `delete` メソッドを使います。

```dart
await application.delete();
```

## まとめ

アプリケーションはHexabaseのワークスペースの下に紐付くデータですが、データストアやファイルストアなどを操作する際の基本になります。管理画面でも作成できますが、SDK経由でも操作できます。

Dart SDKはFlutterでも利用できます。Flutterで使えると言うことは、iOS/Androidといったスマートフォンアプリやタブレットアプリはもちろん、Webやデスクトップアプリ開発でも利用できます。ぜひHexabaseをDart SDKとともに活用してください。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)
downcaseメソッドとlengthメソッドを使って2つの文字列の末尾が一致しているか判断するプログラム

今日も学んだことを忘れないためにメモします

## downcaseメソッド　とは
文字列に含まれる大文字を小文字に変換したいときに使用するメソッド。
```
array = "Hiabc"
puts array.downcase

=> "hiabc"
```
他にも
・文字列に含まれる小文字を大文字に変換するupcaseメソッド
・文字列に含まれる小文字を大文字に、大文字を小文字に変換するswapcaseメソッド
・先頭の小文字を大文字に,他の文字を小文字にするcapitalizeメソッド
がある

## lengthメソッドとは
「文字列の長さ（文字の数）」と「配列の要素の数」を 調べるためのメソッド。
```
str = "abcdefg"
puts str.length

=> 7

data = [1,2,3,4,5,6,7,8,9]
puts data.length

=> 9
```


## プログラム内容
・引数に指定された2つの文字列のうち、どちらかがもう一方の文字列の末尾にある場合は、Trueを出力する
・上記を満たせていない場合は、Falseを出力する
・入力された文字が大文字でも小文字でも、同一の文字として処理を行う

##  記述内容
```
def end_other(a, b)
  a_down = a.downcase
  b_down = b.downcase
  a_len = a_down.length
  b_len = b_down.length
  if b_down.slice(-(a_len)..- 1) == a_down || a_down.slice(-(b_len)..- 1) == b_down
    puts "True"
  else
    puts "False"
  end
end

end_other('Hiabc', 'abc')
end_other('abc', 'HaIoBc')

=> "True"
=> "False"
```

入力された文字が大文字でも小文字でも、同一の文字として処理をする条件のため、downcaseメソッドを使って文字列内の大文字を小文字に変換し、変数に代入する。

lengthメソッドを使って文字列の数を確認して、変数に代入する。（文字列がもう一方の文字列の最後にある場合を区別するために使う）

次にどちらかの文字列がもう一方の文字列の最後にある場合を区別するための処理を書く。
sliceメソッドを使って範囲を指定した文字列を切り取る。
指定する範囲はslice(-(a_len)..- 1)と記述することで末尾（-1で後ろから一番目）からlengthメソッドで文字列の数を確認した分の数。

end_other('Hiabc', 'abc')でメソッドを呼び出した場合はそれぞれ
```
a_down = hiabc
b_down = abc
a_len = 5
b_len = 3
```
となる。

条件式の左辺ではb_down.slice(-(a_len)..- 1)は、b_down.slice(-5..-1)となる。
b_down = abcとなっているので文字数が足らず、インデックス番号-5から-1という条件で切り取ることができなくなり、結果はfalseになる。

条件式の右辺ではa_down.slice(-(b_len)..- 1)はa_down.slice(-3..-1)となる。
a_down = hiabcとなるので、インデックス番号-3から-1という条件で切り取ることが出来る。
sliceメソッドでa_downから-3から-1の範囲の文字列を切り取るとabcが残る。
結果、abc == b_downは等しいと評価されるので、trueとなり"True"が出力される。


以上になります。
iOS App「数字を順番に押す」

https://apps.apple.com/jp/app/%E6%95%B0%E5%AD%97%E3%82%92%E9%A0%86%E7%95%AA%E3%81%AB%E6%8A%BC%E3%81%99/id6443621796

# アプリのチュートリアル動画

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

# アプリの使い方

## 操作方法

1. モードを選択する

2. 数字の範囲を設定する

3. 効果音の有無を設定する

4. スタートを押して開始する

5. 1から順番に数字をタッチする

6. リトライを押して中断or再挑戦する

7. 右上の王冠ボタンを押して、最高記録を確認する

# プライバシーポリシー

## 利用者情報の取得

本アプリが利用者の個人情報を取得することはありません。

## 利用者情報の利用

本アプリが利用者の個人情報を利用することはありません。

## 利用者情報の第三者提供

本アプリが利用者の個人情報を第三者へ提供することはありません。

## 免責事項

本アプリ利用上の不具合・不都合に対して可能な限りサポートを行っておりますが、利用者が本アプリを利用して生じた損害に関して、開発元は責任を負わないものとします。

## お問い合わせ先

本記事にコメントしてくだされば、対応させていただきます。
三次元アプリ開発でよく使われるカメラ操作/設定のパターン

# 三次元アプリ開発でよく使われるカメラ操作/設定のパターン

大きく分けると軌道回転型と自由視点型の2種類、あとはその亜種と捉える事もできます。最終的には【視点座標】と【視線方位】及び視野角などの付随するパラメーターについて、何を元に計算させて決めようかというパターンです。実用性の高いパターンはゲームでもお馴染み、お決まりのカメラ操作パターンになっているので、ゲーマーさんは3Dゲームを何か想像しながら「そういうことね、なるほどね！」と関連付けながら考えると混乱しないかもしれません。

以下、記述は個別のエンジン、ライブラリーによらない一般論としつつ、実装の一例の紹介として Babylon.js の API ドキュメントにリンクします。

## 軌道回転型（アークローテート型）のカメラ

ゲーマーさんにわかりやすく例えると"俗に言うところのTPSカメラの一種"です。CITIESなどシムゲーのカメラモードとして採用される事が多いパターンです。《見たい対象》を基準にカメラを操作させたい場合に使います。

ユーザー（プレイヤー）が指定できるパラメーターは:

- 注視点=《見たい対象》のいる点（座標）
- 方位角=《見たい対象》【への】水平方向の回転軸上ではどの辺り【から】見たいか（角度）
- 仰俯角=《見たい対象》【への】垂直方向の回転軸上ではどの辺り【から】見たいか（角度）
- 距離=見たい対象からカメラまでの距離（距離）

※他に必用に応じて視線軸回転（角度）や視野角（角度）も扱う場合もあります。

※「TPSカメラ」という用語はTPS状態＝第三者視点で対象を見る場合のカメラという意味ではありますが、ゲーマーさんの世界では「FPSに対しての」というFPS/FPSを対義的な状態を表す言葉として踏まえた上でのTPSモードでの視点の事だったり、本節で紹介した方式の視点やカメラ方式の事だったり状況やコンテキストによって意味や意図に揺れが大きい事があります。

- 例: https://playground.babylonjs.com/#SRZRWV#839 (Babylon.js API ArcRotateCamera)
  - https://doc.babylonjs.com/features/featuresDeepDive/cameras/camera_introduction#arc-rotate-camera

## 自由視点型（フリービューポイント型）のカメラ

ゲーマーさんにわかりやすくいうとターゲットロックしてない状態のTPS/FPSカメラです。《視点》を基準にカメラを操作させたい場合に使います。

ユーザー（プレイヤー）が操作できるパラメーターは:

- 視点=《自キャラ》のいる点（座標）
- 方位角=《自キャラ》【からの】水平方向の回転軸上ではどの辺り【を】見たいか（角度）
- 仰俯角=《自キャラ》【からの】垂直方向の回転軸上ではどの辺り【を】見たいか（角度）

※他に必用に応じて視線軸回転（角度）や視野角（角度）も扱う場合もあります。

※軌道回転型カメラの距離を `... → 0` へと近づけると出来上がる絵は自由視点型カメラと同じになりますが、方位角と仰俯角の `+/-` つまり回転方法が互いに逆になります。これはしばしばユーザーの脳のカメラの捉え方や操作の慣れと関連して三次元アプリ、ゲームでも問題となり、一般的な解決方法としてアプリに対して設定画面などでユーザーが設定可能な項目に「Y軸反転」「X軸反転」のオプションを追加する事にも関連しています。

- 例: https://playground.babylonjs.com/#DWPQ9R#1
  - https://doc.babylonjs.com/features/featuresDeepDive/cameras/camera_introduction#universal-camera

## 対象及び視線固定型（ターゲットロック型、フォロー型）のカメラ

ゲーマーさんにわかりやすくいうとターゲットロックしている状態のTPS/FPSカメラです。《見たい対象》と《自キャラ》の座標でカメラの視界を決定する場合に使います。

ユーザー（プレイヤー）が操作できるパラメーターは:

- 注視点＝《見たい対象》のいる点（座標）
- 視点＝《自キャラ》のいる点（座標）

※他に必用に応じて視線軸回転（角度）や視野角（角度）も扱う場合もあります。

※実際のゲームのターゲットロック状態のカメラでは完全にぴったんこ視線を固定ではなく、右スティックやマウスなどの入力を元に若干の方位角や仰俯角も設定できるインターフェースになっている応用/亜種パターンも多くあります。

- 例: https://playground.babylonjs.com/#SRZRWV#6
  - https://doc.babylonjs.com/features/featuresDeepDive/cameras/camera_introduction#followcamera

# おまけ: カメラの視野角のパターン

## FOVY型

視野角(=FOV; `[F]ield [o]f [V]iew`)を最終的に出来上がる2次元の絵（3Dゲーでもスクショとってできあがる絵は2次元ですね！）の垂直軸方向(=Y軸方向)の長さを基準にして、垂直方向の視野角と水平方向の視野角を設定する方式です。画面の横幅は環境によって変わるものの、基本的には画面の高さを基準に視界を出力したい場合に使われます。たいていの横長画面向けの3Dゲームはこの方式です。

## FOVX型

視野角を最終的に出来上がる2次元の絵の水平軸方向(=X軸方向)の長さを基準にして、垂直方向の視野角と水平方向の視野角を設定する方式です。画面の横幅を基準にしたい場合に使います。あまり一般的には使われませんが、画面がいくら横に長い環境でも見える水平視野は変わらないようにしたい（それが重要なアクション要素の難易度に影響する大切な要素でプレイヤー間で差をつけさせたくない場合など）には採用することもあるかもしれません。

## 対角線型（リアルカメラ型）

視野角を最終的に出来上がる2次元の絵の水平軸方向(=X軸方向)の長さを基準にして、垂直方向の視野角と水平方向の視野角を設定する方式です。現実世界のカメラやディスプレイデバイスの画面の大きさの表記などで使われています。もしアプリで現実世界のカメラの視野角の状態を再現したい場合などあれば使う事になりますが、他の用途ではまず使われません。
Hexabase Flutter SDKの使い方（インストールと認証）

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業向けのBaaS（Backend as a Service）を提供しています。認証やデータストア、ファイルストレージ、リアルタイム通知などの機能があり、企業向けのシステム開発に必要な機能をまるっと提供しています。

APIはREST APIとGraphQLを提供しています。そのAPIをラップしたSDKも開発を進めています。SDKは現在、TypeScriptとDart向けに開発しています。Dart向けのSDKは、もちろんFlutterでも利用できます。

この記事ではFlutter SDKについて、インストールと認証の方法について解説します。

## パッケージとソースコード

パッケージはpub.devで公開しています。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)

ソースコードはGitHubにて公開しています。ライセンスはMIT Licenseです。

[hexabase/hexabase-dart: Hexabase SDK for Dart & Flutter](https://github.com/hexabase/hexabase-dart)

## インストール

インストールは `dart pub get` で行えます。

```
dart pub get hexabase
```

## インポート

SDKをインポートします。

```dart
import 'package:hexabase/hexabase.dart';
```

## 初期化

まずインスタンスを作成します。

```dart
var client = Hexabase();
```

別なファイルで再度インポートした場合には、以下でインスタンスを取得してください。

```dart
var client = Hexabase.instance;
```

## 認証

認証は `login` メソッドで行ってください。

```dart
await client.login('user@example.jp', 'your_password');
```

## まとめ

Dart SDKはFlutterでの利用も想定して開発しています。現在はワークスペース、アプリケーション、データストアなどが利用できます。GraphQLをラッピングする形で作っていますので、GraphQLを手軽に使える形になるはずです。

FlutterであればiOS/Androidなどのスマートフォン、タブレットアプリはもちろん、Webやデスクトップアプリ開発でも利用できます。ぜひお試しください。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)
MacのZshでDockerコマンドをタブキーで補完する設定

# はじめに
ubuntuでDockerを利用した時にタブキーによるコマンド補完の便利さに気づき、普段仕事で利用しているMacでもコマンド補完をしたいと思って調べたので記事にしました。
# ZshでDockerコマンドを補完する設定手順
## ①Zshの補完スクリプトを配置するフォルダを作成
```zsh
mkdir ~/.zsh/complation
```
## ②Dockerの補完スクリプトのエイリアスを作成
```zsh
etc=/Applications/Docker.app/Contents/Resources/etc
ln -s $etc/docker.zsh-completion ~/.zsh/complation/_docker
ln -s $etc/docker-compose.zsh-completion ~/.zsh/complation/_docker-compose
```
## ③Zshで補完スクリプトが動作するように.zshrcファイルを編集
zshファイルに以下の内容を追加します。
```zsh:~/.zshrc
# fpathに①で作成したパスを追加する
fpath=(~/.zsh/completion $fpath)
# dockerコマンドの補完の制御処理(正直書き方は意味不明です)
zstyle ':completion:*:*:docker:*' option-stacking yes
zstyle ':completion:*:*:docker-*:*' option-stacking yes
# 保管機能を有効にして、実行する
autoload -Uz compinit && compinit
```
以上でZshを再起動したらタブキーによるDockerコマンドの補完ができるようになっているはずです。

# 参考
https://docs.docker.jp/docker-for-mac/index.html?highlight=%E8%A3%9C%E5%AE%8C#mac-install-shell-completion

https://docs.docker.jp/v1.11/compose/completion.html

https://code-graffiti.com/install-docker-on-mac-and-set-zsh-command-completion/#toc5

https://medium.com/@rukurx/zsh%E3%81%AEcompinit%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E3%82%8Bautoload%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-uz-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-ad471efd84c3
Rust 超入門 → 列挙型

### 列挙型
**列挙型は生成したデータ型です。列挙型はenumを使って定義します。列挙子指定は：：を使います。**

```rust
enum Language_version {
    java,
    php,
    Ruby,
    python,
    nodejs,
}
```

### 列挙型の値
```rust
enum Language_version {
    java(String),
    php(String),
    Ruby(String),
    python(String),
    nodejs(String),
}

fn main() {
    let j = Language_version::java("11".to_string());
    let p = Language_version::java("8.0".to_string());
    let r = Language_version::java("2.7".to_string());
    let y = Language_version::java("3.9".to_string());
    let n = Language_version::java("17-3".to_string());

    println("{:?} {:?} {:?} {:?} {:?} ", j, p, r, y, n);
}
```
エラーハンドリングはResult型活用しようぜ

## Result型って何ですか

RustやSwiftだと馴染み深い`Result`型とは、その名の通り**結果**を表すものです。
TypeScriptだとその実装例として以下のものを私は使用しています。

```tsx

export type Result<T = void, E = void> =
  | { ok: true; value: T }
  | { ok: false; error: E }

export const Ok = <T, E>(value: T): Result<T, E> => ({
  ok: true,
  value,
})

export const Err = <T, E>(error: E): Result<T, E> => ({ ok: false, error })
```

## どう活用できるんですか？

エラーの種類に応じて処理を変えたい場合に相性良く活用できます。

例えば、Sign in処理を行う際に、ユーザーのリクエストが不正である場合と、それ以外のネットワーク起因の場合とで処理を使い分けたいときを想定してみます。
Result型を使うと下記のように書くことが出来ます。

```tsx
// エラーを区別して出す関数
async function signin(payload: SigninPayload): Promise<Result<SigninResponse, "INVALID_REQUEST" | "UNKNOWN_ERROR">> {
	try {
		const res = await fetch("./login", { method: "POST", body: JSON.stringify(payload) })
		if (res.ok) {
			return Ok(res.json() as SigninResponse)
		}

		if (res.status === 400) {
			return Err("INVALID_REQUEST")
		}
		return Err("UNKNOWN_ERROR")
	} catch {
		return Err("UNKNOWN_ERROR")
	}
}

// SomeComponent.tsx
const SomeComponent = () => {
	const handleSubmit = () => {
		const result = await signin(payload)
		if (result.ok) return

		if (result.error === "INVALID_REQUEST") {
			console.log("パスワードとかが間違っているかも")
		}
		if (result.error === "UNKNOWN_ERROR") {
			console.log("レスポンスがJSONじゃなかったり、ネットワークエラーかも...")
		}
	}

	return <form onSubmit={handleSubmit}>...</form>
}
```

`result.ok`が`true`であれば、`result.value`にアクセスしてその結果を受け取ることができ、そうでない場合は`data.error`にアクセスが可能でその値を元に処理を行えます。

Result型を使わないよくある方法として、try catchのcatchでのエラーハンドリングがある思います。

```ts
try {
    const result = await signin(payload)
} catch (err) {
    if (err instanceof CustomError) {
        console.log("独自のErrorクラス定義してハンドリング")
    }

    if (err instanceof Error) {
        console.log("CustomErrorより前にいると引っかかる")
    }
}
```

もちろんこれでも可能ですが、以下のデメリットが存在すると思います。

- catchで掴む値は`any`型なのでちゃんと型安全に行うには、`instanceof CustomError` などを使う必要がある
- Intellisenseのサポートを得られない。
- 新しくスコープを作ってしまうことや、ネストが深くなる

一方Result型は
- 型安全
- Intellisenseのサポートを得られる
- スコープもネストも深くならない
- **何のエラーが返ってくるかという関心の分離が行える**

ちなみにこういったライブラリも既にあるので、興味のある人は導入を検討してみても良いと思います。
（ただ個人的には上記の例程度のもので現状は十分だと感じています。）

よかったら導入を検討してみてください。

https://github.com/vultix/ts-results
グリッドの便利なサービスまとめ

# はじめに

以前グリッドレイアウトについて書きましたが、実際に記述するのが面倒な方やもっと簡単に実装したい方向けに、ジェネレーターやテンプレート、プロパティの確認をしたい時などに役立つチートシートなどについて調べてみました。
どれもグリッドを使う上で、便利で役に立つものかと思いますので、ブックマークしておいて損はないかと思います。

## グリッドジェネレーター

グリッドを簡単に生成できるジェネレーターです。

<a href="https://cssgrid-generator.netlify.com/" target="_blank" rel="nofollow external noopener noreferrer">CSS Grid Generator</a>
![スクリーンショット 2022-09-30 20.34.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664534/520a30bc-b098-9ee2-d920-e45a84859202.png)

## グリッドチートシート

グリッドのプロパティを一覧で確認でき、
カーソルの箇所をコピーできるのでお勧めです。

<a href="https://grid.malven.co/" target="_blank" rel="nofollow external noopener noreferrer">CSS Grid GRID</a>
![スクリーンショット 2022-09-30 20.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664534/64e4060b-73f9-e39e-352c-6d0ae8d47012.png)

## グリッドテンプレート

グリッドのレイアウトがいろいろ用意されていて、
詳細ページではCodePenで実際に確認できます。

<a href="https://gridbyexample.com/examples/" target="_blank" rel="nofollow external noopener noreferrer">Grid by Example</a>
![スクリーンショット 2022-09-30 20.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664534/9c8f41e4-eab2-ef5c-06a8-f9ad0ae9f191.png)

この他にも便利なツールやお勧めのサービスなどあれば追加していこうと思います。
trioによる並行処理 もくじ

pythonの並行処理ライブラリ[trio](https://trio.readthedocs.io/en/stable/)を3年間使ってきました。
学んだことを何回かに分けてまとめていきます。

## trio

- [trioによる並行処理①（非同期開始、open_nursery、await、atomic）](https://qiita.com/Kyosuke_Ichikawa/items/60955d36fa4c181c198e)
- [trioによる並行処理②（Event）](https://qiita.com/Kyosuke_Ichikawa/items/aa4f22f4eb6fb9aacb7e)
- [trioによる並行処理③（move_on_after, move_on_at）](https://qiita.com/Kyosuke_Ichikawa/items/ab35c098e819316bdcf9)
- [trioによる並行処理④（Nursery）](https://qiita.com/Kyosuke_Ichikawa/items/2287de7326facecb0646)
- [trioによる並行処理⑤（CancelScope）](https://qiita.com/Kyosuke_Ichikawa/items/8e95d53104102d1660ca)
- [trioによる並行処理⑥（try~finallyの罠と回避策）](https://qiita.com/Kyosuke_Ichikawa/items/d492cfbc09d4a592d2e3)
- [trioによる並行処理⑦（open_memory_channel）](https://qiita.com/Kyosuke_Ichikawa/items/c9a0cf4553b19bbd845c)

## trio-util

- [trio-utilによるreadableな並行処理①（AsyncValue）](https://qiita.com/Kyosuke_Ichikawa/items/933bc72bd13588dbe33b)

## 参考記事
- [Python + Trio の非同期コーディングパターン](https://qiita.com/yura/items/689d065aba00fe14fbba)
- [非同期入出力library Trioの調べ事](https://qiita.com/gotta_dive_into_python/items/327363ff72e5e4071570)
プログラマとウサギとカメ

- プログラミングを始めたばかりの頃はものすごいスピードで動かなければいけないと思いこんでいた。だけど別の道もある。自分の最適スピードを理解して落ち着いて動くことだ。うさぎか亀か。
- 業務なしに自分でプログラミングの学習をしようとすると途方に暮れてしまう。いまはQiitaの質問やTeratailの質問に答えることで課題を見つけている。自分で課題づくりをするのもそもそもチャレンジだ。課題づくりスキルを磨いてみたい。
- アジャイル開発用のツールPivotal TrackerのUIの悪さには最初3年ぐらい慣れなかった。今では慣れたけど。UIのアンチパターンを無数に敷き詰めたような感じがする。
- テストはしっかりと書くことが脳死でデフォルトになっている。だがトレードオフを考慮してあえてテストを書かないもしくは頑張って書かないという選択肢もあってしかるべきなのかもしれない。品質を落としてスピードを上げる。確かにちゃんとしたテストを書こうとすると実装に2倍以上の時間がかかる場合はある。
- 開発者は自分が作ったアプリケーションに対して意地悪なテストができないという心理は確かにあるのかもしれない。
- テスターは空気を読まない能力も必要だ。「今開発が忙しいからバグチケットを作らないでおこう」なんて考えていたら何も出来ない。何よりもアプリケーションの未来だけを考えるのだ。
- いくら探し切ったと思っても新しく見つかるものがバグだ。モンキーテスト専門家になりたい。
- プロジェクマネージャーは自分本人は開発に加われないにも関わらず開発を成功させなければいけないから大変そう。良さげな人材を集めるところが勝負の半分だろうか。
- 座禅か瞑想か。瞑想はテクニカルであり座禅はノンテクニカルなものだと分類する。どちらにするか。最近はただ坐る座禅を実践していたがマンネリ気味だ。少々しんどい。心地よさを見出す瞑想で楽しみの冒険に出たい。
- 座禅では意思のちからをゼロにしたい。だが0%か100%という二択じゃなくても良いのかも知れない。「最小限の意思を使う」というスタイルも良いのではないか。
- 瞑想中に物思いをしている時は意外に苦痛じゃない。問題は物思いから覚めたときだ。どこにも意識の行く宛がないような感じがしてそわそわする。
- スターバックスで二人連れのサラリーマンがそれぞれカバンを隣の席に置いている。つまり4席を占領している。電源席が使えない。話しかけて席を空けてもらおうかと思ったけれど彼らはその後すぐに席を立った。僕が電源席に移動しようとする前に他の男が電源席の隣に座りそして隣の席にバッグを置いた。バッグで席を占領するのやめてもらっていいですか。
- 瞑想は中心をとらえる。右にずれたかと思えば左に戻す。奥にずれたかと思えば手前に戻す。こうやってセンタリングし続けて中心を保ち続ける。これは体の話でもあるし心の話でもある。「心をまっすぐに立てる」という表現が思い浮かんだ。

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
laravel-dompdfとFPDI+TCPDFで作成したPDFを１つのPDFにする

# 概要
Laravelで、laravel-dompdfで作成したPDFとFPDI+TCPDFで作成したPDFを結合させて
１つのPDFを作成する必要がありました。
（PDF内の順番は1.laravel-dompdf、2.FPDI＋TCPDF）
その際に行った方法を備忘録として残しておきます。

※以下、各コード内のファイル名は、本投稿上の適当な名称です。
# laravel-dompdf
```php
use PDF;
// laravel-dompdfでPDFを作成する
$domPdf = PDF::loadView('generate_pdf');
```
※laravel-dompdfでの詳細なPDFの作成方法は以下を参考に。
[LaravelでPDFを出力する方法(laravel-dompdfを使う)](https://codelikes.com/laravel-dompdf/)

# FPDI+TCPDF
```php
use setasign\Fpdi\TcpdfFpdi;
// FPDI+TCPDFでPDFを作成する
$fpdiTcpdfPdf = new TcpdfFpdi();
```
※FPDI+TCPDFでの詳細なPDFの作成方法は以下を参考に。
[【TCPDF+FPFI】PHPでpdf帳票を作成する方法【グラフも】](https://kumatech-lab.com/tcpdf-fpdi-phplot/)

# laravel-dompdfで作成したPDFとFPDI+TCPDFで作成したPDFの結合
```php
// laravel-dompdfで作成したPDFを保存したファイルパス
$domFileName = $dirPath . '/dom.pdf';
// laravel-dompdfで作成したPDFを一時フォルダに一旦保存する
$domPdf->save($domFileName);
// 2つを結合したPDF
$pdf = new TcpdfFpdi();
// laravel-dompdfで作成したPDFのページ数を取得
$count = $pdf->setSourceFile($domFileName);

// ページ数分繰り返す
for ($i = 1; $i <= $count; $i++) {
 // 空のページを作成
 $pdf->addPage();
 // 結合させるPDFから現在のページを取得して先程作成した空のページに格納
 $pdf->useTemplate($pdf->importPage($i));
}

// FPDI+TCPDFで作成したPDFを保存したファイルパス
$fpdiTcpdfFileName = $dirPath . '/fpditcpdf.pdf';
// FPDI+TCPDFで作成したPDFを一時保存する
$fpdiTcpdfPdf->Output($fpdiTcpdfFileName, 'F');
// FPDI+TCPDFで作成したPDFのページ数を取得
$count = $pdf->setSourceFile($fpdiTcpdfFileName);

// ページ数分繰り返す
for ($i = 1; $i <= $count; $i++) {
 // 空のページを作成
 $pdf->addPage();
 // 結合させるPDFから現在のページを取得して先程作成した空のページに格納
 $pdf->useTemplate($pdf->importPage($i));
}

// 2つのPDFを結合したPDFを出力
$pdf->output();
```
# まとめ
TCPDF＋FPDIで作成されたPDF同士を連結させる方法などはあったものの、
異なるライブラリ（今回のようなパターン）のPDFの結合方法はなかったため、
今回実装方法について残しました。
結合する際のポイントは、laravel-dompdfでPDFを作成して、出来上がったPDFをTCPDF＋FPDIで読み込むことです。

# 参考
[PHP:複数のPDFを連結させる（TCPDF・FPDI）](https://securavita.net/php-pdf-batch/)
Unity の Localization で Table に設定した Entry が String Reference の選択肢に出てこない

# 結論
[Unity] -> [Prefrence] -> [Localization] の `String Search Picker` のチェックを外す

# 経緯
多言語対応のため Localization ライブラリを導入。

こちらの手順に沿って文字列の多言語対応をすすめるが、 String Reference のプルダウンメニューいに登録した Key が出てこない。
https://robotcoders.net/2022/03/unitylocalization/


# 参考
https://forum.unity.com/threads/localization-not-finding-string-reference-in-editor.1295262/

> You need to type in the search field. We know it's bad ux and will improve it in the future. You can also switch to the old system in the preferences.

bad ux だよー x-(
クロージャーがよく分からない、と思ったらもっと根本的な部分で分かってなかった

※　タイトル変更しました

# しっくりこない事

例えば、
```javascript:JSprimerより引用
const createCounter = () => {
    let count = 0;
    return function increment() {
        // 変数`count`を参照し続けている
        count = count + 1;
        return count;
    };
};
// countUpとnewCountUpはそれぞれ別のincrement関数(内側にあるのも別のcount変数)
const countUp = createCounter();
const newCountUp = createCounter();
// 参照してる関数(オブジェクト)は別であるため===は一致しない
console.log(countUp === newCountUp);// false
// それぞれの状態も別となる
console.log(countUp()); // => 1
console.log(newCountUp()); // => 1
```
といった場合に、何が出来るのかは分かる。

？なのは、
`countUp()`や`newCountUp()`を呼ぶたびに、なぜ`let count = 0;`が実行されないのか？ということ。
毎回`count`が初期化されてしまうのでは？と思ってしまう・・・。

これだって、
```javascript:JSprimerより引用
function greaterThan(n) {
    return function(m) {
        return m > n;
    };
}
// 5より大きな値かを判定する関数を作成する
const greaterThan5 = greaterThan(5);
console.log(greaterThan5(4)); // => false
console.log(greaterThan5(5)); // => false
console.log(greaterThan5(6)); // => true
```
const時の5は、普通に`function greaterThan(n)`内`n`に設定されていると思うが、
以降の３回の呼び出しでは`m`に代入されているようだし・・・

現時点での自分の理解としては、
constで定義した後の呼び出しでは、`return`文しか実行されない？？
Terraformを思い出す

## 1.はじめに
Terraformによる構成管理に感動したのは良いのですが、プロジェクトで触らなくってはや3年ちょい。
インフラのコード化はてなんじゃったかのー状態のジジイが勘を取り戻すだけの記事です。

内容は初心者レベルで目新しいことはございません！

作業環境は2021年型Mac(かっこいい)、個人のAWSアカウント、敬愛するtmknom氏著の実践Terraformです。

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

## 2.AWSにログイン(数ヶ月ぶり)
ログインしてなさすぎてなんか毎月数百円取られてるなあ状態でしたが、マメな性格ゆえしっかりとメモしてました。
MFAも設定してて偉すぎる。

確かこの記事を参照して設定した記憶があります。
これもtmknomさんが書かれてますね！

https://qiita.com/tmknom/items/303db2d1d928db720888

## 3.実行環境のセットアップ
AWSCLIのインストールがpipだとできませんでしたが、公式の手順通りに手を動かして解決しました。
ありがとう公式。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

Terraformのバージョンずいぶん上がりましたね。
プロジェクトで書いてた頃って0.11だった記憶があるなw

```
soshi.sato: ~/ % tfenv list-remote
1.3.1
```

特にハマりもなかったけどgit-secretsが何者なのかよくわからず。
次の機会に調べます。

## 4.基本操作
### 4-1.terraform init
initってなんだっけ。。と調べました、初回作業(もしくは作業ディレクトリを初期化したい時)に実行するっぽい。
確かにあまり頻繁に使った記憶無いですね。

https://www.terraform.io/cli/commands/init

そういえばTerraformは公式ドキュメントが鬼充実してるんだった！
バリバリ書いてた頃は記法を調べる→試すをよく試行してました。なつい。

### 4-2.terraform plan
planすら忘れてた自分に驚きだ！！
初回なので軒並み＋ですね、VPCとかSGとか全部デフォルトを使うのかな？と思いましたがそうじゃなければコケるだけの話。

そういえばこんな感じで教えてくれるんでした！

```
Plan: 1 to add, 0 to change, 0 to destroy.
```

### 4-3.terraform apply
Stg環境にapplyしようとしたら実はPrdで全身から冷や汗出たの思い出しました。
ただこの時以降IaCの怖さも思い知り、あらゆる作業に慎重になったので、早めに転んでよかったなとも思う。
当時のチームリーダーへの謝罪はいつでも行いますw

更地にテストインスタンス立てるだけなのでエラーも無く完了。

```
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

マネジメントコンソールからも確認できますね！
パッと見た感じ思いっきりパブリックなインスタンスだったので必要に応じて停止したりすると良いと思います。

タグを追加するapplyも完了。
Terraformは書いて動かした結果がマネジメントコンソールに成果物としてわかりやすく表れるとこが本当に好き。

### 4-4.terraform tfstateとtfnotify
更に思い出しましたが、メルカリのツール`tfnotify`が存在しましたね。
困ったから自分たちで作ってそれをOSSで公開、最高にカッコ良い流れ。
当時もこのブログ読みましたが今読んでも色褪せないですね！

https://engineering.mercari.com/blog/entry/2018-04-09-110000/

### 4-5.terraform destory
今回はCLIからポーンと叩くだけですが、やっぱり怖さがある。
そういう意味でもtfnotifyを使ったりしてSlackやメールで通知する仕組みは本当に重要ですね。

## 5.おわりに
記事というかポエムになってしまってすみません。。けどTerraformを思い出すには十分でした。
あとは実践で補完していこうと思います。久しぶりに業務で使うTerraformが楽しみです！！

以上です。
この記事がどなたかのお役に立てますように:raised_hands:
DB(データベース)のインデックスについて

## ■インデックスとは
インデックスを和訳すると「索引」。データベースの性能を向上させる方法の１つ。

## ■インデックスの利点(メリット)
大量レコードが存在するテーブルで、検索・ソート・結合で多用される項目(カラム)に対してインデックスを作成すると処理速度を上げることができる。

## ■インデックスの欠点(デメリット)
テーブルとは別の領域にインデックスのデータを保持するため、レコード更新や追加や削除する処理が重くなる。

## ■インデックスを使用するには
下記SQLで対象の項目(カラム)にインデックスの作成ができる。

```SQL
CREATE INDEX [インデックス名] ON [対象テーブル名]([対象カラム名]);

/*例) ユーザー情報マスタ(MST_USER_INFO)のユーザー名(userName)にインデックス作成*/
CREATE INDEX index_userName ON MST_USER_INFO(userName);
```

また、テーブル作成時にも下記のようにインデックスを作成できる。

```SQL
CREATE TABLE [対象テーブル名]
 ([カラム名 型],[カラム名 型], ... ,
  INDEX [インデックス名]([対象カラム名]);
```

## ■インデックスの確認方法
あるテーブルのインデックスを確認したい場合は、以下SQLで確認ができる。

```SQL
SELECT * FROM USER_IND_COLUMNS
 WHERE TABLE_NAME = [確認対象テーブル名]
 ORDER BY INDEX_NAME, COLUMN_POSITION;
```

また、対象のDBのインデックスすべてを調べたいときは、以下SQLで確認できる。

```SQL
SELECT * FROM USER_INDEXES;
```
Next.jsの環境構築をDockerで

```terminal
touch Dockerfile docker-compose.yml
```
```Dockerfile
FROM node:18-alpine
RUN mkdir /var/www
WORKDIR /var/www
```
```docker-compose.yml
version: '3.9'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www # ローカルをコンテナ内にマウント
    command: sh -c "cd ./src && npm run dev"
    ports:
      - "3000:3000"
    stdin_open: true 
```
```terminal
docker-compose build 
docker-compose run web npx create-next-app@latest src --typescript
```
`y`でエンター　

srcディレクトリが生成され、その中にいろいろ作られる
```terminal
docker-compose up -d
```

localhost:3000にアクセスで初期画面表示
【GitHub】パッケージを削除する方法

## パッケージを削除する方法
パッケージは以下の手順で削除します。

リポジトリの「Code」の画面右下「Packages」欄のパッケージ名をクリックします。
![スクリーンショット 2022-09-30 18.18.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/fe046150-2e92-8fd2-03af-b04ee50c2a99.png)

するとインストール方法などが記載されたページが開きます。
このページ右下の「Package settings」をクリックします。
![スクリーンショット 2022-09-30 18.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/63a3719f-3c28-2603-a07e-326b7123fe45.png)

開いたページ赤枠内の「Delete this package」をクリックし削除します。
![スクリーンショット 2022-09-30 18.19.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/17fdf4de-44f5-e935-45b8-cf8d8ddfb470.png)
技術文書の長音記号どうする？「コンピューター」と「コンピュータ」2022年現在と過去のルールについてのまとめ

# 長音記号付ける？付けない？問題とは

- "computer" を日本語のカタカナ表記で記載したい場合、歴史的経緯などから次の2通りの表記方法がありえます。
  1. 「コンピューター」 末尾に「長音記号」があるパターン
  1. 「コンピュータ」 末尾に「長音記号」を付けないパターン

# 2022年現在の結論

- 原則的に語尾の「ー」は付ける
  - "computer" => 「コンピューター」

## 迷ったら？

- 原語がUSA英語で単語としてのスペル的にあるいは一般的発音慣習で伸びる場合 => 付ける
  - "computer" => [US] `kəmpjútər` => 「コンピューター」
  - "operator" => [US] `ɑ́pərèitər` => 「オペレーター」
  - "tea" => `tiː`=> 「ティー」
  - "intensity" => `inténsəti` => 「インテンシティー」
  - "memory" => `méməri` => 「メモリー」
  - "register" => `rédʒistər` => 「レジスター」
  - "weekday"  => `wíːkdèi` => 「ウィークデー」

※note: "weekday" は「ウィークデイ」でもよい。同じ文書内などで表記ゆれは望ましくないので統一するのが好ましいが、異なる表現を採用する別プロジェクトなどに攻撃的にならずお互いに存在を許容しましょう。また、業界の慣例や過去の規格を元に長音の無い文書表現を採用するプロジェクトについても機会があれば現行のルールに合わせて改訂するか考慮してもいいかもね、くらいに緩く捉えておきましょう。

### 注: 原語を知らないと迷いそうな日本語

- 「データ」 <= [US] `dǽtə` <= "data" ※そもそも長音要素の無い単語が原語

# 参考 ⇦ この記事の一番だいじなところ

- 日本の政府(文化庁, 内閣府など)の場合
  - 平成3.6.28 内閣告示第2号 ⇨ 原則的に付ける
    - https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kijun/naikaku/gairai/index.html
      - 付録（用例集）の実例も見るとわかりやすい
- JIS Z8301の場合(長音トル「だった」系)
  - 現行 ( 2019改訂版 執筆現在 )
    - §H.6 外来語の表記 ⇨ 《外来語の表記（平成3.6.28 内閣告示第2号）》に従う（=原則的に付ける）
      - https://www.jisc.go.jp/app/jis/general/GnrJISSearch.html (JISC日本産業標準調査会 JIS検索 ⇨ Z8301 で一覧表示)
      -  http://www.kikakurui.com/z8/Z8301-2019-01.html (kikakurui.com 版)
  - 旧2011まで
    - §G.6.2.2 英語の語尾に対応する長音符号の扱い ⇨ 3文字以上では長音をトル
      - https://kikakurui.com/z8/Z8301-2011-01.html (kikakurui.com 版)
- 企業の例
  - Microsoft の場合(2008年以降2022年執筆現在まで)
    - http://web.archive.org/web/20080406153629/http://www.microsoft.com/language/ja/jp/default.mspx  (MicrosoftはURL変更しまくりでもう今このページがどこへ行ったかは探すの大変なので wayback machine)
    - https://atmarkit.itmedia.co.jp/news/200807/25/microsoft.html (`@IT` 当時の解説記事)
- 英単語の発音確認
  - https://eow.alc.co.jp/ (英辞郎 on the WEB オンラインEJサービスでお馴染みのサービス)
[雑記] エントリーポイント(C#)

# エントリーポイント

実行可能(Exe形式等)なプログラムを書く際、最初に実行される処理を **エントリーポイント** と呼ぶ。
C# においては、以下の方法で エントリーポイント を定義できる。

* 特定の条件を満たした `Main` メソッド

https://learn.microsoft.com/ja-jp/dotnet/csharp/fundamentals/program-structure/main-command-line

* トップレベルステートメント (C# 9.0 以降)

https://learn.microsoft.com/ja-jp/dotnet/csharp/fundamentals/program-structure/top-level-statements

## `Main` メソッド

C# では、以下の条件を全て満たすメソッドを エントリーポイント として指定できる(以下 "`Main` メソッド" と表記)。

* メソッド名が `Main`
* 静的メソッド (`static`)
* 引数は なし または `string[]` のどちらか
* 戻り値は以下のいずれか
    * なし (`void`)
    * `int`
    * `Task` (C# 7.1以降)
    * `Task<int>` (C# 7.1以降)

その他、細々としたこと。

* クラス名は任意で、`public`にする必要は無い (`internal` でもエントリーポイントに指定できる)
* `Main` メソッド は `public` にする必要は無い (アクセス修飾子は `private` や 未指定 でも良い)
* `Main` メソッド の引数として `string[]` を指定した場合、実行時のコマンドライン引数を `string`配列 として受け取れる
* `Main` メソッド の戻り値の型が `Task` または `Task<int>` の場合、`async` 修飾子を付与して 非同期メソッド にできる

### `Main` メソッド の例

```csharp
using System;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}
```

### エントリーポイントの指定

スタートアップオブジェクト に指定されたクラスの `Main` メソッド がエントリーポイントとして指定される。
プロジェクト(アセンブリ) に含まれる `Main` メソッド の個数により、スタートアップオブジェクト は以下の通り指定される。

* `Main` メソッド が存在しない場合
    * ビルドエラー(実行不可)
* `Main` メソッド が 1つのクラスにのみ 存在する場合
    * `Main` メソッド が含まれるクラスが スタートアップオブジェクト として暗黙的に指定される
* `Main` メソッド が 複数のクラス に存在する場合
    * 明示的に スタートアップオブジェクト を指定する必要がある
        * ビルドオプション(`-main`)
        * プロジェクト定義(csprojファイル の `StartupObject` タグ)
    * 指定が無い場合、ビルドエラー(実行不可)

なお、スタートアップオブジェクト に指定されたクラスに `Main` メソッド が複数存在する場合、エントリーポイントとして扱うメソッドが特定できない為ビルドエラーとなる。


## トップレベルステートメント

C# 9.0 で導入された、**トップレベル** に書かれた ステートメント を エントリーポイント として扱う仕組み。
トップレベルステートメント は プロジェクトの他のプログラムから実行することは出来ない為、エントリーポイント としてのみ取り扱われる(誤ってプログラム内で エントリーポイント を実行することを防ぐことができる)。

トップレベルステートメント は以下の制約がある。

* プロジェクト(アセンブリ) 全体 で 1つのファイル にのみ、記述できる
* ファイル中の 名前空間 や クラス等 の定義より上にのみ記述できる(基本的にファイルの先頭に記述)

その他、細々としたこと。

* コマンドライン引数が必要な場合、暗黙的に定義される `args` という名前の変数で参照できる
    * `Main` メソッド の引数で `string[] args` と定義した場合に相当する
    * コマンドライン引数が入力されなかった場合、`args` は 長さ 0 の配列になる(`null`にはならない)
* `int` 値 を返すことが出来る
    * `Main` メソッド における戻り値の型を `int` とした場合に相当する
    * `int` 値 を返さないルートがある場合、ビルドエラーになる(メソッドの場合と同様)
      例) 以下のコードはビルドエラー
      ```csharp
      if (args.Length == 0)
      {
          return 1;
      }
      Console.WriteLine($"Hello, World! {args[0]}");
      ```
* `await` を使用して 非同期メソッド を呼び出すことが出来る
    * `Main` メソッド における戻り値の型を `Task` または `Task<int>` とした場合に相当する
* `Main` メソッド と併用できない
    * トップレベルステートメント が存在するプロジェクトで `Main` メソッド を定義した場合、無視される。
      ビルド時に以下の警告が出力される。
      > CS7022 プログラムのエントリ ポイントは、グローバル コードです。エントリ ポイント 'Program.Main()' を無視します。
    * トップレベルステートメント が存在するプロジェクトで スタートアップオブジェクト を指定した場合、ビルドエラーとなる。
      > CS8804 トップレベルのステートメントを含むコンパイル ユニットがある場合、/main を指定することはできません。
* C# 10 では、ビルド時に トップレベルステートメント が暗黙的に作成された `Program` クラスに展開される為、グローバル(名前空間を指定しない) で `Program` クラスを宣言するとビルドエラーになる(クラス名が競合する)。
    * `partial` を付与することでビルドエラーは回避できる。


### トップレベルステートメント の例

```csharp
using System;

Console.WriteLine("Hello, World!");
```
Stripe Checkout / Payment Linksの注文・サブスクリプション申込画面で、「利用規約に同意する」チェックボックスを表示する方法

Webサービスの申込画面などでは、「利用規約に同意する」アクションを設けることがあります。

![スクリーンショット 2022-09-26 16.35.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/7c671327-43c7-5c89-9bf6-e547aa12cb19.png)

「チェックボックスがオンの時のみ、submit操作できる」実装が必要になりますが、Stripeのリダイレクト型決済（Checkout / Payment Links）では、より簡単に対応できます。

## 事前準備: Stripeアカウントに利用規約URLを設定しよう

「利用規約への同意」機能を設定するには、Stripeアカウントに**利用規約URL**を登録する必要があります。

[[設定 > 公開ビジネス設定]](https://dashboard.stripe.com/settings/public)から、[利用規約]URLを設定しましょう。

![スクリーンショット 2022-09-26 16.39.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/38034ed9-8af5-f1e0-6c94-22b63e7db8ca.png)

なお、[特定商取引法に基づく表記]も入力が必要です。
これからアカウントを作られる方は、こちらも忘れずに設定しましょう。

https://qiita.com/hideokamoto/items/382956c50973c7e1fe7b

https://qiita.com/hideokamoto/items/9ca5845a4f68dae808fd

URLの保存ができていれば、準備完了です。

## Payment Linksで、利用規約の同意機能を設定する方法

もっとも簡単に試す方法は、Payment Linksを使うことです。

まず、[Payment Linksの作成](https://dashboard.stripe.com/test/payment-links/create)または作成済みのPayment Linksの編集画面を開きましょう。

[利用規約URL]が保存できていれば、[詳細設定]を開くと[顧客に利用規約の承認を求める]チェックボックスが表示されます。

![スクリーンショット 2022-09-26 16.45.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/af318fd5-c347-f7ed-9bb0-44753c4e5585.png)

このチェックボックスをオンにするだけで、決済画面に「利用規約への同意」チェックボックスが追加されます。

### APIで設定する方法

APIでPayment Linksを作成する場合、`consent_collection.terms_of_service`を利用して有効化できます。

```diff_javascript
    await stripe.paymentLinks.create({
      line_items: [{
        price: 'price_1XXXXXXX',
        quantity: 1
      }],
+      consent_collection: {
+        terms_of_service: 'required'
+      }      
    })
```

## Checkoutで、利用規約への同意機能を設定する方法

Checkoutを利用している場合は、`checkout.sessions.create`APIの引数を１つ追加します。

```diff_javascript
    await stripe.checkout.sessions.create({
      line_items: [{
        price: 'price_1XXXXXXX',
        quantity: 1
      }],
      currency: 'jpy',
      mode: 'subscription',
      success_url: 'https://example.com',
      cancel_url: 'https://example.com',
+      consent_collection: {
+        terms_of_service: 'required'
+      }      
    })
```

もし「特定条件では表示させる必要がない」ケースが発生した場合は、`required`を`none`に変更しましょう。

```diff_javascript
    await stripe.checkout.sessions.create({
      line_items: [{
        price: 'price_1XXXXXXX',
        quantity: 1
      }],
      currency: 'jpy',
      mode: 'subscription',
      success_url: 'https://example.com',
      cancel_url: 'https://example.com',
      consent_collection: {
-        terms_of_service: 'required'
+        terms_of_service: ANY_CONDITION ? 'none' : 'required'
      }      
    })
```

## Documents

https://stripe.com/docs/payments/checkout/customization#collect-a-terms-of-service-agreement


---

## [PR] Stripe開発者向け情報をQiitaにて配信中！

- [Stripe Updates]：開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について週に２〜３本ペースで更新中です。

-> [Stripe Organizationsをフォローして最新情報をQiitaで受け取る](https://qiita.com/organizations/stripe)
ASP.NET MVCで404を正しく処理する方法を教えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509696/2748140d-9bba-8450-7d08-5147622b1180.png)

From　：　https://www.web-dev-qa-db-ja.com/ja/asp.net-mvc/aspnet-mvc%E3%81%A7404%E3%82%92%E6%AD%A3%E3%81%97%E3%81%8F%E5%87%A6%E7%90%86%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82/957780919/
【Git】他人が消したリモートブランチをローカルに反映させる

# 解決したい問題
リモートには存在しないブランチがローカルには存在している
### リモート
![スクリーンショット 2022-09-30 19.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/41dbec3d-e787-206f-9e46-2d494c03a742.png)

### ローカル
![スクリーンショット 2022-09-30 19.05.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/28d3169b-fd3d-91fd-d996-90a5a827db8a.png)


# 解決方法
```:ターミナル
git remote prune origin
```
![スクリーンショット 2022-09-30 19.09.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/25fd5fc8-8d6d-66f9-7dfe-c61904540c25.png)

ローカルにも削除を反映することができました。

# おわり
最近インターンシップで出会った友達とチーム開発を始めて学ぶことが多いです🤗
作るって楽しい！！
Linux 備忘録

### USBフォーマット

~~~
$ udo mkfs.ext4 /dev/sdb1 -L "USB Drive"
$ sudo mkfs.exfat /dev/sdb1 -n "USB Drive"
~~~

### USBマウント

~~~
$ lsblk
$ sudo mount /dev/sdc1 /mnt
~~~

### USBアンマウント

~~~
$ sudo umount /dev/sdc1 /mnt
~~~

### 起動用USB作成(iso)

~~~
$ sudo dd if=/home/username/Downloads/archlinux.iso of=/dev/sdc bs=512k
~~~

### CtrlキーとCaps Lockキーの入れ替え

~~~
$ sudo pacman -S xorg-xmodmap
$ xmodmap -ke > ~/.Xmodmap
$ vi ~/.Xmodmap
~~~
.Xmodmapファイルの末尾に以下を追加
~~~ .Xmodmap
　：
clear lock
clear control
keycode 66 = Control_L
add control = Control_L Control_R
~~~
以下のコマンドで適用する。
~~~
$ xmodmap ~/.Xmodmap
~~~
入れ替えたはずなのに、Caps Lockキーを押してもCtrlの動作をしない場合は再度上記コマンドを実行してみる。
新卒1年目が入社して半年でやったこと

新卒入社して半年の宮副です。
今回はこの半年で自分でやったことを紹介します。

## 基本情報技術試験
この試験はエンジニアとしては当たり前に知っておくべきことが一通り網羅された試験だと思います。
と言いながら、僕はあと一問のところで落ちてしまったのでまだまだエンジニアとして勉強不足です。
こちらの試験に向けて使用した教材を紹介します。

[キタミ式イラストIT塾 基本情報技術者]( https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C04%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF-%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297124513/ref=zg_bs_502776_sccl_5/358-6070205-7406643?pd_rd_i=4297124513&psc=1)
[基本情報技術者過去問道場](https://www.fe-siken.com/fekakomon.php)
## Django + Vue.jsの勉強
TORICOでは、DjangoとNuxtを使ったプロジェクトがあります。
そのためDjangoとNuxtの元となっているVueを使ったアプリの勉強をしました。
使用した教材はこちらです。

https://www.youtube.com/watch?v=Yg5zkd9nm6w

Django Rest Frameworkを使ってAPI通信をしたアプリケーションを学べます。


## ネットワーク
僕が配属された部署ではネットワークを触ることも度々あります。
そのためネットワークの知識が必要と強く感じましたが、初心者でIPアドレスやMACアドレスの違いもいまいち分かっていない状態で教材を探していたところとてもわかりやすい教材を見つけました。

https://www.youtube.com/c/%E3%81%BE%E3%81%95%E3%82%8B%E3%81%AE%E5%8B%89%E5%BC%B7%E9%83%A8%E5%B1%8B

この方の動画は、何もわからない状態の僕でもわかりやすく丁寧に説明してくれています。
ネットワーク以外にもCCNAや情報支処理安全技術者試験に沿った解説動画もあってエンジニアとして基礎の部分を学べる動画がたくさん載っています。
また、実際にハブやスイッチを買って勉強したいけどお金がないという僕と同志の方でも使えるスーパー神教材がこちらです。

[パケットトレーサー](https://www.netacad.com/ja/courses/packet-tracer)


パケットトレーサーはダウンロードするだけでネットワーク構築の仮想環境を提供してくれます。
まさるさんの動画でもパケットトレーサーを使って説明してくれているので一緒に進めていくのもおすすめです。


## 最後に
まだまだ、わかっていないことが多いのでこれからも復習しながら新しい知識を学んでいきます。
Linuxやネットワーク以外にも、DockerやAWSの勉強も今後はやっていきます。
複数のノードをスーパーノードでまとめる(SPSS Modeler データ加工逆引き9-1)

# 複数のノードをスーパーノードでまとめる

![スクリーンショット 2022-09-30 18.37.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ae298a05-ca21-d4eb-b030-d579623b96b7.png)

## 1.想定される利用目的

・煩雑なストリームの整理
・頻度の高いプロセスのルーチン化とチームでの共有


## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/supernode_simple.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-09-30 18.44.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e5d7e11a-1078-65fa-5c76-ea2499a3b624.png)

A.中央３つの[フィールド作成]ノードを範囲指定し、赤枠の星アイコンまたは右クリックで[スーパーノードの作成]を選択
![スクリーンショット 2022-09-30 18.40.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2dd8bf98-69fd-ba1a-b2ec-339939416e9a.png)

３つのノードがカプセル化されました。
![スクリーンショット 2022-09-30 18.42.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/121d50d8-9efe-e9ed-aa49-5c44022497fd.png)

スーパーノードの中のノードを確認する方法は右クリックで[ズームイン]を選択します。なお[展開]を選択すると元のストリームに復元します。
![スクリーンショット 2022-09-30 18.41.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/19828edd-1d3b-5d68-98b8-78190ddd3b33.png)

内部をズームインしました。
![スクリーンショット 2022-09-30 18.42.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8e606676-7c2a-ed75-adc6-d236f3146b78.png)

ダブルクリックして[ノードのロック]ボタンで内部を参照/編集できないようにできます。資産としてプロセスを保護したまま、外部の組織に提供することが可能です。
![スクリーンショット 2022-09-30 18.42.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4cf5ecf3-2b3d-d5c8-f935-31128427a361.png)

B.入力プロセスを含んだスーパーノードはアイコンの左半分が青くなります。

C.出力やエクスポートを含んだスーパーノードはアイコンの右半分が青くなります。

#### 注意事項

スーパーノードの中にスーパーノードをネストすることが可能ですが、深い階層を作ると返って煩雑になります。

複数の分岐を後続に持つプロセスはスーパーノードにはできません。

## 4.参考情報

#### スーパーノードを解説した記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-20/

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
PWA(Progressive Web Apps)とは -Qiitaをスマホで快適に見る-

## QiitaをiPhoneで快適に見たい
1. でも公式アプリってないよね？
1. とりあえずホーム画面に追加するか…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882988/7832dae2-6e7d-f6df-bda1-1b16d05adb48.png)
1. で、生成されたこれを押す。
![S__70516744.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882988/5e1e897f-ecd6-4c39-1c3a-7f789015bf0b.jpeg)
1. するとSafariで開かれず、アドレスバーも何もないネイティブアプリのような画面で表示される。
![S__70516740.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882988/e34c7afe-9f89-c31f-965b-2214c7ca48a4.jpeg)
5. !?

## 調べてみた
どうやらこれはPWA(Progressive Web Apps)という技術を使っているらしい。
> PWAとは、Progressive Web Appsの略称で、モバイルブラウザとネイティブアプリ（アプリストアからダウンロードして使用するアプリ）の利点を融合したWebアプリ（アプリのように振る舞う高速なWebサイト）のこと。
https://www.irep.co.jp/knowledge/glossary/detail/id=10227/

サイト側と端末側が対応している必要があるが、2022年9月現在AndroidとiOSが対応しているのでほとんどのスマホではこの機能が使える模様。

PWAはGoogleが考えついた。やっぱなんでもGoogleのせいなんだね。
[Googleが推す「PWA」とは？　iOS16からプッシュ通知も可能に](https://backapp.co.jp/blog/12558)

2018年頃にiPhoneでも使用可能になった模様。
これの何が嬉しいかというと、
- インストール不要。
- ネイティブアプリとして開発しなくても、ネイティブアプリのような動作をさせられる。
- オフラインでも使用可能(もちろん最新のデータを受信するにはインターネット接続が必要)。
- プッシュ通知を受け取れる。
- 検索に載る。
    - 中身はそのままWebサイトなので、コンテンツが普通にウェブページとして検索に引っかかるのがアプリと違うところ。

デメリットは
- アプリストアに乗らない(流入口が減る)
- 普通のWebサイトを開発するのと比べるとPWA対応のための開発コストがかかる

といったところか。

## 対応サービスの例
- これ(Qiita)
- Twitter
- Instagram
- 日経電子版
- SUUMO
- etc.

## 対応させるには
以下の記事が参考になる。
[PWA導入までの3ステップと、簡単なオフライン対応まで](https://qiita.com/yshrkn/items/519cc58cb54e0f7f61ae)

要点としては
1. HTTPS対応
Service Workerというのが動くのにHTTPSが必須

1. マニフェストの作成・読み込み
マニフェスト: JSONで記述されたPWAの設定ファイル

1. Service Workerの作成・読み込み
なんかファイルを作るらしい。詳しくは[公式](https://developer.chrome.com/docs/workbox/service-worker-overview/)を見てくれ。

## へぇ～
すごい。
技育展に登壇したときの話

# 概要
先日、技育展2022に登壇させていただきました。
仕上げ期間の約3週間、プレゼン期間で感じたことや成長できたことなどを書こうと思います。

# 技育展とは
株式会社サポーターズが主催している学生エンジニアがアウトプットした制作物を展示するイベントです。

# 展示物について
私が開発した制作物について紹介していきます。
私は2つのチームを兼任してたので2つ簡単に紹介しようと思います。

### チャバットボ
これはオンラインコミュニケーションアプリです。
具体的に言うと、投稿した文章が全てバビ語に変換されて面白く会話できるSNSになっています。
ツイッターのようにタイムラインやDM機能、それらに加えいいね数などで投稿ごとに面白さを競うことができるランキング機能も搭載されています。
※バビ語については各自調べていただけると幸いです。

### BreakTime
これは一定時間経過後休憩を促してくれるVSCodeの拡張機能です。
休憩時には前回の休憩から今回の休憩までにどのくらいのコードを書いたのかを可視化されるようになっています。
実際にVSCodeからインストールできますので、「BreakTime」と検索し、使っていただけると幸いです。

# 感じたこと
* 同じ大学生でもつよつよのエンジニアが大勢いること
* 開発経験が短くてもこういったイベントに参加できる可能性があるということ
* いくら素晴らしいプロダクトを制作してもプレゼン力がないと魅力が伝わらないということ

# 成長できたこと
* プレゼンを楽しいと感じることができ、どうすればより面白く伝わるか魅力に伝わるかについて考える思考力がついた
* 開発期間の約1ヶ月ちょっと諦めずに最後まで走り抜けることができたこと
* 新しい技術に触れるときの習得速度が早まった気がする

# まとめ
やっぱり開発するのめっちゃ楽しい！！
あと、個人開発よりチーム開発の方がうまく役割分担できたり、わからないことはすぐにチームメンバーに質問できる環境で開発できるのはモチベーションにも繋がる！しかもチームメンバー全員が同じ目標に向かっていることは大事だと感じました。

また、少し勇気を出して技術的なイベントに参加することで新しい世界が見え、確実に成長できたと感じることができました。
Docker × Laravel 環境でRedisを構築する基本のキ

#### 前提
すでにDockerに環境がある状態で、Redisを追加する場合の手順になります。
クラスター構成ではなく最小で構築します。

# DockerにRedisコンテナを立ち上げる

* **docker-compose.ymlにRedisを追記する**

```
  #redis
  redis:
    image: redis:6.0.9
    command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf
      - ./docker/redis/data:/data
```

:::note info
'--appendonly yes'はデータの永続化を意味します。
volumesに記述するパスは各々の環境に合わせて変更してください。
redisのバージョン指定は例です、指定がなければ'latest'（最新）がオススメです。
:::


* **コマンドを叩いて立ち上げる**

    * `docker-compose build`
    * `docker-compose up`
    ＊こちらでも可↓
    * `docker-compose up --build`

:::note info
キャッシュを使いたくない、またはキャッシュ系でエラーが出たら'--no-cache'オプションをコマンドの末尾につけてみてください。
:::

これだけです！便利ですね😊


# LaravelにRedisクライアントをインストールする

* **コマンドを叩く**
    * `composer require predis/predis`

  　＊バージョン指定の場合↓

    * `composer require predis/predis:x.x.x`

  　＊インストールの進捗を確認したい場合↓

    * `composer require predis/predis -vvv`

:::note info
メモリリークでエラーが起きる場合は、
'COMPOSER_MEMORY_LIMIT=-1 composer require predis/predis'
のようにオプションをつけてみてください。
:::

　　   ちなみに、peclやgitからでもRedisクライアントのインストールは可能です。
　　 ただし、Laravel側で追加設定が必要だったりするので興味ある方は調べてみてください😄


* **database.phpの修正**

```
    'redis' => [

        'client' => env('REDIS_CLIENT', 'predis'),

        'default' => [
            'host' => env('REDIS_HOST', '127.0.0.1'), // or 'redis'
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

    ],
```

:::note info
envファイルが別にある場合はそちらが優先されるのでご注意ください。
:::

:::note info
クラスター構成にする場合は追加の記述が必要です。
:::

以上です。
今回は構築の説明なので具体的な操作や実例は割愛します😃


ここまで問題なく進めると、Redisファサードを用いて操作できるようになっているはずです。
それでは、よいKVSライフを！